On Mon, Jan 30, 2012 at 12:52 PM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote: > On Mon, Jan 30, 2012 at 8:57 AM, Bjorn Helgaas <bhelgaas@xxxxxxxxxx> wrote: >> This adds a list of all PCI host bridges we find and a way to look up >> the host bridge from a pci_dev. >> --- >> drivers/pci/probe.c | 39 ++++++++++++++++++++++++++++++++++----- >> include/linux/pci.h | 5 +++++ >> 2 files changed, 39 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c >> index da0d655..2ffe8a3 100644 >> --- a/drivers/pci/probe.c >> +++ b/drivers/pci/probe.c >> @@ -15,6 +15,8 @@ >> #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ >> #define CARDBUS_RESERVE_BUSNR 3 >> >> +static LIST_HEAD(pci_host_bridges); >> + >> /* Ugh. Need to stop exporting this to modules. */ >> LIST_HEAD(pci_root_buses); >> EXPORT_SYMBOL(pci_root_buses); >> @@ -42,6 +44,23 @@ int no_pci_devices(void) >> } >> 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 >> */ >> @@ -1526,20 +1545,23 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, >> struct pci_ops *ops, void *sysdata, struct list_head *resources) >> { >> int error, i; >> + struct pci_host_bridge *bridge; >> struct pci_bus *b, *b2; >> struct device *dev; >> struct pci_bus_resource *bus_res, *n; >> struct resource *res; >> >> + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); >> + if (!bridge) >> + return NULL; >> + >> b = pci_alloc_bus(); >> if (!b) >> - return NULL; >> + goto err_bus; >> >> dev = kzalloc(sizeof(*dev), GFP_KERNEL); >> - if (!dev) { >> - kfree(b); >> - return NULL; >> - } >> + if (!dev) >> + goto err_dev; >> >> b->sysdata = sysdata; >> b->ops = ops; >> @@ -1576,6 +1598,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, >> >> b->number = b->secondary = bus; >> >> + bridge->bus = b; >> + >> /* Add initial resources to the bus */ >> list_for_each_entry_safe(bus_res, n, resources, list) >> list_move_tail(&bus_res->list, &b->resources); >> @@ -1591,6 +1615,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, >> } >> >> down_write(&pci_bus_sem); >> + list_add_tail(&bridge->list, &pci_host_bridges); >> list_add_tail(&b->node, &pci_root_buses); >> up_write(&pci_bus_sem); > > we already have list for root_bus. So there will be two lists. Yeah, I'm not sure we need both either. If we do end up adding a struct pci_host_bridge, then I think it makes sense to keep a list of *those* (and possibly remove the root_bus list), since that's a slightly higher-level abstraction than root_bus is. > wonder if we can overload bus->self point to struct host_bridge. pci_bus->self points to a struct pci_dev. A host bridge is not a pci_dev. I don't think it's a good idea to simply reuse "self" to point to something of a different type, but maybe you have something different in mind. > or just do not add host_bridge , and instead only add another field > like struct list_head windows in pci_sysdata? The pci_sysdata I see is an x86-specific thing, so I don't see how that would help. Bjorn -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html