Skip to content

Commit

Permalink
PCI: add generic device into pci_host_bridge struct
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yinghai Lu authored and Bjorn Helgaas committed Apr 30, 2012
1 parent 459f58c commit 7b54366
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 48 deletions.
15 changes: 1 addition & 14 deletions drivers/pci/host-bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@

#include "pci.h"

static LIST_HEAD(pci_host_bridges);

void add_to_pci_host_bridges(struct pci_host_bridge *bridge)
{
list_add_tail(&bridge->list, &pci_host_bridges);
}

static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
{
struct pci_bus *bus;
Expand All @@ -30,14 +23,8 @@ static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
{
struct pci_bus *bus = find_pci_root_bus(dev);
struct pci_host_bridge *bridge;

list_for_each_entry(bridge, &pci_host_bridges, list) {
if (bridge->bus == bus)
return bridge;
}

return NULL;
return to_pci_host_bridge(bus->bridge);
}

static bool resource_contains(struct resource *res1, struct resource *res2)
Expand Down
2 changes: 0 additions & 2 deletions drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,6 @@ static inline int pci_ari_enabled(struct pci_bus *bus)
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
extern void pci_disable_bridge_window(struct pci_dev *dev);

void add_to_pci_host_bridges(struct pci_host_bridge *bridge);

/* Single Root I/O Virtualization */
struct pci_sriov {
int pos; /* capability position */
Expand Down
66 changes: 35 additions & 31 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1571,42 +1590,37 @@ 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 */
dev_dbg(&b2->dev, "bus already known\n");
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);

Expand All @@ -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
Expand All @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,13 @@ struct pci_host_bridge_window {
};

struct pci_host_bridge {
struct list_head list;
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* pci_host_bridge_windows */
};

#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)

/*
* 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
Expand Down

0 comments on commit 7b54366

Please sign in to comment.