Skip to content

Commit

Permalink
Merge branch 'topic/yinghai-hostbridge-cleanup' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
Bjorn Helgaas committed Apr 30, 2012
2 parents 977f857 + c57ca65 commit 29473ec
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 267 deletions.
116 changes: 71 additions & 45 deletions arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

struct pci_root_info {
struct acpi_device *bridge;
char *name;
char name[16];
unsigned int res_num;
struct resource *res;
struct list_head *resources;
int busnum;
struct pci_sysdata sd;
};

static bool pci_use_crs = true;
Expand Down Expand Up @@ -287,7 +287,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
}
}

static void add_resources(struct pci_root_info *info)
static void add_resources(struct pci_root_info *info,
struct list_head *resources)
{
int i;
struct resource *res, *root, *conflict;
Expand All @@ -311,53 +312,74 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
else
pci_add_resource(info->resources, res);
pci_add_resource(resources, res);
}
}

static void free_pci_root_info_res(struct pci_root_info *info)
{
kfree(info->res);
info->res = NULL;
info->res_num = 0;
}

static void __release_pci_root_info(struct pci_root_info *info)
{
int i;
struct resource *res;

for (i = 0; i < info->res_num; i++) {
res = &info->res[i];

if (!res->parent)
continue;

if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
continue;

release_resource(res);
}

free_pci_root_info_res(info);

kfree(info);
}
static void release_pci_root_info(struct pci_host_bridge *bridge)
{
struct pci_root_info *info = bridge->release_data;

__release_pci_root_info(info);
}

static void
get_current_resources(struct acpi_device *device, int busnum,
int domain, struct list_head *resources)
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
int busnum, int domain)
{
struct pci_root_info info;
size_t size;

info.bridge = device;
info.res_num = 0;
info.resources = resources;
info->bridge = device;
info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
&info);
if (!info.res_num)
info);
if (!info->res_num)
return;

size = sizeof(*info.res) * info.res_num;
info.res = kmalloc(size, GFP_KERNEL);
if (!info.res)
size = sizeof(*info->res) * info->res_num;
info->res_num = 0;
info->res = kmalloc(size, GFP_KERNEL);
if (!info->res)
return;

info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
if (!info.name)
goto name_alloc_fail;
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);

info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
&info);

if (pci_use_crs) {
add_resources(&info);

return;
}

kfree(info.name);

name_alloc_fail:
kfree(info.res);
info);
}

struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
Expand Down Expand Up @@ -389,17 +411,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != -1 && !node_online(node))
node = -1;

/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) {
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL;
}

sd = &info->sd;
sd->domain = domain;
sd->node = node;
/*
Expand All @@ -413,22 +432,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
kfree(info);
} else {
get_current_resources(device, busnum, domain, &resources);
probe_pci_root_info(info, device, busnum, domain);

/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
if (!pci_use_crs)
if (pci_use_crs)
add_resources(info, &resources);
else {
free_pci_root_info_res(info);
x86_pci_root_bus_resources(busnum, &resources);
}

bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
if (bus) {
bus->subordinate = pci_scan_child_bus(bus);
else
pci_set_host_bridge_release(
to_pci_host_bridge(bus->bridge),
release_pci_root_info, info);
} else {
pci_free_resource_list(&resources);
__release_pci_root_info(info);
}
}

/* After the PCI-E bus has been walked and all devices discovered,
Expand All @@ -445,9 +474,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
}

if (!bus)
kfree(sd);

if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
Expand Down
76 changes: 27 additions & 49 deletions arch/x86/pci/amd_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {

#define RANGE_NUM 16

static struct pci_root_info __init *find_pci_root_info(int node, int link)
{
struct pci_root_info *info;

/* find the position */
list_for_each_entry(info, &pci_root_infos, list)
if (info->node == node && info->link == link)
return info;

return NULL;
}

/**
* early_fill_mp_bus_to_node()
* called before pcibios_scan_root and pci_scan_bus
Expand All @@ -50,7 +62,6 @@ static int __init early_fill_mp_bus_info(void)
int def_link;
struct pci_root_info *info;
u32 reg;
struct resource *res;
u64 start;
u64 end;
struct range range[RANGE_NUM];
Expand Down Expand Up @@ -86,7 +97,6 @@ static int __init early_fill_mp_bus_info(void)
if (!found)
return 0;

pci_root_num = 0;
for (i = 0; i < 4; i++) {
int min_bus;
int max_bus;
Expand All @@ -105,13 +115,8 @@ static int __init early_fill_mp_bus_info(void)
#endif
link = (reg >> 8) & 0x03;

info = &pci_root_info[pci_root_num];
info->bus_min = min_bus;
info->bus_max = max_bus;
info->node = node;
info->link = link;
info = alloc_pci_root_info(min_bus, max_bus, node, link);
sprintf(info->name, "PCI Bus #%02x", min_bus);
pci_root_num++;
}

/* get the default node and link for left over res */
Expand All @@ -134,16 +139,10 @@ static int __init early_fill_mp_bus_info(void)
link = (reg >> 4) & 0x03;
end = (reg & 0xfff000) | 0xfff;

/* find the position */
for (j = 0; j < pci_root_num; j++) {
info = &pci_root_info[j];
if (info->node == node && info->link == link)
break;
}
if (j == pci_root_num)
info = find_pci_root_info(node, link);
if (!info)
continue; /* not found */

info = &pci_root_info[j];
printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
node, link, start, end);

Expand All @@ -155,13 +154,8 @@ static int __init early_fill_mp_bus_info(void)
}
/* add left over io port range to def node/link, [0, 0xffff] */
/* find the position */
for (j = 0; j < pci_root_num; j++) {
info = &pci_root_info[j];
if (info->node == def_node && info->link == def_link)
break;
}
if (j < pci_root_num) {
info = &pci_root_info[j];
info = find_pci_root_info(def_node, def_link);
if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
Expand Down Expand Up @@ -214,16 +208,10 @@ static int __init early_fill_mp_bus_info(void)
end <<= 8;
end |= 0xffff;

/* find the position */
for (j = 0; j < pci_root_num; j++) {
info = &pci_root_info[j];
if (info->node == node && info->link == link)
break;
}
if (j == pci_root_num)
continue; /* not found */
info = find_pci_root_info(node, link);

info = &pci_root_info[j];
if (!info)
continue;

printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
node, link, start, end);
Expand Down Expand Up @@ -291,14 +279,8 @@ static int __init early_fill_mp_bus_info(void)
* add left over mmio range to def node/link ?
* that is tricky, just record range in from start_min to 4G
*/
for (j = 0; j < pci_root_num; j++) {
info = &pci_root_info[j];
if (info->node == def_node && info->link == def_link)
break;
}
if (j < pci_root_num) {
info = &pci_root_info[j];

info = find_pci_root_info(def_node, def_link);
if (info) {
for (i = 0; i < RANGE_NUM; i++) {
if (!range[i].end)
continue;
Expand All @@ -309,20 +291,16 @@ static int __init early_fill_mp_bus_info(void)
}
}

for (i = 0; i < pci_root_num; i++) {
int res_num;
list_for_each_entry(info, &pci_root_infos, list) {
int busnum;
struct pci_root_res *root_res;

info = &pci_root_info[i];
res_num = info->res_num;
busnum = info->bus_min;
printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
info->bus_min, info->bus_max, info->node, info->link);
for (j = 0; j < res_num; j++) {
res = &info->res[j];
printk(KERN_DEBUG "bus: %02x index %x %pR\n",
busnum, j, res);
}
list_for_each_entry(root_res, &info->resources, list)
printk(KERN_DEBUG "bus: %02x %pR\n",
busnum, &root_res->res);
}

return 0;
Expand Down
12 changes: 4 additions & 8 deletions arch/x86/pci/broadcom_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,15 @@
static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
{
struct pci_root_info *info;
struct pci_root_res *root_res;
struct resource res;
u16 word1, word2;
u8 fbus, lbus;
int i;

info = &pci_root_info[pci_root_num];
pci_root_num++;

/* read the PCI bus numbers */
fbus = read_pci_config_byte(bus, slot, func, 0x44);
lbus = read_pci_config_byte(bus, slot, func, 0x45);
info->bus_min = fbus;
info->bus_max = lbus;
info = alloc_pci_root_info(fbus, lbus, 0, 0);

/*
* Add the legacy IDE ports on bus 0
Expand Down Expand Up @@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
res.flags = IORESOURCE_BUS;
printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);

for (i = 0; i < info->res_num; i++)
printk(KERN_INFO "host bridge window %pR\n", &info->res[i]);
list_for_each_entry(root_res, &info->resources, list)
printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
}

static int __init broadcom_postcore_init(void)
Expand Down
Loading

0 comments on commit 29473ec

Please sign in to comment.