WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Make PCI device release function generic

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Make PCI device release function generic
From: Espen Skoglund <espen.skoglund@xxxxxxxxxxxxx>
Date: Wed, 9 Jul 2008 14:03:14 +0100
Delivery-date: Wed, 09 Jul 2008 06:04:03 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Make PCI device release function generic

Release all pci devices before doing iommu domain teardown.  Also moved
pdev_flr() into generic pci code.

Signed-off-by: Espen Skoglund <espen.skoglund@xxxxxxxxxxxxx>

--
diff -r 7a0121d7add6 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/arch/x86/domain.c     Wed Jul 09 14:02:59 2008 +0100
@@ -30,6 +30,7 @@
 #include <xen/percpu.h>
 #include <xen/compat.h>
 #include <xen/acpi.h>
+#include <xen/pci.h>
 #include <asm/regs.h>
 #include <asm/mc146818rtc.h>
 #include <asm/system.h>
@@ -473,6 +474,7 @@
     if ( is_hvm_domain(d) )
         hvm_domain_destroy(d);
 
+    pci_release_devices(d);
     if ( !is_idle_domain(d) )
         iommu_domain_destroy(d);
 
diff -r 7a0121d7add6 xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Wed Jul 09 13:12:21 
2008 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Wed Jul 09 14:02:59 
2008 +0100
@@ -485,8 +485,6 @@
     }
 }
 
-extern void pdev_flr(u8 bus, u8 devfn);
-
 static int reassign_device( struct domain *source, struct domain *target,
                             u8 bus, u8 devfn)
 {
@@ -498,6 +496,7 @@
     if ( !pdev )
        return -ENODEV;
 
+    pdev_flr(pdev);
     bdf = (bus << 8) | devfn;
     /* supported device? */
     iommu = (bdf < ivrs_bdf_entries) ?
@@ -545,24 +544,7 @@
             ivrs_mappings[req_id].read_permission);
     }
 
-    pdev_flr(bus, devfn);
     return reassign_device(dom0, d, bus, devfn);
-}
-
-static void release_domain_devices(struct domain *d)
-{
-    struct pci_dev *pdev;
-    u8 bus, devfn;
-
-    while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) )
-    {
-        pdev_flr(pdev->bus, pdev->devfn);
-       bus = pdev->bus; devfn = pdev->devfn;
-       spin_unlock(&pdev->lock);
-        amd_iov_info("release domain %d devices %x:%x.%x\n", d->domain_id,
-                    bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-        reassign_device(d, dom0, bus, devfn);
-    }
 }
 
 static void deallocate_next_page_table(void *table, unsigned long index,
@@ -618,13 +600,11 @@
 static void amd_iommu_domain_destroy(struct domain *d)
 {
     deallocate_iommu_page_tables(d);
-    release_domain_devices(d);
 }
 
 static int amd_iommu_return_device(
     struct domain *s, struct domain *t, u8 bus, u8 devfn)
 {
-    pdev_flr(bus, devfn);
     return reassign_device(s, t, bus, devfn);
 }
 
diff -r 7a0121d7add6 xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c     Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/drivers/passthrough/pci.c     Wed Jul 09 14:02:59 2008 +0100
@@ -17,9 +17,11 @@
 
 #include <xen/sched.h>
 #include <xen/pci.h>
+#include <xen/pci_regs.h>
 #include <xen/list.h>
 #include <xen/prefetch.h>
 #include <xen/iommu.h>
+#include <xen/delay.h>
 #include <xen/keyhandler.h>
 
 
@@ -145,6 +147,85 @@
     return ret;
 }
 
+void pci_release_devices(struct domain *d)
+{
+    struct pci_dev *pdev;
+    u8 bus, devfn;
+
+    while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) )
+    {
+        pci_cleanup_msi(pdev);
+        bus = pdev->bus; devfn = pdev->devfn;
+        spin_unlock(&pdev->lock);
+        deassign_device(d, bus, devfn);
+    }
+}
+
+#define PCI_D3hot              (3)
+#define PCI_CONFIG_DWORD_SIZE   (64)
+#define PCI_EXP_DEVCAP_FLR      (1 << 28)
+#define PCI_EXP_DEVCTL_FLR      (1 << 15)
+
+void pdev_flr(struct pci_dev *pdev)
+{
+    u8 pos;
+    u32 dev_cap, dev_status, pm_ctl;
+    int flr = 0;
+    u8 dev = PCI_SLOT(pdev->devfn);
+    u8 func = PCI_FUNC(pdev->devfn);
+
+    pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_EXP);
+    if ( pos != 0 )
+    {
+        dev_cap = pci_conf_read32(pdev->bus, dev, func, pos + PCI_EXP_DEVCAP);
+        if ( dev_cap & PCI_EXP_DEVCAP_FLR )
+        {
+            pci_conf_write32(pdev->bus, dev, func,
+                             pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR);
+            do {
+                dev_status = pci_conf_read32(pdev->bus, dev, func,
+                                             pos + PCI_EXP_DEVSTA);
+            } while ( dev_status & PCI_EXP_DEVSTA_TRPND );
+
+            flr = 1;
+        }
+    }
+
+    /* If this device doesn't support function level reset,
+     * program device from D0 t0 D3hot, and then return to D0
+     * to implement function level reset
+     */
+    if ( flr == 0 )
+    {
+        pos = pci_find_cap_offset(pdev->bus, dev, func, PCI_CAP_ID_PM);
+        if ( pos != 0 )
+        {
+            int i;
+            u32 config[PCI_CONFIG_DWORD_SIZE];
+            for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
+                config[i] = pci_conf_read32(pdev->bus, dev, func, i*4);
+
+            /* Enter D3hot without soft reset */
+            pm_ctl = pci_conf_read32(pdev->bus, dev, func, pos + PCI_PM_CTRL);
+            pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET;
+            pm_ctl &= ~PCI_PM_CTRL_STATE_MASK;
+            pm_ctl |= PCI_D3hot;
+            pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, pm_ctl);
+            mdelay(10);
+
+            /* From D3hot to D0 */
+            pci_conf_write32(pdev->bus, dev, func, pos + PCI_PM_CTRL, 0);
+            mdelay(10);
+
+            /* Write saved configurations to device */
+            for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
+                pci_conf_write32(pdev->bus, dev, func, i*4, config[i]);
+
+            flr = 1;
+        }
+    }
+}
+
 static void dump_pci_devices(unsigned char ch)
 {
     struct pci_dev *pdev;
@@ -174,3 +255,14 @@
     return 0;
 }
 __initcall(setup_dump_pcidevs);
+
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 7a0121d7add6 xen/drivers/passthrough/vtd/extern.h
--- a/xen/drivers/passthrough/vtd/extern.h      Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/drivers/passthrough/vtd/extern.h      Wed Jul 09 14:02:59 2008 +0100
@@ -28,7 +28,6 @@
 
 void print_iommu_regs(struct acpi_drhd_unit *drhd);
 void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn);
-void pdev_flr(u8 bus, u8 devfn);
 
 int qinval_setup(struct iommu *iommu);
 int intremap_setup(struct iommu *iommu);
diff -r 7a0121d7add6 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Wed Jul 09 14:02:59 2008 +0100
@@ -1366,7 +1366,7 @@
     if ( !(pdev = pci_lock_domain_pdev(source, bus, devfn)) )
         return -ENODEV;
 
-    pdev_flr(bus, devfn);
+    pdev_flr(pdev);
     drhd = acpi_find_matched_drhd_unit(bus, devfn);
     pdev_iommu = drhd->iommu;
     domain_context_unmap(bus, devfn);
@@ -1397,28 +1397,6 @@
     return ret;
 }
 
-void return_devices_to_dom0(struct domain *d)
-{
-    struct pci_dev *pdev;
-
-    while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) )
-    {
-        pci_cleanup_msi(pdev);
-        spin_unlock(&pdev->lock);
-        reassign_device_ownership(d, dom0, pdev->bus, pdev->devfn);
-    }
-
-#ifdef VTD_DEBUG
-    read_lock(&pcidevs_lock);
-    for_each_pdev ( dom0, pdev )
-        dprintk(XENLOG_INFO VTDPREFIX,
-                "return_devices_to_dom0:%x: bdf = %x:%x:%x\n",
-                dom0->domain_id, pdev->bus,
-                PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-    read_unlock(&pcidevs_lock);
-#endif
-}
-
 void iommu_domain_teardown(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -1426,7 +1404,6 @@
     if ( list_empty(&acpi_drhd_units) )
         return;
 
-    return_devices_to_dom0(d);
     iommu_free_pagetable(hd->pgd_maddr, agaw_to_level(hd->agaw));
     hd->pgd_maddr = 0;
     iommu_domid_release(d);
diff -r 7a0121d7add6 xen/drivers/passthrough/vtd/utils.c
--- a/xen/drivers/passthrough/vtd/utils.c       Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/drivers/passthrough/vtd/utils.c       Wed Jul 09 14:02:59 2008 +0100
@@ -93,71 +93,6 @@
 
     dprintk(XENLOG_INFO VTDPREFIX,
             "Disabled protected memory registers\n");
-}
-
-#define PCI_D3hot   (3)
-#define PCI_CONFIG_DWORD_SIZE   (64)
-#define PCI_EXP_DEVCAP_FLR      (1 << 28)
-#define PCI_EXP_DEVCTL_FLR      (1 << 15)
-
-void pdev_flr(u8 bus, u8 devfn)
-{
-    u8 pos;
-    u32 dev_cap, dev_status, pm_ctl;
-    int flr = 0;
-    u8 dev = PCI_SLOT(devfn);
-    u8 func = PCI_FUNC(devfn);
-
-    pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_EXP);
-    if ( pos != 0 )
-    {
-        dev_cap = pci_conf_read32(bus, dev, func, pos + PCI_EXP_DEVCAP);
-        if ( dev_cap & PCI_EXP_DEVCAP_FLR )
-        {
-            pci_conf_write32(bus, dev, func,
-                             pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR);
-            do {
-                dev_status = pci_conf_read32(bus, dev, func,
-                                             pos + PCI_EXP_DEVSTA);
-            } while ( dev_status & PCI_EXP_DEVSTA_TRPND );
-
-            flr = 1;
-        }
-    }
-
-    /* If this device doesn't support function level reset,
-     * program device from D0 t0 D3hot, and then return to D0
-     * to implement function level reset
-     */
-    if ( flr == 0 )
-    {
-        pos = pci_find_cap_offset(bus, dev, func, PCI_CAP_ID_PM);
-        if ( pos != 0 )
-        {
-            int i;
-            u32 config[PCI_CONFIG_DWORD_SIZE];
-            for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
-                config[i] = pci_conf_read32(bus, dev, func, i*4);
-
-            /* Enter D3hot without soft reset */
-            pm_ctl = pci_conf_read32(bus, dev, func, pos + PCI_PM_CTRL);
-            pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET;
-            pm_ctl &= ~PCI_PM_CTRL_STATE_MASK;
-            pm_ctl |= PCI_D3hot;
-            pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl);
-            mdelay(10);
-
-            /* From D3hot to D0 */
-            pci_conf_write32(bus, dev, func, pos + PCI_PM_CTRL, 0);
-            mdelay(10);
-
-            /* Write saved configurations to device */
-            for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
-                pci_conf_write32(bus, dev, func, i*4, config[i]);
-
-            flr = 1;
-        }
-    }
 }
 
 void print_iommu_regs(struct acpi_drhd_unit *drhd)
diff -r 7a0121d7add6 xen/include/xen/pci.h
--- a/xen/include/xen/pci.h     Wed Jul 09 13:12:21 2008 +0100
+++ b/xen/include/xen/pci.h     Wed Jul 09 14:02:59 2008 +0100
@@ -56,6 +56,8 @@
 struct pci_dev *pci_lock_pdev(int bus, int devfn);
 struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn);
 
+void pdev_flr(struct pci_dev *pdev);
+void pci_release_devices(struct domain *d);
 int pci_add_device(u8 bus, u8 devfn);
 int pci_remove_device(u8 bus, u8 devfn);
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] Make PCI device release function generic, Espen Skoglund <=