Subversion Repositories shark

Rev

Rev 430 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
428 giacomo 1
#include <linux/pci.h>
2
#include <linux/module.h>
3
#include "pci.h"
4
 
5
#undef DEBUG
6
 
7
#ifdef DEBUG
8
#define DBG(x...) printk(x)
9
#else
10
#define DBG(x...)
11
#endif
12
 
13
static void pci_free_resources(struct pci_dev *dev)
14
{
15
        int i;
16
 
17
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
18
                struct resource *res = dev->resource + i;
19
                if (res->parent)
20
                        release_resource(res);
21
        }
22
}
23
 
24
static void pci_destroy_dev(struct pci_dev *dev)
25
{
26
        pci_proc_detach_device(dev);
27
        device_unregister(&dev->dev);
28
 
29
        /* Remove the device from the device lists, and prevent any further
30
         * list accesses from this device */
31
        spin_lock(&pci_bus_lock);
32
        list_del(&dev->bus_list);
33
        list_del(&dev->global_list);
34
        dev->bus_list.next = dev->bus_list.prev = NULL;
35
        dev->global_list.next = dev->global_list.prev = NULL;
36
        spin_unlock(&pci_bus_lock);
37
 
38
        pci_free_resources(dev);
39
        pci_dev_put(dev);
40
}
41
 
42
/**
43
 * pci_remove_device_safe - remove an unused hotplug device
44
 * @dev: the device to remove
45
 *
46
 * Delete the device structure from the device lists and
47
 * notify userspace (/sbin/hotplug), but only if the device
48
 * in question is not being used by a driver.
49
 * Returns 0 on success.
50
 */
51
int pci_remove_device_safe(struct pci_dev *dev)
52
{
53
        if (pci_dev_driver(dev))
54
                return -EBUSY;
55
        pci_destroy_dev(dev);
56
        return 0;
57
}
58
EXPORT_SYMBOL(pci_remove_device_safe);
59
 
60
/**
61
 * pci_remove_bus_device - remove a PCI device and any children
62
 * @dev: the device to remove
63
 *
64
 * Remove a PCI device from the device lists, informing the drivers
65
 * that the device has been removed.  We also remove any subordinate
66
 * buses and children in a depth-first manner.
67
 *
68
 * For each device we remove, delete the device structure from the
69
 * device lists, remove the /proc entry, and notify userspace
70
 * (/sbin/hotplug).
71
 */
72
void pci_remove_bus_device(struct pci_dev *dev)
73
{
74
        if (dev->subordinate) {
75
                struct pci_bus *b = dev->subordinate;
76
 
77
                pci_remove_behind_bridge(dev);
78
                pci_proc_detach_bus(b);
79
 
80
                spin_lock(&pci_bus_lock);
81
                list_del(&b->node);
82
                spin_unlock(&pci_bus_lock);
83
 
84
                kfree(b);
85
                dev->subordinate = NULL;
86
        }
87
 
88
        pci_destroy_dev(dev);
89
}
90
 
91
/**
92
 * pci_remove_behind_bridge - remove all devices behind a PCI bridge
93
 * @dev: PCI bridge device
94
 *
95
 * Remove all devices on the bus, except for the parent bridge.
96
 * This also removes any child buses, and any devices they may
97
 * contain in a depth-first manner.
98
 */
99
void pci_remove_behind_bridge(struct pci_dev *dev)
100
{
101
        struct list_head *l, *n;
102
 
103
        if (dev->subordinate) {
104
                list_for_each_safe(l, n, &dev->subordinate->devices) {
105
                        struct pci_dev *dev = pci_dev_b(l);
106
 
107
                        pci_remove_bus_device(dev);
108
                }
109
        }
110
}
111
 
112
EXPORT_SYMBOL(pci_remove_bus_device);
113
EXPORT_SYMBOL(pci_remove_behind_bridge);