linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc
@ 2012-03-01  3:00 Yinghai Lu
  2012-03-01  3:00 ` [PATCH 01/36] PCI: Separate host_bridge code out from probe.c Yinghai Lu
                   ` (36 more replies)
  0 siblings, 37 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

The first 13 patches are hostbridge clean up.
will add struct device dev into host_bridge struct.
also will add release support to make sure allocated resource get
freed during root bus removal including hostbridge and pci_sysdata.

others 23 patches are busn_alloc related.
Set up iobusn_resource tree, and register bus number range to it.
Later when need to find bus range, will try to allocate from the tree
Need to test on arches other than x86. esp for ia64 and powerpc that support
  more than on peer root buses.

The patches need to apply to pci/for-linus and pci/linux-next
because one patch that is needed only is only in pci/for-linus

could get from
        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-next

please put them into pci/linux-next branch for more testing.

-v2: dropped the patch that is with x86 pcibios_bus_to_resource that Bjorn objected.
     reorder the patchesset to mold one appended patch into previous patch.

Thanks

Yinghai

Yinghai Lu (36):
  PCI: Separate host_bridge code out from probe.c
  x86, PCI: Fix memleak with get_current_resources
  PCI: rename pci_host_bridge() to find_pci_root_bridge()
  PCI: add generic device into pci_host_bridge struct
  PCI: add host bridge release support
  x86, PCI: break down get_current_resource()
  x86, PCI: add host bridge resource release for using _CRS
  x86, PCI: embed name acpi version pci_root_info struct
  x86, PCI: embed pci_sysdata into pci_root_info on acpi path
  x86, PCI: Allocating pci_root_info for not using _CRS path
  x86, PCI: Merge root info printing for nocrs path
  x86, PCI: add print all root info for nocrs path
  x86, PCI: allocate temp range array in amd_bus pci_root_info probing
  x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node
  PCI: Add busn_res into struct pci_bus.
  PCI: Add busn_res operation functions
  PCI: release busn when removing bus
  PCI: insert busn_res in pci_create_root_bus
  PCI: checking busn_res in pci_scan_root_bus
  PCI: default busn_resource
  PCI: add default res for pci_scan_bus
  x86, PCI: add busn into resources list for acpi path
  x86, PCI: put busn resource in pci_root_info for no_crs path
  PCI, ia64: Register busn_res for root buses
  PCI, sparc: Register busn_res for root buses
  PCI, powerpc: Register busn_res for root buses
  PCI, parisc: Register busn_res for root buses
  PCI: Add pci_bus_extend/shrink_top()
  PCI: Probe safe range that we can use for unassigned bridge.
  PCI: Strict checking of valid range for bridge
  PCI: Allocate bus range instead of use max blindly
  PCI: kill pci_fixup_parent_subordinate_busnr()
  PCI: Seperate child bus scanning to two passes overall
  pcmcia: remove workaround for fixing pci parent bus subordinate
  PCI: Double checking setting for bus register and bus struct.
  PCI, pciehp: Remove not needed bus number range checking

 arch/ia64/pci/pci.c                   |    2 +
 arch/powerpc/include/asm/pci-bridge.h |    1 +
 arch/powerpc/kernel/pci-common.c      |   10 +-
 arch/sparc/kernel/pci.c               |    4 +
 arch/sparc/kernel/pci_impl.h          |    1 +
 arch/x86/pci/acpi.c                   |  121 ++++---
 arch/x86/pci/amd_bus.c                |   88 ++----
 arch/x86/pci/broadcom_bus.c           |   17 +-
 arch/x86/pci/bus_numa.c               |  100 +++++--
 arch/x86/pci/bus_numa.h               |   23 +-
 arch/x86/pci/common.c                 |   27 +--
 drivers/parisc/dino.c                 |    5 +
 drivers/parisc/lba_pci.c              |    3 +
 drivers/pci/Makefile                  |    2 +-
 drivers/pci/host-bridge.c             |   96 ++++++
 drivers/pci/hotplug/pciehp_pci.c      |   12 +-
 drivers/pci/probe.c                   |  601 ++++++++++++++++++++++-----------
 drivers/pci/remove.c                  |    1 +
 drivers/pcmcia/yenta_socket.c         |   75 ----
 include/linux/pci.h                   |   15 +-
 20 files changed, 752 insertions(+), 452 deletions(-)
 create mode 100644 drivers/pci/host-bridge.c

-- 
1.7.7


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 01/36] PCI: Separate host_bridge code out from probe.c
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
                   ` (35 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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] 44+ messages in thread

* [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
  2012-03-01  3:00 ` [PATCH 01/36] PCI: Separate host_bridge code out from probe.c Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-15  8:39   ` Taku Izumi
  2012-03-01  3:00 ` [PATCH 03/36] PCI: rename pci_host_bridge() to find_pci_root_bridge() Yinghai Lu
                   ` (34 subsequent siblings)
  36 siblings, 1 reply; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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] 44+ messages in thread

* [PATCH 03/36] PCI: rename pci_host_bridge() to find_pci_root_bridge()
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
  2012-03-01  3:00 ` [PATCH 01/36] PCI: Separate host_bridge code out from probe.c Yinghai Lu
  2012-03-01  3:00 ` [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 04/36] PCI: add generic device into pci_host_bridge struct Yinghai Lu
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 5ca4220..78adcc0 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;
@@ -41,7 +48,7 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
 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 *bridge = find_pci_host_bridge(dev);
 	struct pci_host_bridge_window *window;
 	resource_size_t offset = 0;
 
@@ -69,12 +76,13 @@ static bool region_contains(struct pci_bus_region *region1,
 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 *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] 44+ messages in thread

* [PATCH 04/36] PCI: add generic device into pci_host_bridge struct
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (2 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 03/36] PCI: rename pci_host_bridge() to find_pci_root_bridge() Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 05/36] PCI: add host bridge release support Yinghai Lu
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 78adcc0..a55c3f8 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] 44+ messages in thread

* [PATCH 05/36] PCI: add host bridge release support
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (3 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 04/36] PCI: add generic device into pci_host_bridge struct Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 06/36] x86, PCI: break down get_current_resource() Yinghai Lu
                   ` (31 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 a55c3f8..3b2cb40 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] 44+ messages in thread

* [PATCH 06/36] x86, PCI: break down get_current_resource()
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (4 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 05/36] PCI: add host bridge release support Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 07/36] x86, PCI: add host bridge resource release for using _CRS Yinghai Lu
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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] 44+ messages in thread

* [PATCH 07/36] x86, PCI: add host bridge resource release for using _CRS
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (5 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 06/36] x86, PCI: break down get_current_resource() Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 08/36] x86, PCI: embed name acpi version pci_root_info struct Yinghai Lu
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 |   63 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 763f7bb..c7a230f 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,11 +305,40 @@ static void add_resources(struct pci_root_info *info,
 	}
 }
 
-static void free_pci_root_info(struct pci_root_info *info)
+static void free_pci_root_info_res(struct pci_root_info *info)
 {
 	kfree(info->name);
 	kfree(info->res);
-	memset(info, 0, sizeof(struct pci_root_info));
+	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
@@ -342,7 +371,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);
@@ -387,7 +416,13 @@ 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));
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		kfree(sd);
+		printk(KERN_WARNING "pci_bus %04x:%02x: "
+		       "ignored (out of memory)\n", domain, busnum);
+		return NULL;
+	}
 	/*
 	 * 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,29 +434,33 @@ 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_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);
-
-		if (!bus && pci_use_crs)
-			free_pci_root_info(&info);
+			__release_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] 44+ messages in thread

* [PATCH 08/36] x86, PCI: embed name acpi version pci_root_info struct
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (6 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 07/36] x86, PCI: add host bridge resource release for using _CRS Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 09/36] x86, PCI: embed pci_sysdata into pci_root_info on acpi path Yinghai Lu
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 c7a230f..11c3ae7 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_res(struct pci_root_info *info)
 {
-	kfree(info->name);
 	kfree(info->res);
 	info->res = NULL;
 	info->res_num = 0;
@@ -360,9 +359,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] 44+ messages in thread

* [PATCH 09/36] x86, PCI: embed pci_sysdata into pci_root_info on acpi path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (7 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 08/36] x86, PCI: embed name acpi version pci_root_info struct Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 10/36] x86, PCI: Allocating pci_root_info for not using _CRS path Yinghai Lu
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

So that part memory will be released on remove path.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/acpi.c |   21 ++++-----------------
 1 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 11c3ae7..2331ccb 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -13,6 +13,7 @@ struct pci_root_info {
 	unsigned int res_num;
 	struct resource *res;
 	int busnum;
+	struct pci_sysdata sd;
 };
 
 static bool pci_use_crs = true;
@@ -400,26 +401,16 @@ 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;
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		kfree(sd);
-		printk(KERN_WARNING "pci_bus %04x:%02x: "
-		       "ignored (out of memory)\n", domain, busnum);
-		return NULL;
-	}
 	/*
 	 * 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.
@@ -432,7 +423,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 		 */
 		memcpy(bus->sysdata, sd, sizeof(*sd));
 		kfree(info);
-		kfree(sd);
 	} else {
 		probe_pci_root_info(info, device, busnum, domain);
 
@@ -474,9 +464,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)
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/36] x86, PCI: Allocating pci_root_info for not using _CRS path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (8 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 09/36] x86, PCI: embed pci_sysdata into pci_root_info on acpi path Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 11/36] x86, PCI: Merge root info printing for nocrs path Yinghai Lu
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 |   12 ++----
 arch/x86/pci/bus_numa.c     |   69 ++++++++++++++++++++++++++------------
 arch/x86/pci/bus_numa.h     |   18 ++++++----
 4 files changed, 88 insertions(+), 87 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..614392c 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -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
@@ -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)
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] 44+ messages in thread

* [PATCH 11/36] x86, PCI: Merge root info printing for nocrs path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (9 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 10/36] x86, PCI: Allocating pci_root_info for not using _CRS path Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 12/36] x86, PCI: add print all root info " Yinghai Lu
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, 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 614392c..a03a14a 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -76,14 +76,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] 44+ messages in thread

* [PATCH 12/36] x86, PCI: add print all root info for nocrs path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (10 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 11/36] x86, PCI: Merge root info printing for nocrs path Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 13/36] x86, PCI: allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
                   ` (24 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/amd_bus.c  |    2 +-
 arch/x86/pci/bus_numa.c |    8 ++++++++
 arch/x86/pci/bus_numa.h |    1 +
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0b6abbe..5f30a98 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -291,7 +291,7 @@ static int __init early_fill_mp_bus_info(void)
 		}
 	}
 
-	print_pci_root_info(info, "bus:", true);
+	print_all_pci_root_info("ht link", true);
 
 	return 0;
 }
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 7251011..772949f 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -94,6 +94,14 @@ void print_pci_root_info(struct pci_root_info *info, char *name, bool nodelink)
 				 &root_res->res);
 }
 
+void print_all_pci_root_info(char *name, bool nodelink)
+{
+	struct pci_root_info *info;
+
+	list_for_each_entry(info, &pci_root_infos, list)
+		print_pci_root_info(info, name, nodelink);
+}
+
 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 d19ac93..deada6a 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -23,6 +23,7 @@ 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);
+void print_all_pci_root_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] 44+ messages in thread

* [PATCH 13/36] x86, PCI: allocate temp range array in amd_bus pci_root_info probing
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (11 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 12/36] x86, PCI: add print all root info " Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 14/36] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/amd_bus.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 5f30a98..aff155d 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -30,7 +30,7 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
 	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
 };
 
-#define RANGE_NUM 16
+#define RANGE_NUM 128
 
 static struct pci_root_info __init *find_pci_root_info(int node, int link)
 {
@@ -64,7 +64,7 @@ static int __init early_fill_mp_bus_info(void)
 	u32 reg;
 	u64 start;
 	u64 end;
-	struct range range[RANGE_NUM];
+	struct range *range;
 	u64 val;
 	u32 address;
 	bool found;
@@ -125,7 +125,10 @@ static int __init early_fill_mp_bus_info(void)
 	reg = read_pci_config(bus, slot, 0, 0x64);
 	def_link = (reg >> 8) & 0x03;
 
-	memset(range, 0, sizeof(range));
+	range = kcalloc(RANGE_NUM, sizeof(struct range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+
 	add_range(range, RANGE_NUM, 0, 0, 0xffff + 1);
 	/* io port resource */
 	for (i = 0; i < 4; i++) {
@@ -291,6 +294,8 @@ static int __init early_fill_mp_bus_info(void)
 		}
 	}
 
+	kfree(range);
+
 	print_all_pci_root_info("ht link", true);
 
 	return 0;
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 14/36] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (12 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 13/36] x86, PCI: allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 15/36] PCI: Add busn_res into struct pci_bus Yinghai Lu
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Those two almost the same.
Let pcibios_scan_root call pci_scan_bus_on_node instead.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/common.c |   27 ++++-----------------------
 1 files changed, 4 insertions(+), 23 deletions(-)

diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 323481e..8e04ec5 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -430,9 +430,7 @@ void __init dmi_check_pciprobe(void)
 
 struct pci_bus * __devinit pcibios_scan_root(int busnum)
 {
-	LIST_HEAD(resources);
 	struct pci_bus *bus = NULL;
-	struct pci_sysdata *sd;
 
 	while ((bus = pci_find_next_bus(bus)) != NULL) {
 		if (bus->number == busnum) {
@@ -441,28 +439,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
 		}
 	}
 
-	/* 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) {
-		printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
-		return NULL;
-	}
-
-	sd->node = get_mp_bus_to_node(busnum);
-
-	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
-	x86_pci_root_bus_resources(busnum, &resources);
-	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
-	if (!bus) {
-		pci_free_resource_list(&resources);
-		kfree(sd);
-	}
-
-	return bus;
+	return pci_scan_bus_on_node(busnum, &pci_root_ops,
+					get_mp_bus_to_node(busnum));
 }
+
 void __init pcibios_set_cache_line_size(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -656,6 +636,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
 	}
 	sd->node = node;
 	x86_pci_root_bus_resources(busno, &resources);
+	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
 	bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
 	if (!bus) {
 		pci_free_resource_list(&resources);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 15/36] PCI: Add busn_res into struct pci_bus.
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (13 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 14/36] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 16/36] PCI: Add busn_res operation functions Yinghai Lu
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, Andrew Morton

will use it to have bus number resource tree.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 include/linux/pci.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index d93d3ae..7c03852 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -419,6 +419,7 @@ struct pci_bus {
 	struct list_head slots;		/* list of slots on this bus */
 	struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
 	struct list_head resources;	/* address space routed to this bus */
+	struct resource busn_res;	/* track registered bus num range */
 
 	struct pci_ops	*ops;		/* configuration access functions */
 	void		*sysdata;	/* hook for sys-specific extension */
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 16/36] PCI: Add busn_res operation functions
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (14 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 15/36] PCI: Add busn_res into struct pci_bus Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 17/36] PCI: release busn when removing bus Yinghai Lu
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

will use them insert/update busn res in pci_bus

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h |    3 +++
 2 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 675d7ed..ed82369 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1678,6 +1678,56 @@ err_out:
 	return NULL;
 }
 
+void pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
+{
+	struct resource *res = &b->busn_res;
+	struct resource *parent_res;
+	int ret;
+
+	res->start = bus;
+	res->end = bus_max;
+	res->flags = IORESOURCE_BUS;
+
+	/* no parent for root bus' busn_res */
+	if (!pci_is_root_bus(b)) {
+		parent_res = &b->parent->busn_res;
+
+		ret = insert_resource(parent_res, res);
+
+		dev_printk(KERN_DEBUG, &b->dev,
+			"busn_res: %pR %s inserted under %pR\n",
+			res, ret ? "can not be" : "is", parent_res);
+	} else
+		dev_printk(KERN_DEBUG, &b->dev,
+			"busn_res: %pR for root bus\n",
+			res);
+}
+
+void pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
+{
+	struct resource *res = &b->busn_res;
+	struct resource old_res = *res;
+
+	res->end = bus_max;
+	dev_printk(KERN_DEBUG, &b->dev,
+			"busn_res: %pR end updated to %pR\n",
+			&old_res, res);
+}
+
+void pci_bus_release_busn_res(struct pci_bus *b)
+{
+	struct resource *res = &b->busn_res;
+	int ret;
+
+	if (!res->flags)
+		return;
+
+	ret = release_resource(res);
+	dev_printk(KERN_DEBUG, &b->dev,
+			"busn_res: %pR %s released\n",
+			res, ret ? "can not be" : "is");
+}
+
 struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7c03852..e494759 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -669,6 +669,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
+void pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
+void pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
+void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 17/36] PCI: release busn when removing bus
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (15 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 16/36] PCI: Add busn_res operation functions Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 18/36] PCI: insert busn_res in pci_create_root_bus Yinghai Lu
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/remove.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index fd77e2b..04a4861 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
 
 	down_write(&pci_bus_sem);
 	list_del(&pci_bus->node);
+	pci_bus_release_busn_res(pci_bus);
 	up_write(&pci_bus_sem);
 	if (!pci_bus->is_added)
 		return;
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 18/36] PCI: insert busn_res in pci_create_root_bus
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (16 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 17/36] PCI: release busn when removing bus Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 19/36] PCI: checking busn_res in pci_scan_root_bus Yinghai Lu
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

that busn_res is from resources list

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ed82369..25a7ef8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1649,7 +1649,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 		list_move_tail(&window->list, &bridge->windows);
 		res = window->res;
 		offset = window->offset;
-		pci_bus_add_resource(b, res, 0);
+		if (res->flags & IORESOURCE_BUS)
+			pci_bus_insert_busn_res(b, res->start, res->end);
+		else
+			pci_bus_add_resource(b, res, 0);
 		if (offset) {
 			if (resource_type(res) == IORESOURCE_IO)
 				fmt = " (bus address [%#06llx-%#06llx])";
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 19/36] PCI: checking busn_res in pci_scan_root_bus
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (17 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 18/36] PCI: insert busn_res in pci_create_root_bus Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 20/36] PCI: default busn_resource Yinghai Lu
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

some calling may not have end decided yet, and may not pass busn_res in
resources list.

try to do insert big one and shrink.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 25a7ef8..6f3bdbc 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1735,12 +1735,34 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 	struct pci_bus *b;
+	struct pci_host_bridge_window *window, *n;
+	struct resource *res;
+	bool found;
+
+	list_for_each_entry_safe(window, n, resources, list) {
+		res = window->res;
+		if (res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+	}
 
 	b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
 	if (!b)
 		return NULL;
 
+	if (!found) {
+		dev_info(&b->dev,
+		 "No busn resource found for root bus, will use [%02x, ff]\n",
+			bus);
+		pci_bus_insert_busn_res(b, bus, 255);
+	}
+
 	b->subordinate = pci_scan_child_bus(b);
+
+	if (!found)
+		pci_bus_update_busn_res_end(b, b->subordinate);
+
 	pci_bus_add_devices(b);
 	return b;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 20/36] PCI: default busn_resource
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (18 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 19/36] PCI: checking busn_res in pci_scan_root_bus Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 21/36] PCI: add default res for pci_scan_bus Yinghai Lu
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

We need to put into the resources list

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |    7 +++++++
 include/linux/pci.h |    2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6f3bdbc..1149109 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,6 +15,13 @@
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
 
+struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
+
 /* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e494759..40606c1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -368,6 +368,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
 	return (pdev->error_state != pci_channel_io_normal);
 }
 
+extern struct resource busn_resource;
+
 struct pci_host_bridge_window {
 	struct list_head list;
 	struct resource *res;		/* host bridge aperture (CPU address) */
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 21/36] PCI: add default res for pci_scan_bus
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (19 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 20/36] PCI: default busn_resource Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 22/36] x86, PCI: add busn into resources list for acpi path Yinghai Lu
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1149109..1c07aba 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1784,6 +1784,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
 
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &iomem_resource);
+	pci_add_resource(&resources, &busn_resource);
 	b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
 	if (b)
 		b->subordinate = pci_scan_child_bus(b);
@@ -1801,6 +1802,7 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
 
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &iomem_resource);
+	pci_add_resource(&resources, &busn_resource);
 	b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
 	if (b) {
 		b->subordinate = pci_scan_child_bus(b);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 22/36] x86, PCI: add busn into resources list for acpi path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (20 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 21/36] PCI: add default res for pci_scan_bus Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 23/36] x86, PCI: put busn resource in pci_root_info for no_crs path Yinghai Lu
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

will put it in resources list and pass it for create_root_bus

Bjorn thought that we should just use that in acpi_root.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/acpi.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 2331ccb..5178917 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,6 @@ struct pci_root_info {
 	char name[16];
 	unsigned int res_num;
 	struct resource *res;
-	int busnum;
 	struct pci_sysdata sd;
 };
 
@@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 {
 	size_t size;
 
+	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
 	info->bridge = device;
+
 	info->res_num = 0;
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
 				info);
@@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 	if (!info->res)
 		return;
 
-	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
-
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 				info);
 }
@@ -430,9 +429,11 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 		 * _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) {
+                       /* insert busn res at first */
+			pci_add_resource(&resources,  &root->secondary);
 			add_resources(info, &resources);
-		else {
+		} else {
 			free_pci_root_info_res(info);
 			x86_pci_root_bus_resources(busnum, &resources);
 		}
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 23/36] x86, PCI: put busn resource in pci_root_info for no_crs path
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (21 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 22/36] x86, PCI: add busn into resources list for acpi path Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 24/36] PCI, ia64: Register busn_res for root buses Yinghai Lu
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

will put it in resources list and pass it for create_root_bus

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/amd_bus.c  |    1 -
 arch/x86/pci/bus_numa.c |   22 ++++++++++++++--------
 arch/x86/pci/bus_numa.h |    3 +--
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index aff155d..03397ea 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -116,7 +116,6 @@ static int __init early_fill_mp_bus_info(void)
 		link = (reg >> 8) & 0x03;
 
 		info = alloc_pci_root_info(min_bus, max_bus, node, link);
-		sprintf(info->name, "PCI Bus #%02x", min_bus);
 	}
 
 	/* get the default node and link for left over res */
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 772949f..b5b9d91 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
 		return NULL;
 
 	list_for_each_entry(info, &pci_root_infos, list)
-		if (info->bus_min == bus)
+		if (info->busn.start == bus)
 			return info;
 
 	return NULL;
@@ -31,6 +31,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
 	printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
 	       bus);
 
+	pci_add_resource(resources, &info->busn);
+
 	list_for_each_entry(root_res, &info->resources, list) {
 		struct resource *res;
 		struct resource *root;
@@ -54,6 +56,7 @@ default_resources:
 	printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
 	pci_add_resource(resources, &ioport_resource);
 	pci_add_resource(resources, &iomem_resource);
+	pci_add_resource(resources, &busn_resource);
 }
 
 struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
@@ -66,9 +69,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
 	if (!info)
 		return info;
 
+	sprintf(info->name, "PCI Bus #%02x", bus_min);
+
 	INIT_LIST_HEAD(&info->resources);
-	info->bus_min = bus_min;
-	info->bus_max = bus_max;
+	info->busn.name  = info->name;
+	info->busn.start = bus_min;
+	info->busn.end   = bus_max;
+	info->busn.flags = IORESOURCE_BUS;
 	info->node = node;
 	info->link = link;
 
@@ -80,14 +87,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
 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;
+	int busnum = info->busn.start;
 
 	if (!nodelink)
-		printk(KERN_DEBUG "%s: [%02x, %02x]\n", name,
-				info->bus_min, info->bus_max);
+		printk(KERN_DEBUG "%s: %pR\n", name, &info->busn);
 	else
-		printk(KERN_DEBUG "%s: [%02x, %02x] on node %x link %x\n", name,
-			info->bus_min, info->bus_max, info->node, info->link);
+		printk(KERN_DEBUG "%s: %pR on node %x link %x\n", name,
+			&info->busn, info->node, info->link);
 
 	list_for_each_entry(root_res, &info->resources, list)
 		printk(KERN_DEBUG "%s: %02x %pR\n", name, busnum,
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index deada6a..f9919c3 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -13,8 +13,7 @@ struct pci_root_info {
 	struct list_head list;
 	char name[12];
 	struct list_head resources;
-	int bus_min;
-	int bus_max;
+	struct resource busn;
 	int node;
 	int link;
 };
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 24/36] PCI, ia64: Register busn_res for root buses
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (22 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 23/36] x86, PCI: put busn resource in pci_root_info for no_crs path Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 25/36] PCI, sparc: " Yinghai Lu
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, Fenghua Yu, linux-ia64

-v2: according to Bjorn, use root->secondary directly.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64@vger.kernel.org
---
 arch/ia64/pci/pci.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index d1ce320..6c7c4ae 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -352,6 +352,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
 #endif
 
 	INIT_LIST_HEAD(&info.resources);
+	/* insert busn resource at first */
+	pci_add_resource(&info.resources, &root->secondary);
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
 			&windows);
 	if (windows) {
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 25/36] PCI, sparc: Register busn_res for root buses
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (23 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 24/36] PCI, ia64: Register busn_res for root buses Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 26/36] PCI, powerpc: " Yinghai Lu
                   ` (11 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, sparclinux

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
---
 arch/sparc/kernel/pci.c      |    4 ++++
 arch/sparc/kernel/pci_impl.h |    1 +
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 253e8ac..1687fed 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -695,6 +695,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
 				pbm->io_space.start);
 	pci_add_resource_offset(&resources, &pbm->mem_space,
 				pbm->mem_space.start);
+	pbm->busn.start = pbm->pci_first_busno;
+	pbm->busn.end	= pbm->pci_last_busn;
+	pbm->busn.flags	= IORESOURCE_BUS;
+	pci_add_resource(&resources, &pbm->busn);
 	bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
 				  pbm, &resources);
 	if (!bus) {
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 6beb60d..918a203 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -97,6 +97,7 @@ struct pci_pbm_info {
 	/* PBM I/O and Memory space resources. */
 	struct resource			io_space;
 	struct resource			mem_space;
+	struct resource			busn;
 
 	/* Base of PCI Config space, can be per-PBM or shared. */
 	unsigned long			config_space;
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 26/36] PCI, powerpc: Register busn_res for root buses
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (24 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 25/36] PCI, sparc: " Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 27/36] PCI, parisc: " Yinghai Lu
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, Paul Mackerras, linuxppc-dev

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
 arch/powerpc/include/asm/pci-bridge.h |    1 +
 arch/powerpc/kernel/pci-common.c      |   10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 5d48765..11cebf0 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -30,6 +30,7 @@ struct pci_controller {
 	int first_busno;
 	int last_busno;
 	int self_busno;
+	struct resource busn;
 
 	void __iomem *io_base_virt;
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 910b9de..ee8c0c9 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1648,6 +1648,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 	/* Wire up PHB bus resources */
 	pcibios_setup_phb_resources(hose, &resources);
 
+	hose->busn.start = hose->first_busno;
+	hose->busn.end	 = hose->last_busno;
+	hose->busn.flags = IORESOURCE_BUS;
+	pci_add_resource(&resources, &hose->busn);
+
 	/* Create an empty bus for the toplevel */
 	bus = pci_create_root_bus(hose->parent, hose->first_busno,
 				  hose->ops, hose, &resources);
@@ -1670,8 +1675,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 		of_scan_bus(node, bus);
 	}
 
-	if (mode == PCI_PROBE_NORMAL)
+	if (mode == PCI_PROBE_NORMAL) {
+		pci_bus_update_busn_res_end(bus, 255);
 		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+		pci_bus_update_busn_res_end(bus, bus->subordinate);
+	}
 
 	/* Platform gets a chance to do some global fixups before
 	 * we proceed to resource allocation
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 27/36] PCI, parisc: Register busn_res for root buses
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (25 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 26/36] PCI, powerpc: " Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, Kyle McMartin, Helge Deller, linux-parisc

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
---
 drivers/parisc/dino.c    |    5 +++++
 drivers/parisc/lba_pci.c |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 0610e91..def94af 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -984,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev)
 	if (dino_dev->hba.gmmio_space.flags)
 		pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
 
+	dino_dev->hba.bus_num.start = dino_current_bus;
+	dino_dev->hba.bus_num.end = 255;
+	dino_dev->hba.bus_num.flags |= IORESOURCE_BUS;
+	pci_add_resource(&resources, &dino_dev->hba.bus_num);
 	/*
 	** It's not used to avoid chicken/egg problems
 	** with configuration accessor functions.
@@ -999,6 +1003,7 @@ static int __init dino_probe(struct parisc_device *dev)
 		return 0;
 	}
 
+	pci_bus_update_busn_res_end(bus, bus->subordinate);
 	bus->subordinate = pci_scan_child_bus(bus);
 
 	/* This code *depends* on scanning being single threaded
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index e885764..df1e9f9 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1503,6 +1503,9 @@ lba_driver_probe(struct parisc_device *dev)
 	if (lba_dev->hba.gmmio_space.flags)
 		pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
 
+	lba_dev->hba.bus_num.flags |= IORESOURCE_BUS;
+	pci_add_resource(&resources, &lba_dev->hba.bus_num);
+
 	dev->dev.platform_data = lba_dev;
 	lba_bus = lba_dev->hba.hba_bus =
 		pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top()
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (26 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 27/36] PCI, parisc: " Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-16 19:36   ` Bjorn Helgaas
  2012-03-01  3:00 ` [PATCH 29/36] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
                   ` (8 subsequent siblings)
  36 siblings, 1 reply; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

extend or shrink bus and parent buses top (subordinate)

extended range is verified safe range, and stop at recorded parent_res.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1c07aba..96259f8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -655,6 +655,42 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 	}
 }
 
+static void __devinit pci_bus_update_top(struct pci_bus *parent,
+		 long size, struct resource *parent_res)
+{
+	struct resource *res;
+
+	if (!size)
+		return;
+
+	while (parent) {
+		res = &parent->busn_res;
+		if (res == parent_res)
+			break;
+		res->end += size;
+		parent->subordinate += size;
+		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS,
+					 parent->subordinate);
+		dev_printk(KERN_DEBUG, &parent->dev,
+				"busn_res: %s %02lx to %pR\n",
+				(size > 0) ? "extended" : "shrunk",
+				abs(size), res);
+		parent = parent->parent;
+	}
+}
+
+static void __devinit pci_bus_extend_top(struct pci_bus *parent,
+		 long size, struct resource *parent_res)
+{
+	pci_bus_update_top(parent, size, parent_res);
+}
+
+static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
+		 long size, struct resource *parent_res)
+{
+	pci_bus_update_top(parent, -size, parent_res);
+}
+
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 29/36] PCI: Probe safe range that we can use for unassigned bridge.
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (27 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 30/36] PCI: Strict checking of valid range for bridge Yinghai Lu
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Try to allocate from parent bus busn_res. if can not find any big enough, will try
to extend parent bus top. even the extending is through allocating, after allocating
will pad the range to parent buses top.

When extending happens, We will record the parent_res, so could use it as stopper
for really extend/shrink top later.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 96259f8..c540022 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -691,6 +691,116 @@ static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
 	pci_bus_update_top(parent, -size, parent_res);
 }
 
+static resource_size_t __devinit find_res_top_free_size(struct resource *res)
+{
+	resource_size_t n_size;
+	struct resource tmp_res;
+
+	/*
+	 *   find out number below res->end, that we can use at first
+	 *	res->start can not be used.
+	 */
+	n_size = resource_size(res) - 1;
+	memset(&tmp_res, 0, sizeof(struct resource));
+	while (n_size > 0) {
+		int ret;
+
+		ret = allocate_resource(res, &tmp_res, n_size,
+			res->end - n_size + 1, res->end,
+			1, NULL, NULL);
+		if (ret == 0) {
+			release_resource(&tmp_res);
+			break;
+		}
+		n_size--;
+	}
+
+	return n_size;
+}
+
+static int __devinit pci_bridge_probe_busn_res(struct pci_bus *bus,
+			 struct pci_dev *dev, struct resource *busn_res,
+			 resource_size_t needed_size, struct resource **p)
+{
+	int ret = -ENOMEM;
+	resource_size_t n_size;
+	struct pci_bus *parent;
+	struct resource *parent_res = NULL;
+	resource_size_t tmp = bus->busn_res.end + 1;
+	int free_sz = -1;
+
+again:
+	/*
+	 * find bigest range in bus->busn_res that we can use in the middle
+	 *  and we can not use bus->busn_res.start.
+	 */
+	n_size = resource_size(&bus->busn_res) - 1;
+	memset(busn_res, 0, sizeof(struct resource));
+	dev_printk(KERN_DEBUG, &dev->dev,
+			"find free busn in busn_res: %pR\n", &bus->busn_res);
+	while (n_size >= needed_size) {
+		ret = allocate_resource(&bus->busn_res, busn_res, n_size,
+				bus->busn_res.start + 1, bus->busn_res.end,
+				1, NULL, NULL);
+		if (ret == 0) {
+			/* found one, prepare to return */
+			release_resource(busn_res);
+
+			return ret;
+		}
+		n_size--;
+	}
+
+	/* try extend the top of parent bus, find free under top af first */
+	if (free_sz < 0) {
+		free_sz = find_res_top_free_size(&bus->busn_res);
+		dev_printk(KERN_DEBUG, &dev->dev,
+			"found free busn %d in busn_res: %pR top\n",
+				free_sz, &bus->busn_res);
+	}
+	n_size = free_sz;
+
+	/* can not extend cross domain boundary */
+	if ((0xff - bus->busn_res.end) < (needed_size - n_size))
+		goto reduce_needed_size;
+
+	/* find exteded range */
+	memset(busn_res, 0, sizeof(struct resource));
+	parent = bus->parent;
+	while (parent) {
+		ret = allocate_resource(&parent->busn_res, busn_res,
+			 needed_size - n_size,
+			 tmp, tmp + needed_size - n_size - 1,
+			 1, NULL, NULL);
+		if (ret == 0)
+			break;
+		parent = parent->parent;
+	}
+
+reduce_needed_size:
+	if (ret != 0) {
+		needed_size--;
+		if (!needed_size)
+			return ret;
+
+		goto again;
+	}
+
+	/* save parent_res, we need it as stopper later */
+	parent_res = busn_res->parent;
+
+	/* prepare busn_res for return */
+	release_resource(busn_res);
+	busn_res->start -= n_size;
+
+	/* extend parent bus top*/
+	pci_bus_extend_top(bus, needed_size - n_size, parent_res);
+
+	*p = parent_res;
+
+	return ret;
+}
+
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 30/36] PCI: Strict checking of valid range for bridge
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (28 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 29/36] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 31/36] PCI: Allocate bus range instead of use max blindly Yinghai Lu
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

children bridges busn range should be able to be allocated from parent bus range.

to avoid overlapping between sibling bridges on same bus.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c540022..5c031f0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -801,6 +801,30 @@ reduce_needed_size:
 	return ret;
 }
 
+static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
+				struct pci_dev *dev,
+				int secondary, int subordinate)
+{
+	int broken = 0;
+
+	struct resource busn_res;
+	int ret;
+
+	memset(&busn_res, 0, sizeof(struct resource));
+	dev_printk(KERN_DEBUG, &dev->dev,
+		 "check if busn %02x-%02x is in busn_res: %pR\n",
+		 secondary, subordinate, &bus->busn_res);
+	ret = allocate_resource(&bus->busn_res, &busn_res,
+			 (subordinate - secondary + 1),
+			 secondary, subordinate,
+			 1, NULL, NULL);
+	if (ret)
+		broken = 1;
+	else
+		release_resource(&busn_res);
+
+	return broken;
+}
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 31/36] PCI: Allocate bus range instead of use max blindly
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (29 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 30/36] PCI: Strict checking of valid range for bridge Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 32/36] PCI: kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

every bus have extra busn_res, and linked them toghter to iobusn_resource.

when need to find usable bus number range, try probe from iobusn_resource tree.

To avoid falling to small hole in the middle, we try from 8 spare bus.
if can not find 8 or more in the middle, will try to append 8 on top later.
then if can not append, will try to find 7 from the middle, then will try to append 7 on top.
then if can not append, will try to find 6 from the middle...

for cardbus will only find 4 spare.

if extend from top, at last will shrink back to really needed range...

-v4: fix checking with pci rescan. Found by Bjorn.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |  100 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 59 insertions(+), 41 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5c031f0..f22a209 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -839,10 +839,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 {
 	struct pci_bus *child;
 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
-	u32 buses, i, j = 0;
+	u32 buses;
 	u16 bctl;
 	u8 primary, secondary, subordinate;
 	int broken = 0;
+	struct resource *parent_res = NULL;
 
 	pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
 	primary = buses & 0xFF;
@@ -859,10 +860,16 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 
 	/* Check if setup is sensible at all */
 	if (!pass &&
-	    (primary != bus->number || secondary <= bus->number)) {
-		dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
+	    (primary != bus->number || secondary <= bus->number))
 		broken = 1;
-	}
+
+	/* more strict checking */
+	if (!pass && !broken && !dev->subordinate)
+		broken = pci_bridge_check_busn_broken(bus, dev,
+						   secondary, subordinate);
+
+	if (broken)
+		dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
 
 	/* Disable MasterAbortMode during probing to avoid reporting
 	   of bus errors (in some architectures) */ 
@@ -895,6 +902,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			child->primary = primary;
 			child->subordinate = subordinate;
 			child->bridge_ctl = bctl;
+
+			pci_bus_insert_busn_res(child, secondary, subordinate);
 		}
 
 		cmax = pci_scan_child_bus(child);
@@ -907,6 +916,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		 * We need to assign a number to this bus which we always
 		 * do in the second pass.
 		 */
+		long shrink_size;
+		struct resource busn_res;
+		int ret = -ENOMEM;
+		int old_max = max;
+
 		if (!pass) {
 			if (pcibios_assign_all_busses() || broken)
 				/* Temporarily disable forwarding of the
@@ -923,20 +937,43 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		/* Clear errors */
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-		/* Prevent assigning a bus number that already exists.
-		 * This can happen when a bridge is hot-plugged, so in
-		 * this case we only re-scan this bus. */
-		child = pci_find_bus(pci_domain_nr(bus), max+1);
-		if (!child) {
-			child = pci_add_new_bus(bus, dev, ++max);
-			if (!child)
-				goto out;
+		if (dev->subordinate) {
+			/* We get here only for cardbus */
+			child = dev->subordinate;
+			if  (!is_cardbus)
+				dev_warn(&dev->dev,
+				 "rescan scaned bridge as broken one again ?");
+
+			goto out;
 		}
+		/*
+		 * For CardBus bridges, we leave 4 bus numbers
+		 * as cards with a PCI-to-PCI bridge can be
+		 * inserted later.
+		 * other just allocate 8 bus to avoid we fall into
+		 *  small hole in the middle.
+		 */
+		ret = pci_bridge_probe_busn_res(bus, dev, &busn_res,
+				is_cardbus ? (CARDBUS_RESERVE_BUSNR + 1) : 8,
+				&parent_res);
+
+		if (ret != 0)
+			goto out;
+
+		child = pci_add_new_bus(bus, dev, busn_res.start);
+		if (!child)
+			goto out;
+
+		child->subordinate = busn_res.end;
+		pci_bus_insert_busn_res(child, busn_res.start, busn_res.end);
+
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
 		      | ((unsigned int)(child->subordinate) << 16);
 
+		max = child->subordinate;
+
 		/*
 		 * yenta.c forces a secondary latency timer of 176.
 		 * Copy that behaviour here.
@@ -967,43 +1004,24 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			 * the real value of max.
 			 */
 			pci_fixup_parent_subordinate_busnr(child, max);
+
 		} else {
-			/*
-			 * For CardBus bridges, we leave 4 bus numbers
-			 * as cards with a PCI-to-PCI bridge can be
-			 * inserted later.
-			 */
-			for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) {
-				struct pci_bus *parent = bus;
-				if (pci_find_bus(pci_domain_nr(bus),
-							max+i+1))
-					break;
-				while (parent->parent) {
-					if ((!pcibios_assign_all_busses()) &&
-					    (parent->subordinate > max) &&
-					    (parent->subordinate <= max+i)) {
-						j = 1;
-					}
-					parent = parent->parent;
-				}
-				if (j) {
-					/*
-					 * Often, there are two cardbus bridges
-					 * -- try to leave one valid bus number
-					 * for each one.
-					 */
-					i /= 2;
-					break;
-				}
-			}
-			max += i;
 			pci_fixup_parent_subordinate_busnr(child, max);
 		}
 		/*
 		 * Set the subordinate bus number to its real value.
 		 */
+		shrink_size = child->subordinate - max;
 		child->subordinate = max;
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+		pci_bus_update_busn_res_end(child, max);
+
+		/* shrink some back, if we extend top before */
+		if (!is_cardbus && (shrink_size > 0) && parent_res)
+			pci_bus_shrink_top(bus, shrink_size, parent_res);
+
+		if (old_max > max)
+			max = old_max;
 	}
 
 	sprintf(child->name,
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 32/36] PCI: kill pci_fixup_parent_subordinate_busnr()
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (30 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 31/36] PCI: Allocate bus range instead of use max blindly Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 33/36] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Now we can safely extend parent top and shrink them according iobusn_resource tree.

Don't need that any more.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   32 --------------------------------
 1 files changed, 0 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f22a209..ba51902 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -639,22 +639,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
 	return child;
 }
 
-static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
-{
-	struct pci_bus *parent = child->parent;
-
-	/* Attempts to fix that up are really dangerous unless
-	   we're going to re-assign all bus numbers. */
-	if (!pcibios_assign_all_busses())
-		return;
-
-	while (parent->parent && parent->subordinate < max) {
-		parent->subordinate = max;
-		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
-		parent = parent->parent;
-	}
-}
-
 static void __devinit pci_bus_update_top(struct pci_bus *parent,
 		 long size, struct resource *parent_res)
 {
@@ -990,23 +974,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 
 		if (!is_cardbus) {
 			child->bridge_ctl = bctl;
-			/*
-			 * Adjust subordinate busnr in parent buses.
-			 * We do this before scanning for children because
-			 * some devices may not be detected if the bios
-			 * was lazy.
-			 */
-			pci_fixup_parent_subordinate_busnr(child, max);
-			/* Now we can scan all subordinate buses... */
 			max = pci_scan_child_bus(child);
-			/*
-			 * now fix it up again since we have found
-			 * the real value of max.
-			 */
-			pci_fixup_parent_subordinate_busnr(child, max);
-
-		} else {
-			pci_fixup_parent_subordinate_busnr(child, max);
 		}
 		/*
 		 * Set the subordinate bus number to its real value.
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 33/36] PCI: Seperate child bus scanning to two passes overall
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (31 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 32/36] PCI: kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 34/36] pcmcia: remove workaround for fixing pci parent bus subordinate Yinghai Lu
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

In extreme case: Two bridges are properly setup.
       bridge A
               bridge AA
               bridge AB
       bridge B
	       bridge BA
	       bridge BB
   but AA, AB are not setup properly.
   bridge A has small range, and bridge AB could need more, when do the
       first pass0 for bridge A, it will do pass0 and pass1 for AA and AB,
	during that process, it will extend range of A for AB blindly.
	because bridge B is not registered yet.
       that could overlap range that is used by bridge B.

Right way should be:
       do pass0 for all good bridges at first.
So we could do pass0 for bridge B before pass1 for bridge AB.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   50 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ba51902..4a38ef4 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -809,6 +809,9 @@ static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
 
 	return broken;
 }
+
+static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
+						 int pass);
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -865,11 +868,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 	    !is_cardbus && !broken) {
 		unsigned int cmax;
 		/*
-		 * Bus already configured by firmware, process it in the first
-		 * pass and just note the configuration.
+		 * Bus already configured by firmware, still process it in two
+		 * passes in extreme case like two adjaced bridges have children
+		 * bridges that are not setup properly.
 		 */
-		if (pass)
-			goto out;
 
 		/*
 		 * If we already got to this bus through a different bridge,
@@ -890,7 +892,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			pci_bus_insert_busn_res(child, secondary, subordinate);
 		}
 
-		cmax = pci_scan_child_bus(child);
+		cmax = __pci_scan_child_bus(child, pass);
 		if (cmax > max)
 			max = cmax;
 		if (child->subordinate > max)
@@ -1704,12 +1706,13 @@ void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
 }
 EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
+						 int pass)
 {
-	unsigned int devfn, pass, max = bus->secondary;
+	unsigned int devfn, max = bus->secondary;
 	struct pci_dev *dev;
 
-	dev_dbg(&bus->dev, "scanning bus\n");
+	dev_dbg(&bus->dev, "scanning bus pass %d\n", pass);
 
 	/* Go find them, Rover! */
 	for (devfn = 0; devfn < 0x100; devfn += 8)
@@ -1723,18 +1726,16 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 	 * all PCI-to-PCI bridges on this bus.
 	 */
 	if (!bus->is_added) {
-		dev_dbg(&bus->dev, "fixups for bus\n");
+		dev_dbg(&bus->dev, "fixups for bus pass %d\n", pass);
 		pcibios_fixup_bus(bus);
 		if (pci_is_root_bus(bus))
 			bus->is_added = 1;
 	}
 
-	for (pass=0; pass < 2; pass++)
-		list_for_each_entry(dev, &bus->devices, bus_list) {
-			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
-			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-				max = pci_scan_bridge(bus, dev, max, pass);
-		}
+	list_for_each_entry(dev, &bus->devices, bus_list)
+		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+			max = pci_scan_bridge(bus, dev, max, pass);
 
 	/*
 	 * We've scanned the bus and so we know all about what's on
@@ -1743,7 +1744,24 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 	 *
 	 * Return how far we've got finding sub-buses.
 	 */
-	dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
+	dev_dbg(&bus->dev, "bus scan returning with max=%02x pass %d\n",
+			max, pass);
+
+	return max;
+}
+
+unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+{
+	int pass;
+	unsigned int max = 0, tmp;
+
+	for (pass = 0; pass < 2;  pass++) {
+		tmp = __pci_scan_child_bus(bus, pass);
+
+		if (tmp > max)
+			max = tmp;
+	}
+
 	return max;
 }
 
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 34/36] pcmcia: remove workaround for fixing pci parent bus subordinate
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (32 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 33/36] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 35/36] PCI: Double checking setting for bus register and bus struct Yinghai Lu
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu, Rusty Russell, Mauro Carvalho Chehab,
	linux-pcmcia

Now pci busn allocation code is there, and it will preallocate bus number and it
will make sure parent buses subordinate is right.

So remove workaround here.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Tested-by: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: linux-pcmcia@lists.infradead.org
---
 drivers/pcmcia/yenta_socket.c |   75 -----------------------------------------
 1 files changed, 0 insertions(+), 75 deletions(-)

diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 849c0c1..5757cae 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1064,79 +1064,6 @@ static void yenta_config_init(struct yenta_socket *socket)
 	config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 }
 
-/**
- * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge
- * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to
- *
- * Checks if devices on the bus which the CardBus bridge bridges to would be
- * invisible during PCI scans because of a misconfigured subordinate number
- * of the parent brige - some BIOSes seem to be too lazy to set it right.
- * Does the fixup carefully by checking how far it can go without conflicts.
- * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information.
- */
-static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
-{
-	struct list_head *tmp;
-	unsigned char upper_limit;
-	/*
-	 * We only check and fix the parent bridge: All systems which need
-	 * this fixup that have been reviewed are laptops and the only bridge
-	 * which needed fixing was the parent bridge of the CardBus bridge:
-	 */
-	struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
-
-	/* Check bus numbers are already set up correctly: */
-	if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
-		return; /* The subordinate number is ok, nothing to do */
-
-	if (!bridge_to_fix->parent)
-		return; /* Root bridges are ok */
-
-	/* stay within the limits of the bus range of the parent: */
-	upper_limit = bridge_to_fix->parent->subordinate;
-
-	/* check the bus ranges of all silbling bridges to prevent overlap */
-	list_for_each(tmp, &bridge_to_fix->parent->children) {
-		struct pci_bus *silbling = pci_bus_b(tmp);
-		/*
-		 * If the silbling has a higher secondary bus number
-		 * and it's secondary is equal or smaller than our
-		 * current upper limit, set the new upper limit to
-		 * the bus number below the silbling's range:
-		 */
-		if (silbling->secondary > bridge_to_fix->subordinate
-		    && silbling->secondary <= upper_limit)
-			upper_limit = silbling->secondary - 1;
-	}
-
-	/* Show that the wanted subordinate number is not possible: */
-	if (cardbus_bridge->subordinate > upper_limit)
-		dev_printk(KERN_WARNING, &cardbus_bridge->dev,
-			   "Upper limit for fixing this "
-			   "bridge's parent bridge: #%02x\n", upper_limit);
-
-	/* If we have room to increase the bridge's subordinate number, */
-	if (bridge_to_fix->subordinate < upper_limit) {
-
-		/* use the highest number of the hidden bus, within limits */
-		unsigned char subordinate_to_assign =
-			min(cardbus_bridge->subordinate, upper_limit);
-
-		dev_printk(KERN_INFO, &bridge_to_fix->dev,
-			   "Raising subordinate bus# of parent "
-			   "bus (#%02x) from #%02x to #%02x\n",
-			   bridge_to_fix->number,
-			   bridge_to_fix->subordinate, subordinate_to_assign);
-
-		/* Save the new subordinate in the bus struct of the bridge */
-		bridge_to_fix->subordinate = subordinate_to_assign;
-
-		/* and update the PCI config space with the new subordinate */
-		pci_write_config_byte(bridge_to_fix->self,
-			PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
-	}
-}
-
 /*
  * Initialize a cardbus controller. Make sure we have a usable
  * interrupt, and that we can map the cardbus area. Fill in the
@@ -1257,8 +1184,6 @@ static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id
 	dev_printk(KERN_INFO, &dev->dev,
 		   "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 
-	yenta_fixup_parent_bridge(dev->subordinate);
-
 	/* Register it with the pcmcia layer.. */
 	ret = pcmcia_register_socket(&socket->socket);
 	if (ret == 0) {
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 35/36] PCI: Double checking setting for bus register and bus struct.
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (33 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 34/36] pcmcia: remove workaround for fixing pci parent bus subordinate Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-01  3:00 ` [PATCH 36/36] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
  2012-03-15  6:40 ` [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Taku Izumi
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

User could use setpci change bridge's bus register. that could make value of register
and struct is out of sync.
User later will use rescan to see the devices is moving.

In the rescaning, we need to double check the range and remove the old struct at first.

to make thing working user may need have script to remove children devices under bridge
at first, and then use setpci update bus register and then rescan.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |   40 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 4a38ef4..67071b0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -850,6 +850,46 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 	    (primary != bus->number || secondary <= bus->number))
 		broken = 1;
 
+	if (!pass && dev->subordinate) {
+		child = dev->subordinate;
+		/*
+		 * User could change bus register in bridge manually with
+		 * setpci and rescan. So double check the setting, and remove
+		 * old structs.  Don't set broken yet, let following check
+		 * to see if the new setting good.
+		 */
+		if (primary != child->primary ||
+		    secondary != child->secondary ||
+		    subordinate != child->subordinate) {
+			dev_info(&dev->dev,
+				"someone changed bus register from pri:%02x, sec:%02x, sub:%02x to pri:%02x, sec:%02x, sub:%02x\n",
+				child->primary, child->secondary, child->subordinate,
+				primary, secondary, subordinate);
+			if (!list_empty(&dev->subordinate->devices)) {
+				u32 old_buses;
+
+				dev_info(&dev->dev,
+				 "but children devices are not removed manually before that.\n");
+				/*
+				 * Try best to remove left children devices
+				 * but we need to set bus register back, otherwise
+				 * We can not access children device and stop them
+				 */
+				old_buses = (buses & 0xff000000)
+				   | ((unsigned int)(child->primary)     <<  0)
+				   | ((unsigned int)(child->secondary)   <<  8)
+				   | ((unsigned int)(child->subordinate) << 16);
+				pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+							 old_buses);
+				pci_stop_and_remove_behind_bridge(dev);
+				pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+							 buses);
+			}
+			pci_remove_bus(dev->subordinate);
+			dev->subordinate = NULL;
+		}
+	}
+
 	/* more strict checking */
 	if (!pass && !broken && !dev->subordinate)
 		broken = pci_bridge_check_busn_broken(bus, dev,
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 36/36] PCI, pciehp: Remove not needed bus number range checking
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (34 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 35/36] PCI: Double checking setting for bus register and bus struct Yinghai Lu
@ 2012-03-01  3:00 ` Yinghai Lu
  2012-03-15  6:40 ` [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Taku Izumi
  36 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-01  3:00 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86
  Cc: Bjorn Helgaas, Dominik Brodowski, linux-pci, linux-kernel,
	linux-arch, Yinghai Lu

Found hotplug adding one EM with bridge fail, bios only leave one bus range
 for slot.

[ 1169.621444] pciehp: No bus number available for hot-added bridge 0000:55:00.0
[ 1169.633277] pcieport 0000:40:03.0: PCI bridge to [bus 55-55]

With busn_res tracking and allocating, we don't need that checking anymore.

Parent bridges' bus number will be extended safely.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/hotplug/pciehp_pci.c |   12 +-----------
 1 files changed, 1 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 47d9dc0..e21171c 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -37,18 +37,8 @@
 static int __ref pciehp_add_bridge(struct pci_dev *dev)
 {
 	struct pci_bus *parent = dev->bus;
-	int pass, busnr, start = parent->secondary;
-	int end = parent->subordinate;
+	int pass, busnr = parent->secondary;
 
-	for (busnr = start; busnr <= end; busnr++) {
-		if (!pci_find_bus(pci_domain_nr(parent), busnr))
-			break;
-	}
-	if (busnr-- > end) {
-		err("No bus number available for hot-added bridge %s\n",
-				pci_name(dev));
-		return -1;
-	}
 	for (pass = 0; pass < 2; pass++)
 		busnr = pci_scan_bridge(parent, dev, busnr, pass);
 	if (!dev->subordinate)
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* RE: [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc
  2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
                   ` (35 preceding siblings ...)
  2012-03-01  3:00 ` [PATCH 36/36] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
@ 2012-03-15  6:40 ` Taku Izumi
  2012-03-15 17:40   ` Yinghai Lu
  36 siblings, 1 reply; 44+ messages in thread
From: Taku Izumi @ 2012-03-15  6:40 UTC (permalink / raw)
  To: 'Yinghai Lu'; +Cc: linux-pci

> 
> The first 13 patches are hostbridge clean up.
> will add struct device dev into host_bridge struct.
> also will add release support to make sure allocated resource get
> freed during root bus removal including hostbridge and pci_sysdata.
> 
> others 23 patches are busn_alloc related.
> Set up iobusn_resource tree, and register bus number range to it.
> Later when need to find bus range, will try to allocate from the tree
> Need to test on arches other than x86. esp for ia64 and powerpc that support
>   more than on peer root buses.
> 
> The patches need to apply to pci/for-linus and pci/linux-next
> because one patch that is needed only is only in pci/for-linus

 I can't apply your patchset to pci/linux-next.
 I reckon your patchset needs refresh, or did I do something wrong?

 My impression is you should split your patchset between hostbridge part and
 bus-allocation part.

 Taku Izumi

> 
> could get from
>         git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-next
> 
> please put them into pci/linux-next branch for more testing.
> 
> -v2: dropped the patch that is with x86 pcibios_bus_to_resource that Bjorn objected.
>      reorder the patchesset to mold one appended patch into previous patch.
> 
> Thanks
> 
> Yinghai
> 
> Yinghai Lu (36):
>   PCI: Separate host_bridge code out from probe.c
>   x86, PCI: Fix memleak with get_current_resources
>   PCI: rename pci_host_bridge() to find_pci_root_bridge()
>   PCI: add generic device into pci_host_bridge struct
>   PCI: add host bridge release support
>   x86, PCI: break down get_current_resource()
>   x86, PCI: add host bridge resource release for using _CRS
>   x86, PCI: embed name acpi version pci_root_info struct
>   x86, PCI: embed pci_sysdata into pci_root_info on acpi path
>   x86, PCI: Allocating pci_root_info for not using _CRS path
>   x86, PCI: Merge root info printing for nocrs path
>   x86, PCI: add print all root info for nocrs path
>   x86, PCI: allocate temp range array in amd_bus pci_root_info probing
>   x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node
>   PCI: Add busn_res into struct pci_bus.
>   PCI: Add busn_res operation functions
>   PCI: release busn when removing bus
>   PCI: insert busn_res in pci_create_root_bus
>   PCI: checking busn_res in pci_scan_root_bus
>   PCI: default busn_resource
>   PCI: add default res for pci_scan_bus
>   x86, PCI: add busn into resources list for acpi path
>   x86, PCI: put busn resource in pci_root_info for no_crs path
>   PCI, ia64: Register busn_res for root buses
>   PCI, sparc: Register busn_res for root buses
>   PCI, powerpc: Register busn_res for root buses
>   PCI, parisc: Register busn_res for root buses
>   PCI: Add pci_bus_extend/shrink_top()
>   PCI: Probe safe range that we can use for unassigned bridge.
>   PCI: Strict checking of valid range for bridge
>   PCI: Allocate bus range instead of use max blindly
>   PCI: kill pci_fixup_parent_subordinate_busnr()
>   PCI: Seperate child bus scanning to two passes overall
>   pcmcia: remove workaround for fixing pci parent bus subordinate
>   PCI: Double checking setting for bus register and bus struct.
>   PCI, pciehp: Remove not needed bus number range checking
> 
>  arch/ia64/pci/pci.c                   |    2 +
>  arch/powerpc/include/asm/pci-bridge.h |    1 +
>  arch/powerpc/kernel/pci-common.c      |   10 +-
>  arch/sparc/kernel/pci.c               |    4 +
>  arch/sparc/kernel/pci_impl.h          |    1 +
>  arch/x86/pci/acpi.c                   |  121 ++++---
>  arch/x86/pci/amd_bus.c                |   88 ++----
>  arch/x86/pci/broadcom_bus.c           |   17 +-
>  arch/x86/pci/bus_numa.c               |  100 +++++--
>  arch/x86/pci/bus_numa.h               |   23 +-
>  arch/x86/pci/common.c                 |   27 +--
>  drivers/parisc/dino.c                 |    5 +
>  drivers/parisc/lba_pci.c              |    3 +
>  drivers/pci/Makefile                  |    2 +-
>  drivers/pci/host-bridge.c             |   96 ++++++
>  drivers/pci/hotplug/pciehp_pci.c      |   12 +-
>  drivers/pci/probe.c                   |  601 ++++++++++++++++++++++-----------
>  drivers/pci/remove.c                  |    1 +
>  drivers/pcmcia/yenta_socket.c         |   75 ----
>  include/linux/pci.h                   |   15 +-
>  20 files changed, 752 insertions(+), 452 deletions(-)
>  create mode 100644 drivers/pci/host-bridge.c
> 
> --
> 1.7.7
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



^ permalink raw reply	[flat|nested] 44+ messages in thread

* RE: [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources
  2012-03-01  3:00 ` [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
@ 2012-03-15  8:39   ` Taku Izumi
  2012-03-15 17:44     ` Yinghai Lu
  0 siblings, 1 reply; 44+ messages in thread
From: Taku Izumi @ 2012-03-15  8:39 UTC (permalink / raw)
  To: 'Yinghai Lu'; +Cc: linux-pci



> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-owner@vger.kernel.org] On Behalf Of Yinghai Lu
> Sent: Thursday, March 01, 2012 12:00 PM
> To: Jesse Barnes; Benjamin Herrenschmidt; Tony Luck; David Miller; x86
> Cc: Bjorn Helgaas; Dominik Brodowski; linux-pci@vger.kernel.org; linux-kernel@vger.kernel.org;
> linux-arch@vger.kernel.org; Yinghai Lu
> Subject: [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources
> 
> 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));
> +}
> +

  This function leads to misunderstanding.
  I'm convinced that the function of the name starts with "free" 
  should free resources completely.


>  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
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc
  2012-03-15  6:40 ` [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Taku Izumi
@ 2012-03-15 17:40   ` Yinghai Lu
  0 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-15 17:40 UTC (permalink / raw)
  To: Taku Izumi; +Cc: linux-pci

>> The patches need to apply to pci/for-linus and pci/linux-next
>> because one patch that is needed only is only in pci/for-linus
>
>  I can't apply your patchset to pci/linux-next.
>  I reckon your patchset needs refresh, or did I do something wrong?

pci/linux-next missed one patch that is already in linus tree.

>
>  My impression is you should split your patchset between hostbridge part and
>  bus-allocation part.

After Jesse rebase pci/linux-next today or tomorrow.  Because he need
to update some patches from Bjorn.

I will split them and rebase them
1. hostbridge clean up
2. busn_res alloc.
3. root bus hotplug related
4. more hotplug clean up.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources
  2012-03-15  8:39   ` Taku Izumi
@ 2012-03-15 17:44     ` Yinghai Lu
  0 siblings, 0 replies; 44+ messages in thread
From: Yinghai Lu @ 2012-03-15 17:44 UTC (permalink / raw)
  To: Taku Izumi; +Cc: linux-pci

On Thu, Mar 15, 2012 at 1:39 AM, Taku Izumi <izumi.taku@jp.fujitsu.com> wrote:
>
>
>> -----Original Message-----
>> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-owner@vger.kernel.org] On Behalf Of Yinghai Lu
>> Sent: Thursday, March 01, 2012 12:00 PM
>> To: Jesse Barnes; Benjamin Herrenschmidt; Tony Luck; David Miller; x86
>> Cc: Bjorn Helgaas; Dominik Brodowski; linux-pci@vger.kernel.org; linux-kernel@vger.kernel.org;
>> linux-arch@vger.kernel.org; Yinghai Lu
>> Subject: [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources
>>
>> 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));
>> +}
>> +
>
>  This function leads to misunderstanding.
>  I'm convinced that the function of the name starts with "free"
>  should free resources completely.

after patchset it will become:

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);
}

Is that still confusing?

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top()
  2012-03-01  3:00 ` [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
@ 2012-03-16 19:36   ` Bjorn Helgaas
  2012-03-16 20:42     ` Yinghai Lu
  0 siblings, 1 reply; 44+ messages in thread
From: Bjorn Helgaas @ 2012-03-16 19:36 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, linux-pci, linux-kernel, linux-arch

On Wed, Feb 29, 2012 at 8:00 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> extend or shrink bus and parent buses top (subordinate)
>
> extended range is verified safe range, and stop at recorded parent_res.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> ---
>  drivers/pci/probe.c |   36 ++++++++++++++++++++++++++++++++++++
>  1 files changed, 36 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 1c07aba..96259f8 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -655,6 +655,42 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
>        }
>  }
>
> +static void __devinit pci_bus_update_top(struct pci_bus *parent,
> +                long size, struct resource *parent_res)
> +{
> +       struct resource *res;
> +
> +       if (!size)
> +               return;
> +
> +       while (parent) {
> +               res = &parent->busn_res;
> +               if (res == parent_res)
> +                       break;
> +               res->end += size;

I've objected to this before on the grounds that it's not safe to
update res->end because res is already linked into the resource tree,
but I just noticed another problem.

Tree updates are protected by resource_lock, but we don't hold that
here.  I'm sure you "know" that this update can't race with any other
conflicting resource operations, but its safety certainly is not
obvious from the patch.

I think a better implementation would be to add something like
"resource_extend()" that could live in kernel/resource.c so it could
do the appropriate locking and checking.  Such an interface could also
be independent of the resource type, which may be useful when doing
mem/io resource reassignment.

This patch is already in Jesse's linux-next branch (commit
c901d4c0407), so I'm leaving it up to you and Jesse to figure out
what, if anything, to do about this.

Bjorn

> +               parent->subordinate += size;
> +               pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS,
> +                                        parent->subordinate);
> +               dev_printk(KERN_DEBUG, &parent->dev,
> +                               "busn_res: %s %02lx to %pR\n",
> +                               (size > 0) ? "extended" : "shrunk",
> +                               abs(size), res);
> +               parent = parent->parent;
> +       }
> +}
> +
> +static void __devinit pci_bus_extend_top(struct pci_bus *parent,
> +                long size, struct resource *parent_res)
> +{
> +       pci_bus_update_top(parent, size, parent_res);
> +}
> +
> +static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
> +                long size, struct resource *parent_res)
> +{
> +       pci_bus_update_top(parent, -size, parent_res);
> +}
> +
>  /*
>  * If it's a bridge, configure it and scan the bus behind it.
>  * For CardBus bridges, we don't scan behind as the devices will
> --
> 1.7.7
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top()
  2012-03-16 19:36   ` Bjorn Helgaas
@ 2012-03-16 20:42     ` Yinghai Lu
  2012-03-16 21:04       ` Bjorn Helgaas
  0 siblings, 1 reply; 44+ messages in thread
From: Yinghai Lu @ 2012-03-16 20:42 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, linux-pci, linux-kernel, linux-arch

On Fri, Mar 16, 2012 at 12:36 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> I've objected to this before on the grounds that it's not safe to
> update res->end because res is already linked into the resource tree,
> but I just noticed another problem.
>
> Tree updates are protected by resource_lock, but we don't hold that
> here.  I'm sure you "know" that this update can't race with any other
> conflicting resource operations, but its safety certainly is not
> obvious from the patch.
>
> I think a better implementation would be to add something like
> "resource_extend()" that could live in kernel/resource.c so it could
> do the appropriate locking and checking.  Such an interface could also
> be independent of the resource type, which may be useful when doing
> mem/io resource reassignment.

Thanks for point it out.

Let me thinking about it.

>
> This patch is already in Jesse's linux-next branch (commit
> c901d4c0407), so I'm leaving it up to you and Jesse to figure out
> what, if anything, to do about this.

No, this patch is one in busn_alloc patchset. Jesse did NOT pick that
patchset yet.

Yinghai

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top()
  2012-03-16 20:42     ` Yinghai Lu
@ 2012-03-16 21:04       ` Bjorn Helgaas
  0 siblings, 0 replies; 44+ messages in thread
From: Bjorn Helgaas @ 2012-03-16 21:04 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, linux-pci, linux-kernel, linux-arch

On Fri, Mar 16, 2012 at 2:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Fri, Mar 16, 2012 at 12:36 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> I've objected to this before on the grounds that it's not safe to
>> update res->end because res is already linked into the resource tree,
>> but I just noticed another problem.
>>
>> Tree updates are protected by resource_lock, but we don't hold that
>> here.  I'm sure you "know" that this update can't race with any other
>> conflicting resource operations, but its safety certainly is not
>> obvious from the patch.
>>
>> I think a better implementation would be to add something like
>> "resource_extend()" that could live in kernel/resource.c so it could
>> do the appropriate locking and checking.  Such an interface could also
>> be independent of the resource type, which may be useful when doing
>> mem/io resource reassignment.
>
> Thanks for point it out.
>
> Let me thinking about it.
>
>>
>> This patch is already in Jesse's linux-next branch (commit
>> c901d4c0407), so I'm leaving it up to you and Jesse to figure out
>> what, if anything, to do about this.
>
> No, this patch is one in busn_alloc patchset. Jesse did NOT pick that
> patchset yet.

Ah, right you are.  I guess I still had your for-pci-root-bus-hotplug
branch checked out when this occurred to me.  Sorry for the confusion.

Bjorn

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2012-03-16 21:04 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-01  3:00 [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Yinghai Lu
2012-03-01  3:00 ` [PATCH 01/36] PCI: Separate host_bridge code out from probe.c Yinghai Lu
2012-03-01  3:00 ` [PATCH 02/36] x86, PCI: Fix memleak with get_current_resources Yinghai Lu
2012-03-15  8:39   ` Taku Izumi
2012-03-15 17:44     ` Yinghai Lu
2012-03-01  3:00 ` [PATCH 03/36] PCI: rename pci_host_bridge() to find_pci_root_bridge() Yinghai Lu
2012-03-01  3:00 ` [PATCH 04/36] PCI: add generic device into pci_host_bridge struct Yinghai Lu
2012-03-01  3:00 ` [PATCH 05/36] PCI: add host bridge release support Yinghai Lu
2012-03-01  3:00 ` [PATCH 06/36] x86, PCI: break down get_current_resource() Yinghai Lu
2012-03-01  3:00 ` [PATCH 07/36] x86, PCI: add host bridge resource release for using _CRS Yinghai Lu
2012-03-01  3:00 ` [PATCH 08/36] x86, PCI: embed name acpi version pci_root_info struct Yinghai Lu
2012-03-01  3:00 ` [PATCH 09/36] x86, PCI: embed pci_sysdata into pci_root_info on acpi path Yinghai Lu
2012-03-01  3:00 ` [PATCH 10/36] x86, PCI: Allocating pci_root_info for not using _CRS path Yinghai Lu
2012-03-01  3:00 ` [PATCH 11/36] x86, PCI: Merge root info printing for nocrs path Yinghai Lu
2012-03-01  3:00 ` [PATCH 12/36] x86, PCI: add print all root info " Yinghai Lu
2012-03-01  3:00 ` [PATCH 13/36] x86, PCI: allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
2012-03-01  3:00 ` [PATCH 14/36] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
2012-03-01  3:00 ` [PATCH 15/36] PCI: Add busn_res into struct pci_bus Yinghai Lu
2012-03-01  3:00 ` [PATCH 16/36] PCI: Add busn_res operation functions Yinghai Lu
2012-03-01  3:00 ` [PATCH 17/36] PCI: release busn when removing bus Yinghai Lu
2012-03-01  3:00 ` [PATCH 18/36] PCI: insert busn_res in pci_create_root_bus Yinghai Lu
2012-03-01  3:00 ` [PATCH 19/36] PCI: checking busn_res in pci_scan_root_bus Yinghai Lu
2012-03-01  3:00 ` [PATCH 20/36] PCI: default busn_resource Yinghai Lu
2012-03-01  3:00 ` [PATCH 21/36] PCI: add default res for pci_scan_bus Yinghai Lu
2012-03-01  3:00 ` [PATCH 22/36] x86, PCI: add busn into resources list for acpi path Yinghai Lu
2012-03-01  3:00 ` [PATCH 23/36] x86, PCI: put busn resource in pci_root_info for no_crs path Yinghai Lu
2012-03-01  3:00 ` [PATCH 24/36] PCI, ia64: Register busn_res for root buses Yinghai Lu
2012-03-01  3:00 ` [PATCH 25/36] PCI, sparc: " Yinghai Lu
2012-03-01  3:00 ` [PATCH 26/36] PCI, powerpc: " Yinghai Lu
2012-03-01  3:00 ` [PATCH 27/36] PCI, parisc: " Yinghai Lu
2012-03-01  3:00 ` [PATCH 28/36] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
2012-03-16 19:36   ` Bjorn Helgaas
2012-03-16 20:42     ` Yinghai Lu
2012-03-16 21:04       ` Bjorn Helgaas
2012-03-01  3:00 ` [PATCH 29/36] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
2012-03-01  3:00 ` [PATCH 30/36] PCI: Strict checking of valid range for bridge Yinghai Lu
2012-03-01  3:00 ` [PATCH 31/36] PCI: Allocate bus range instead of use max blindly Yinghai Lu
2012-03-01  3:00 ` [PATCH 32/36] PCI: kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
2012-03-01  3:00 ` [PATCH 33/36] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
2012-03-01  3:00 ` [PATCH 34/36] pcmcia: remove workaround for fixing pci parent bus subordinate Yinghai Lu
2012-03-01  3:00 ` [PATCH 35/36] PCI: Double checking setting for bus register and bus struct Yinghai Lu
2012-03-01  3:00 ` [PATCH 36/36] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
2012-03-15  6:40 ` [PATCH -v2 00/36] PCI: pci_host_bridge related cleanup and busn_alloc Taku Izumi
2012-03-15 17:40   ` Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).