References: bnc#787169

# HG changeset patch
# User Jan Beulich <jbeulich@suse.com>
# Date 1357559549 -3600
# Node ID afb598bd0f5436bea15b7ef842e8ad5c6adefa1a
# Parent  75cc4943b1ff509c4074800a23ff51d773233b8a
VT-d: adjust context map/unmap parameters

... to use a (struct pci_dev *, devfn) pair.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>

Index: xen-4.2.3-testing/xen/drivers/passthrough/vtd/extern.h
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/vtd/extern.h
+++ xen-4.2.3-testing/xen/drivers/passthrough/vtd/extern.h
@@ -95,7 +95,7 @@ void free_pgtable_maddr(u64 maddr);
 void *map_vtd_domain_page(u64 maddr);
 void unmap_vtd_domain_page(void *va);
 int domain_context_mapping_one(struct domain *domain, struct iommu *iommu,
-                               u8 bus, u8 devfn);
+                               u8 bus, u8 devfn, const struct pci_dev *);
 int domain_context_unmap_one(struct domain *domain, struct iommu *iommu,
                              u8 bus, u8 devfn);
 
Index: xen-4.2.3-testing/xen/drivers/passthrough/vtd/iommu.c
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/vtd/iommu.c
+++ xen-4.2.3-testing/xen/drivers/passthrough/vtd/iommu.c
@@ -1311,7 +1311,7 @@ static void __init intel_iommu_dom0_init
 int domain_context_mapping_one(
     struct domain *domain,
     struct iommu *iommu,
-    u8 bus, u8 devfn)
+    u8 bus, u8 devfn, const struct pci_dev *pdev)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
     struct context_entry *context, *context_entries;
@@ -1328,11 +1328,9 @@ int domain_context_mapping_one(
     if ( context_present(*context) )
     {
         int res = 0;
-        struct pci_dev *pdev = NULL;
 
-        /* First try to get domain ownership from device structure.  If that's
+        /* Try to get domain ownership from device structure.  If that's
          * not available, try to read it from the context itself. */
-        pdev = pci_get_pdev(seg, bus, devfn);
         if ( pdev )
         {
             if ( pdev->domain != domain )
@@ -1451,13 +1449,12 @@ int domain_context_mapping_one(
 }
 
 static int domain_context_mapping(
-    struct domain *domain, u16 seg, u8 bus, u8 devfn)
+    struct domain *domain, u8 devfn, const struct pci_dev *pdev)
 {
     struct acpi_drhd_unit *drhd;
     int ret = 0;
     u32 type;
-    u8 secbus;
-    struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
+    u8 seg = pdev->seg, bus = pdev->bus, secbus;
 
     drhd = acpi_find_matched_drhd_unit(pdev);
     if ( !drhd )
@@ -1478,8 +1475,9 @@ static int domain_context_mapping(
             dprintk(VTDPREFIX, "d%d:PCIe: map %04x:%02x:%02x.%u\n",
                     domain->domain_id, seg, bus,
                     PCI_SLOT(devfn), PCI_FUNC(devfn));
-        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
-        if ( !ret && ats_device(pdev, drhd) > 0 )
+        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
+                                         pdev);
+        if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
             enable_ats_device(seg, bus, devfn);
 
         break;
@@ -1490,14 +1488,16 @@ static int domain_context_mapping(
                     domain->domain_id, seg, bus,
                     PCI_SLOT(devfn), PCI_FUNC(devfn));
 
-        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
+        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
+                                         pdev);
         if ( ret )
             break;
 
         if ( find_upstream_bridge(seg, &bus, &devfn, &secbus) < 1 )
             break;
 
-        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
+        ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
+                                         pci_get_pdev(seg, bus, devfn));
 
         /*
          * Devices behind PCIe-to-PCI/PCIx bridge may generate different
@@ -1506,7 +1506,8 @@ static int domain_context_mapping(
          */
         if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE &&
              (secbus != pdev->bus || pdev->devfn != 0) )
-            ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0);
+            ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0,
+                                             pci_get_pdev(seg, secbus, 0));
 
         break;
 
@@ -1579,18 +1580,15 @@ int domain_context_unmap_one(
 }
 
 static int domain_context_unmap(
-    struct domain *domain, u16 seg, u8 bus, u8 devfn)
+    struct domain *domain, u8 devfn, const struct pci_dev *pdev)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
     int ret = 0;
     u32 type;
-    u8 tmp_bus, tmp_devfn, secbus;
-    struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
+    u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus;
     int found = 0;
 
-    BUG_ON(!pdev);
-
     drhd = acpi_find_matched_drhd_unit(pdev);
     if ( !drhd )
         return -ENODEV;
@@ -1610,7 +1608,7 @@ static int domain_context_unmap(
                     domain->domain_id, seg, bus,
                     PCI_SLOT(devfn), PCI_FUNC(devfn));
         ret = domain_context_unmap_one(domain, iommu, bus, devfn);
-        if ( !ret && ats_device(pdev, drhd) > 0 )
+        if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
             disable_ats_device(seg, bus, devfn);
 
         break;
@@ -1704,11 +1702,11 @@ static int reassign_device_ownership(
     if ( (target != dom0) && !iommu_intremap )
         untrusted_msi = 1;
 
-    ret = domain_context_unmap(source, pdev->seg, pdev->bus, devfn);
+    ret = domain_context_unmap(source, devfn, pdev);
     if ( ret )
         return ret;
 
-    ret = domain_context_mapping(target, pdev->seg, pdev->bus, devfn);
+    ret = domain_context_mapping(target, devfn, pdev);
     if ( ret )
         return ret;
 
@@ -1918,7 +1916,7 @@ static int intel_iommu_add_device(u8 dev
     if ( !pdev->domain )
         return -EINVAL;
 
-    ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
+    ret = domain_context_mapping(pdev->domain, devfn, pdev);
     if ( ret )
     {
         dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
@@ -1978,14 +1976,14 @@ static int intel_iommu_remove_device(u8
         }
     }
 
-    return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
+    return domain_context_unmap(pdev->domain, devfn, pdev);
 }
 
 static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
 {
     int err;
 
-    err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
+    err = domain_context_mapping(pdev->domain, devfn, pdev);
     if ( !err && devfn == pdev->devfn )
         pci_vtd_quirk(pdev);
     return err;
Index: xen-4.2.3-testing/xen/drivers/passthrough/vtd/quirks.c
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/vtd/quirks.c
+++ xen-4.2.3-testing/xen/drivers/passthrough/vtd/quirks.c
@@ -319,7 +319,7 @@ static void map_me_phantom_function(stru
     /* map or unmap ME phantom function */
     if ( map )
         domain_context_mapping_one(domain, drhd->iommu, 0,
-                                   PCI_DEVFN(dev, 7));
+                                   PCI_DEVFN(dev, 7), NULL);
     else
         domain_context_unmap_one(domain, drhd->iommu, 0,
                                  PCI_DEVFN(dev, 7));
