Commit 5a21d70d authored by Bjorn Helgaas's avatar Bjorn Helgaas

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: default avatarBjorn Helgaas <bhelgaas@google.com>
parent a5390aa6
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3 #define CARDBUS_RESERVE_BUSNR 3
static LIST_HEAD(pci_host_bridges);
/* Ugh. Need to stop exporting this to modules. */ /* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses); LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses); EXPORT_SYMBOL(pci_root_buses);
...@@ -42,6 +44,23 @@ int no_pci_devices(void) ...@@ -42,6 +44,23 @@ int no_pci_devices(void)
} }
EXPORT_SYMBOL(no_pci_devices); EXPORT_SYMBOL(no_pci_devices);
static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
{
struct pci_bus *bus;
struct pci_host_bridge *bridge;
bus = dev->bus;
while (bus->parent)
bus = bus->parent;
list_for_each_entry(bridge, &pci_host_bridges, list) {
if (bridge->bus == bus)
return bridge;
}
return NULL;
}
/* /*
* PCI Bus Class * PCI Bus Class
*/ */
...@@ -1544,20 +1563,23 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1544,20 +1563,23 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources) struct pci_ops *ops, void *sysdata, struct list_head *resources)
{ {
int error, i; int error, i;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2; struct pci_bus *b, *b2;
struct device *dev; struct device *dev;
struct pci_bus_resource *bus_res, *n; struct pci_bus_resource *bus_res, *n;
struct resource *res; struct resource *res;
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return NULL;
b = pci_alloc_bus(); b = pci_alloc_bus();
if (!b) if (!b)
return NULL; goto err_bus;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) { if (!dev)
kfree(b); goto err_dev;
return NULL;
}
b->sysdata = sysdata; b->sysdata = sysdata;
b->ops = ops; b->ops = ops;
...@@ -1594,6 +1616,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1594,6 +1616,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->number = b->secondary = bus; b->number = b->secondary = bus;
bridge->bus = b;
/* Add initial resources to the bus */ /* Add initial resources to the bus */
list_for_each_entry_safe(bus_res, n, resources, list) list_for_each_entry_safe(bus_res, n, resources, list)
list_move_tail(&bus_res->list, &b->resources); 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,6 +1633,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
} }
down_write(&pci_bus_sem); down_write(&pci_bus_sem);
list_add_tail(&bridge->list, &pci_host_bridges);
list_add_tail(&b->node, &pci_root_buses); list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem); up_write(&pci_bus_sem);
...@@ -1618,11 +1643,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1618,11 +1643,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
device_unregister(dev); device_unregister(dev);
dev_reg_err: dev_reg_err:
down_write(&pci_bus_sem); down_write(&pci_bus_sem);
list_del(&bridge->list);
list_del(&b->node); list_del(&b->node);
up_write(&pci_bus_sem); up_write(&pci_bus_sem);
err_out: err_out:
kfree(dev); kfree(dev);
err_dev:
kfree(b); kfree(b);
err_bus:
kfree(bridge);
return NULL; return NULL;
} }
......
...@@ -368,6 +368,11 @@ static inline int pci_channel_offline(struct pci_dev *pdev) ...@@ -368,6 +368,11 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
return (pdev->error_state != pci_channel_io_normal); return (pdev->error_state != pci_channel_io_normal);
} }
struct pci_host_bridge {
struct list_head list;
struct pci_bus *bus; /* root bus */
};
/* /*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
* to P2P or CardBus bridge windows) go in a table. Additional ones (for * to P2P or CardBus bridge windows) go in a table. Additional ones (for
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment