linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn
@ 2012-03-19  5:42 Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path Yinghai Lu
                   ` (30 more replies)
  0 siblings, 31 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

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 linux v3.3 + pci-next and
        [PATCH -v3] PCI: pci_host_bridge related cleanup

could be found at:
        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-busn-alloc

-v2: according to Jesse, split to more small patches.
-v3: address some request from Bjorn. like make use %pR for busn_res debug print
        out, and move the comment change with code change.
-v4: fixes the problem about rescan that Bjorn found.
-v5: add /proc/iobusn that is requested by Bjorn.
     remove old workaround from pciehp.
     add rescan_bridge for pci bridge in /sys
-v6: remove global iobusn_resource, and every root bus's busn_res will be root
     of children buses' busn_res.
     pc cardbus change is tested by pcmcia maintainter.
-v7: remove pci_scan_root_bus_max requested by Bjorn and Jesse.
-v8: rebase on top other patches with arch/x86/pci/bus_numa.c changes
     also only include busn_res related changes.
-v9: Add busn into pci_root_info, and add it to resources list and pass it
     to pci_create_root_bus.
-v11: convert busn_res probe to generic probe_resource with resource lock holding
     add more strict checking about not scaned peer bridges.

Yinghai Lu (30):
  x86, PCI: Add print all root info for not using _CRS 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_res when removing bus
  PCI: Insert busn_res in pci_create_root_bus()
  PCI: Checking busn_res in pci_scan_root_bus()
  PCI: Add default busn_resource
  PCI: Add default busn_res for pci_scan_bus()
  x86, PCI: Add busn_res into resources list for acpi path
  x86, PCI: Put busn resource in pci_root_info for not using _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
  resources: Add probe_resource()
  resources: Replace registered resource in tree.
  PCI: Add pci_bus_extend/shrink_top()
  PCI: Probe safe range that we can use for unassigned bridge.
  PCI: Add pci_bus_replace_busn_res()
  PCI: Allocate bus range instead of use max blindly
  PCI: Strict checking of valid range for bridge
  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
  PCI: More strict checking of valid range for bridge
  PCI: Don't shrink too much for hotplug bridge

 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                   |   11 +-
 arch/x86/pci/amd_bus.c                |   14 +-
 arch/x86/pci/bus_numa.c               |   30 ++-
 arch/x86/pci/bus_numa.h               |    4 +-
 arch/x86/pci/common.c                 |   27 +--
 drivers/parisc/dino.c                 |    5 +
 drivers/parisc/lba_pci.c              |    3 +
 drivers/pci/hotplug/pciehp_pci.c      |   12 +-
 drivers/pci/probe.c                   |  439 +++++++++++++++++++++++++++------
 drivers/pci/remove.c                  |    1 +
 drivers/pcmcia/yenta_socket.c         |   75 ------
 include/linux/ioport.h                |    8 +
 include/linux/pci.h                   |    6 +
 kernel/resource.c                     |  175 +++++++++++++-
 19 files changed, 613 insertions(+), 215 deletions(-)

-- 
1.7.7


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

* [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 02/30] x86, PCI: Allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
                   ` (29 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 02/30] x86, PCI: Allocate temp range array in amd_bus pci_root_info probing
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 03/30] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 03/30] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 02/30] x86, PCI: Allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus Yinghai Lu
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Those two are 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] 49+ messages in thread

* [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (2 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 03/30] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-04-30 23:25   ` Bjorn Helgaas
  2012-03-19  5:42 ` [PATCH -v11 05/30] PCI: Add busn_res operation functions Yinghai Lu
                   ` (26 subsequent siblings)
  30 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Will use it to track 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] 49+ messages in thread

* [PATCH -v11 05/30] PCI: Add busn_res operation functions
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (3 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-04-30 23:29   ` Bjorn Helgaas
  2012-03-19  5:42 ` [PATCH -v11 06/30] PCI: Release busn_res when removing bus Yinghai Lu
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Will use them insert/update busn res in pci_bus struct.

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 d30948d..9235b16 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1679,6 +1679,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 || !res->parent)
+		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] 49+ messages in thread

* [PATCH -v11 06/30] PCI: Release busn_res when removing bus
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (4 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 05/30] PCI: Add busn_res operation functions Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 07/30] PCI: Insert busn_res in pci_create_root_bus() Yinghai Lu
                   ` (24 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 07/30] PCI: Insert busn_res in pci_create_root_bus()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (5 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 06/30] PCI: Release busn_res when removing bus Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 08/30] PCI: Checking busn_res in pci_scan_root_bus() Yinghai Lu
                   ` (23 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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 9235b16..3d11836 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] 49+ messages in thread

* [PATCH -v11 08/30] PCI: Checking busn_res in pci_scan_root_bus()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (6 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 07/30] PCI: Insert busn_res in pci_create_root_bus() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 09/30] PCI: Add default busn_resource Yinghai Lu
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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.

Also print out one info about that, so we could find out which path
does not have busn_res in resources list.

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 3d11836..654c727 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1736,12 +1736,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] 49+ messages in thread

* [PATCH -v11 09/30] PCI: Add default busn_resource
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (7 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 08/30] PCI: Checking busn_res in pci_scan_root_bus() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 10/30] PCI: Add default busn_res for pci_scan_bus() Yinghai Lu
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

We need to put into the resources list for legacy system.

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 654c727..2378531 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] 49+ messages in thread

* [PATCH -v11 10/30] PCI: Add default busn_res for pci_scan_bus()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (8 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 09/30] PCI: Add default busn_resource Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 11/30] x86, PCI: Add busn_res into resources list for acpi path Yinghai Lu
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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 2378531..8a77b8b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1785,6 +1785,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);
@@ -1802,6 +1803,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] 49+ messages in thread

* [PATCH -v11 11/30] x86, PCI: Add busn_res into resources list for acpi path
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (9 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 10/30] PCI: Add default busn_res for pci_scan_bus() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 12/30] x86, PCI: Put busn resource in pci_root_info for not using _CRS path Yinghai Lu
                   ` (19 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

will put it in resources list and pass it for create_root_bus

-v2: Bjorn thought that we should just use that in acpi_root instead
     of have another one pci_root_info.

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 8a17b23..da0149d 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;
 };
 
@@ -357,7 +356,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);
@@ -370,8 +371,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);
 }
@@ -440,9 +439,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] 49+ messages in thread

* [PATCH -v11 12/30] x86, PCI: Put busn resource in pci_root_info for not using _CRS path
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (10 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 11/30] x86, PCI: Add busn_res into resources list for acpi path Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 13/30] PCI, ia64: Register busn_res for root buses Yinghai Lu
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 13/30] PCI, ia64: Register busn_res for root buses
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (11 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 12/30] x86, PCI: Put busn resource in pci_root_info for not using _CRS path Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 14/30] PCI, sparc: " Yinghai Lu
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 14/30] PCI, sparc: Register busn_res for root buses
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (12 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 13/30] PCI, ia64: Register busn_res for root buses Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 15/30] PCI, powerpc: " Yinghai Lu
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 15/30] PCI, powerpc: Register busn_res for root buses
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (13 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 14/30] PCI, sparc: " Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 16/30] PCI, parisc: " Yinghai Lu
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 16/30] PCI, parisc: Register busn_res for root buses
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (14 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 15/30] PCI, powerpc: " Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 17/30] resources: Add probe_resource() Yinghai Lu
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 17/30] resources: Add probe_resource()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (15 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 16/30] PCI, parisc: " Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-05-01 23:57   ` Bjorn Helgaas
  2012-03-19  5:42 ` [PATCH -v11 18/30] resources: Replace registered resource in tree Yinghai Lu
                   ` (13 subsequent siblings)
  30 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

It is changed from busn_res only version, because Bjorn found that version
was not holding resource_lock.
Even it may be ok for busn_res not holding resource_lock.
It would be better to have it to be generic and use lock and we would
use it for other resources.

probe_resource() will try to find specified size or more in parent bus.
If can not find current parent resource, and it will try to expand parents
top.
If still can not find that specified on top, it will try to reduce target size
until find one.

It will return 0, if it find any resource that it could use.

Returned resource already register in the tree.

So caller may still need call resource_replace to put real resource in
the tree.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 include/linux/ioport.h |    7 ++
 kernel/resource.c      |  160 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 162 insertions(+), 5 deletions(-)

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index e885ba2..20a30df 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -156,6 +156,13 @@ extern int allocate_resource(struct resource *root, struct resource *new,
 						       resource_size_t,
 						       resource_size_t),
 			     void *alignf_data);
+void resource_shrink_parents_top(struct resource *b_res,
+				 long size, struct resource *parent_res);
+struct device;
+int probe_resource(struct resource *b_res,
+			struct device *dev, struct resource *busn_res,
+			resource_size_t needed_size, struct resource **p,
+			int skip_nr, int limit, char *name);
 struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
 		    resource_size_t size);
diff --git a/kernel/resource.c b/kernel/resource.c
index 7640b3a..0c9616f 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -521,14 +521,14 @@ out:
  * @alignf: alignment function, optional, called if not NULL
  * @alignf_data: arbitrary data to pass to the @alignf function
  */
-int allocate_resource(struct resource *root, struct resource *new,
+static int __allocate_resource(struct resource *root, struct resource *new,
 		      resource_size_t size, resource_size_t min,
 		      resource_size_t max, resource_size_t align,
 		      resource_size_t (*alignf)(void *,
 						const struct resource *,
 						resource_size_t,
 						resource_size_t),
-		      void *alignf_data)
+		      void *alignf_data, bool lock)
 {
 	int err;
 	struct resource_constraint constraint;
@@ -542,19 +542,33 @@ int allocate_resource(struct resource *root, struct resource *new,
 	constraint.alignf = alignf;
 	constraint.alignf_data = alignf_data;
 
-	if ( new->parent ) {
+	if (new->parent && lock) {
 		/* resource is already allocated, try reallocating with
 		   the new constraints */
 		return reallocate_resource(root, new, size, &constraint);
 	}
 
-	write_lock(&resource_lock);
+	if (lock)
+		write_lock(&resource_lock);
 	err = find_resource(root, new, size, &constraint);
 	if (err >= 0 && __request_resource(root, new))
 		err = -EBUSY;
-	write_unlock(&resource_lock);
+	if (lock)
+		write_unlock(&resource_lock);
 	return err;
 }
+int allocate_resource(struct resource *root, struct resource *new,
+		      resource_size_t size, resource_size_t min,
+		      resource_size_t max, resource_size_t align,
+		      resource_size_t (*alignf)(void *,
+						const struct resource *,
+						resource_size_t,
+						resource_size_t),
+		      void *alignf_data)
+{
+	return __allocate_resource(root, new, size, min, max, align,
+				   alignf, alignf_data, true);
+}
 
 EXPORT_SYMBOL(allocate_resource);
 
@@ -962,6 +976,142 @@ void __release_region(struct resource *parent, resource_size_t start,
 }
 EXPORT_SYMBOL(__release_region);
 
+static void __resource_update_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	struct resource *res = b_res;
+
+	if (!size)
+		return;
+
+	while (res) {
+		if (res == parent_res)
+			break;
+		res->end += size;
+		res = res->parent;
+	}
+}
+
+static void __resource_extend_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	__resource_update_parents_top(b_res, size, parent_res);
+}
+
+void resource_shrink_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	write_lock(&resource_lock);
+	__resource_update_parents_top(b_res, -size, parent_res);
+	write_unlock(&resource_lock);
+}
+
+static resource_size_t __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, false);
+		if (ret == 0) {
+			__release_resource(&tmp_res);
+			break;
+		}
+		n_size--;
+	}
+
+	return n_size;
+}
+
+int probe_resource(struct resource *b_res,
+			 struct device *dev, struct resource *busn_res,
+			 resource_size_t needed_size, struct resource **p,
+			 int skip_nr, int limit, char *name)
+{
+	int ret = -ENOMEM;
+	resource_size_t n_size;
+	struct resource *parent_res = NULL;
+	resource_size_t tmp = b_res->end + 1;
+
+again:
+	/*
+	 * find biggest range in b_res that we can use in the middle
+	 *  and we can not use some spots from start of b_res.
+	 */
+	n_size = resource_size(b_res);
+	if (n_size > skip_nr)
+		n_size -= skip_nr;
+	else
+		n_size = 0;
+
+	memset(busn_res, 0, sizeof(struct resource));
+	dev_printk(KERN_DEBUG, dev, "find free %s in res: %pR\n", name, b_res);
+	while (n_size >= needed_size) {
+		ret = allocate_resource(b_res, busn_res, n_size,
+				b_res->start + skip_nr, b_res->end,
+				1, NULL, NULL);
+		if (!ret)
+			return ret;
+		n_size--;
+	}
+
+	/* try extend the top of parent bus, find free under top at first */
+	write_lock(&resource_lock);
+	n_size = __find_res_top_free_size(b_res);
+	dev_printk(KERN_DEBUG, dev, "found free %s %ld in res: %pR top\n",
+			name, (unsigned long)n_size, b_res);
+
+	/* can not extend cross local boundary */
+	if ((limit - b_res->end) < (needed_size - n_size))
+		goto reduce_needed_size;
+
+	/* find extended range */
+	memset(busn_res, 0, sizeof(struct resource));
+	parent_res = b_res;
+	while (parent_res) {
+		ret = __allocate_resource(parent_res, busn_res,
+			 needed_size - n_size,
+			 tmp, tmp + needed_size - n_size - 1,
+			 1, NULL, NULL, false);
+		if (!ret) {
+			/* save parent_res, we need it as stopper later */
+			*p = parent_res;
+
+			/* prepare busn_res for return */
+			__release_resource(busn_res);
+			busn_res->start -= n_size;
+
+			/* extend parent bus top*/
+			__resource_extend_parents_top(b_res,
+					 needed_size - n_size, parent_res);
+			__request_resource(b_res, busn_res);
+
+			write_unlock(&resource_lock);
+			return ret;
+		}
+		parent_res = parent_res->parent;
+	}
+
+reduce_needed_size:
+	write_unlock(&resource_lock);
+	/* ret must not be 0 here */
+	needed_size--;
+	if (needed_size)
+		goto again;
+
+	return ret;
+}
+
 /*
  * Managed region resource
  */
-- 
1.7.7


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

* [PATCH -v11 18/30] resources: Replace registered resource in tree.
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (16 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 17/30] resources: Add probe_resource() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 19/30] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

We could have one resource inserted in tree at first during proble.

Later we need to put real resource into the tree.

So try to hold the lock to swap them.

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

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 20a30df..62af212 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -163,6 +163,7 @@ int probe_resource(struct resource *b_res,
 			struct device *dev, struct resource *busn_res,
 			resource_size_t needed_size, struct resource **p,
 			int skip_nr, int limit, char *name);
+void resource_replace(struct resource *old_res, struct resource *new_res);
 struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
 		    resource_size_t size);
diff --git a/kernel/resource.c b/kernel/resource.c
index 0c9616f..ea96dcf 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -1112,6 +1112,21 @@ reduce_needed_size:
 	return ret;
 }
 
+/* replace old with new in the resource tree */
+void resource_replace(struct resource *old, struct resource *new)
+{
+	struct resource *parent;
+
+	write_lock(&resource_lock);
+	parent = old->parent;
+	new->start = old->start;
+	new->end = old->end;
+	new->flags = old->flags;
+	__release_resource(old);
+	__request_resource(parent, new);
+	write_unlock(&resource_lock);
+}
+
 /*
  * Managed region resource
  */
-- 
1.7.7


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

* [PATCH -v11 19/30] PCI: Add pci_bus_extend/shrink_top()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (17 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 18/30] resources: Replace registered resource in tree Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 20/30] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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.

-v2: Remove busn_res change, it is updated in other function.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8a77b8b..3e32b34 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -655,6 +655,41 @@ 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;
+		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] 49+ messages in thread

* [PATCH -v11 20/30] PCI: Probe safe range that we can use for unassigned bridge.
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (18 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 19/30] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 21/30] PCI: Add pci_bus_replace_busn_res() Yinghai Lu
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Try to allocate from parent bus busn_res. If we 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.

-v4: Use generic probe_resource()

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3e32b34..67cd0a7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -690,6 +690,31 @@ static void __devinit pci_bus_shrink_top(struct pci_bus *parent,
 	pci_bus_update_top(parent, -size, parent_res);
 }
 
+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;
+	int old_size = resource_size(&bus->busn_res);
+
+	ret = probe_resource(&bus->busn_res, &dev->dev, busn_res, needed_size,
+			p, 1, 0xff, "busn");
+
+	if (ret)
+		return ret;
+
+	busn_res->flags = IORESOURCE_BUS;
+
+	if (*p) {
+		/* extend parent bus top*/
+		int new_size = resource_size(&bus->busn_res);
+
+		pci_bus_extend_top(bus, new_size - old_size, *p);
+	}
+
+	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] 49+ messages in thread

* [PATCH -v11 21/30] PCI: Add pci_bus_replace_busn_res()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (19 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 20/30] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 22/30] PCI: Allocate bus range instead of use max blindly Yinghai Lu
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

It will use resource_replace to put bus's busn_res in the resource tree.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 67cd0a7..c5fe935 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -626,6 +626,21 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 	return child;
 }
 
+static void pci_bus_replace_busn_res(struct pci_bus *b,
+					 struct resource *busn_res)
+{
+	struct resource *res = &b->busn_res;
+
+	/* busn_res must be registered already*/
+	if (!busn_res->parent)
+		return;
+
+	resource_replace(busn_res, res);
+
+	dev_printk(KERN_DEBUG, &b->dev, "busn_res: %pR is updated under %pR\n",
+			res, res->parent);
+}
+
 struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
 	struct pci_bus *child;
-- 
1.7.7


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

* [PATCH -v11 22/30] PCI: Allocate bus range instead of use max blindly
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (20 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 21/30] PCI: Add pci_bus_replace_busn_res() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 23/30] PCI: Strict checking of valid range for bridge Yinghai Lu
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Every bus have extra busn_res, and linked them together under root bus busn_res

When need to find usable bus number range, try probe it.

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.
-v5: Use update bridge probe busn_res function and resource_replace

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c5fe935..bf577e8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -744,10 +744,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;
@@ -764,10 +765,11 @@ 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;
-	}
+
+	if (broken)
+		dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
 
 	/* Disable MasterAbortMode during probing to avoid reporting
 	   of bus errors (in some architectures) */ 
@@ -800,6 +802,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);
@@ -812,6 +816,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
@@ -828,20 +837,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_replace_busn_res(child, &busn_res);
+
 		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.
@@ -872,43 +904,27 @@ 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) {
+			resource_shrink_parents_top(&bus->busn_res, shrink_size,
+						 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] 49+ messages in thread

* [PATCH -v11 23/30] PCI: Strict checking of valid range for bridge
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (21 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 22/30] PCI: Allocate bus range instead of use max blindly Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 24/30] PCI: Kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Children bridges busn range should be allocated from parent bus range.

So we could avoid overlapping between sibling bridges on same bus.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bf577e8..5710411 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -730,6 +730,28 @@ static int __devinit pci_bridge_probe_busn_res(struct pci_bus *bus,
 	return ret;
 }
 
+static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
+				struct pci_dev *dev,
+				int secondary, int subordinate)
+{
+	int ret;
+	struct resource busn_res;
+
+	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)
+		return 1;
+
+	release_resource(&busn_res);
+
+	return 0;
+}
 /*
  * 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
@@ -768,6 +790,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 	    (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");
 
-- 
1.7.7


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

* [PATCH -v11 24/30] PCI: Kill pci_fixup_parent_subordinate_busnr()
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (22 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 23/30] PCI: Strict checking of valid range for bridge Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 25/30] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Now we can safely extend parent top and shrink them by probing them.

Don't need that anymore.

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 5710411..6577105 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -654,22 +654,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)
 {
@@ -917,23 +901,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] 49+ messages in thread

* [PATCH -v11 25/30] PCI: Seperate child bus scanning to two passes overall
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (23 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 24/30] PCI: Kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 26/30] pcmcia: Remove workaround for fixing pci parent bus subordinate Yinghai Lu
                   ` (5 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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 6577105..5567428 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -736,6 +736,9 @@ static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
 
 	return 0;
 }
+
+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
@@ -792,11 +795,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,
@@ -817,7 +819,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)
@@ -1634,12 +1636,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)
@@ -1653,18 +1656,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
@@ -1673,7 +1674,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] 49+ messages in thread

* [PATCH -v11 26/30] pcmcia: Remove workaround for fixing pci parent bus subordinate
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (24 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 25/30] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 27/30] PCI: Double checking setting for bus register and bus struct Yinghai Lu
                   ` (4 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 27/30] PCI: Double checking setting for bus register and bus struct.
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (25 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 26/30] pcmcia: Remove workaround for fixing pci parent bus subordinate Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:42 ` [PATCH -v11 28/30] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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 |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5567428..8a4e90f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -777,6 +777,48 @@ 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] 49+ messages in thread

* [PATCH -v11 28/30] PCI, pciehp: Remove not needed bus number range checking
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (26 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 27/30] PCI: Double checking setting for bus register and bus struct Yinghai Lu
@ 2012-03-19  5:42 ` Yinghai Lu
  2012-03-19  5:43 ` [PATCH -v11 29/30] PCI: More strict checking of valid range for bridge Yinghai Lu
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:42 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, 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] 49+ messages in thread

* [PATCH -v11 29/30] PCI: More strict checking of valid range for bridge
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (27 preceding siblings ...)
  2012-03-19  5:42 ` [PATCH -v11 28/30] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
@ 2012-03-19  5:43 ` Yinghai Lu
  2012-03-19  5:43 ` [PATCH -v11 30/30] PCI: Don't shrink too much for hotplug bridge Yinghai Lu
  2012-05-02 21:22 ` [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Bjorn Helgaas
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:43 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Found one sick system with two sibling bridge have overlaping range from BIOS.
00:02.1 bus range is 0x30-0x30
00:02.2 bus range is 0x30-0x3f, and it have two children under it.

RHEL 6.2 kernel, will just 00:02.1 have child bus 0x30, and bridge 00:02.2 will
not have.

before this patch, this patchset will have 00:02.1 to have bus 0x30,
and 00:02.2 will have reallocate range bus 01.
but 00:02.1 will have scaned at first, so later it will have two fake devices.

To fix the problem, We need to check with unscaned sibling bridge about range
overlapping.
If there is overlapping found, will mark both sides to be broken.
So we could prevent one side take too big range.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8a4e90f..01ba48e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -714,6 +714,48 @@ static int __devinit pci_bridge_probe_busn_res(struct pci_bus *bus,
 	return ret;
 }
 
+static int __devinit pci_bridge_check_busn_broken_with_unscaned(
+				struct pci_bus *bus,
+				struct pci_dev *dev,
+				int secondary, int subordinate)
+{
+	u32 buses2;
+	int broken = 0;
+	struct pci_dev *dev2;
+	int secondary2, subordinate2;
+	int common_start, common_end;
+
+	/* need to check with not scaned sibling bridges */
+	list_for_each_entry(dev2, &bus->devices, bus_list) {
+		if (dev2->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
+		    dev2->hdr_type != PCI_HEADER_TYPE_CARDBUS)
+			continue;
+		if (dev2->subordinate)
+			continue;
+		if (dev2 == dev)
+			continue;
+
+		pci_read_config_dword(dev2, PCI_PRIMARY_BUS, &buses2);
+		secondary2 = (buses2 >> 8) & 0xFF;
+		subordinate2 = (buses2 >> 16) & 0xFF;
+
+		/* overlapping between them ? */
+		common_start = max(secondary, secondary2);
+		common_end = min(subordinate, subordinate2);
+		if (common_start <= common_end) {
+			/*
+			 * Temporarily disable forwarding of the
+			 * configuration cycles on this sibling bridge
+			 */
+			pci_write_config_dword(dev2, PCI_PRIMARY_BUS,
+					       buses2 & ~0xffffff);
+			broken = 1;
+		}
+	}
+
+	return broken;
+}
+
 static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
 				struct pci_dev *dev,
 				int secondary, int subordinate)
@@ -734,7 +776,8 @@ static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
 
 	release_resource(&busn_res);
 
-	return 0;
+	return pci_bridge_check_busn_broken_with_unscaned(bus, dev,
+					secondary, subordinate);
 }
 
 static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
-- 
1.7.7


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

* [PATCH -v11 30/30] PCI: Don't shrink too much for hotplug bridge
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (28 preceding siblings ...)
  2012-03-19  5:43 ` [PATCH -v11 29/30] PCI: More strict checking of valid range for bridge Yinghai Lu
@ 2012-03-19  5:43 ` Yinghai Lu
  2012-05-02 21:22 ` [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Bjorn Helgaas
  30 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:43 UTC (permalink / raw)
  To: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller, x86
  Cc: Bjorn Helgaas, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch,
	Yinghai Lu

Otherwise may have problem later if we plug pcie cards with bridges.

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

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 01ba48e..38e0448 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -782,6 +782,7 @@ static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus,
 
 static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
 						 int pass);
+#define HOTPLUG_BRIDGE_RESERVE_BUSNR 8
 /*
  * 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
@@ -993,6 +994,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		/*
 		 * Set the subordinate bus number to its real value.
 		 */
+		if (dev->is_hotplug_bridge && child->subordinate > max &&
+		    (max - child->secondary) < HOTPLUG_BRIDGE_RESERVE_BUSNR)
+			max = min_t(int, child->secondary +
+					 HOTPLUG_BRIDGE_RESERVE_BUSNR,
+				    child->subordinate);
 		shrink_size = child->subordinate - max;
 		child->subordinate = max;
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
-- 
1.7.7


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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-03-19  5:42 ` [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus Yinghai Lu
@ 2012-04-30 23:25   ` Bjorn Helgaas
  2012-05-01  0:32     ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-04-30 23:25 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> Will use it to track 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 */

struct pci_bus already includes "secondary" and "subordinate".    This
new "busn_res" looks like it will contain the same information.  Why
do we need both?

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

* Re: [PATCH -v11 05/30] PCI: Add busn_res operation functions
  2012-03-19  5:42 ` [PATCH -v11 05/30] PCI: Add busn_res operation functions Yinghai Lu
@ 2012-04-30 23:29   ` Bjorn Helgaas
  2012-05-01  0:34     ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-04-30 23:29 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> Will use them insert/update busn res in pci_bus struct.
>
> 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 d30948d..9235b16 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1679,6 +1679,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;

I've mentioned before that I'm not comfortable with updating the
struct resource after it's been inserted into the tree.  If you want
to do an in-place update, I think you need to add a new interface in
kernel/resource.c so it can make sure the resource tree remains
consistent.

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-04-30 23:25   ` Bjorn Helgaas
@ 2012-05-01  0:32     ` Yinghai Lu
  2012-05-01  4:02       ` Bjorn Helgaas
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-01  0:32 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Mon, Apr 30, 2012 at 4:25 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> --- 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 */
>
> struct pci_bus already includes "secondary" and "subordinate".    This
> new "busn_res" looks like it will contain the same information.  Why
> do we need both?

In some case the could be different.
for root bus from _CRS, busn_res could bigger than subordinate,
because scan_childbus will update subordinate.

and also we have one resource to insert it into the resource tree, so
later could probe/allocate bus num range.

Yinghai

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

* Re: [PATCH -v11 05/30] PCI: Add busn_res operation functions
  2012-04-30 23:29   ` Bjorn Helgaas
@ 2012-05-01  0:34     ` Yinghai Lu
  2012-05-01  7:19       ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-01  0:34 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Mon, Apr 30, 2012 at 4:29 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> +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;
>
> I've mentioned before that I'm not comfortable with updating the
> struct resource after it's been inserted into the tree.  If you want
> to do an in-place update, I think you need to add a new interface in
> kernel/resource.c so it can make sure the resource tree remains
> consistent.

ok, will add one function in kernel/resource.c to make sure that end
could be updated safely
by checking parent and children.

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-05-01  0:32     ` Yinghai Lu
@ 2012-05-01  4:02       ` Bjorn Helgaas
  2012-05-01  6:27         ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-01  4:02 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Mon, Apr 30, 2012 at 6:32 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Mon, Apr 30, 2012 at 4:25 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>> --- 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 */
>>
>> struct pci_bus already includes "secondary" and "subordinate".    This
>> new "busn_res" looks like it will contain the same information.  Why
>> do we need both?
>
> In some case the could be different.
> for root bus from _CRS, busn_res could bigger than subordinate,
> because scan_childbus will update subordinate.

For a bus below a P2P bridge, I think it's always the case that the
bridge's Subordinate Bus Number in config space == bus->subordinate ==
bus->busn_res.end (correct me if I'm wrong).  I don't like the
redundancy in this case.

For a root bus where you set bus->busn_res from _CRS and
bus->subordinate = pci_scan_child_bus(), bus->busn_res.end will
generally be different from bus->subordinate, but there's no point in
keeping track of bus->subordinate.

The reason we care about secondary and subordinate is so we can
allocate bus numbers when enumerating devices behind a bridge.  The
only thing we need for that is the aperture of the upstream bridge and
the apertures of any peer bridges on the same bus.  Let's say we have
this:

        pci 00:00.0 bridge to [bus a-b]
        pci a:01.0 bridge to [bus c-d]  (already enumerated)
        pci a:02.0 bridge to [bus e-f]  (already enumerated)
        pci a:03.0 bridge to [bus x-y]  (enumerating now)

We know [c-d] is contained in [a-b]; [e-f] is contained in [a-b]; a <
c; and a < e.  To enumerate behind a:03.0, we need to assign x & y
such that a < x; [x-y] is contained in [a-b]; and [x-y] does not
overlap [c-d] or [e-f].  The value from pci_scan_child_bus() is
probably useful for setting y, but we don't have to save it in the
struct pci_bus for that.

> and also we have one resource to insert it into the resource tree, so
> later could probe/allocate bus num range.

Sorry, I didn't understand this.

Bjorn

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-05-01  4:02       ` Bjorn Helgaas
@ 2012-05-01  6:27         ` Yinghai Lu
  2012-05-01 15:40           ` Bjorn Helgaas
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-01  6:27 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Mon, Apr 30, 2012 at 9:02 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Mon, Apr 30, 2012 at 6:32 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> On Mon, Apr 30, 2012 at 4:25 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>>> --- 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 */
>>>
>>> struct pci_bus already includes "secondary" and "subordinate".    This
>>> new "busn_res" looks like it will contain the same information.  Why
>>> do we need both?
>>
>> In some case the could be different.
>> for root bus from _CRS, busn_res could bigger than subordinate,
>> because scan_childbus will update subordinate.
>
> For a bus below a P2P bridge, I think it's always the case that the
> bridge's Subordinate Bus Number in config space == bus->subordinate ==
> bus->busn_res.end (correct me if I'm wrong).  I don't like the
> redundancy in this case.

there are about 70 bus->subordinate reference and 40 bus->secondary reference.

could try to update them in following patch set.

>
> For a root bus where you set bus->busn_res from _CRS and
> bus->subordinate = pci_scan_child_bus(), bus->busn_res.end will
> generally be different from bus->subordinate, but there's no point in
> keeping track of bus->subordinate.
>
> The reason we care about secondary and subordinate is so we can
> allocate bus numbers when enumerating devices behind a bridge.  The
> only thing we need for that is the aperture of the upstream bridge and
> the apertures of any peer bridges on the same bus.  Let's say we have
> this:
>
>        pci 00:00.0 bridge to [bus a-b]
>        pci a:01.0 bridge to [bus c-d]  (already enumerated)
>        pci a:02.0 bridge to [bus e-f]  (already enumerated)
>        pci a:03.0 bridge to [bus x-y]  (enumerating now)
>
> We know [c-d] is contained in [a-b]; [e-f] is contained in [a-b]; a <
> c; and a < e.  To enumerate behind a:03.0, we need to assign x & y
> such that a < x; [x-y] is contained in [a-b]; and [x-y] does not
> overlap [c-d] or [e-f].  The value from pci_scan_child_bus() is
> probably useful for setting y, but we don't have to save it in the
> struct pci_bus for that.

busn alloc will try to solve x-y may need big range than [a,b], it
will extend top of b and parents of bus a.
instead of just b+1 blindly.

and will have more strict checking to avoid overlapping.

>
>> and also we have one resource to insert it into the resource tree, so
>> later could probe/allocate bus num range.
>
> Sorry, I didn't understand this.

Using busn_res to track and allocate busn range, by put them in the
resource tree could reuse resource allocating code.

Yinghai

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

* Re: [PATCH -v11 05/30] PCI: Add busn_res operation functions
  2012-05-01  0:34     ` Yinghai Lu
@ 2012-05-01  7:19       ` Yinghai Lu
  0 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-05-01  7:19 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

[-- Attachment #1: Type: text/plain, Size: 1049 bytes --]

On Mon, Apr 30, 2012 at 5:34 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Mon, Apr 30, 2012 at 4:29 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>>> +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;
>>
>> I've mentioned before that I'm not comfortable with updating the
>> struct resource after it's been inserted into the tree.  If you want
>> to do an in-place update, I think you need to add a new interface in
>> kernel/resource.c so it can make sure the resource tree remains
>> consistent.
>
> ok, will add one function in kernel/resource.c to make sure that end
> could be updated safely
> by checking parent and children.

Rebased busn_alloc branch and added attached patch into that.

as for removing bus->subordinate and bus->secondary, like to do that later.

Thanks

Yinghai

[-- Attachment #2: resource_update.patch --]
[-- Type: application/octet-stream, Size: 2391 bytes --]

Subject: [PATCH] resources: Update registered resource start/end in tree.

Need to check if the new range is
1. fully covered by parent resource if it exists
2. not overlapped with sibling resources if they exist.
3. fully covering chilren resources if they exist.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>

---
 include/linux/ioport.h |    2 ++
 kernel/resource.c      |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

Index: linux-2.6/include/linux/ioport.h
===================================================================
--- linux-2.6.orig/include/linux/ioport.h
+++ linux-2.6/include/linux/ioport.h
@@ -141,6 +141,8 @@ extern struct resource *request_resource
 extern int request_resource(struct resource *root, struct resource *new);
 extern int release_resource(struct resource *new);
 void release_child_resources(struct resource *new);
+int update_resource(struct resource *r, resource_size_t start,
+			 resource_size_t end);
 extern void reserve_region_with_split(struct resource *root,
 			     resource_size_t start, resource_size_t end,
 			     const char *name);
Index: linux-2.6/kernel/resource.c
===================================================================
--- linux-2.6.orig/kernel/resource.c
+++ linux-2.6/kernel/resource.c
@@ -227,6 +227,55 @@ void release_child_resources(struct reso
 	write_unlock(&resource_lock);
 }
 
+int update_resource(struct resource *r, resource_size_t start,
+			resource_size_t end)
+{
+	int ret = 0;
+	struct resource *parent;
+	struct resource *p;
+
+	if (start > end)
+		return -EINVAL;
+
+	write_lock(&resource_lock);
+	parent = r->parent;
+	if (parent) {
+		if (start < parent->start ||
+		    end > parent->end) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		p = parent->child;
+		while (p) {
+			if (p != r &&
+			    max_t(resource_size_t, p->start, start) <=
+			    min_t(resource_size_t, p->end, end)) {
+				ret = -EINVAL;
+				goto out;
+			}
+			p = p->sibling;
+		}
+	}
+
+	p = r->child;
+	while (p) {
+		if (p->start < start || p->end > end) {
+			ret = -EINVAL;
+			goto out;
+		}
+		p = p->sibling;
+	}
+
+	r->start = start;
+	r->end = end;
+
+out:
+	write_unlock(&resource_lock);
+
+	return ret;
+}
+
 /**
  * request_resource_conflict - request and reserve an I/O or memory resource
  * @root: root resource descriptor

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-05-01  6:27         ` Yinghai Lu
@ 2012-05-01 15:40           ` Bjorn Helgaas
  2012-05-01 19:28             ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-01 15:40 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Tue, May 1, 2012 at 12:27 AM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Mon, Apr 30, 2012 at 9:02 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> On Mon, Apr 30, 2012 at 6:32 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>>> On Mon, Apr 30, 2012 at 4:25 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>>>> --- 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 */
>>>>
>>>> struct pci_bus already includes "secondary" and "subordinate".    This
>>>> new "busn_res" looks like it will contain the same information.  Why
>>>> do we need both?
>>>
>>> In some case the could be different.
>>> for root bus from _CRS, busn_res could bigger than subordinate,
>>> because scan_childbus will update subordinate.
>>
>> For a bus below a P2P bridge, I think it's always the case that the
>> bridge's Subordinate Bus Number in config space == bus->subordinate ==
>> bus->busn_res.end (correct me if I'm wrong).  I don't like the
>> redundancy in this case.
>
> there are about 70 bus->subordinate reference and 40 bus->secondary reference.
>
> could try to update them in following patch set.

If you're proposing this:
  1. add bus->busn_res
  2. remove bus->subordinate and bus->secondary
I fully support that, and I'd like to merge both pieces at the same
time (different patches is fine; I just want to make sure both pieces
actually happen).

>> For a root bus where you set bus->busn_res from _CRS and
>> bus->subordinate = pci_scan_child_bus(), bus->busn_res.end will
>> generally be different from bus->subordinate, but there's no point in
>> keeping track of bus->subordinate.
>>
>> The reason we care about secondary and subordinate is so we can
>> allocate bus numbers when enumerating devices behind a bridge.  The
>> only thing we need for that is the aperture of the upstream bridge and
>> the apertures of any peer bridges on the same bus.  Let's say we have
>> this:
>>
>>        pci 00:00.0 bridge to [bus a-b]
>>        pci a:01.0 bridge to [bus c-d]  (already enumerated)
>>        pci a:02.0 bridge to [bus e-f]  (already enumerated)
>>        pci a:03.0 bridge to [bus x-y]  (enumerating now)
>>
>> We know [c-d] is contained in [a-b]; [e-f] is contained in [a-b]; a <
>> c; and a < e.  To enumerate behind a:03.0, we need to assign x & y
>> such that a < x; [x-y] is contained in [a-b]; and [x-y] does not
>> overlap [c-d] or [e-f].  The value from pci_scan_child_bus() is
>> probably useful for setting y, but we don't have to save it in the
>> struct pci_bus for that.
>
> busn alloc will try to solve x-y may need big range than [a,b], it
> will extend top of b and parents of bus a.
> instead of just b+1 blindly.
>
> and will have more strict checking to avoid overlapping.

Obviously the completely general problem of allocating bus numbers may
require traversing up the tree.  My point is that I don't think it's
necessary to keep both busn_res.end and subordinate to do that.

>>> and also we have one resource to insert it into the resource tree, so
>>> later could probe/allocate bus num range.
>>
>> Sorry, I didn't understand this.
>
> Using busn_res to track and allocate busn range, by put them in the
> resource tree could reuse resource allocating code.

Yes, I agree that replacing secondary & subordinate with a struct
resource is a good idea.  That will allow a resource tree of bus
numbers, as well as other useful things like the ability to "%pR".

I just don't want *both* busn_resource and secondary & subordinate.

Bjorn

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-05-01 15:40           ` Bjorn Helgaas
@ 2012-05-01 19:28             ` Yinghai Lu
  2012-05-02  5:07               ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-01 19:28 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Tue, May 1, 2012 at 8:40 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>> bridge's Subordinate Bus Number in config space == bus->subordinate ==
>>> bus->busn_res.end (correct me if I'm wrong).  I don't like the
>>> redundancy in this case.
>>
>> there are about 70 bus->subordinate reference and 40 bus->secondary reference.
>>
>> could try to update them in following patch set.
>
> If you're proposing this:
>  1. add bus->busn_res
>  2. remove bus->subordinate and bus->secondary
> I fully support that, and I'd like to merge both pieces at the same
> time (different patches is fine; I just want to make sure both pieces
> actually happen).

yes. Can you consider applying  "removing bus->subordinate" patch set
to be applied after:
for-pci-busn-alloc
for-pci-root-bus-hotplug
for-pci-for-each-res-addon
for-pci-res-alloc

otherwise there would be some extra rebase work for last three patch set.

Yinghai

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

* Re: [PATCH -v11 17/30] resources: Add probe_resource()
  2012-03-19  5:42 ` [PATCH -v11 17/30] resources: Add probe_resource() Yinghai Lu
@ 2012-05-01 23:57   ` Bjorn Helgaas
  2012-05-02  5:19     ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-01 23:57 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> It is changed from busn_res only version, because Bjorn found that version
> was not holding resource_lock.
> Even it may be ok for busn_res not holding resource_lock.
> It would be better to have it to be generic and use lock and we would
> use it for other resources.
>
> probe_resource() will try to find specified size or more in parent bus.
> If can not find current parent resource, and it will try to expand parents
> top.
> If still can not find that specified on top, it will try to reduce target size
> until find one.
>
> It will return 0, if it find any resource that it could use.
>
> Returned resource already register in the tree.
>
> So caller may still need call resource_replace to put real resource in
> the tree.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> ---
>  include/linux/ioport.h |    7 ++
>  kernel/resource.c      |  160 ++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 162 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/ioport.h b/include/linux/ioport.h
> index e885ba2..20a30df 100644
> --- a/include/linux/ioport.h
> +++ b/include/linux/ioport.h
> @@ -156,6 +156,13 @@ extern int allocate_resource(struct resource *root, struct resource *new,
>                                                       resource_size_t,
>                                                       resource_size_t),
>                             void *alignf_data);
> +void resource_shrink_parents_top(struct resource *b_res,
> +                                long size, struct resource *parent_res);
> +struct device;
> +int probe_resource(struct resource *b_res,
> +                       struct device *dev, struct resource *busn_res,
> +                       resource_size_t needed_size, struct resource **p,
> +                       int skip_nr, int limit, char *name);

This interface is a mess.  I have a vague impression that this is
supposed to figure out whether a resource can be expanded, but why
does it need a struct device *?  (I can read the code and see how you
use it, but it just doesn't fit in the resource abstraction.)
Supplying one struct resource * makes sense, but you have three.  A
char * name?  What's skip_nr?  This just doesn't make sense to me.

I think you need a simpler, more general interface.  update_resource()
seems OK to me -- it's pretty straightforward and has an obvious
meaning.  Maybe you can make a resource_expand() or something that
just expands a resource in both directions as far as possible (until
it hits a sibling or the parent limits).  Then you would know the
maximum possible size, and you could use update_resource() to shrink
it again and give up anything you don't need.

I spent most of the day merging the patches up to this point, and they
mostly make sense, but this one and the following ones are beyond my
ken, so I gave up.

>  struct resource *lookup_resource(struct resource *root, resource_size_t start);
>  int adjust_resource(struct resource *res, resource_size_t start,
>                    resource_size_t size);
> diff --git a/kernel/resource.c b/kernel/resource.c
> index 7640b3a..0c9616f 100644
> --- a/kernel/resource.c
> +++ b/kernel/resource.c
> @@ -521,14 +521,14 @@ out:
>  * @alignf: alignment function, optional, called if not NULL
>  * @alignf_data: arbitrary data to pass to the @alignf function
>  */
> -int allocate_resource(struct resource *root, struct resource *new,
> +static int __allocate_resource(struct resource *root, struct resource *new,
>                      resource_size_t size, resource_size_t min,
>                      resource_size_t max, resource_size_t align,
>                      resource_size_t (*alignf)(void *,
>                                                const struct resource *,
>                                                resource_size_t,
>                                                resource_size_t),
> -                     void *alignf_data)
> +                     void *alignf_data, bool lock)
>  {
>        int err;
>        struct resource_constraint constraint;
> @@ -542,19 +542,33 @@ int allocate_resource(struct resource *root, struct resource *new,
>        constraint.alignf = alignf;
>        constraint.alignf_data = alignf_data;
>
> -       if ( new->parent ) {
> +       if (new->parent && lock) {
>                /* resource is already allocated, try reallocating with
>                   the new constraints */
>                return reallocate_resource(root, new, size, &constraint);
>        }
>
> -       write_lock(&resource_lock);
> +       if (lock)
> +               write_lock(&resource_lock);
>        err = find_resource(root, new, size, &constraint);
>        if (err >= 0 && __request_resource(root, new))
>                err = -EBUSY;
> -       write_unlock(&resource_lock);
> +       if (lock)
> +               write_unlock(&resource_lock);
>        return err;
>  }
> +int allocate_resource(struct resource *root, struct resource *new,
> +                     resource_size_t size, resource_size_t min,
> +                     resource_size_t max, resource_size_t align,
> +                     resource_size_t (*alignf)(void *,
> +                                               const struct resource *,
> +                                               resource_size_t,
> +                                               resource_size_t),
> +                     void *alignf_data)
> +{
> +       return __allocate_resource(root, new, size, min, max, align,
> +                                  alignf, alignf_data, true);
> +}
>
>  EXPORT_SYMBOL(allocate_resource);
>
> @@ -962,6 +976,142 @@ void __release_region(struct resource *parent, resource_size_t start,
>  }
>  EXPORT_SYMBOL(__release_region);
>
> +static void __resource_update_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       struct resource *res = b_res;
> +
> +       if (!size)
> +               return;
> +
> +       while (res) {
> +               if (res == parent_res)
> +                       break;
> +               res->end += size;
> +               res = res->parent;
> +       }
> +}
> +
> +static void __resource_extend_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       __resource_update_parents_top(b_res, size, parent_res);
> +}
> +
> +void resource_shrink_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       write_lock(&resource_lock);
> +       __resource_update_parents_top(b_res, -size, parent_res);
> +       write_unlock(&resource_lock);
> +}
> +
> +static resource_size_t __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, false);
> +               if (ret == 0) {
> +                       __release_resource(&tmp_res);
> +                       break;
> +               }
> +               n_size--;
> +       }
> +
> +       return n_size;
> +}
> +
> +int probe_resource(struct resource *b_res,
> +                        struct device *dev, struct resource *busn_res,
> +                        resource_size_t needed_size, struct resource **p,
> +                        int skip_nr, int limit, char *name)
> +{
> +       int ret = -ENOMEM;
> +       resource_size_t n_size;
> +       struct resource *parent_res = NULL;
> +       resource_size_t tmp = b_res->end + 1;
> +
> +again:
> +       /*
> +        * find biggest range in b_res that we can use in the middle
> +        *  and we can not use some spots from start of b_res.
> +        */
> +       n_size = resource_size(b_res);
> +       if (n_size > skip_nr)
> +               n_size -= skip_nr;
> +       else
> +               n_size = 0;
> +
> +       memset(busn_res, 0, sizeof(struct resource));
> +       dev_printk(KERN_DEBUG, dev, "find free %s in res: %pR\n", name, b_res);
> +       while (n_size >= needed_size) {
> +               ret = allocate_resource(b_res, busn_res, n_size,
> +                               b_res->start + skip_nr, b_res->end,
> +                               1, NULL, NULL);
> +               if (!ret)
> +                       return ret;
> +               n_size--;
> +       }
> +
> +       /* try extend the top of parent bus, find free under top at first */
> +       write_lock(&resource_lock);
> +       n_size = __find_res_top_free_size(b_res);
> +       dev_printk(KERN_DEBUG, dev, "found free %s %ld in res: %pR top\n",
> +                       name, (unsigned long)n_size, b_res);
> +
> +       /* can not extend cross local boundary */
> +       if ((limit - b_res->end) < (needed_size - n_size))
> +               goto reduce_needed_size;
> +
> +       /* find extended range */
> +       memset(busn_res, 0, sizeof(struct resource));
> +       parent_res = b_res;
> +       while (parent_res) {
> +               ret = __allocate_resource(parent_res, busn_res,
> +                        needed_size - n_size,
> +                        tmp, tmp + needed_size - n_size - 1,
> +                        1, NULL, NULL, false);
> +               if (!ret) {
> +                       /* save parent_res, we need it as stopper later */
> +                       *p = parent_res;
> +
> +                       /* prepare busn_res for return */
> +                       __release_resource(busn_res);
> +                       busn_res->start -= n_size;
> +
> +                       /* extend parent bus top*/
> +                       __resource_extend_parents_top(b_res,
> +                                        needed_size - n_size, parent_res);
> +                       __request_resource(b_res, busn_res);
> +
> +                       write_unlock(&resource_lock);
> +                       return ret;
> +               }
> +               parent_res = parent_res->parent;
> +       }
> +
> +reduce_needed_size:
> +       write_unlock(&resource_lock);
> +       /* ret must not be 0 here */
> +       needed_size--;
> +       if (needed_size)
> +               goto again;
> +
> +       return ret;
> +}
> +
>  /*
>  * Managed region resource
>  */
> --
> 1.7.7
>

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

* Re: [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus.
  2012-05-01 19:28             ` Yinghai Lu
@ 2012-05-02  5:07               ` Yinghai Lu
  0 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-05-02  5:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

[-- Attachment #1: Type: text/plain, Size: 1333 bytes --]

On Tue, May 1, 2012 at 12:28 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Tue, May 1, 2012 at 8:40 AM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>>> bridge's Subordinate Bus Number in config space == bus->subordinate ==
>>>> bus->busn_res.end (correct me if I'm wrong).  I don't like the
>>>> redundancy in this case.
>>>
>>> there are about 70 bus->subordinate reference and 40 bus->secondary reference.
>>>
>>> could try to update them in following patch set.
>>
>> If you're proposing this:
>>  1. add bus->busn_res
>>  2. remove bus->subordinate and bus->secondary
>> I fully support that, and I'd like to merge both pieces at the same
>> time (different patches is fine; I just want to make sure both pieces
>> actually happen).
>
> yes. Can you consider applying  "removing bus->subordinate" patch set
> to be applied after:
> for-pci-busn-alloc
> for-pci-root-bus-hotplug
> for-pci-for-each-res-addon
> for-pci-res-alloc
>
> otherwise there would be some extra rebase work for last three patch set.

spent several hours today to have attached patch that will remove
pci_bus secondary/subordinate.
and tested with my setups with remove/scan test case.
looks ok.

need to apply it after
for-pci-busn-alloc
for-pci-root-bus-hotplug.

Please check if i miss anything.

Thanks

Yinghai

[-- Attachment #2: kill_bus_subordinate_x.patch --]
[-- Type: application/octet-stream, Size: 35939 bytes --]

Subject: [PATCH] PCI: Remove secondary/subordinate in pci_bus

We already have busn_res in pci_bus, so remove the duplicated
secondary/subordinate.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/alpha/kernel/pci.c                    |    2 
 arch/arm/kernel/bios32.c                   |    2 
 arch/ia64/pci/pci.c                        |    2 
 arch/microblaze/pci/pci-common.c           |    3 -
 arch/mips/pci/pci.c                        |    2 
 arch/powerpc/kernel/pci-common.c           |    9 +--
 arch/powerpc/kernel/pci_64.c               |    2 
 arch/powerpc/kernel/pci_of_scan.c          |    2 
 arch/powerpc/platforms/powernv/pci-ioda.c  |    8 +-
 arch/powerpc/platforms/pseries/pci_dlpar.c |    2 
 arch/sh/drivers/pci/pci.c                  |    2 
 arch/sparc/kernel/pci.c                    |    4 -
 arch/tile/kernel/pci.c                     |    9 ++-
 arch/x86/pci/acpi.c                        |    2 
 arch/xtensa/kernel/pci.c                   |    2 
 drivers/iommu/intel-iommu.c                |    2 
 drivers/net/ethernet/broadcom/tg3.c        |    4 -
 drivers/parisc/dino.c                      |   13 ++--
 drivers/parisc/iosapic.c                   |    2 
 drivers/parisc/lba_pci.c                   |   23 ++++----
 drivers/pci/hotplug-pci.c                  |    2 
 drivers/pci/hotplug/acpiphp_glue.c         |    8 +-
 drivers/pci/hotplug/shpchp_sysfs.c         |    6 +-
 drivers/pci/iov.c                          |    4 -
 drivers/pci/pci.c                          |    2 
 drivers/pci/probe.c                        |   83 +++++++++++++----------------
 drivers/pci/setup-bus.c                    |   22 +++----
 drivers/pcmcia/cardbus.c                   |    2 
 drivers/pcmcia/yenta_socket.c              |    4 -
 include/linux/pci.h                        |    2 
 30 files changed, 112 insertions(+), 120 deletions(-)

Index: linux-2.6/arch/alpha/kernel/pci.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/pci.c
+++ linux-2.6/arch/alpha/kernel/pci.c
@@ -359,7 +359,7 @@ common_init_pci(void)
 					hose, &resources);
 		hose->bus = bus;
 		hose->need_domain_info = need_domain_info;
-		next_busno = bus->subordinate + 1;
+		next_busno = bus->busn_res.end + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */ 
 		if (next_busno > 224) {
Index: linux-2.6/arch/arm/kernel/bios32.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/bios32.c
+++ linux-2.6/arch/arm/kernel/bios32.c
@@ -445,7 +445,7 @@ static void __init pcibios_init_hw(struc
 			if (!sys->bus)
 				panic("PCI: unable to scan bus!");
 
-			busnr = sys->bus->subordinate + 1;
+			busnr = sys->bus->busn_res.end + 1;
 
 			list_add(&sys->node, &hw->buses);
 		} else {
Index: linux-2.6/arch/ia64/pci/pci.c
===================================================================
--- linux-2.6.orig/arch/ia64/pci/pci.c
+++ linux-2.6/arch/ia64/pci/pci.c
@@ -386,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root
 		return NULL;
 	}
 
-	pbus->subordinate = pci_scan_child_bus(pbus);
+	pci_scan_child_bus(pbus);
 	return pbus;
 
 out3:
Index: linux-2.6/arch/microblaze/pci/pci-common.c
===================================================================
--- linux-2.6.orig/arch/microblaze/pci/pci-common.c
+++ linux-2.6/arch/microblaze/pci/pci-common.c
@@ -1505,10 +1505,9 @@ static void __devinit pcibios_scan_phb(s
 		pci_free_resource_list(&resources);
 		return;
 	}
-	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
-	hose->last_busno = bus->subordinate;
+	hose->last_busno = bus->busn_res.end;
 }
 
 static int __init pcibios_init(void)
Index: linux-2.6/arch/mips/pci/pci.c
===================================================================
--- linux-2.6.orig/arch/mips/pci/pci.c
+++ linux-2.6/arch/mips/pci/pci.c
@@ -101,7 +101,7 @@ static void __devinit pcibios_scanbus(st
 	need_domain_info = need_domain_info || hose->index;
 	hose->need_domain_info = need_domain_info;
 	if (bus) {
-		next_busno = bus->subordinate + 1;
+		next_busno = bus->busn_res.end + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
 		if (next_busno > 224) {
Index: linux-2.6/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/pci-common.c
+++ linux-2.6/arch/powerpc/kernel/pci-common.c
@@ -1651,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct p
 		pci_free_resource_list(&resources);
 		return;
 	}
-	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
 	/* Get probe mode and perform scan */
@@ -1659,15 +1658,13 @@ void __devinit pcibios_scan_phb(struct p
 	if (node && ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
 	pr_debug("    probe mode: %d\n", mode);
-	if (mode == PCI_PROBE_DEVTREE) {
-		bus->subordinate = hose->last_busno;
+	if (mode == PCI_PROBE_DEVTREE)
 		of_scan_bus(node, bus);
-	}
 
 	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);
+		hose->last_busno = pci_scan_child_bus(bus);
+		pci_bus_update_busn_res_end(bus, hose->last_busno);
 	}
 
 	/* Platform gets a chance to do some global fixups before
Index: linux-2.6/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/pci_64.c
+++ linux-2.6/arch/powerpc/kernel/pci_64.c
@@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, un
 
 	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
 		bus = pci_bus_b(ln);
-		if (in_bus >= bus->number && in_bus <= bus->subordinate)
+		if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
 			break;
 		bus = NULL;
 	}
Index: linux-2.6/arch/powerpc/kernel/pci_of_scan.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/pci_of_scan.c
+++ linux-2.6/arch/powerpc/kernel/pci_of_scan.c
@@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct
 	}
 
 	bus->primary = dev->bus->number;
-	bus->subordinate = busrange[1];
+	pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
 	bus->bridge_ctl = 0;
 
 	/* parse ranges property */
Index: linux-2.6/arch/powerpc/platforms/powernv/pci-ioda.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/powernv/pci-ioda.c
+++ linux-2.6/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_
 		dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
 		fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
 		parent = pe->pbus->self;
-		count = pe->pbus->subordinate - pe->pbus->secondary + 1;
+		count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
 		switch(count) {
 		case  1: bcomp = OpalPciBusAll;		break;
 		case  2: bcomp = OpalPciBus7Bits;	break;
@@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus
 	pe->pdev = NULL;
 	pe->tce32_seg = -1;
 	pe->mve_number = -1;
-	pe->rid = bus->secondary << 8;
+	pe->rid = bus->busn_res.start << 8;
 	pe->dma_weight = 0;
 
-	pe_info(pe, "Secondary busses %d..%d associated with PE\n",
-		bus->secondary, bus->subordinate);
+	pe_info(pe, "Secondary busses %pR associated with PE\n",
+		&bus->busn_res);
 
 	if (pnv_ioda_configure_pe(phb, pe)) {
 		/* XXX What do we do here ? */
Index: linux-2.6/arch/powerpc/platforms/pseries/pci_dlpar.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ linux-2.6/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_
 		if (!num)
 			return;
 		pcibios_setup_bus_devices(bus);
-		max = bus->secondary;
+		max = bus->busn_res.start;
 		for (pass=0; pass < 2; pass++)
 			list_for_each_entry(dev, &bus->devices, bus_list) {
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
Index: linux-2.6/arch/sh/drivers/pci/pci.c
===================================================================
--- linux-2.6.orig/arch/sh/drivers/pci/pci.c
+++ linux-2.6/arch/sh/drivers/pci/pci.c
@@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(st
 	need_domain_info = need_domain_info || hose->index;
 	hose->need_domain_info = need_domain_info;
 	if (bus) {
-		next_busno = bus->subordinate + 1;
+		next_busno = bus->busn_res.end + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
 		if (next_busno > 224) {
Index: linux-2.6/arch/sparc/kernel/pci.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/pci.c
+++ linux-2.6/arch/sparc/kernel/pci.c
@@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge
 	}
 
 	bus->primary = dev->bus->number;
-	bus->subordinate = busrange[1];
+	pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
 	bus->bridge_ctl = 0;
 
 	/* parse ranges property, or cook one up by hand for Simba */
@@ -697,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_
 		pci_free_resource_list(&resources);
 		return NULL;
 	}
-	bus->secondary = pbm->pci_first_busno;
-	bus->subordinate = pbm->pci_last_busno;
 
 	pci_of_scan_bus(pbm, node, bus);
 	pci_bus_add_devices(bus);
Index: linux-2.6/arch/tile/kernel/pci.c
===================================================================
--- linux-2.6.orig/arch/tile/kernel/pci.c
+++ linux-2.6/arch/tile/kernel/pci.c
@@ -310,6 +310,7 @@ int __init pcibios_init(void)
 		if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
 			struct pci_controller *controller = &controllers[i];
 			struct pci_bus *bus;
+			LIST_HEAD(resources);
 
 			if (tile_init_irqs(i, controller)) {
 				pr_err("PCI: Could not initialize IRQs\n");
@@ -327,9 +328,11 @@ int __init pcibios_init(void)
 			 * This is inlined in linux/pci.h and calls into
 			 * pci_scan_bus_parented() in probe.c.
 			 */
-			bus = pci_scan_bus(0, controller->ops, controller);
+			pci_add_resource(&resources, &ioport_resource);
+			pci_add_resource(&resources, &iomem_resource);
+			bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources);
 			controller->root_bus = bus;
-			controller->last_busno = bus->subordinate;
+			controller->last_busno = bus->busn_res.end;
 		}
 	}
 
@@ -366,7 +369,7 @@ int __init pcibios_init(void)
 				 */
 				if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
 					(PCI_SLOT(dev->devfn) == 0)) {
-					next_bus = dev->subordinate;
+					next_bus = dev->busn_res.end;
 					controllers[i].mem_resources[0] =
 						*next_bus->resource[0];
 					controllers[i].mem_resources[1] =
Index: linux-2.6/arch/x86/pci/acpi.c
===================================================================
--- linux-2.6.orig/arch/x86/pci/acpi.c
+++ linux-2.6/arch/x86/pci/acpi.c
@@ -451,7 +451,7 @@ struct pci_bus * __devinit pci_acpi_scan
 		bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
 					  &resources);
 		if (bus) {
-			bus->subordinate = pci_scan_child_bus(bus);
+			pci_scan_child_bus(bus);
 			pci_set_host_bridge_release(
 				to_pci_host_bridge(bus->bridge),
 				release_pci_root_info, info);
Index: linux-2.6/arch/xtensa/kernel/pci.c
===================================================================
--- linux-2.6.orig/arch/xtensa/kernel/pci.c
+++ linux-2.6/arch/xtensa/kernel/pci.c
@@ -187,7 +187,7 @@ static int __init pcibios_init(void)
 		bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
 					pci_ctrl->ops, pci_ctrl, &resources);
 		pci_ctrl->bus = bus;
-		pci_ctrl->last_busno = bus->subordinate;
+		pci_ctrl->last_busno = bus->busn_res.end;
 		if (next_busno <= pci_ctrl->last_busno)
 			next_busno = pci_ctrl->last_busno+1;
 	}
Index: linux-2.6/drivers/iommu/intel-iommu.c
===================================================================
--- linux-2.6.orig/drivers/iommu/intel-iommu.c
+++ linux-2.6/drivers/iommu/intel-iommu.c
@@ -660,7 +660,7 @@ static struct intel_iommu *device_to_iom
 			if (drhd->devices[i] &&
 			    drhd->devices[i]->subordinate &&
 			    drhd->devices[i]->subordinate->number <= bus &&
-			    drhd->devices[i]->subordinate->subordinate >= bus)
+			    drhd->devices[i]->subordinate->busn_res.end >= bus)
 				return drhd->iommu;
 		}
 
Index: linux-2.6/drivers/net/ethernet/broadcom/tg3.c
===================================================================
--- linux-2.6.orig/drivers/net/ethernet/broadcom/tg3.c
+++ linux-2.6/drivers/net/ethernet/broadcom/tg3.c
@@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(
 			if (bridge->subordinate &&
 			    (bridge->subordinate->number <=
 			     tp->pdev->bus->number) &&
-			    (bridge->subordinate->subordinate >=
+			    (bridge->subordinate->busn_res.end >=
 			     tp->pdev->bus->number)) {
 				tg3_flag_set(tp, 5701_DMA_BUG);
 				pci_dev_put(bridge);
@@ -14224,7 +14224,7 @@ static int __devinit tg3_get_invariants(
 			if (bridge && bridge->subordinate &&
 			    (bridge->subordinate->number <=
 			     tp->pdev->bus->number) &&
-			    (bridge->subordinate->subordinate >=
+			    (bridge->subordinate->busn_res.end >=
 			     tp->pdev->bus->number)) {
 				tg3_flag_set(tp, 40BIT_DMA_BUG);
 				pci_dev_put(bridge);
Index: linux-2.6/drivers/parisc/dino.c
===================================================================
--- linux-2.6.orig/drivers/parisc/dino.c
+++ linux-2.6/drivers/parisc/dino.c
@@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus
 		int size, u32 *val)
 {
 	struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
@@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus
 	int size, u32 val)
 {
 	struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
@@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus)
         struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
 
 	DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n",
-	    __func__, bus, bus->secondary,
+	    __func__, bus, bus->busn_res.start,
 	    bus->bridge->platform_data);
 
 	/* Firmware doesn't set up card-mode dino, so we have to */
@@ -898,6 +898,7 @@ static int __init dino_probe(struct pari
 	LIST_HEAD(resources);
 	struct pci_bus *bus;
 	unsigned long hpa = dev->hpa.start;
+	int max;
 
 	name = "Dino";
 	if (is_card_dino(&dev->id)) {
@@ -1002,13 +1003,13 @@ static int __init dino_probe(struct pari
 		return 0;
 	}
 
-	pci_bus_update_busn_res_end(bus, bus->subordinate);
-	bus->subordinate = pci_scan_child_bus(bus);
+	max = pci_scan_child_bus(bus);
+	pci_bus_update_busn_res_end(bus, max);
 
 	/* This code *depends* on scanning being single threaded
 	 * if it isn't, this global bus number count will fail
 	 */
-	dino_current_bus = bus->subordinate + 1;
+	dino_current_bus = max + 1;
 	pci_bus_assign_resources(bus);
 	pci_bus_add_devices(bus);
 	return 0;
Index: linux-2.6/drivers/parisc/iosapic.c
===================================================================
--- linux-2.6.orig/drivers/parisc/iosapic.c
+++ linux-2.6/drivers/parisc/iosapic.c
@@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *i
 		intr_slot = PCI_SLOT(pcidev->devfn);
 	}
 	DBG_IRT("iosapic_xlate_pin:  bus %d slot %d pin %d\n",
-				pcidev->bus->secondary, intr_slot, intr_pin);
+			pcidev->bus->busn_res.start, intr_slot, intr_pin);
 
 	return irt_find_irqline(isi, intr_slot, intr_pin);
 }
Index: linux-2.6/drivers/parisc/lba_pci.c
===================================================================
--- linux-2.6.orig/drivers/parisc/lba_pci.c
+++ linux-2.6/drivers/parisc/lba_pci.c
@@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d)
 
 static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
 {
-	u8 first_bus = d->hba.hba_bus->secondary;
-	u8 last_sub_bus = d->hba.hba_bus->subordinate;
+	u8 first_bus = d->hba.hba_bus->busn_res.start;
+	u8 last_sub_bus = d->hba.hba_bus->busn_res.end;
 
 	if ((bus < first_bus) ||
 	    (bus > last_sub_bus) ||
@@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok
 static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 tok = LBA_CFG_TOK(local_bus, devfn);
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
@@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus
 		return 0;
 	}
 
-	if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {
+	if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) {
 		DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos);
 		/* either don't want to look or know device isn't present. */
 		*data = ~0U;
@@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok
 static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 tok = LBA_CFG_TOK(local_bus,devfn);
 
 	if ((pos > 255) || (devfn > 255))
@@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bu
 		return 0;
 	}
 
-	if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) {
+	if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) {
 		DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data);
 		return 1; /* New Workaround */
 	}
@@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = {
 static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 tok = LBA_CFG_TOK(local_bus, devfn);
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
@@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
 	u32 tok = LBA_CFG_TOK(local_bus,devfn);
 
 	if ((pos > 255) || (devfn > 255))
@@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus)
 	struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
 
 	DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
-		bus, bus->secondary, bus->bridge->platform_data);
+		bus, (int)bus->busn_res.start, bus->bridge->platform_data);
 
 	/*
 	** Properly Setup MMIO resources for this bus.
@@ -1366,6 +1366,7 @@ lba_driver_probe(struct parisc_device *d
 	void *tmp_obj;
 	char *version;
 	void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
+	int max;
 
 	/* Read HW Rev First */
 	func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1514,7 +1515,7 @@ lba_driver_probe(struct parisc_device *d
 		return 0;
 	}
 
-	lba_bus->subordinate = pci_scan_child_bus(lba_bus);
+	max = pci_scan_child_bus(lba_bus);
 
 	/* This is in lieu of calling pci_assign_unassigned_resources() */
 	if (is_pdc_pat()) {
@@ -1544,7 +1545,7 @@ lba_driver_probe(struct parisc_device *d
 		lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
 	}
 
-	lba_next_bus = lba_bus->subordinate + 1;
+	lba_next_bus = max + 1;
 	pci_bus_add_devices(lba_bus);
 
 	/* Whew! Finally done! Tell services we got this one covered. */
Index: linux-2.6/drivers/pci/hotplug-pci.c
===================================================================
--- linux-2.6.orig/drivers/pci/hotplug-pci.c
+++ linux-2.6/drivers/pci/hotplug-pci.c
@@ -7,7 +7,7 @@
 int __ref pci_hp_add_bridge(struct pci_dev *dev)
 {
 	struct pci_bus *parent = dev->bus;
-	int pass, busnr = parent->secondary;
+	int pass, busnr = parent->busn_res.start;
 
 	for (pass = 0; pass < 2; pass++)
 		busnr = pci_scan_bridge(parent, dev, busnr, pass);
Index: linux-2.6/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-2.6/drivers/pci/hotplug/acpiphp_glue.c
@@ -100,11 +100,11 @@ static int post_dock_fixups(struct notif
 			PCI_PRIMARY_BUS,
 			&buses);
 
-	if (((buses >> 8) & 0xff) != bus->secondary) {
+	if (((buses >> 8) & 0xff) != bus->busn_res.start) {
 		buses = (buses & 0xff000000)
 			| ((unsigned int)(bus->primary)     <<  0)
-			| ((unsigned int)(bus->secondary)   <<  8)
-			| ((unsigned int)(bus->subordinate) << 16);
+			| ((unsigned int)(bus->busn_res.start)   <<  8)
+			| ((unsigned int)(bus->busn_res.end) << 16);
 		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
 	}
 	return NOTIFY_OK;
@@ -628,7 +628,7 @@ static unsigned char acpiphp_max_busnr(s
 	 * bus->subordinate value because it could have
 	 * padding in it.
 	 */
-	max = bus->secondary;
+	max = bus->busn_res.start;
 
 	list_for_each(tmp, &bus->children) {
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
Index: linux-2.6/drivers/pci/hotplug/shpchp_sysfs.c
===================================================================
--- linux-2.6.orig/drivers/pci/hotplug/shpchp_sysfs.c
+++ linux-2.6/drivers/pci/hotplug/shpchp_sysfs.c
@@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device
 		}
 	}
 	out += sprintf(out, "Free resources: bus numbers\n");
-	for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
+	for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) {
 		if (!pci_find_bus(pci_domain_nr(bus), busnr))
 			break;
 	}
-	if (busnr < bus->subordinate)
+	if (busnr < bus->busn_res.end)
 		out += sprintf(out, "start = %8.8x, length = %8.8x\n",
-				busnr, (bus->subordinate - busnr));
+				busnr, (int)(bus->busn_res.end - busnr));
 
 	return out - buf;
 }
Index: linux-2.6/drivers/pci/iov.c
===================================================================
--- linux-2.6.orig/drivers/pci/iov.c
+++ linux-2.6/drivers/pci/iov.c
@@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(st
 	if (!child)
 		return NULL;
 
-	child->subordinate = busnr;
+	pci_bus_insert_busn_res(child, busnr, busnr);
 	child->dev.parent = bus->bridge;
 	rc = pci_bus_add_child(child);
 	if (rc) {
@@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *
 	iov->offset = offset;
 	iov->stride = stride;
 
-	if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) {
+	if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) {
 		dev_err(&dev->dev, "SR-IOV: bus number out of range\n");
 		return -ENOMEM;
 	}
Index: linux-2.6/drivers/pci/pci.c
===================================================================
--- linux-2.6.orig/drivers/pci/pci.c
+++ linux-2.6/drivers/pci/pci.c
@@ -109,7 +109,7 @@ unsigned char pci_bus_max_busnr(struct p
 	struct list_head *tmp;
 	unsigned char max, n;
 
-	max = bus->subordinate;
+	max = bus->busn_res.end;
 	list_for_each(tmp, &bus->children) {
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		if(n > max)
Index: linux-2.6/drivers/pci/probe.c
===================================================================
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -388,8 +388,7 @@ void __devinit pci_read_bridge_bases(str
 	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
 		return;
 
-	dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
-		 child->secondary, child->subordinate,
+	dev_info(&dev->dev, "PCI bridge to %pR%s\n", &child->busn_res,
 		 dev->transparent ? " (subtractive decode)" : "");
 
 	pci_bus_remove_resources(child);
@@ -606,9 +605,8 @@ static struct pci_bus *pci_alloc_child_b
 	 * Set up the primary, secondary and subordinate
 	 * bus numbers.
 	 */
-	child->number = child->secondary = busnr;
-	child->primary = parent->secondary;
-	child->subordinate = 0xff;
+	child->number = busnr;
+	child->primary = parent->busn_res.start;
 
 	if (!bridge)
 		return child;
@@ -668,9 +666,8 @@ static void __devinit pci_bus_update_top
 		res = &parent->busn_res;
 		if (res == parent_res)
 			break;
-		parent->subordinate += size;
 		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS,
-					 parent->subordinate);
+					 parent->busn_res.end);
 		dev_printk(KERN_DEBUG, &parent->dev,
 				"busn_res: %s %02lx to %pR\n",
 				(size > 0) ? "extended" : "shrunk",
@@ -832,12 +829,12 @@ int __devinit pci_scan_bridge(struct pci
 		 * to see if the new setting good.
 		 */
 		if (primary != child->primary ||
-		    secondary != child->secondary ||
-		    subordinate != child->subordinate) {
+		    secondary != child->busn_res.start ||
+		    subordinate != child->busn_res.end) {
 			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,
+				child->primary, (int)child->busn_res.start,
+				(int)child->busn_res.end,
 				primary, secondary, subordinate);
 			if (!list_empty(&dev->subordinate->devices)) {
 				u32 old_buses;
@@ -852,8 +849,8 @@ int __devinit pci_scan_bridge(struct pci
 				 */
 				old_buses = (buses & 0xff000000)
 				   | ((unsigned int)(child->primary)     <<  0)
-				   | ((unsigned int)(child->secondary)   <<  8)
-				   | ((unsigned int)(child->subordinate) << 16);
+				   | ((unsigned int)(child->busn_res.start)   <<  8)
+				   | ((unsigned int)(child->busn_res.end) << 16);
 				pci_write_config_dword(dev, PCI_PRIMARY_BUS,
 							 old_buses);
 				pci_stop_and_remove_behind_bridge(dev);
@@ -901,7 +898,6 @@ int __devinit pci_scan_bridge(struct pci
 			if (!child)
 				goto out;
 			child->primary = primary;
-			child->subordinate = subordinate;
 			child->bridge_ctl = bctl;
 
 			pci_bus_insert_busn_res(child, secondary, subordinate);
@@ -910,8 +906,8 @@ int __devinit pci_scan_bridge(struct pci
 		cmax = __pci_scan_child_bus(child, pass);
 		if (cmax > max)
 			max = cmax;
-		if (child->subordinate > max)
-			max = child->subordinate;
+		if (child->busn_res.end > max)
+			max = child->busn_res.end;
 	} else {
 		/*
 		 * We need to assign a number to this bus which we always
@@ -965,15 +961,14 @@ int __devinit pci_scan_bridge(struct pci
 		if (!child)
 			goto out;
 
-		child->subordinate = busn_res.end;
 		pci_bus_replace_busn_res(child, &busn_res);
 
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
-		      | ((unsigned int)(child->secondary)   <<  8)
-		      | ((unsigned int)(child->subordinate) << 16);
+		      | ((unsigned int)(child->busn_res.start)   <<  8)
+		      | ((unsigned int)(child->busn_res.end) << 16);
 
-		max = child->subordinate;
+		max = child->busn_res.end;
 
 		/*
 		 * yenta.c forces a secondary latency timer of 176.
@@ -996,13 +991,12 @@ int __devinit pci_scan_bridge(struct pci
 		/*
 		 * Set the subordinate bus number to its real value.
 		 */
-		if (dev->is_hotplug_bridge && child->subordinate > max &&
-		    (max - child->secondary) < HOTPLUG_BRIDGE_RESERVE_BUSNR)
-			max = min_t(int, child->secondary +
+		if (dev->is_hotplug_bridge && child->busn_res.end > max &&
+		    (max - child->busn_res.start) < HOTPLUG_BRIDGE_RESERVE_BUSNR)
+			max = min_t(int, child->busn_res.start +
 					 HOTPLUG_BRIDGE_RESERVE_BUSNR,
-				    child->subordinate);
-		shrink_size = child->subordinate - max;
-		child->subordinate = max;
+				    child->busn_res.end);
+		shrink_size = (int)child->busn_res.end - max;
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 		pci_bus_update_busn_res_end(child, max);
 
@@ -1023,19 +1017,19 @@ int __devinit pci_scan_bridge(struct pci
 
 	/* Has only triggered on CardBus, fixup is in yenta_socket */
 	while (bus->parent) {
-		if ((child->subordinate > bus->subordinate) ||
-		    (child->number > bus->subordinate) ||
+		if ((child->busn_res.end > bus->busn_res.end) ||
+		    (child->number > bus->busn_res.end) ||
 		    (child->number < bus->number) ||
-		    (child->subordinate < bus->number)) {
-			dev_info(&child->dev, "[bus %02x-%02x] %s "
-				"hidden behind%s bridge %s [bus %02x-%02x]\n",
-				child->number, child->subordinate,
-				(bus->number > child->subordinate &&
-				 bus->subordinate < child->number) ?
+		    (child->busn_res.end < bus->number)) {
+			dev_info(&child->dev, "%pR %s "
+				"hidden behind%s bridge %s %pR\n",
+				&child->busn_res,
+				(bus->number > child->busn_res.end &&
+				 bus->busn_res.end < child->number) ?
 					"wholly" : "partially",
 				bus->self->transparent ? " transparent" : "",
 				dev_name(&bus->dev),
-				bus->number, bus->subordinate);
+				&bus->busn_res);
 		}
 		bus = bus->parent;
 	}
@@ -1736,7 +1730,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_set
 static unsigned int __devinit __pci_scan_child_bus(struct pci_bus *bus,
 						 int pass)
 {
-	unsigned int devfn, max = bus->secondary;
+	unsigned int devfn, max = bus->busn_res.start;
 	struct pci_dev *dev;
 
 	dev_dbg(&bus->dev, "scanning bus pass %d\n", pass);
@@ -1845,7 +1839,7 @@ struct pci_bus *pci_create_root_bus(stru
 	/* Create legacy_io and legacy_mem files for this bus */
 	pci_create_legacy_files(b);
 
-	b->number = b->secondary = bus;
+	b->number = bus;
 
 	if (parent)
 		dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
@@ -1857,9 +1851,11 @@ struct pci_bus *pci_create_root_bus(stru
 		list_move_tail(&window->list, &bridge->windows);
 		res = window->res;
 		offset = window->offset;
-		if (res->flags & IORESOURCE_BUS)
+		if (res->flags & IORESOURCE_BUS) {
+			if (bus != res->start)
+				res->start = bus;
 			pci_bus_insert_busn_res(b, res->start, res->end);
-		else
+		} else
 			pci_bus_add_resource(b, res, 0);
 		if (offset) {
 			if (resource_type(res) == IORESOURCE_IO)
@@ -1947,6 +1943,7 @@ struct pci_bus * __devinit pci_scan_root
 	struct pci_host_bridge_window *window, *n;
 	struct resource *res;
 	bool found;
+	int max;
 
 	list_for_each_entry_safe(window, n, resources, list) {
 		res = window->res;
@@ -1967,10 +1964,10 @@ struct pci_bus * __devinit pci_scan_root
 		pci_bus_insert_busn_res(b, bus, 255);
 	}
 
-	b->subordinate = pci_scan_child_bus(b);
+	max = pci_scan_child_bus(b);
 
 	if (!found)
-		pci_bus_update_busn_res_end(b, b->subordinate);
+		pci_bus_update_busn_res_end(b, max);
 
 	pci_bus_add_devices(b);
 	return b;
@@ -1989,7 +1986,7 @@ struct pci_bus * __devinit pci_scan_bus_
 	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);
+		pci_scan_child_bus(b);
 	else
 		pci_free_resource_list(&resources);
 	return b;
@@ -2007,7 +2004,7 @@ struct pci_bus * __devinit pci_scan_bus(
 	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);
+		pci_scan_child_bus(b);
 		pci_bus_add_devices(b);
 	} else {
 		pci_free_resource_list(&resources);
Index: linux-2.6/drivers/pci/setup-bus.c
===================================================================
--- linux-2.6.orig/drivers/pci/setup-bus.c
+++ linux-2.6/drivers/pci/setup-bus.c
@@ -404,8 +404,7 @@ void pci_setup_cardbus(struct pci_bus *b
 	struct resource *res;
 	struct pci_bus_region region;
 
-	dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
-		 bus->secondary, bus->subordinate);
+	dev_info(&bridge->dev, "CardBus bridge to %pR\n", &bus->busn_res);
 
 	res = bus->resource[0];
 	pcibios_resource_to_bus(bridge, &region, res);
@@ -553,8 +552,7 @@ static void __pci_setup_bridge(struct pc
 {
 	struct pci_dev *bridge = bus->self;
 
-	dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
-		 bus->secondary, bus->subordinate);
+	dev_info(&bridge->dev, "PCI bridge to %pR\n", &bus->busn_res);
 
 	if (type & IORESOURCE_IO)
 		pci_setup_bridge_io(bus);
@@ -745,8 +743,8 @@ static void pbus_size_io(struct pci_bus
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
-				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
-				 bus->secondary, bus->subordinate);
+				 "%pR to %pR (unused)\n", b_res,
+				 &bus->busn_res);
 		b_res->flags = 0;
 		return;
 	}
@@ -757,8 +755,8 @@ static void pbus_size_io(struct pci_bus
 	if (size1 > size0 && realloc_head) {
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
-				 "%pR to [bus %02x-%02x] add_size %lx\n", b_res,
-				 bus->secondary, bus->subordinate, size1-size0);
+				 "%pR to %pR add_size %lx\n", b_res,
+				 &bus->busn_res, size1-size0);
 	}
 }
 
@@ -863,8 +861,8 @@ static int pbus_size_mem(struct pci_bus
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
-				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
-				 bus->secondary, bus->subordinate);
+				 "%pR to %pR (unused)\n", b_res,
+				 &bus->busn_res);
 		b_res->flags = 0;
 		return 1;
 	}
@@ -874,8 +872,8 @@ static int pbus_size_mem(struct pci_bus
 	if (size1 > size0 && realloc_head) {
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
-				 "%pR to [bus %02x-%02x] add_size %llx\n", b_res,
-				 bus->secondary, bus->subordinate, (unsigned long long)size1-size0);
+				 "%pR to %pR add_size %llx\n", b_res,
+				 &bus->busn_res, (unsigned long long)size1-size0);
 	}
 	return 1;
 }
Index: linux-2.6/drivers/pcmcia/cardbus.c
===================================================================
--- linux-2.6.orig/drivers/pcmcia/cardbus.c
+++ linux-2.6/drivers/pcmcia/cardbus.c
@@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
 	pci_fixup_cardbus(bus);
 
-	max = bus->secondary;
+	max = bus->busn_res.start;
 	for (pass = 0; pass < 2; pass++)
 		list_for_each_entry(dev, &bus->devices, bus_list)
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
Index: linux-2.6/drivers/pcmcia/yenta_socket.c
===================================================================
--- linux-2.6.orig/drivers/pcmcia/yenta_socket.c
+++ linux-2.6/drivers/pcmcia/yenta_socket.c
@@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yen
 	config_writeb(socket, PCI_LATENCY_TIMER, 168);
 	config_writel(socket, PCI_PRIMARY_BUS,
 		(176 << 24) |			   /* sec. latency timer */
-		(dev->subordinate->subordinate << 16) | /* subordinate bus */
-		(dev->subordinate->secondary << 8) |  /* secondary bus */
+		((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */
+		((unsigned int)dev->subordinate->busn_res.start << 8) |  /* secondary bus */
 		dev->subordinate->primary);		   /* primary bus */
 
 	/*
Index: linux-2.6/include/linux/pci.h
===================================================================
--- linux-2.6.orig/include/linux/pci.h
+++ linux-2.6/include/linux/pci.h
@@ -429,8 +429,6 @@ struct pci_bus {
 
 	unsigned char	number;		/* bus number */
 	unsigned char	primary;	/* number of primary bridge */
-	unsigned char	secondary;	/* number of secondary bridge */
-	unsigned char	subordinate;	/* max number of subordinate buses */
 	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
 

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

* Re: [PATCH -v11 17/30] resources: Add probe_resource()
  2012-05-01 23:57   ` Bjorn Helgaas
@ 2012-05-02  5:19     ` Yinghai Lu
  2012-05-02  7:01       ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-02  5:19 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Tue, May 1, 2012 at 4:57 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> It is changed from busn_res only version, because Bjorn found that version
>> was not holding resource_lock.
>> Even it may be ok for busn_res not holding resource_lock.
>> It would be better to have it to be generic and use lock and we would
>> use it for other resources.
>>
>> probe_resource() will try to find specified size or more in parent bus.
>> If can not find current parent resource, and it will try to expand parents
>> top.
>> If still can not find that specified on top, it will try to reduce target size
>> until find one.
>>
>> It will return 0, if it find any resource that it could use.
>>
>> Returned resource already register in the tree.
>>
>> So caller may still need call resource_replace to put real resource in
>> the tree.
>>
>> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> ---
>>  include/linux/ioport.h |    7 ++
>>  kernel/resource.c      |  160 ++++++++++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 162 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/linux/ioport.h b/include/linux/ioport.h
>> index e885ba2..20a30df 100644
>> --- a/include/linux/ioport.h
>> +++ b/include/linux/ioport.h
>> @@ -156,6 +156,13 @@ extern int allocate_resource(struct resource *root, struct resource *new,
>>                                                       resource_size_t,
>>                                                       resource_size_t),
>>                             void *alignf_data);
>> +void resource_shrink_parents_top(struct resource *b_res,
>> +                                long size, struct resource *parent_res);
>> +struct device;
>> +int probe_resource(struct resource *b_res,
>> +                       struct device *dev, struct resource *busn_res,
>> +                       resource_size_t needed_size, struct resource **p,
>> +                       int skip_nr, int limit, char *name);
>
> This interface is a mess.  I have a vague impression that this is
> supposed to figure out whether a resource can be expanded, but why
> does it need a struct device *?  (I can read the code and see how you
> use it, but it just doesn't fit in the resource abstraction.)

for debug printing purpose.

> Supplying one struct resource * makes sense, but you have three.  A
> char * name?  What's skip_nr?  This just doesn't make sense to me.

name is for debug purpose too.

skip_nr is for skipping.

for example: parent [60-7e]

when we try to probe for child buses, we need skip 60 as it is used already for
pci devices.


>
> I think you need a simpler, more general interface.  update_resource()
> seems OK to me -- it's pretty straightforward and has an obvious
> meaning.  Maybe you can make a resource_expand() or something that
> just expands a resource in both directions as far as possible (until
> it hits a sibling or the parent limits).  Then you would know the
> maximum possible size, and you could use update_resource() to shrink
> it again and give up anything you don't need.

both directions may need more code.

>
> I spent most of the day merging the patches up to this point, and they
> mostly make sense, but this one and the following ones are beyond my
> ken, so I gave up.

ok, let me check if i could simplify that code more.

Thanks

Yinghai

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

* Re: [PATCH -v11 17/30] resources: Add probe_resource()
  2012-05-02  5:19     ` Yinghai Lu
@ 2012-05-02  7:01       ` Yinghai Lu
  2012-05-02 15:14         ` Bjorn Helgaas
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-02  7:01 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

[-- Attachment #1: Type: text/plain, Size: 481 bytes --]

On Tue, May 1, 2012 at 10:19 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Tue, May 1, 2012 at 4:57 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> I spent most of the day merging the patches up to this point, and they
>> mostly make sense, but this one and the following ones are beyond my
>> ken, so I gave up.
>
> ok, let me check if i could simplify that code more.

Split this one into two patches, and add more comments.

Please check if it is readable.

Thanks

Yinghai

[-- Attachment #2: probe_resource_1.patch --]
[-- Type: application/octet-stream, Size: 2278 bytes --]

Subject: [PATCH] resources: Split out __allocate_resource()

It will take bool lock, so we could use it in other functions that
hold the resource lock.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>


---
 kernel/resource.c |   24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

Index: linux-2.6/kernel/resource.c
===================================================================
--- linux-2.6.orig/kernel/resource.c
+++ linux-2.6/kernel/resource.c
@@ -570,14 +570,14 @@ out:
  * @alignf: alignment function, optional, called if not NULL
  * @alignf_data: arbitrary data to pass to the @alignf function
  */
-int allocate_resource(struct resource *root, struct resource *new,
+static int __allocate_resource(struct resource *root, struct resource *new,
 		      resource_size_t size, resource_size_t min,
 		      resource_size_t max, resource_size_t align,
 		      resource_size_t (*alignf)(void *,
 						const struct resource *,
 						resource_size_t,
 						resource_size_t),
-		      void *alignf_data)
+		      void *alignf_data, bool lock)
 {
 	int err;
 	struct resource_constraint constraint;
@@ -591,19 +591,33 @@ int allocate_resource(struct resource *r
 	constraint.alignf = alignf;
 	constraint.alignf_data = alignf_data;
 
-	if ( new->parent ) {
+	if (new->parent && lock) {
 		/* resource is already allocated, try reallocating with
 		   the new constraints */
 		return reallocate_resource(root, new, size, &constraint);
 	}
 
-	write_lock(&resource_lock);
+	if (lock)
+		write_lock(&resource_lock);
 	err = find_resource(root, new, size, &constraint);
 	if (err >= 0 && __request_resource(root, new))
 		err = -EBUSY;
-	write_unlock(&resource_lock);
+	if (lock)
+		write_unlock(&resource_lock);
 	return err;
 }
+int allocate_resource(struct resource *root, struct resource *new,
+		      resource_size_t size, resource_size_t min,
+		      resource_size_t max, resource_size_t align,
+		      resource_size_t (*alignf)(void *,
+						const struct resource *,
+						resource_size_t,
+						resource_size_t),
+		      void *alignf_data)
+{
+	return __allocate_resource(root, new, size, min, max, align,
+				   alignf, alignf_data, true);
+}
 
 EXPORT_SYMBOL(allocate_resource);
 

[-- Attachment #3: probe_resource_2.patch --]
[-- Type: application/octet-stream, Size: 6313 bytes --]

Subject: [PATCH] resources: Add probe_resource()

It is changed from busn_res only version, because Bjorn found that version
was not holding resource_lock.
Even it may be ok for busn_res not holding resource_lock.
It would be better to have it to be generic and use lock and we would
use it for other resources.

probe_resource() will try to find specified size or more in parent bus.
If can not find current parent resource, and it will try to expand parents
top.
If still can not find that specified on top, it will try to reduce target size
until find one.

It will return 0, if it find any resource that it could use.

Returned resource already register in the tree.

So caller may still need call replace_resource to put real resource in
the tree.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>


---
 include/linux/ioport.h |    7 ++
 kernel/resource.c      |  157 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)

Index: linux-2.6/include/linux/ioport.h
===================================================================
--- linux-2.6.orig/include/linux/ioport.h
+++ linux-2.6/include/linux/ioport.h
@@ -158,6 +158,13 @@ extern int allocate_resource(struct reso
 						       resource_size_t,
 						       resource_size_t),
 			     void *alignf_data);
+void resource_shrink_parents_top(struct resource *b_res,
+				 long size, struct resource *parent_res);
+struct device;
+int probe_resource(struct resource *b_res,
+			struct device *dev, struct resource *busn_res,
+			resource_size_t needed_size, struct resource **p,
+			int skip_nr, int limit, char *name);
 struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
 		    resource_size_t size);
Index: linux-2.6/kernel/resource.c
===================================================================
--- linux-2.6.orig/kernel/resource.c
+++ linux-2.6/kernel/resource.c
@@ -1024,6 +1024,163 @@ void __release_region(struct resource *p
 }
 EXPORT_SYMBOL(__release_region);
 
+static void __resource_update_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	struct resource *res = b_res;
+
+	if (!size)
+		return;
+
+	while (res) {
+		if (res == parent_res)
+			break;
+		res->end += size;
+		res = res->parent;
+	}
+}
+
+static void __resource_extend_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	__resource_update_parents_top(b_res, size, parent_res);
+}
+
+void resource_shrink_parents_top(struct resource *b_res,
+		 long size, struct resource *parent_res)
+{
+	write_lock(&resource_lock);
+	__resource_update_parents_top(b_res, -size, parent_res);
+	write_unlock(&resource_lock);
+}
+
+static resource_size_t __find_res_top_free_size(struct resource *res,
+						 int skip_nr)
+{
+	resource_size_t n_size;
+	struct resource tmp_res;
+
+	/*
+	 *   find out free number below res->end that we can use.
+	 *	res->start to res->start + skip_nr - 1 can not be used.
+	 */
+	n_size = resource_size(res);
+	if (n_size <= skip_nr)
+		return 0;
+
+	n_size -= skip_nr;
+	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 + skip_nr, res->end,
+			1, NULL, NULL, false);
+		if (ret == 0) {
+			__release_resource(&tmp_res);
+			break;
+		}
+		n_size--;
+	}
+
+	return n_size;
+}
+
+/**
+ * probe_resource - Probe resource in parent resource.
+ * @b_res: parent resource descriptor
+ * @dev: debug purpose
+ * @busn_res: return probed resource
+ * @needed_size: target size
+ * @p: pointer to farest parent that we extend the top
+ * @skip_nr: number in b_res start that we need to skip.
+ * @limit: local boundary
+ * @name: debug purpose
+ *
+ * will try to allocate resource in b_res, if can not find the range
+ *  will try to extend parent resources' top.
+ * if still can not make it, will reduce needed_size.
+ */
+int probe_resource(struct resource *b_res,
+			 struct device *dev, struct resource *busn_res,
+			 resource_size_t needed_size, struct resource **p,
+			 int skip_nr, int limit, char *name)
+{
+	int ret = -ENOMEM;
+	resource_size_t n_size;
+	struct resource *parent_res = NULL;
+	resource_size_t tmp = b_res->end + 1;
+
+again:
+	/*
+	 * We first try to allocate biggest range in b_res that
+	 *  we can use in b_res directly.
+	 *  we can not use skip_nr from start of b_res.
+	 */
+	n_size = resource_size(b_res);
+	if (n_size > skip_nr)
+		n_size -= skip_nr;
+	else
+		n_size = 0;
+	memset(busn_res, 0, sizeof(struct resource));
+	dev_printk(KERN_DEBUG, dev, "find free %s in res: %pR\n", name, b_res);
+	while (n_size >= needed_size) {
+		ret = allocate_resource(b_res, busn_res, n_size,
+				b_res->start + skip_nr, b_res->end,
+				1, NULL, NULL);
+		if (!ret)
+			return ret;
+		n_size--;
+	}
+
+	/* We need to extend the top of parent resources to meet needed_size */
+
+	/* find out free range under top at first */
+	write_lock(&resource_lock);
+	n_size = __find_res_top_free_size(b_res, skip_nr);
+	dev_printk(KERN_DEBUG, dev, "found free %s %ld in res: %pR top\n",
+			name, (unsigned long)n_size, b_res);
+	/* can not extend cross local boundary */
+	if ((limit - b_res->end) < (needed_size - n_size))
+		goto reduce_needed_size;
+
+	/* Probe extended range above top */
+	memset(busn_res, 0, sizeof(struct resource));
+	parent_res = b_res->parent;
+	while (parent_res) {
+		ret = __allocate_resource(parent_res, busn_res,
+			 needed_size - n_size,
+			 tmp, tmp + needed_size - n_size - 1,
+			 1, NULL, NULL, false);
+		if (!ret) {
+			/* save parent_res, we need it as stopper later */
+			*p = parent_res;
+
+			/* prepare busn_res for return */
+			__release_resource(busn_res);
+			busn_res->start -= n_size;
+
+			/* extend parent resources top*/
+			__resource_extend_parents_top(b_res,
+					 needed_size - n_size, parent_res);
+			__request_resource(b_res, busn_res);
+
+			write_unlock(&resource_lock);
+			return ret;
+		}
+		parent_res = parent_res->parent;
+	}
+
+reduce_needed_size:
+	write_unlock(&resource_lock);
+	/* ret must not be 0 here */
+	needed_size--;
+	if (needed_size)
+		goto again;
+
+	return ret;
+}
+
 /*
  * Managed region resource
  */

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

* Re: [PATCH -v11 17/30] resources: Add probe_resource()
  2012-05-02  7:01       ` Yinghai Lu
@ 2012-05-02 15:14         ` Bjorn Helgaas
  0 siblings, 0 replies; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-02 15:14 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Wed, May 2, 2012 at 1:01 AM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Tue, May 1, 2012 at 10:19 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> On Tue, May 1, 2012 at 4:57 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>> I spent most of the day merging the patches up to this point, and they
>>> mostly make sense, but this one and the following ones are beyond my
>>> ken, so I gave up.
>>
>> ok, let me check if i could simplify that code more.

I suggested that you need a simpler *interface*, not just smaller
patches and more comments.  If the interfaces make sense and the code
is good, you don't need many comments.

> Split this one into two patches, and add more comments.
>
> Please check if it is readable.

Nope, sorry, I'm not putting my name on that.  If you still think
that's the only reasonable way to do it, you might be able to find
somebody else to merge the resource.c changes, and I'll just worry
about the drivers/pci parts.

Bjorn

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

* Re: [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn
  2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
                   ` (29 preceding siblings ...)
  2012-03-19  5:43 ` [PATCH -v11 30/30] PCI: Don't shrink too much for hotplug bridge Yinghai Lu
@ 2012-05-02 21:22 ` Bjorn Helgaas
  2012-05-03  9:08   ` Yinghai Lu
  30 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-02 21:22 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> 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 linux v3.3 + pci-next and
>        [PATCH -v3] PCI: pci_host_bridge related cleanup
>
> could be found at:
>        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-busn-alloc

I started merging this series, but I didn't get very far.  I stopped
at the "resources: Add probe_resource()" patch because I don't think
that interface makes sense yet.  My work-in-progress is at
git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git on the
topic/yinghai-busn-alloc branch.

I *could* merge that branch, but I don't think they fix anything (that
would come in the later patches), and there are still some issues in
my mind.

  - I think we really want a [bus 00-ff] resource for each *domain*,
with each host bridge in the domain requesting part of that range.  I
think these patches only track bus number usage within each host
bridge, and I'm not sure there's any place we would detect conflicts
between host bridges.

  - I think I made a mistake in the pci_create_root_bus() and
pci_scan_root_bus() interfaces.  They currently take a bus number and
a list of resources, and we expect the arch to include the bus number
aperture in the list.  The bus number argument should have been
replaced with a bus number aperture resource.  The bus number aperture
is essential, while the MMIO/IO aperture list may be empty.  And it's
stupid to pass both the starting bus number and a bus resource that
contains the starting bus number.  Fixing this would make some of
these patches quite a bit simpler.

  - In some of the arches (sparc, powerpc), you added a bus number
resource right next to existing first_busno, last_busno fields.  So
now that data lives two places, which will bite us later.

Bjorn


> Yinghai Lu (30):
>  x86, PCI: Add print all root info for not using _CRS 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_res when removing bus
>  PCI: Insert busn_res in pci_create_root_bus()
>  PCI: Checking busn_res in pci_scan_root_bus()
>  PCI: Add default busn_resource
>  PCI: Add default busn_res for pci_scan_bus()
>  x86, PCI: Add busn_res into resources list for acpi path
>  x86, PCI: Put busn resource in pci_root_info for not using _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
>  resources: Add probe_resource()
>  resources: Replace registered resource in tree.
>  PCI: Add pci_bus_extend/shrink_top()
>  PCI: Probe safe range that we can use for unassigned bridge.
>  PCI: Add pci_bus_replace_busn_res()
>  PCI: Allocate bus range instead of use max blindly
>  PCI: Strict checking of valid range for bridge
>  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
>  PCI: More strict checking of valid range for bridge
>  PCI: Don't shrink too much for hotplug bridge
>
>  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                   |   11 +-
>  arch/x86/pci/amd_bus.c                |   14 +-
>  arch/x86/pci/bus_numa.c               |   30 ++-
>  arch/x86/pci/bus_numa.h               |    4 +-
>  arch/x86/pci/common.c                 |   27 +--
>  drivers/parisc/dino.c                 |    5 +
>  drivers/parisc/lba_pci.c              |    3 +
>  drivers/pci/hotplug/pciehp_pci.c      |   12 +-
>  drivers/pci/probe.c                   |  439 +++++++++++++++++++++++++++------
>  drivers/pci/remove.c                  |    1 +
>  drivers/pcmcia/yenta_socket.c         |   75 ------
>  include/linux/ioport.h                |    8 +
>  include/linux/pci.h                   |    6 +
>  kernel/resource.c                     |  175 +++++++++++++-
>  19 files changed, 613 insertions(+), 215 deletions(-)
>
> --
> 1.7.7
>

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

* Re: [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn
  2012-05-02 21:22 ` [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Bjorn Helgaas
@ 2012-05-03  9:08   ` Yinghai Lu
  2012-05-03 23:47     ` Bjorn Helgaas
  0 siblings, 1 reply; 49+ messages in thread
From: Yinghai Lu @ 2012-05-03  9:08 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Wed, May 2, 2012 at 2:22 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> 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 linux v3.3 + pci-next and
>>        [PATCH -v3] PCI: pci_host_bridge related cleanup
>>
>> could be found at:
>>        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-busn-alloc
>
> I started merging this series, but I didn't get very far.  I stopped
> at the "resources: Add probe_resource()" patch because I don't think
> that interface makes sense yet.  My work-in-progress is at
> git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git on the
> topic/yinghai-busn-alloc branch.
>
> I *could* merge that branch, but I don't think they fix anything (that
> would come in the later patches), and there are still some issues in
> my mind.
>
>  - I think we really want a [bus 00-ff] resource for each *domain*,
> with each host bridge in the domain requesting part of that range.  I
> think these patches only track bus number usage within each host
> bridge, and I'm not sure there's any place we would detect conflicts
> between host bridges.

I updated the patch set a bit. now it have domain busn_res.

It could detect the conflicts. later could add code to resolve the conflicts.

int 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;

        if (!pci_is_root_bus(b))
                parent_res = &b->parent->busn_res;
        else {
                parent_res = get_pci_domain_busn_res(pci_domain_nr(b));
                res->flags |= IORESOURCE_PCI_FIXED;
        }

        ret = insert_resource(parent_res, res);

        dev_printk(KERN_DEBUG, &b->dev,
                        "busn_res: %pR %s inserted under %s %pR\n",
                        res, ret ? "can not be" : "is",
                        pci_is_root_bus(b) ? "domain":"", parent_res);

        return ret;
}


>
>  - I think I made a mistake in the pci_create_root_bus() and
> pci_scan_root_bus() interfaces.  They currently take a bus number and
> a list of resources, and we expect the arch to include the bus number
> aperture in the list.  The bus number argument should have been
> replaced with a bus number aperture resource.  The bus number aperture
> is essential, while the MMIO/IO aperture list may be empty.  And it's
> stupid to pass both the starting bus number and a bus resource that
> contains the starting bus number.  Fixing this would make some of
> these patches quite a bit simpler.

Yes, could try to address that later to make it more clean.

>  - In some of the arches (sparc, powerpc), you added a bus number
> resource right next to existing first_busno, last_busno fields.  So
> now that data lives two places, which will bite us later.

then later we should kill first_busno and last_busno in those arches.

Yinghai

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

* Re: [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn
  2012-05-03  9:08   ` Yinghai Lu
@ 2012-05-03 23:47     ` Bjorn Helgaas
  2012-05-04 20:07       ` Yinghai Lu
  0 siblings, 1 reply; 49+ messages in thread
From: Bjorn Helgaas @ 2012-05-03 23:47 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Thu, May 3, 2012 at 3:08 AM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Wed, May 2, 2012 at 2:22 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>>> 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.

>>  - I think we really want a [bus 00-ff] resource for each *domain*,
>> with each host bridge in the domain requesting part of that range.  I
>> think these patches only track bus number usage within each host
>> bridge, and I'm not sure there's any place we would detect conflicts
>> between host bridges.
>
> I updated the patch set a bit. now it have domain busn_res.

I like the domain bus range stuff ("Add busn_res for pci domain").
I'd like it better if we centralized more of the PCI domain support in
the core, e.g., supply the domain directly to pci_scan_root_bus() and
get rid of the arch-specific pci_domain_nr() implementations.  But
that can be done later.

> It could detect the conflicts. later could add code to resolve the conflicts.

This is in "Add busn_res operation functions".  I think this makes
sense, too.  If you look at the branch I started merging
(topic/yinghai-busn-alloc), I tweaked it to print the conflicting
resource when the insertion fails.  That information is almost always
useful when debugging, so it'd be nice if you picked that up, too.

>>  - In some of the arches (sparc, powerpc), you added a bus number
>> resource right next to existing first_busno, last_busno fields.  So
>> now that data lives two places, which will bite us later.
>
> then later we should kill first_busno and last_busno in those arches.

I want to be sensitive to the arch maintainers by doing our homework,
minimizing the number of patches we ask them to review, and grouping
related changes all at one time.  I propose the following, using
powerpc as an example:

  - Add "struct resource busn_res" to struct pci_bus.
  - powerpc: Replace pci_controller.first_busno/last_busno by "struct
resource busno" everywhere.  This will touch many places, but should
be completely mechanical and obvious.
  - powerpc: Replace all pci_bus.secondary/subordinate references with
busn_res.  This also be only obvious changes.
  - powerpc: Add the pci_add_resource() and pci_bus_update_busn_res_end() calls.
  - powerpc: Add pci_bus_insert_busn_res() call in
of_scan_pci_bridge().  (This is currently buried in the "Remove
secondary/subordinate in pci_bus" patch, but it doesn't fit there.)
  - Replace all non-arch pci_bus.secondary/subordinate references with
busn_res.  Obvious changes only.
  - Remove secondary/subordinate from struct pci_bus.
  - Add pci_bus_insert_busn_res() calls.  Again, this is logically
separate from "Remove secondary/subordinate in pci_bus".

I would split up the "Remove secondary/subordinate in pci_bus" patch,
which currently touches 30 files across 11 arches, so an arch
maintainer doesn't have to read the whole patch.

Ben, Dave, feel free to chime in if I'm going astray.

I did a fair amount of work updating changelogs and tweaking the code
in my topic/yinghai-busn-alloc branch.  I know I'm currently a
bottleneck here, and it's worse because I'm a bit obsessive.  It would
save me time if you picked up those tweaks so I don't have to re-do
them.

You have over 100 patches outstanding, and I'm having a hard time
making forward progress.  I think we need to focus on just replacing
secondary/subordinate with busn_res, doing the corresponding
arch-specific replacements, and adding the insert_resource() stuff to
build the resource trees for bus numbers.  I'm not going to merge the
probe_resource() stuff, so let's defer that and the resource
assignment stuff for later.  Also defer the unrelated
pci_hp_add_bridge() stuff that crept into your for-pci-busn-alloc
branch.  If you defer all that stuff and split out the arch stuff,
that should leave us with around 30 patches that deal *only* with
adding busn_res and building the resource trees.  I don't think this
will fix any bugs or add any new functionality, but at least it's a
manageable step towards getting the infrastructure in place, so it's
reasonable to consider merging it.

These patches need to appear on the mailing list.  In general, people
aren't going to pull your git tree and review them as I've been doing.
 But *only* post the stuff mentioned above (busn_res and related
things).  I'm not ready to consider the rest yet, so they would only
confuse things.

Bjorn

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

* Re: [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn
  2012-05-03 23:47     ` Bjorn Helgaas
@ 2012-05-04 20:07       ` Yinghai Lu
  0 siblings, 0 replies; 49+ messages in thread
From: Yinghai Lu @ 2012-05-04 20:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jesse Barnes, Benjamin Herrenschmidt, Tony Luck, David Miller,
	x86, Dominik Brodowski, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-arch

On Thu, May 3, 2012 at 4:47 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>
>> It could detect the conflicts. later could add code to resolve the conflicts.
>
> This is in "Add busn_res operation functions".  I think this makes
> sense, too.  If you look at the branch I started merging
> (topic/yinghai-busn-alloc), I tweaked it to print the conflicting
> resource when the insertion fails.  That information is almost always
> useful when debugging, so it'd be nice if you picked that up, too.

ok, will check that branch and put that change in.

>
>>>  - In some of the arches (sparc, powerpc), you added a bus number
>>> resource right next to existing first_busno, last_busno fields.  So
>>> now that data lives two places, which will bite us later.
>>
>> then later we should kill first_busno and last_busno in those arches.
>
> I want to be sensitive to the arch maintainers by doing our homework,
> minimizing the number of patches we ask them to review, and grouping
> related changes all at one time.  I propose the following, using
> powerpc as an example:
>
>  - Add "struct resource busn_res" to struct pci_bus.
>  - powerpc: Replace pci_controller.first_busno/last_busno by "struct
> resource busno" everywhere.  This will touch many places, but should
> be completely mechanical and obvious.
>  - powerpc: Replace all pci_bus.secondary/subordinate references with
> busn_res.  This also be only obvious changes.
>  - powerpc: Add the pci_add_resource() and pci_bus_update_busn_res_end() calls.
>  - powerpc: Add pci_bus_insert_busn_res() call in
> of_scan_pci_bridge().  (This is currently buried in the "Remove
> secondary/subordinate in pci_bus" patch, but it doesn't fit there.)
>  - Replace all non-arch pci_bus.secondary/subordinate references with
> busn_res.  Obvious changes only.
>  - Remove secondary/subordinate from struct pci_bus.
>  - Add pci_bus_insert_busn_res() calls.  Again, this is logically
> separate from "Remove secondary/subordinate in pci_bus".
>
> I would split up the "Remove secondary/subordinate in pci_bus" patch,
> which currently touches 30 files across 11 arches, so an arch
> maintainer doesn't have to read the whole patch.

could split that a little. not sure if it is worth it.

1. core update subordinate and busn_res.end at same time.
2. update subordinate and busn_res.end at same time
2. remove using secondary/subordinate in arch
3. remove using secondary/suborindate in core

>
> Ben, Dave, feel free to chime in if I'm going astray.
>
> I did a fair amount of work updating changelogs and tweaking the code
> in my topic/yinghai-busn-alloc branch.  I know I'm currently a
> bottleneck here, and it's worse because I'm a bit obsessive.  It would
> save me time if you picked up those tweaks so I don't have to re-do
> them.

ok, will pick them up.

>
> You have over 100 patches outstanding, and I'm having a hard time
> making forward progress.  I think we need to focus on just replacing
> secondary/subordinate with busn_res, doing the corresponding
> arch-specific replacements, and adding the insert_resource() stuff to
> build the resource trees for bus numbers.  I'm not going to merge the
> probe_resource() stuff, so let's defer that and the resource
> assignment stuff for later.  Also defer the unrelated
> pci_hp_add_bridge() stuff that crept into your for-pci-busn-alloc
> branch.  If you defer all that stuff and split out the arch stuff,
> that should leave us with around 30 patches that deal *only* with
> adding busn_res and building the resource trees.  I don't think this
> will fix any bugs or add any new functionality, but at least it's a
> manageable step towards getting the infrastructure in place, so it's
> reasonable to consider merging it.

let me check if i change to that order.

>
> These patches need to appear on the mailing list.  In general, people
> aren't going to pull your git tree and review them as I've been doing.
>  But *only* post the stuff mentioned above (busn_res and related
> things).  I'm not ready to consider the rest yet, so they would only
> confuse things.

ok.

Yinghai

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

end of thread, other threads:[~2012-05-04 20:07 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 02/30] x86, PCI: Allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 03/30] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus Yinghai Lu
2012-04-30 23:25   ` Bjorn Helgaas
2012-05-01  0:32     ` Yinghai Lu
2012-05-01  4:02       ` Bjorn Helgaas
2012-05-01  6:27         ` Yinghai Lu
2012-05-01 15:40           ` Bjorn Helgaas
2012-05-01 19:28             ` Yinghai Lu
2012-05-02  5:07               ` Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 05/30] PCI: Add busn_res operation functions Yinghai Lu
2012-04-30 23:29   ` Bjorn Helgaas
2012-05-01  0:34     ` Yinghai Lu
2012-05-01  7:19       ` Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 06/30] PCI: Release busn_res when removing bus Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 07/30] PCI: Insert busn_res in pci_create_root_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 08/30] PCI: Checking busn_res in pci_scan_root_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 09/30] PCI: Add default busn_resource Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 10/30] PCI: Add default busn_res for pci_scan_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 11/30] x86, PCI: Add busn_res into resources list for acpi path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 12/30] x86, PCI: Put busn resource in pci_root_info for not using _CRS path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 13/30] PCI, ia64: Register busn_res for root buses Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 14/30] PCI, sparc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 15/30] PCI, powerpc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 16/30] PCI, parisc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 17/30] resources: Add probe_resource() Yinghai Lu
2012-05-01 23:57   ` Bjorn Helgaas
2012-05-02  5:19     ` Yinghai Lu
2012-05-02  7:01       ` Yinghai Lu
2012-05-02 15:14         ` Bjorn Helgaas
2012-03-19  5:42 ` [PATCH -v11 18/30] resources: Replace registered resource in tree Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 19/30] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 20/30] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 21/30] PCI: Add pci_bus_replace_busn_res() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 22/30] PCI: Allocate bus range instead of use max blindly Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 23/30] PCI: Strict checking of valid range for bridge Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 24/30] PCI: Kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 25/30] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 26/30] pcmcia: Remove workaround for fixing pci parent bus subordinate Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 27/30] PCI: Double checking setting for bus register and bus struct Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 28/30] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
2012-03-19  5:43 ` [PATCH -v11 29/30] PCI: More strict checking of valid range for bridge Yinghai Lu
2012-03-19  5:43 ` [PATCH -v11 30/30] PCI: Don't shrink too much for hotplug bridge Yinghai Lu
2012-05-02 21:22 ` [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Bjorn Helgaas
2012-05-03  9:08   ` Yinghai Lu
2012-05-03 23:47     ` Bjorn Helgaas
2012-05-04 20:07       ` 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).