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>
This commit is contained in:
parent
459f58ce51
commit
7b54366358
|
@ -9,13 +9,6 @@
|
||||||
|
|
||||||
#include "pci.h"
|
#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)
|
static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct pci_bus *bus;
|
struct pci_bus *bus;
|
||||||
|
@ -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)
|
static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct pci_bus *bus = find_pci_root_bus(dev);
|
struct pci_bus *bus = find_pci_root_bus(dev);
|
||||||
struct pci_host_bridge *bridge;
|
|
||||||
|
|
||||||
list_for_each_entry(bridge, &pci_host_bridges, list) {
|
return to_pci_host_bridge(bus->bridge);
|
||||||
if (bridge->bus == bus)
|
|
||||||
return bridge;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool resource_contains(struct resource *res1, struct resource *res2)
|
static bool resource_contains(struct resource *res1, struct resource *res2)
|
||||||
|
|
|
@ -231,8 +231,6 @@ static inline int pci_ari_enabled(struct pci_bus *bus)
|
||||||
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
|
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
|
||||||
extern void pci_disable_bridge_window(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 */
|
/* Single Root I/O Virtualization */
|
||||||
struct pci_sriov {
|
struct pci_sriov {
|
||||||
int pos; /* capability position */
|
int pos; /* capability position */
|
||||||
|
|
|
@ -422,6 +422,19 @@ static struct pci_bus * pci_alloc_bus(void)
|
||||||
return b;
|
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[] = {
|
static unsigned char pcix_bus_speed[] = {
|
||||||
PCI_SPEED_UNKNOWN, /* 0 */
|
PCI_SPEED_UNKNOWN, /* 0 */
|
||||||
PCI_SPEED_66MHz_PCIX, /* 1 */
|
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)
|
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)
|
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;
|
int error;
|
||||||
struct pci_host_bridge *bridge;
|
struct pci_host_bridge *bridge;
|
||||||
struct pci_bus *b, *b2;
|
struct pci_bus *b, *b2;
|
||||||
struct device *dev;
|
|
||||||
struct pci_host_bridge_window *window, *n;
|
struct pci_host_bridge_window *window, *n;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
resource_size_t offset;
|
resource_size_t offset;
|
||||||
char bus_addr[64];
|
char bus_addr[64];
|
||||||
char *fmt;
|
char *fmt;
|
||||||
|
|
||||||
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
|
|
||||||
if (!bridge)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
b = pci_alloc_bus();
|
b = pci_alloc_bus();
|
||||||
if (!b)
|
if (!b)
|
||||||
goto err_bus;
|
return NULL;
|
||||||
|
|
||||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
|
||||||
if (!dev)
|
|
||||||
goto err_dev;
|
|
||||||
|
|
||||||
b->sysdata = sysdata;
|
b->sysdata = sysdata;
|
||||||
b->ops = ops;
|
b->ops = ops;
|
||||||
|
|
||||||
b2 = pci_find_bus(pci_domain_nr(b), bus);
|
b2 = pci_find_bus(pci_domain_nr(b), bus);
|
||||||
if (b2) {
|
if (b2) {
|
||||||
/* If we already got to this bus through a different bridge, ignore it */
|
/* 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;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->parent = parent;
|
bridge = pci_alloc_host_bridge(b);
|
||||||
dev->release = pci_release_bus_bridge_dev;
|
if (!bridge)
|
||||||
dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus);
|
goto err_out;
|
||||||
error = device_register(dev);
|
|
||||||
|
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)
|
if (error)
|
||||||
goto dev_reg_err;
|
goto bridge_dev_reg_err;
|
||||||
b->bridge = get_device(dev);
|
b->bridge = get_device(&bridge->dev);
|
||||||
device_enable_async_suspend(b->bridge);
|
device_enable_async_suspend(b->bridge);
|
||||||
pci_set_bus_of_node(b);
|
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;
|
b->number = b->secondary = bus;
|
||||||
|
|
||||||
bridge->bus = b;
|
|
||||||
INIT_LIST_HEAD(&bridge->windows);
|
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
|
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
|
||||||
else
|
else
|
||||||
|
@ -1653,25 +1664,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(&pci_bus_sem);
|
down_write(&pci_bus_sem);
|
||||||
add_to_pci_host_bridges(bridge);
|
|
||||||
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);
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
|
|
||||||
class_dev_reg_err:
|
class_dev_reg_err:
|
||||||
device_unregister(dev);
|
put_device(&bridge->dev);
|
||||||
dev_reg_err:
|
device_unregister(&bridge->dev);
|
||||||
down_write(&pci_bus_sem);
|
bridge_dev_reg_err:
|
||||||
list_del(&bridge->list);
|
|
||||||
list_del(&b->node);
|
|
||||||
up_write(&pci_bus_sem);
|
|
||||||
err_out:
|
|
||||||
kfree(dev);
|
|
||||||
err_dev:
|
|
||||||
kfree(b);
|
|
||||||
err_bus:
|
|
||||||
kfree(bridge);
|
kfree(bridge);
|
||||||
|
err_out:
|
||||||
|
kfree(b);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -375,11 +375,13 @@ struct pci_host_bridge_window {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pci_host_bridge {
|
struct pci_host_bridge {
|
||||||
struct list_head list;
|
struct device dev;
|
||||||
struct pci_bus *bus; /* root bus */
|
struct pci_bus *bus; /* root bus */
|
||||||
struct list_head windows; /* pci_host_bridge_windows */
|
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
|
* 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
|
||||||
|
|
Loading…
Reference in New Issue