# 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
|