ia64/xen-unstable

changeset 9417:799957f5092c

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@epoch.ncsc.mil>
author kaf24@firebug.cl.cam.ac.uk
date Thu Mar 23 10:53:55 2006 +0100 (2006-03-23)
parents b7facd6aa72e
children 05daa762a8e2
files linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c	Thu Mar 23 10:50:34 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c	Thu Mar 23 10:53:55 2006 +0100
     1.3 @@ -56,19 +56,19 @@ static int do_pci_op(struct pcifront_dev
     1.4  	notify_remote_via_evtchn(port);
     1.5  
     1.6  	/*
     1.7 -	 * We set a poll timeout of 5 seconds but give up on return after
     1.8 -	 * 4 seconds. It is better to time out too late rather than too early
     1.9 +	 * We set a poll timeout of 3 seconds but give up on return after
    1.10 +	 * 2 seconds. It is better to time out too late rather than too early
    1.11  	 * (in the latter case we end up continually re-executing poll() with a
    1.12  	 * timeout in the past). 1s difference gives plenty of slack for error.
    1.13  	 */
    1.14  	do_gettimeofday(&tv);
    1.15 -	ns_timeout = timeval_to_ns(&tv) + 4 * (nsec_t)NSEC_PER_SEC;
    1.16 +	ns_timeout = timeval_to_ns(&tv) + 2 * (nsec_t)NSEC_PER_SEC;
    1.17  
    1.18  	clear_evtchn(port);
    1.19  
    1.20  	while (test_bit(_XEN_PCIF_active,
    1.21  			(unsigned long *)&pdev->sh_info->flags)) {
    1.22 -		if (HYPERVISOR_poll(&port, 1, jiffies + 5*HZ))
    1.23 +		if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
    1.24  			BUG();
    1.25  		clear_evtchn(port);
    1.26  		do_gettimeofday(&tv);
    1.27 @@ -173,7 +173,7 @@ static void pcifront_claim_resource(stru
    1.28  
    1.29  		if (!r->parent && r->start && r->flags) {
    1.30  			dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
    1.31 -					pci_name(dev), i);
    1.32 +				pci_name(dev), i);
    1.33  			pci_claim_resource(dev, i);
    1.34  		}
    1.35  	}
    1.36 @@ -234,25 +234,38 @@ int pcifront_scan_root(struct pcifront_d
    1.37  	return err;
    1.38  }
    1.39  
    1.40 +static void free_root_bus_devs(struct pci_bus *bus)
    1.41 +{
    1.42 +	struct pci_dev *dev;
    1.43 +
    1.44 +	spin_lock(&pci_bus_lock);
    1.45 +	while (!list_empty(&bus->devices)) {
    1.46 +		dev = container_of(bus->devices.next, struct pci_dev, bus_list);
    1.47 +		spin_unlock(&pci_bus_lock);
    1.48 +
    1.49 +		dev_dbg(&dev->dev, "removing device\n");
    1.50 +		pci_remove_bus_device(dev);
    1.51 +
    1.52 +		spin_lock(&pci_bus_lock);
    1.53 +	}
    1.54 +	spin_unlock(&pci_bus_lock);
    1.55 +}
    1.56 +
    1.57  void pcifront_free_roots(struct pcifront_device *pdev)
    1.58  {
    1.59  	struct pci_bus_entry *bus_entry, *t;
    1.60  
    1.61 +	dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
    1.62 +
    1.63  	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
    1.64 -		/* TODO: Removing a PCI Bus is untested (as it normally
    1.65 -		 * just goes away on domain shutdown)
    1.66 -		 */
    1.67  		list_del(&bus_entry->list);
    1.68  
    1.69 -		spin_lock(&pci_bus_lock);
    1.70 -		list_del(&bus_entry->bus->node);
    1.71 -		spin_unlock(&pci_bus_lock);
    1.72 +		free_root_bus_devs(bus_entry->bus);
    1.73  
    1.74  		kfree(bus_entry->bus->sysdata);
    1.75  
    1.76  		device_unregister(bus_entry->bus->bridge);
    1.77 -
    1.78 -		/* Do we need to free() the bus itself? */
    1.79 +		pci_remove_bus(bus_entry->bus);
    1.80  
    1.81  		kfree(bus_entry);
    1.82  	}
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c	Thu Mar 23 10:50:34 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c	Thu Mar 23 10:53:55 2006 +0100
     2.3 @@ -50,6 +50,8 @@ static void free_pdev(struct pcifront_de
     2.4  {
     2.5  	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
     2.6  
     2.7 +	pcifront_free_roots(pdev);
     2.8 +
     2.9  	if (pdev->evtchn != INVALID_EVTCHN)
    2.10  		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
    2.11