* [PATCH 01/11] PCI: Separate host_bridge code out from probe.c
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 02/11] x86, PCI: have own version for pcibios_bus_to_resource Yinghai Lu
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
-v2: Bjorn want add_to_pci_host_bridges to pass struct pci_host_bridge *
instead of list head pointer.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/Makefile | 2 +-
drivers/pci/host-bridge.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.h | 2 +
drivers/pci/probe.c | 81 +--------------------------------------
4 files changed, 97 insertions(+), 81 deletions(-)
create mode 100644 drivers/pci/host-bridge.c
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 083a49f..2c224ed 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PCI bus specific drivers.
#
-obj-y += access.o bus.o probe.o remove.o pci.o \
+obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
new file mode 100644
index 0000000..5ca4220
--- /dev/null
+++ b/drivers/pci/host-bridge.c
@@ -0,0 +1,93 @@
+/*
+ * host_bridge.c - host bridge related code
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.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_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;
+}
+
+static bool resource_contains(struct resource *res1, struct resource *res2)
+{
+ return res1->start <= res2->start && res1->end >= res2->end;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ if (resource_contains(window->res, res)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+static bool region_contains(struct pci_bus_region *region1,
+ struct pci_bus_region *region2)
+{
+ return region1->start <= region2->start && region1->end >= region2->end;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge_window *window;
+ struct pci_bus_region bus_region;
+ resource_size_t offset = 0;
+
+ list_for_each_entry(window, &bridge->windows, list) {
+ if (resource_type(res) != resource_type(window->res))
+ continue;
+
+ bus_region.start = window->res->start - window->offset;
+ bus_region.end = window->res->end - window->offset;
+
+ if (region_contains(&bus_region, region)) {
+ offset = window->offset;
+ break;
+ }
+ }
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index e494347..c695a92 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -231,6 +231,8 @@ 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 */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 944e05a..89a82a3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,13 +15,10 @@
#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);
-
static int find_anything(struct device *dev, void *data)
{
return 1;
@@ -44,82 +41,6 @@ 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;
-}
-
-static bool resource_contains(struct resource *res1, struct resource *res2)
-{
- return res1->start <= res2->start && res1->end >= res2->end;
-}
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- if (resource_contains(window->res, res)) {
- offset = window->offset;
- break;
- }
- }
-
- region->start = res->start - offset;
- region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-static bool region_contains(struct pci_bus_region *region1,
- struct pci_bus_region *region2)
-{
- return region1->start <= region2->start && region1->end >= region2->end;
-}
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
-{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
- struct pci_host_bridge_window *window;
- struct pci_bus_region bus_region;
- resource_size_t offset = 0;
-
- list_for_each_entry(window, &bridge->windows, list) {
- if (resource_type(res) != resource_type(window->res))
- continue;
-
- bus_region.start = window->res->start - window->offset;
- bus_region.end = window->res->end - window->offset;
-
- if (region_contains(&bus_region, region)) {
- offset = window->offset;
- break;
- }
- }
-
- res->start = region->start + offset;
- res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
/*
* PCI Bus Class
*/
@@ -1731,7 +1652,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);
+ add_to_pci_host_bridges(bridge);
list_add_tail(&b->node, &pci_root_buses);
up_write(&pci_bus_sem);
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/11] x86, PCI: have own version for pcibios_bus_to_resource
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
2012-02-28 2:03 ` [PATCH 01/11] PCI: Separate host_bridge code out from probe.c Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 03/11] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
x86 does not need to offset the address. So we can skip that costing offset
searching.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/i386.c | 14 ++++++++++++++
drivers/pci/host-bridge.c | 9 +++++----
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 33e6a0b..eeed28e 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -335,6 +335,20 @@ void __init pcibios_resource_survey(void)
*/
fs_initcall(pcibios_assign_resources);
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ region->start = res->start;
+ region->end = res->end;
+}
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ res->start = region->start;
+ res->end = region->end;
+}
+
static const struct vm_operations_struct pci_mmap_ops = {
.access = generic_access_phys,
};
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 5ca4220..dfaff3f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -38,8 +38,9 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
return res1->start <= res2->start && res1->end >= res2->end;
}
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
+void __weak pcibios_resource_to_bus(struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res)
{
struct pci_host_bridge *bridge = pci_host_bridge(dev);
struct pci_host_bridge_window *window;
@@ -66,8 +67,8 @@ static bool region_contains(struct pci_bus_region *region1,
return region1->start <= region2->start && region1->end >= region2->end;
}
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- struct pci_bus_region *region)
+void __weak pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
{
struct pci_host_bridge *bridge = pci_host_bridge(dev);
struct pci_host_bridge_window *window;
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/11] x86, PCI: Fix memleak with get_current_resources
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
2012-02-28 2:03 ` [PATCH 01/11] PCI: Separate host_bridge code out from probe.c Yinghai Lu
2012-02-28 2:03 ` [PATCH 02/11] x86, PCI: have own version for pcibios_bus_to_resource Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 04/11] PCI: rename pci_host_bridge() to find_pci_root_bridge() Yinghai Lu
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
in pci_scan_acpi_root, when pci_use_crs is set, get_current_resources is used
to get pci_root_info, and it will allocate name and res array.
later if pci_create_root_bus can not create bus (could be already there...)
it will only free bus res list. but the name and res array is not freed.
let get_current_resource take info pointer instead have local info.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/acpi.c | 49 ++++++++++++++++++++++++++++++-------------------
1 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 7cc0a44..304ccf0 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,49 +305,55 @@ static void add_resources(struct pci_root_info *info)
}
}
+static void free_pci_root_info(struct pci_root_info *info)
+{
+ kfree(info->name);
+ kfree(info->res);
+ memset(info, 0, sizeof(struct pci_root_info));
+}
+
static void
-get_current_resources(struct acpi_device *device, int busnum,
+get_current_resources(struct pci_root_info *info,
+ struct acpi_device *device, int busnum,
int domain, struct list_head *resources)
{
- 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;
+ info->resources = resources;
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 = kmalloc(size, GFP_KERNEL);
+ if (!info->res)
return;
- info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
- if (!info.name)
+ info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
+ if (!info->name)
goto name_alloc_fail;
- info.res_num = 0;
+ info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
- &info);
+ info);
if (pci_use_crs) {
- add_resources(&info);
+ add_resources(info);
return;
}
- kfree(info.name);
-
name_alloc_fail:
- kfree(info.res);
+ free_pci_root_info(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;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
@@ -392,6 +398,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
sd->domain = domain;
sd->node = node;
+ memset(&info, 0, sizeof(struct pci_root_info));
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -405,7 +412,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else {
- get_current_resources(device, busnum, domain, &resources);
+ get_current_resources(&info, device, busnum, domain,
+ &resources);
/*
* _CRS with no apertures is normal, so only fall back to
@@ -419,6 +427,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
bus->subordinate = pci_scan_child_bus(bus);
else
pci_free_resource_list(&resources);
+
+ if (!bus && pci_use_crs)
+ free_pci_root_info(&info);
}
/* After the PCI-E bus has been walked and all devices discovered,
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/11] PCI: rename pci_host_bridge() to find_pci_root_bridge()
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (2 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 03/11] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 05/11] PCI: add generic device into pci_host_bridge struct Yinghai Lu
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
Separate find_pci_root_bus out.
-v2: according to Bjorn, remove extra null checking.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/host-bridge.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index dfaff3f..b3ddcc5 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -16,15 +16,22 @@ void add_to_pci_host_bridges(struct pci_host_bridge *bridge)
list_add_tail(&bridge->list, &pci_host_bridges);
}
-static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
+static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
{
struct pci_bus *bus;
- struct pci_host_bridge *bridge;
bus = dev->bus;
while (bus->parent)
bus = bus->parent;
+ return bus;
+}
+
+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;
@@ -42,7 +49,7 @@ void __weak pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region,
struct resource *res)
{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
struct pci_host_bridge_window *window;
resource_size_t offset = 0;
@@ -70,12 +77,13 @@ static bool region_contains(struct pci_bus_region *region1,
void __weak pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
- struct pci_host_bridge *bridge = pci_host_bridge(dev);
+ struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
struct pci_host_bridge_window *window;
- struct pci_bus_region bus_region;
resource_size_t offset = 0;
list_for_each_entry(window, &bridge->windows, list) {
+ struct pci_bus_region bus_region;
+
if (resource_type(res) != resource_type(window->res))
continue;
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/11] PCI: add generic device into pci_host_bridge struct
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (3 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 04/11] PCI: rename pci_host_bridge() to find_pci_root_bridge() Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 06/11] PCI: add host bridge release support Yinghai Lu
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
use that device for pci_root_bus bridge pointer.
With that make code more simple.
Also we can use pci_release_bus_bridge_dev() to release allocated
pci_host_bridge during removing path.
At last, we can use root bus bridge pointer to get host bridge pointer instead
of going over host bridge list, so could kill that host bridge list.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/host-bridge.c | 15 +---------
drivers/pci/pci.h | 2 -
drivers/pci/probe.c | 65 +++++++++++++++++++++++---------------------
include/linux/pci.h | 4 ++-
4 files changed, 38 insertions(+), 48 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index b3ddcc5..03d8db1 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -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;
@@ -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)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index c695a92..e494347 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -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 */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 89a82a3..fb3dd4b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -421,6 +421,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 */
@@ -1121,7 +1134,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)
@@ -1570,28 +1589,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 */
@@ -1599,13 +1609,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);
@@ -1624,9 +1638,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
@@ -1652,25 +1663,17 @@ 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);
+ device_unregister(&bridge->dev);
+bridge_dev_reg_err:
+ kfree(bridge);
err_out:
- kfree(dev);
-err_dev:
kfree(b);
-err_bus:
- kfree(bridge);
return NULL;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5584aac..310610e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -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
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/11] PCI: add host bridge release support
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (4 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 05/11] PCI: add generic device into pci_host_bridge struct Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 07/11] x86, PCI: break down get_current_resource() Yinghai Lu
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
We need one hook to release host bridge resource that are created for host
bridge.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/host-bridge.c | 8 ++++++++
drivers/pci/probe.c | 3 ++-
include/linux/pci.h | 5 +++++
3 files changed, 15 insertions(+), 1 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 03d8db1..a710a60 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -27,6 +27,14 @@ static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
return to_pci_host_bridge(bus->bridge);
}
+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data)
+{
+ bridge->release_fn = release_fn;
+ bridge->release_data = release_data;
+}
+
static bool resource_contains(struct resource *res1, struct resource *res2)
{
return res1->start <= res2->start && res1->end >= res2->end;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fb3dd4b..675d7ed 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1136,7 +1136,8 @@ static void pci_release_bus_bridge_dev(struct device *dev)
{
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
- /* TODO: need to free window->res */
+ if (bridge->release_fn)
+ bridge->release_fn(bridge);
pci_free_resource_list(&bridge->windows);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 310610e..d93d3ae 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -378,9 +378,14 @@ struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* pci_host_bridge_windows */
+ void (*release_fn)(struct pci_host_bridge *);
+ void *release_data;
};
#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+ void (*release_fn)(struct pci_host_bridge *),
+ void *release_data);
/*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/11] x86, PCI: break down get_current_resource()
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (5 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 06/11] PCI: add host bridge release support Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 08/11] x86, PCI: add host bridge resource release for using _CRS Yinghai Lu
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
change it to probe_pci_root_info, aka only do one thing.
1. remove resource list head from pci_root_info
2. make get_current_resources() not pass resources
move out add_resources calling out of yet.
3. rename get_current_resourcs name to probe_pci_root_info
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/acpi.c | 34 +++++++++++++---------------------
1 files changed, 13 insertions(+), 21 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 304ccf0..763f7bb 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,6 @@ struct pci_root_info {
char *name;
unsigned int res_num;
struct resource *res;
- struct list_head *resources;
int busnum;
};
@@ -277,7 +276,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;
@@ -301,7 +301,7 @@ 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);
}
}
@@ -313,41 +313,30 @@ static void free_pci_root_info(struct pci_root_info *info)
}
static void
-get_current_resources(struct pci_root_info *info,
- 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)
{
size_t size;
info->bridge = device;
info->res_num = 0;
- info->resources = resources;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
info);
if (!info->res_num)
return;
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;
+ return;
- info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
-
- if (pci_use_crs) {
- add_resources(info);
-
- return;
- }
-
-name_alloc_fail:
- free_pci_root_info(info);
}
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
@@ -412,15 +401,18 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else {
- get_current_resources(&info, 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(&info);
x86_pci_root_bus_resources(busnum, &resources);
+ }
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/11] x86, PCI: add host bridge resource release for using _CRS
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (6 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 07/11] x86, PCI: break down get_current_resource() Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 09/11] x86, PCI: embed name acpi version pci_root_info struct Yinghai Lu
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
1. allocate pci_root_info instead of use local stack. we need to pass around info
for release fn.
2. add release_pci_root_info
3. set x86 own host bridge release fn, so will make sure root bridge
related resources get freed during root bus removal.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/acpi.c | 66 +++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 763f7bb..208f257 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -309,7 +309,33 @@ static void free_pci_root_info(struct pci_root_info *info)
{
kfree(info->name);
kfree(info->res);
- memset(info, 0, sizeof(struct pci_root_info));
+ kfree(info);
+}
+
+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(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
@@ -342,7 +368,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
- struct pci_root_info info;
+ struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
@@ -379,15 +405,16 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* It's arguable whether it's worth the trouble to care.
*/
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
- if (!sd) {
- printk(KERN_WARNING "pci_bus %04x:%02x: "
- "ignored (out of memory)\n", domain, busnum);
- return NULL;
- }
+ if (!sd)
+ goto out_no_memory;
sd->domain = domain;
sd->node = node;
- memset(&info, 0, sizeof(struct pci_root_info));
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ kfree(sd);
+ goto out_no_memory;
+ }
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -399,20 +426,22 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
+ kfree(info);
kfree(sd);
} else {
- probe_pci_root_info(&info, device, busnum, domain);
+ 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)
- add_resources(&info, &resources);
+ add_resources(info, &resources);
else {
- free_pci_root_info(&info);
+ free_pci_root_info(info);
x86_pci_root_bus_resources(busnum, &resources);
}
+
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
@@ -420,8 +449,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
else
pci_free_resource_list(&resources);
- if (!bus && pci_use_crs)
- free_pci_root_info(&info);
+ if (pci_use_crs) {
+ if (bus)
+ pci_set_host_bridge_release(
+ to_pci_host_bridge(bus->bridge),
+ release_pci_root_info, info);
+ else
+ __release_pci_root_info(info);
+ }
}
/* After the PCI-E bus has been walked and all devices discovered,
@@ -452,6 +487,11 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
return bus;
+
+out_no_memory:
+ printk(KERN_WARNING "pci_bus %04x:%02x: "
+ "ignored (out of memory)\n", domain, busnum);
+ return NULL;
}
int __init pci_acpi_init(void)
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/11] x86, PCI: embed name acpi version pci_root_info struct
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (7 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 08/11] x86, PCI: add host bridge resource release for using _CRS Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 10/11] x86, PCI: Allocating pci_root_info for nocrs path Yinghai Lu
2012-02-28 2:03 ` [PATCH 11/11] x86, PCI: Merge root info printing " Yinghai Lu
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
Now We allocate info, and keep that in during whole life of hostbridge.
So don't allocate info->name seperately, just put name into struct.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/acpi.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 208f257..7538fad 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -9,7 +9,7 @@
struct pci_root_info {
struct acpi_device *bridge;
- char *name;
+ char name[16];
unsigned int res_num;
struct resource *res;
int busnum;
@@ -307,7 +307,6 @@ static void add_resources(struct pci_root_info *info,
static void free_pci_root_info(struct pci_root_info *info)
{
- kfree(info->name);
kfree(info->res);
kfree(info);
}
@@ -357,9 +356,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
if (!info->res)
return;
- info->name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
- if (!info->name)
- return;
+ sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info);
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/11] x86, PCI: Allocating pci_root_info for nocrs path
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (8 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 09/11] x86, PCI: embed name acpi version pci_root_info struct Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
2012-02-28 2:03 ` [PATCH 11/11] x86, PCI: Merge root info printing " Yinghai Lu
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
so we could get ride of static allocation and hard limits.
We could save some bytes, and can handle system with more than 4
peer root buses.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/amd_bus.c | 76 +++++++++++++++---------------------------
arch/x86/pci/broadcom_bus.c | 9 ++---
arch/x86/pci/bus_numa.c | 69 ++++++++++++++++++++++++++------------
arch/x86/pci/bus_numa.h | 18 ++++++----
4 files changed, 88 insertions(+), 84 deletions(-)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0567df3..459a731 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -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
@@ -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];
@@ -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;
@@ -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 */
@@ -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);
@@ -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;
@@ -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);
@@ -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;
@@ -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;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index f3a7c56..521a374 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -22,13 +22,12 @@
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++;
+ info = alloc_pci_root_info(0, 0, 0, 0);
/* read the PCI bus numbers */
fbus = read_pci_config_byte(bus, slot, func, 0x44);
@@ -86,8 +85,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)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index fd3f655..306579f 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -4,35 +4,38 @@
#include "bus_numa.h"
-int pci_root_num;
-struct pci_root_info pci_root_info[PCI_ROOT_NR];
+LIST_HEAD(pci_root_infos);
-void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+static struct pci_root_info *x86_find_pci_root_info(int bus)
{
- int i;
- int j;
struct pci_root_info *info;
- if (!pci_root_num)
- goto default_resources;
+ if (list_empty(&pci_root_infos))
+ return NULL;
- for (i = 0; i < pci_root_num; i++) {
- if (pci_root_info[i].bus_min == bus)
- break;
- }
+ list_for_each_entry(info, &pci_root_infos, list)
+ if (info->bus_min == bus)
+ return info;
+
+ return NULL;
+}
- if (i == pci_root_num)
+void x86_pci_root_bus_resources(int bus, struct list_head *resources)
+{
+ struct pci_root_info *info = x86_find_pci_root_info(bus);
+ struct pci_root_res *root_res;
+
+ if (!info)
goto default_resources;
printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
bus);
- info = &pci_root_info[i];
- for (j = 0; j < info->res_num; j++) {
+ list_for_each_entry(root_res, &info->resources, list) {
struct resource *res;
struct resource *root;
- res = &info->res[j];
+ res = &root_res->res;
pci_add_resource(resources, res);
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
@@ -53,11 +56,32 @@ default_resources:
pci_add_resource(resources, &iomem_resource);
}
+struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link)
+{
+ struct pci_root_info *info;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+ if (!info)
+ return info;
+
+ INIT_LIST_HEAD(&info->resources);
+ info->bus_min = bus_min;
+ info->bus_max = bus_max;
+ info->node = node;
+ info->link = link;
+
+ list_add_tail(&info->list, &pci_root_infos);
+
+ return info;
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
- int i;
struct resource *res;
+ struct pci_root_res *root_res;
if (start > end)
return;
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
goto addit;
/* try to merge it with old one */
- for (i = 0; i < info->res_num; i++) {
+ list_for_each_entry(root_res, &info->resources, list) {
resource_size_t final_start, final_end;
resource_size_t common_start, common_end;
- res = &info->res[i];
+ res = &root_res->res;
if (res->flags != flags)
continue;
@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
addit:
/* need to add that */
- if (info->res_num >= RES_NUM)
+ root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
+ if (!root_res)
return;
- res = &info->res[info->res_num];
+ res = &root_res->res;
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
- res->child = NULL;
- info->res_num++;
+
+ list_add_tail(&root_res->list, &info->resources);
}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 804a4b4..226a466 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -4,22 +4,24 @@
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there.
*/
-#define RES_NUM 16
+struct pci_root_res {
+ struct list_head list;
+ struct resource res;
+};
+
struct pci_root_info {
+ struct list_head list;
char name[12];
- unsigned int res_num;
- struct resource res[RES_NUM];
+ struct list_head resources;
int bus_min;
int bus_max;
int node;
int link;
};
-/* 4 at this time, it may become to 32 */
-#define PCI_ROOT_NR 4
-extern int pci_root_num;
-extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
-
+extern struct list_head pci_root_infos;
+struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
+ int node, int link);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 11/11] x86, PCI: Merge root info printing for nocrs path
2012-02-28 2:03 [PATCH -v2 00/11] PCI: pci_host_bridge related cleanup Yinghai Lu
` (9 preceding siblings ...)
2012-02-28 2:03 ` [PATCH 10/11] x86, PCI: Allocating pci_root_info for nocrs path Yinghai Lu
@ 2012-02-28 2:03 ` Yinghai Lu
10 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2012-02-28 2:03 UTC (permalink / raw)
To: Jesse Barnes; +Cc: Bjorn Helgaas, linux-pci, linux-kernel, Yinghai Lu
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/amd_bus.c | 12 +-----------
arch/x86/pci/broadcom_bus.c | 9 +--------
arch/x86/pci/bus_numa.c | 17 +++++++++++++++++
arch/x86/pci/bus_numa.h | 1 +
4 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 459a731..0b6abbe 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -291,17 +291,7 @@ static int __init early_fill_mp_bus_info(void)
}
}
- list_for_each_entry(info, &pci_root_infos, list) {
- int busnum;
- struct pci_root_res *root_res;
-
- 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);
- list_for_each_entry(root_res, &info->resources, list)
- printk(KERN_DEBUG "bus: %02x %pR\n",
- busnum, &root_res->res);
- }
+ print_pci_root_info(info, "bus:", true);
return 0;
}
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index 521a374..ec5c66f 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -79,14 +79,7 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
update_res(info, res.start, res.end, res.flags, 0);
}
- /* print information about this host bridge */
- res.start = fbus;
- res.end = lbus;
- res.flags = IORESOURCE_BUS;
- printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
-
- list_for_each_entry(root_res, &info->resources, list)
- printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
+ print_pci_root_info(info, "host bridge windows: ", false);
}
static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 306579f..7251011 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -77,6 +77,23 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
return info;
}
+void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink)
+{
+ struct pci_root_res *root_res;
+ int busnum = info->bus_min;
+
+ if (!nodelink)
+ printk(KERN_DEBUG "%s: [%02x, %02x]\n", name,
+ info->bus_min, info->bus_max);
+ else
+ printk(KERN_DEBUG "%s: [%02x, %02x] on node %x link %x\n", name,
+ info->bus_min, info->bus_max, info->node, info->link);
+
+ list_for_each_entry(root_res, &info->resources, list)
+ printk(KERN_DEBUG "%s: %02x %pR\n", name, busnum,
+ &root_res->res);
+}
+
void __devinit update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge)
{
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 226a466..d19ac93 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -22,6 +22,7 @@ struct pci_root_info {
extern struct list_head pci_root_infos;
struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
int node, int link);
+void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink);
extern void update_res(struct pci_root_info *info, resource_size_t start,
resource_size_t end, unsigned long flags, int merge);
#endif
--
1.7.7
^ permalink raw reply related [flat|nested] 12+ messages in thread