diff options
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r-- | drivers/pci/bus.c | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index cef28a79103f..628ea20a8841 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -14,9 +14,56 @@ | |||
14 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
15 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | ||
17 | 18 | ||
18 | #include "pci.h" | 19 | #include "pci.h" |
19 | 20 | ||
21 | void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, | ||
22 | unsigned int flags) | ||
23 | { | ||
24 | struct pci_bus_resource *bus_res; | ||
25 | |||
26 | bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); | ||
27 | if (!bus_res) { | ||
28 | dev_err(&bus->dev, "can't add %pR resource\n", res); | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | bus_res->res = res; | ||
33 | bus_res->flags = flags; | ||
34 | list_add_tail(&bus_res->list, &bus->resources); | ||
35 | } | ||
36 | |||
37 | struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) | ||
38 | { | ||
39 | struct pci_bus_resource *bus_res; | ||
40 | |||
41 | if (n < PCI_BRIDGE_RESOURCE_NUM) | ||
42 | return bus->resource[n]; | ||
43 | |||
44 | n -= PCI_BRIDGE_RESOURCE_NUM; | ||
45 | list_for_each_entry(bus_res, &bus->resources, list) { | ||
46 | if (n-- == 0) | ||
47 | return bus_res->res; | ||
48 | } | ||
49 | return NULL; | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(pci_bus_resource_n); | ||
52 | |||
53 | void pci_bus_remove_resources(struct pci_bus *bus) | ||
54 | { | ||
55 | struct pci_bus_resource *bus_res, *tmp; | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | ||
59 | bus->resource[i] = 0; | ||
60 | |||
61 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { | ||
62 | list_del(&bus_res->list); | ||
63 | kfree(bus_res); | ||
64 | } | ||
65 | } | ||
66 | |||
20 | /** | 67 | /** |
21 | * pci_bus_alloc_resource - allocate a resource from a parent bus | 68 | * pci_bus_alloc_resource - allocate a resource from a parent bus |
22 | * @bus: PCI bus | 69 | * @bus: PCI bus |
@@ -36,11 +83,14 @@ int | |||
36 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | 83 | pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, |
37 | resource_size_t size, resource_size_t align, | 84 | resource_size_t size, resource_size_t align, |
38 | resource_size_t min, unsigned int type_mask, | 85 | resource_size_t min, unsigned int type_mask, |
39 | void (*alignf)(void *, struct resource *, resource_size_t, | 86 | resource_size_t (*alignf)(void *, |
40 | resource_size_t), | 87 | const struct resource *, |
88 | resource_size_t, | ||
89 | resource_size_t), | ||
41 | void *alignf_data) | 90 | void *alignf_data) |
42 | { | 91 | { |
43 | int i, ret = -ENOMEM; | 92 | int i, ret = -ENOMEM; |
93 | struct resource *r; | ||
44 | resource_size_t max = -1; | 94 | resource_size_t max = -1; |
45 | 95 | ||
46 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; | 96 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; |
@@ -49,8 +99,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
49 | if (!(res->flags & IORESOURCE_MEM_64)) | 99 | if (!(res->flags & IORESOURCE_MEM_64)) |
50 | max = PCIBIOS_MAX_MEM_32; | 100 | max = PCIBIOS_MAX_MEM_32; |
51 | 101 | ||
52 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 102 | pci_bus_for_each_resource(bus, r, i) { |
53 | struct resource *r = bus->resource[i]; | ||
54 | if (!r) | 103 | if (!r) |
55 | continue; | 104 | continue; |
56 | 105 | ||
@@ -240,9 +289,9 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |||
240 | next = dev->bus_list.next; | 289 | next = dev->bus_list.next; |
241 | 290 | ||
242 | /* Run device routines with the device locked */ | 291 | /* Run device routines with the device locked */ |
243 | down(&dev->dev.sem); | 292 | device_lock(&dev->dev); |
244 | retval = cb(dev, userdata); | 293 | retval = cb(dev, userdata); |
245 | up(&dev->dev.sem); | 294 | device_unlock(&dev->dev); |
246 | if (retval) | 295 | if (retval) |
247 | break; | 296 | break; |
248 | } | 297 | } |