aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:18:59 -0500
committerBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:18:59 -0500
commit5a21d70dbd33d20713fb735ad9381711b0ae2c9b (patch)
treef3c6c65295f1356f62389fafad777d7be047aca5
parenta5390aa6dc3646b08bed421944cef0daf78ab994 (diff)
PCI: add struct pci_host_bridge and a list of all bridges found
This adds a list of all PCI host bridges we find and a way to look up the host bridge from a pci_dev. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/probe.c39
-rw-r--r--include/linux/pci.h5
2 files changed, 39 insertions, 5 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e4c0d1c6324d..3a30023a123c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,6 +15,8 @@
15#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ 15#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
16#define CARDBUS_RESERVE_BUSNR 3 16#define CARDBUS_RESERVE_BUSNR 3
17 17
18static LIST_HEAD(pci_host_bridges);
19
18/* Ugh. Need to stop exporting this to modules. */ 20/* Ugh. Need to stop exporting this to modules. */
19LIST_HEAD(pci_root_buses); 21LIST_HEAD(pci_root_buses);
20EXPORT_SYMBOL(pci_root_buses); 22EXPORT_SYMBOL(pci_root_buses);
@@ -42,6 +44,23 @@ int no_pci_devices(void)
42} 44}
43EXPORT_SYMBOL(no_pci_devices); 45EXPORT_SYMBOL(no_pci_devices);
44 46
47static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
48{
49 struct pci_bus *bus;
50 struct pci_host_bridge *bridge;
51
52 bus = dev->bus;
53 while (bus->parent)
54 bus = bus->parent;
55
56 list_for_each_entry(bridge, &pci_host_bridges, list) {
57 if (bridge->bus == bus)
58 return bridge;
59 }
60
61 return NULL;
62}
63
45/* 64/*
46 * PCI Bus Class 65 * PCI Bus Class
47 */ 66 */
@@ -1544,20 +1563,23 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1544 struct pci_ops *ops, void *sysdata, struct list_head *resources) 1563 struct pci_ops *ops, void *sysdata, struct list_head *resources)
1545{ 1564{
1546 int error, i; 1565 int error, i;
1566 struct pci_host_bridge *bridge;
1547 struct pci_bus *b, *b2; 1567 struct pci_bus *b, *b2;
1548 struct device *dev; 1568 struct device *dev;
1549 struct pci_bus_resource *bus_res, *n; 1569 struct pci_bus_resource *bus_res, *n;
1550 struct resource *res; 1570 struct resource *res;
1551 1571
1572 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
1573 if (!bridge)
1574 return NULL;
1575
1552 b = pci_alloc_bus(); 1576 b = pci_alloc_bus();
1553 if (!b) 1577 if (!b)
1554 return NULL; 1578 goto err_bus;
1555 1579
1556 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1580 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1557 if (!dev) { 1581 if (!dev)
1558 kfree(b); 1582 goto err_dev;
1559 return NULL;
1560 }
1561 1583
1562 b->sysdata = sysdata; 1584 b->sysdata = sysdata;
1563 b->ops = ops; 1585 b->ops = ops;
@@ -1594,6 +1616,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1594 1616
1595 b->number = b->secondary = bus; 1617 b->number = b->secondary = bus;
1596 1618
1619 bridge->bus = b;
1620
1597 /* Add initial resources to the bus */ 1621 /* Add initial resources to the bus */
1598 list_for_each_entry_safe(bus_res, n, resources, list) 1622 list_for_each_entry_safe(bus_res, n, resources, list)
1599 list_move_tail(&bus_res->list, &b->resources); 1623 list_move_tail(&bus_res->list, &b->resources);
@@ -1609,6 +1633,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1609 } 1633 }
1610 1634
1611 down_write(&pci_bus_sem); 1635 down_write(&pci_bus_sem);
1636 list_add_tail(&bridge->list, &pci_host_bridges);
1612 list_add_tail(&b->node, &pci_root_buses); 1637 list_add_tail(&b->node, &pci_root_buses);
1613 up_write(&pci_bus_sem); 1638 up_write(&pci_bus_sem);
1614 1639
@@ -1618,11 +1643,15 @@ class_dev_reg_err:
1618 device_unregister(dev); 1643 device_unregister(dev);
1619dev_reg_err: 1644dev_reg_err:
1620 down_write(&pci_bus_sem); 1645 down_write(&pci_bus_sem);
1646 list_del(&bridge->list);
1621 list_del(&b->node); 1647 list_del(&b->node);
1622 up_write(&pci_bus_sem); 1648 up_write(&pci_bus_sem);
1623err_out: 1649err_out:
1624 kfree(dev); 1650 kfree(dev);
1651err_dev:
1625 kfree(b); 1652 kfree(b);
1653err_bus:
1654 kfree(bridge);
1626 return NULL; 1655 return NULL;
1627} 1656}
1628 1657
diff --git a/include/linux/pci.h b/include/linux/pci.h
index bcaa51ca7858..2c946b3bbf77 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -368,6 +368,11 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
368 return (pdev->error_state != pci_channel_io_normal); 368 return (pdev->error_state != pci_channel_io_normal);
369} 369}
370 370
371struct pci_host_bridge {
372 struct list_head list;
373 struct pci_bus *bus; /* root bus */
374};
375
371/* 376/*
372 * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond 377 * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
373 * to P2P or CardBus bridge windows) go in a table. Additional ones (for 378 * to P2P or CardBus bridge windows) go in a table. Additional ones (for