[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH, RFC 2/7] IOMMU: IOMMU: adjust add/remove operation parameters


  • To: "xen-devel" <xen-devel@xxxxxxxxxxxxx>
  • From: "Jan Beulich" <JBeulich@xxxxxxxx>
  • Date: Wed, 28 Nov 2012 09:48:53 +0000
  • Delivery-date: Wed, 28 Nov 2012 09:48:23 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

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

--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ b/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)
@@ -295,16 +294,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);
@@ -312,7 +311,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);
 
@@ -327,7 +326,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);
 }
@@ -350,7 +350,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 )
     {
@@ -363,7 +363,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);
@@ -449,7 +449,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;
@@ -462,16 +462,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;
@@ -484,12 +484,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;
 }
 
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -164,7 +164,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)
@@ -194,7 +194,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);
 }
 
 /*
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -743,7 +743,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)
@@ -764,12 +764,12 @@ 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);
             }
             else if ( pdev->domain == dom_xen )
             {
                 pdev->domain = ctxt->d;
-                ctxt->handler(pdev);
+                ctxt->handler(devfn, pdev);
                 pdev->domain = dom_xen;
             }
             else if ( pdev->domain != ctxt->d )
@@ -783,7 +783,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 };
 
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -50,7 +50,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,
@@ -1873,7 +1873,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;
@@ -1884,8 +1884,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",
@@ -1897,7 +1896,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 )
@@ -1922,7 +1921,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;
@@ -1940,19 +1939,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)
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -94,9 +94,9 @@ struct msi_msg;
 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,
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -100,7 +100,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);

Attachment: IOMMU-add-remove-params.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.