aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r--drivers/pci/bus.c61
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
21void 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
37struct 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}
51EXPORT_SYMBOL_GPL(pci_bus_resource_n);
52
53void 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
36pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, 83pci_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 }