summaryrefslogtreecommitdiffstats
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-04-03 03:31:53 +0200
committerBjorn Helgaas <bhelgaas@google.com>2012-04-30 21:53:42 +0200
commit7b54366358008241f88228f02cc80ab352265eac (patch)
tree4de6ae8ce83afabf1b4405cba6895b09d1bc790d /drivers/pci/probe.c
parentPCI: rename pci_host_bridge() to find_pci_root_bridge() (diff)
downloadlinux-7b54366358008241f88228f02cc80ab352265eac.tar.xz
linux-7b54366358008241f88228f02cc80ab352265eac.zip
PCI: add generic device into pci_host_bridge struct
Use that device for pci_root_bus bridge pointer. Use pci_release_bus_bridge_dev() to release allocated pci_host_bridge in remove path. Use root bus bridge pointer to get host bridge pointer instead of searching host bridge list. That leaves the host bridge list unused, so remove it. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c66
1 files changed, 35 insertions, 31 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bcea52b90e0d..8d291ee15257 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -422,6 +422,19 @@ static struct pci_bus * pci_alloc_bus(void)
return b;
}
+static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+{
+ struct pci_host_bridge *bridge;
+
+ bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+ if (bridge) {
+ INIT_LIST_HEAD(&bridge->windows);
+ bridge->bus = b;
+ }
+
+ return bridge;
+}
+
static unsigned char pcix_bus_speed[] = {
PCI_SPEED_UNKNOWN, /* 0 */
PCI_SPEED_66MHz_PCIX, /* 1 */
@@ -1122,7 +1135,13 @@ int pci_cfg_space_size(struct pci_dev *dev)
static void pci_release_bus_bridge_dev(struct device *dev)
{
- kfree(dev);
+ struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+ /* TODO: need to free window->res */
+
+ pci_free_resource_list(&bridge->windows);
+
+ kfree(bridge);
}
struct pci_dev *alloc_pci_dev(void)
@@ -1571,28 +1590,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int error;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct device *dev;
struct pci_host_bridge_window *window, *n;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
char *fmt;
- bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
- if (!bridge)
- return NULL;
b = pci_alloc_bus();
if (!b)
- goto err_bus;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- goto err_dev;
+ return NULL;
b->sysdata = sysdata;
b->ops = ops;
-
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1600,13 +1610,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
goto err_out;
}
- dev->parent = parent;
- dev->release = pci_release_bus_bridge_dev;
- dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus);
- error = device_register(dev);
+ bridge = pci_alloc_host_bridge(b);
+ if (!bridge)
+ goto err_out;
+
+ bridge->dev.parent = parent;
+ bridge->dev.release = pci_release_bus_bridge_dev;
+ dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ error = device_register(&bridge->dev);
if (error)
- goto dev_reg_err;
- b->bridge = get_device(dev);
+ goto bridge_dev_reg_err;
+ b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
pci_set_bus_of_node(b);
@@ -1625,9 +1639,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->number = b->secondary = bus;
- bridge->bus = b;
- INIT_LIST_HEAD(&bridge->windows);
-
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else
@@ -1653,25 +1664,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}
down_write(&pci_bus_sem);
- add_to_pci_host_bridges(bridge);
list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem);
return b;
class_dev_reg_err:
- device_unregister(dev);
-dev_reg_err:
- down_write(&pci_bus_sem);
- list_del(&bridge->list);
- list_del(&b->node);
- up_write(&pci_bus_sem);
+ put_device(&bridge->dev);
+ device_unregister(&bridge->dev);
+bridge_dev_reg_err:
+ kfree(bridge);
err_out:
- kfree(dev);
-err_dev:
kfree(b);
-err_bus:
- kfree(bridge);
return NULL;
}