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

[Xen-changelog] The PCI Frontend doesn't properly clean-up PCI buses and their devices



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 799957f5092c6b745cfc7df89ec7a27ca2eae610
# Parent  b7facd6aa72efa087db768af65fc2dca371a8eb4
The PCI Frontend doesn't properly clean-up PCI buses and their devices
that are in-use if the PCI Backend goes away. This patch corrects that.

This patch also shortens the timeout in drivers/xen/pcifront/pci_op.c
(in an attempt to minimize the amount of time spent waiting with
interrupts disabled).

Signed-off-by: Ryan Wilson <hap9@xxxxxxxxxxxxxx>

diff -r b7facd6aa72e -r 799957f5092c 
linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c
--- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c        Thu Mar 23 
09:50:34 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c        Thu Mar 23 
09:53:55 2006
@@ -56,19 +56,19 @@
        notify_remote_via_evtchn(port);
 
        /*
-        * We set a poll timeout of 5 seconds but give up on return after
-        * 4 seconds. It is better to time out too late rather than too early
+        * We set a poll timeout of 3 seconds but give up on return after
+        * 2 seconds. It is better to time out too late rather than too early
         * (in the latter case we end up continually re-executing poll() with a
         * timeout in the past). 1s difference gives plenty of slack for error.
         */
        do_gettimeofday(&tv);
-       ns_timeout = timeval_to_ns(&tv) + 4 * (nsec_t)NSEC_PER_SEC;
+       ns_timeout = timeval_to_ns(&tv) + 2 * (nsec_t)NSEC_PER_SEC;
 
        clear_evtchn(port);
 
        while (test_bit(_XEN_PCIF_active,
                        (unsigned long *)&pdev->sh_info->flags)) {
-               if (HYPERVISOR_poll(&port, 1, jiffies + 5*HZ))
+               if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
                        BUG();
                clear_evtchn(port);
                do_gettimeofday(&tv);
@@ -173,7 +173,7 @@
 
                if (!r->parent && r->start && r->flags) {
                        dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
-                                       pci_name(dev), i);
+                               pci_name(dev), i);
                        pci_claim_resource(dev, i);
                }
        }
@@ -234,25 +234,38 @@
        return err;
 }
 
+static void free_root_bus_devs(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       spin_lock(&pci_bus_lock);
+       while (!list_empty(&bus->devices)) {
+               dev = container_of(bus->devices.next, struct pci_dev, bus_list);
+               spin_unlock(&pci_bus_lock);
+
+               dev_dbg(&dev->dev, "removing device\n");
+               pci_remove_bus_device(dev);
+
+               spin_lock(&pci_bus_lock);
+       }
+       spin_unlock(&pci_bus_lock);
+}
+
 void pcifront_free_roots(struct pcifront_device *pdev)
 {
        struct pci_bus_entry *bus_entry, *t;
 
+       dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
+
        list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
-               /* TODO: Removing a PCI Bus is untested (as it normally
-                * just goes away on domain shutdown)
-                */
                list_del(&bus_entry->list);
 
-               spin_lock(&pci_bus_lock);
-               list_del(&bus_entry->bus->node);
-               spin_unlock(&pci_bus_lock);
+               free_root_bus_devs(bus_entry->bus);
 
                kfree(bus_entry->bus->sysdata);
 
                device_unregister(bus_entry->bus->bridge);
-
-               /* Do we need to free() the bus itself? */
+               pci_remove_bus(bus_entry->bus);
 
                kfree(bus_entry);
        }
diff -r b7facd6aa72e -r 799957f5092c 
linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c        Thu Mar 23 
09:50:34 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c        Thu Mar 23 
09:53:55 2006
@@ -49,6 +49,8 @@
 static void free_pdev(struct pcifront_device *pdev)
 {
        dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
+
+       pcifront_free_roots(pdev);
 
        if (pdev->evtchn != INVALID_EVTCHN)
                xenbus_free_evtchn(pdev->xdev, pdev->evtchn);

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


 


Rackspace

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