aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/bus.c46
-rw-r--r--drivers/pci/probe.c17
2 files changed, 59 insertions, 4 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index e75d219fd107..712250f5874a 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -17,6 +17,52 @@
17 17
18#include "pci.h" 18#include "pci.h"
19 19
20void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
21 unsigned int flags)
22{
23 struct pci_bus_resource *bus_res;
24
25 bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
26 if (!bus_res) {
27 dev_err(&bus->dev, "can't add %pR resource\n", res);
28 return;
29 }
30
31 bus_res->res = res;
32 bus_res->flags = flags;
33 list_add_tail(&bus_res->list, &bus->resources);
34}
35
36struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
37{
38 struct pci_bus_resource *bus_res;
39
40 if (n < PCI_BRIDGE_RESOURCE_NUM)
41 return bus->resource[n];
42
43 n -= PCI_BRIDGE_RESOURCE_NUM;
44 list_for_each_entry(bus_res, &bus->resources, list) {
45 if (n-- == 0)
46 return bus_res->res;
47 }
48 return NULL;
49}
50EXPORT_SYMBOL_GPL(pci_bus_resource_n);
51
52void pci_bus_remove_resources(struct pci_bus *bus)
53{
54 struct pci_bus_resource *bus_res, *tmp;
55 int i;
56
57 for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
58 bus->resource[i] = 0;
59
60 list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
61 list_del(&bus_res->list);
62 kfree(bus_res);
63 }
64}
65
20/** 66/**
21 * pci_bus_alloc_resource - allocate a resource from a parent bus 67 * pci_bus_alloc_resource - allocate a resource from a parent bus
22 * @bus: PCI bus 68 * @bus: PCI bus
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 70c4ed2e67cc..270d069819f7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -89,6 +89,7 @@ static void release_pcibus_dev(struct device *dev)
89 89
90 if (pci_bus->bridge) 90 if (pci_bus->bridge)
91 put_device(pci_bus->bridge); 91 put_device(pci_bus->bridge);
92 pci_bus_remove_resources(pci_bus);
92 kfree(pci_bus); 93 kfree(pci_bus);
93} 94}
94 95
@@ -394,6 +395,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
394void __devinit pci_read_bridge_bases(struct pci_bus *child) 395void __devinit pci_read_bridge_bases(struct pci_bus *child)
395{ 396{
396 struct pci_dev *dev = child->self; 397 struct pci_dev *dev = child->self;
398 struct resource *res;
397 int i; 399 int i;
398 400
399 if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ 401 if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
@@ -403,17 +405,23 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
403 child->secondary, child->subordinate, 405 child->secondary, child->subordinate,
404 dev->transparent ? " (subtractive decode)" : ""); 406 dev->transparent ? " (subtractive decode)" : "");
405 407
408 pci_bus_remove_resources(child);
409 for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
410 child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
411
406 pci_read_bridge_io(child); 412 pci_read_bridge_io(child);
407 pci_read_bridge_mmio(child); 413 pci_read_bridge_mmio(child);
408 pci_read_bridge_mmio_pref(child); 414 pci_read_bridge_mmio_pref(child);
409 415
410 if (dev->transparent) { 416 if (dev->transparent) {
411 for (i = 3; i < PCI_BUS_NUM_RESOURCES; i++) { 417 pci_bus_for_each_resource(child->parent, res, i) {
412 child->resource[i] = child->parent->resource[i - 3]; 418 if (res) {
413 if (child->resource[i]) 419 pci_bus_add_resource(child, res,
420 PCI_SUBTRACTIVE_DECODE);
414 dev_printk(KERN_DEBUG, &dev->dev, 421 dev_printk(KERN_DEBUG, &dev->dev,
415 " bridge window %pR (subtractive decode)\n", 422 " bridge window %pR (subtractive decode)\n",
416 child->resource[i]); 423 res);
424 }
417 } 425 }
418 } 426 }
419} 427}
@@ -428,6 +436,7 @@ static struct pci_bus * pci_alloc_bus(void)
428 INIT_LIST_HEAD(&b->children); 436 INIT_LIST_HEAD(&b->children);
429 INIT_LIST_HEAD(&b->devices); 437 INIT_LIST_HEAD(&b->devices);
430 INIT_LIST_HEAD(&b->slots); 438 INIT_LIST_HEAD(&b->slots);
439 INIT_LIST_HEAD(&b->resources);
431 b->max_bus_speed = PCI_SPEED_UNKNOWN; 440 b->max_bus_speed = PCI_SPEED_UNKNOWN;
432 b->cur_bus_speed = PCI_SPEED_UNKNOWN; 441 b->cur_bus_speed = PCI_SPEED_UNKNOWN;
433 } 442 }