References: bnc#787169

# HG changeset patch
# User Jan Beulich <jbeulich@suse.com>
# Date 1357559482 -3600
# Node ID 75cc4943b1ff509c4074800a23ff51d773233b8a
# Parent  62dd78a4e3fc9d190840549f13b4d613f2d19c41
IOMMU: adjust add/remove operation 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/amd/pci_amd_iommu.c
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ xen-4.2.3-testing/xen/drivers/passthrough/amd/pci_amd_iommu.c
@@ -83,14 +83,14 @@ static void disable_translation(u32 *dte
 }
 
 static void amd_iommu_setup_domain_device(
-    struct domain *domain, struct amd_iommu *iommu, int bdf)
+    struct domain *domain, struct amd_iommu *iommu,
+    u8 devfn, struct pci_dev *pdev)
 {
     void *dte;
     unsigned long flags;
     int req_id, valid = 1;
     int dte_i = 0;
-    u8 bus = PCI_BUS(bdf);
-    u8 devfn = PCI_DEVFN2(bdf);
+    u8 bus = pdev->bus;
 
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
 
@@ -103,7 +103,7 @@ static void amd_iommu_setup_domain_devic
         dte_i = 1;
 
     /* get device-table entry */
-    req_id = get_dma_requestor_id(iommu->seg, bdf);
+    req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
     dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
 
     spin_lock_irqsave(&iommu->lock, flags);
@@ -115,7 +115,7 @@ static void amd_iommu_setup_domain_devic
             (u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
             hd->paging_mode, valid);
 
-        if ( pci_ats_device(iommu->seg, bus, devfn) &&
+        if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
              iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
             iommu_dte_set_iotlb((u32 *)dte, dte_i);
 
@@ -132,32 +132,31 @@ static void amd_iommu_setup_domain_devic
 
     ASSERT(spin_is_locked(&pcidevs_lock));
 
-    if ( pci_ats_device(iommu->seg, bus, devfn) &&
-         !pci_ats_enabled(iommu->seg, bus, devfn) )
+    if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
+         !pci_ats_enabled(iommu->seg, bus, pdev->devfn) )
     {
-        struct pci_dev *pdev;
+        if ( devfn == pdev->devfn )
+            enable_ats_device(iommu->seg, bus, devfn);
 
-        enable_ats_device(iommu->seg, bus, devfn);
-
-        ASSERT(spin_is_locked(&pcidevs_lock));
-        pdev = pci_get_pdev(iommu->seg, bus, devfn);
-
-        ASSERT( pdev != NULL );
         amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
     }
 }
 
-static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
+static int __init amd_iommu_setup_dom0_device(u8 devfn, struct pci_dev *pdev)
 {
     int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
     struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
 
-    if ( likely(iommu != NULL) )
-        amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
-    else
+    if ( unlikely(!iommu) )
+    {
         AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
                         pdev->seg, pdev->bus,
-                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+                        PCI_SLOT(devfn), PCI_FUNC(devfn));
+        return -ENODEV;
+    }
+
+    amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
+    return 0;
 }
 
 int __init amd_iov_detect(void)
@@ -311,16 +310,16 @@ static void __init amd_iommu_dom0_init(s
 }
 
 void amd_iommu_disable_domain_device(struct domain *domain,
-                                     struct amd_iommu *iommu, int bdf)
+                                     struct amd_iommu *iommu,
+                                     u8 devfn, struct pci_dev *pdev)
 {
     void *dte;
     unsigned long flags;
     int req_id;
-    u8 bus = PCI_BUS(bdf);
-    u8 devfn = PCI_DEVFN2(bdf);
+    u8 bus = pdev->bus;
 
     BUG_ON ( iommu->dev_table.buffer == NULL );
-    req_id = get_dma_requestor_id(iommu->seg, bdf);
+    req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
     dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
 
     spin_lock_irqsave(&iommu->lock, flags);
@@ -328,7 +327,7 @@ void amd_iommu_disable_domain_device(str
     {
         disable_translation((u32 *)dte);
 
-        if ( pci_ats_device(iommu->seg, bus, devfn) &&
+        if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
              iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
             iommu_dte_set_iotlb((u32 *)dte, 0);
 
@@ -343,7 +342,8 @@ void amd_iommu_disable_domain_device(str
 
     ASSERT(spin_is_locked(&pcidevs_lock));
 
-    if ( pci_ats_device(iommu->seg, bus, devfn) &&
+    if ( devfn == pdev->devfn &&
+         pci_ats_device(iommu->seg, bus, devfn) &&
          pci_ats_enabled(iommu->seg, bus, devfn) )
         disable_ats_device(iommu->seg, bus, devfn);
 }
@@ -366,7 +366,7 @@ static int reassign_device(struct domain
         return -ENODEV;
     }
 
-    amd_iommu_disable_domain_device(source, iommu, bdf);
+    amd_iommu_disable_domain_device(source, iommu, devfn, pdev);
 
     if ( devfn == pdev->devfn )
     {
@@ -379,7 +379,7 @@ static int reassign_device(struct domain
     if ( t->root_table == NULL )
         allocate_domain_resources(t);
 
-    amd_iommu_setup_domain_device(target, iommu, bdf);
+    amd_iommu_setup_domain_device(target, iommu, devfn, pdev);
     AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
                     pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                     source->domain_id, target->domain_id);
@@ -469,7 +469,7 @@ static void amd_iommu_domain_destroy(str
     amd_iommu_flush_all_pages(d);
 }
 
-static int amd_iommu_add_device(struct pci_dev *pdev)
+static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev)
 {
     struct amd_iommu *iommu;
     u16 bdf;
@@ -482,16 +482,16 @@ static int amd_iommu_add_device(struct p
     {
         AMD_IOMMU_DEBUG("Fail to find iommu."
                         " %04x:%02x:%02x.%u cannot be assigned to dom%d\n",
-                        pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
-                        PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
+                        pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                        pdev->domain->domain_id);
         return -ENODEV;
     }
 
-    amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
+    amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
     return 0;
 }
 
-static int amd_iommu_remove_device(struct pci_dev *pdev)
+static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
 {
     struct amd_iommu *iommu;
     u16 bdf;
@@ -504,12 +504,12 @@ static int amd_iommu_remove_device(struc
     {
         AMD_IOMMU_DEBUG("Fail to find iommu."
                         " %04x:%02x:%02x.%u cannot be removed from dom%d\n",
-                        pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
-                        PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
+                        pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                        pdev->domain->domain_id);
         return -ENODEV;
     }
 
-    amd_iommu_disable_domain_device(pdev->domain, iommu, bdf);
+    amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev);
     return 0;
 }
 
Index: xen-4.2.3-testing/xen/drivers/passthrough/iommu.c
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/iommu.c
+++ xen-4.2.3-testing/xen/drivers/passthrough/iommu.c
@@ -167,7 +167,7 @@ int iommu_add_device(struct pci_dev *pde
     if ( !iommu_enabled || !hd->platform_ops )
         return 0;
 
-    return hd->platform_ops->add_device(pdev);
+    return hd->platform_ops->add_device(pdev->devfn, pdev);
 }
 
 int iommu_enable_device(struct pci_dev *pdev)
@@ -197,7 +197,7 @@ int iommu_remove_device(struct pci_dev *
     if ( !iommu_enabled || !hd->platform_ops )
         return 0;
 
-    return hd->platform_ops->remove_device(pdev);
+    return hd->platform_ops->remove_device(pdev->devfn, pdev);
 }
 
 /*
Index: xen-4.2.3-testing/xen/drivers/passthrough/pci.c
===================================================================
--- xen-4.2.3-testing.orig/xen/drivers/passthrough/pci.c
+++ xen-4.2.3-testing/xen/drivers/passthrough/pci.c
@@ -715,7 +715,7 @@ int __init scan_pci_devices(void)
 
 struct setup_dom0 {
     struct domain *d;
-    void (*handler)(struct pci_dev *);
+    int (*handler)(u8 devfn, struct pci_dev *);
 };
 
 static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
@@ -734,7 +734,7 @@ static int __init _setup_dom0_pci_device
 
             pdev->domain = ctxt->d;
             list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
-            ctxt->handler(pdev);
+            ctxt->handler(devfn, pdev);
         }
     }
 
@@ -742,7 +742,7 @@ static int __init _setup_dom0_pci_device
 }
 
 void __init setup_dom0_pci_devices(
-    struct domain *d, void (*handler)(struct pci_dev *))
+    struct domain *d, int (*handler)(u8 devfn, struct pci_dev *))
 {
     struct setup_dom0 ctxt = { .d = d, .handler = handler };
 
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
@@ -52,7 +52,7 @@ int nr_iommus;
 
 static struct tasklet vtd_fault_tasklet;
 
-static void setup_dom0_device(struct pci_dev *);
+static int setup_dom0_device(u8 devfn, struct pci_dev *);
 static void setup_dom0_rmrr(struct domain *d);
 
 static int domain_iommu_domid(struct domain *d,
@@ -1907,7 +1907,7 @@ static int rmrr_identity_mapping(struct
     return 0;
 }
 
-static int intel_iommu_add_device(struct pci_dev *pdev)
+static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev)
 {
     struct acpi_rmrr_unit *rmrr;
     u16 bdf;
@@ -1918,8 +1918,7 @@ static int intel_iommu_add_device(struct
     if ( !pdev->domain )
         return -EINVAL;
 
-    ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus,
-                                 pdev->devfn);
+    ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
     if ( ret )
     {
         dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
@@ -1931,7 +1930,7 @@ static int intel_iommu_add_device(struct
     {
         if ( rmrr->segment == pdev->seg &&
              PCI_BUS(bdf) == pdev->bus &&
-             PCI_DEVFN2(bdf) == pdev->devfn )
+             PCI_DEVFN2(bdf) == devfn )
         {
             ret = rmrr_identity_mapping(pdev->domain, rmrr);
             if ( ret )
@@ -1956,7 +1955,7 @@ static int intel_iommu_enable_device(str
     return ret >= 0 ? 0 : ret;
 }
 
-static int intel_iommu_remove_device(struct pci_dev *pdev)
+static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
 {
     struct acpi_rmrr_unit *rmrr;
     u16 bdf;
@@ -1974,19 +1973,22 @@ static int intel_iommu_remove_device(str
         {
             if ( rmrr->segment == pdev->seg &&
                  PCI_BUS(bdf) == pdev->bus &&
-                 PCI_DEVFN2(bdf) == pdev->devfn )
+                 PCI_DEVFN2(bdf) == devfn )
                 return 0;
         }
     }
 
-    return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus,
-                                pdev->devfn);
+    return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
 }
 
-static void __init setup_dom0_device(struct pci_dev *pdev)
+static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
 {
-    domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, pdev->devfn);
-    pci_vtd_quirk(pdev);
+    int err;
+
+    err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
+    if ( !err && devfn == pdev->devfn )
+        pci_vtd_quirk(pdev);
+    return err;
 }
 
 void clear_fault_bits(struct iommu *iommu)
Index: xen-4.2.3-testing/xen/include/xen/iommu.h
===================================================================
--- xen-4.2.3-testing.orig/xen/include/xen/iommu.h
+++ xen-4.2.3-testing/xen/include/xen/iommu.h
@@ -120,9 +120,9 @@ bool_t pt_irq_need_timer(uint32_t flags)
 struct iommu_ops {
     int (*init)(struct domain *d);
     void (*dom0_init)(struct domain *d);
-    int (*add_device)(struct pci_dev *pdev);
+    int (*add_device)(u8 devfn, struct pci_dev *);
     int (*enable_device)(struct pci_dev *pdev);
-    int (*remove_device)(struct pci_dev *pdev);
+    int (*remove_device)(u8 devfn, struct pci_dev *);
     int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *);
     void (*teardown)(struct domain *d);
     int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
Index: xen-4.2.3-testing/xen/include/xen/pci.h
===================================================================
--- xen-4.2.3-testing.orig/xen/include/xen/pci.h
+++ xen-4.2.3-testing/xen/include/xen/pci.h
@@ -101,7 +101,8 @@ struct pci_dev *pci_lock_pdev(int seg, i
 struct pci_dev *pci_lock_domain_pdev(
     struct domain *, int seg, int bus, int devfn);
 
-void setup_dom0_pci_devices(struct domain *, void (*)(struct pci_dev *));
+void setup_dom0_pci_devices(struct domain *,
+                            int (*)(u8 devfn, struct pci_dev *));
 void pci_release_devices(struct domain *d);
 int pci_add_segment(u16 seg);
 const unsigned long *pci_get_ro_map(u16 seg);
