Эх сурвалжийг харах

Merge branch 'topic/yinghai-busn-alloc' into next

* topic/yinghai-busn-alloc: (33 commits)
  PCI: hotplug: remove pci_do_scan_bus()
  PCI: sgihp: use generic pci_hp_add_bridge()
  PCI: ibmhp: use generic pci_hp_add_bridge()
  PCI: cpqhp: use generic pci_hp_add_bridge()
  PCI: shpchp: use generic pci_hp_add_bridge()
  PCI: cpci_hotplug: use generic pci_hp_add_bridge()
  PCI: pciehp: use generic pci_hp_add_bridge()
  PCI: add generic pci_hp_add_bridge()
  PCI: sgihp: register busn_res
  PCI: ibmhp: register busn_res
  PCI: cpqhp: register busn_res
  PCI: shpchp: register busn_res
  PCI: cpci_hotplug: register busn_res
  PCI: insert busn_res for child bus
  PCI: register busn_res for iov bus
  tile/PCI: use pci_scan_root_bus instead pci_scan_bus
  parisc/PCI: register busn_res for root buses
  powerpc/PCI: register busn_res for root buses
  sparc/PCI: register busn_res for root buses
  ia64/PCI: register busn_res for root buses
  ...
Bjorn Helgaas 13 жил өмнө
parent
commit
4d17e8516a
44 өөрчлөгдсөн 367 нэмэгдсэн , 245 устгасан
  1. 1 1
      arch/alpha/kernel/pci.c
  2. 1 1
      arch/arm/kernel/bios32.c
  3. 3 1
      arch/ia64/pci/pci.c
  4. 2 2
      arch/microblaze/pci/pci-common.c
  5. 1 1
      arch/mips/pci/pci.c
  6. 1 0
      arch/powerpc/include/asm/pci-bridge.h
  7. 11 6
      arch/powerpc/kernel/pci-common.c
  8. 1 1
      arch/powerpc/kernel/pci_64.c
  9. 1 1
      arch/powerpc/kernel/pci_of_scan.c
  10. 4 4
      arch/powerpc/platforms/powernv/pci-ioda.c
  11. 1 1
      arch/powerpc/platforms/pseries/pci_dlpar.c
  12. 1 1
      arch/sh/drivers/pci/pci.c
  13. 5 3
      arch/sparc/kernel/pci.c
  14. 1 0
      arch/sparc/kernel/pci_impl.h
  15. 6 3
      arch/tile/kernel/pci.c
  16. 5 4
      arch/x86/pci/acpi.c
  17. 3 4
      arch/x86/pci/amd_bus.c
  18. 19 3
      arch/x86/pci/bus_numa.c
  19. 1 2
      arch/x86/pci/bus_numa.h
  20. 1 1
      arch/xtensa/kernel/pci.c
  21. 1 1
      drivers/iommu/intel-iommu.c
  22. 2 2
      drivers/net/ethernet/broadcom/tg3.c
  23. 11 5
      drivers/parisc/dino.c
  24. 1 1
      drivers/parisc/iosapic.c
  25. 15 11
      drivers/parisc/lba_pci.c
  26. 19 11
      drivers/pci/hotplug-pci.c
  27. 4 4
      drivers/pci/hotplug/acpiphp_glue.c
  28. 6 29
      drivers/pci/hotplug/cpci_hotplug_pci.c
  29. 4 4
      drivers/pci/hotplug/cpqphp_pci.c
  30. 4 4
      drivers/pci/hotplug/ibmphp_core.c
  31. 2 26
      drivers/pci/hotplug/pciehp_pci.c
  32. 5 7
      drivers/pci/hotplug/sgi_hotplug.c
  33. 15 30
      drivers/pci/hotplug/shpchp_pci.c
  34. 3 3
      drivers/pci/hotplug/shpchp_sysfs.c
  35. 2 2
      drivers/pci/iov.c
  36. 1 1
      drivers/pci/pci.c
  37. 1 1
      drivers/pci/pci.h
  38. 161 30
      drivers/pci/probe.c
  39. 1 0
      drivers/pci/remove.c
  40. 12 12
      drivers/pci/setup-bus.c
  41. 1 1
      drivers/pcmcia/cardbus.c
  42. 13 13
      drivers/pcmcia/yenta_socket.c
  43. 6 2
      include/linux/pci.h
  44. 8 5
      kernel/resource.c

+ 1 - 1
arch/alpha/kernel/pci.c

@@ -359,7 +359,7 @@ common_init_pci(void)
 					hose, &resources);
 					hose, &resources);
 		hose->bus = bus;
 		hose->bus = bus;
 		hose->need_domain_info = need_domain_info;
 		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 -
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */ 
 		   reserve some space for bridges. */ 
 		if (next_busno > 224) {
 		if (next_busno > 224) {

+ 1 - 1
arch/arm/kernel/bios32.c

@@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 			if (!sys->bus)
 			if (!sys->bus)
 				panic("PCI: unable to scan bus!");
 				panic("PCI: unable to scan bus!");
 
 
-			busnr = sys->bus->subordinate + 1;
+			busnr = sys->bus->busn_res.end + 1;
 
 
 			list_add(&sys->node, head);
 			list_add(&sys->node, head);
 		} else {
 		} else {

+ 3 - 1
arch/ia64/pci/pci.c

@@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
 #endif
 #endif
 
 
 	INIT_LIST_HEAD(&info.resources);
 	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,
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
 			&windows);
 			&windows);
 	if (windows) {
 	if (windows) {
@@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	pbus->subordinate = pci_scan_child_bus(pbus);
+	pci_scan_child_bus(pbus);
 	return pbus;
 	return pbus;
 
 
 out3:
 out3:

+ 2 - 2
arch/microblaze/pci/pci-common.c

@@ -1506,10 +1506,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
 		pci_free_resource_list(&resources);
 		pci_free_resource_list(&resources);
 		return;
 		return;
 	}
 	}
-	bus->secondary = hose->first_busno;
+	bus->busn_res.start = hose->first_busno;
 	hose->bus = bus;
 	hose->bus = bus;
 
 
-	hose->last_busno = bus->subordinate;
+	hose->last_busno = bus->busn_res.end;
 }
 }
 
 
 static int __init pcibios_init(void)
 static int __init pcibios_init(void)

+ 1 - 1
arch/mips/pci/pci.c

@@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
 	need_domain_info = need_domain_info || hose->index;
 	need_domain_info = need_domain_info || hose->index;
 	hose->need_domain_info = need_domain_info;
 	hose->need_domain_info = need_domain_info;
 	if (bus) {
 	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 -
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
 		   reserve some space for bridges. */
 		if (next_busno > 224) {
 		if (next_busno > 224) {

+ 1 - 0
arch/powerpc/include/asm/pci-bridge.h

@@ -30,6 +30,7 @@ struct pci_controller {
 	int first_busno;
 	int first_busno;
 	int last_busno;
 	int last_busno;
 	int self_busno;
 	int self_busno;
+	struct resource busn;
 
 
 	void __iomem *io_base_virt;
 	void __iomem *io_base_virt;
 #ifdef CONFIG_PPC64
 #ifdef CONFIG_PPC64

+ 11 - 6
arch/powerpc/kernel/pci-common.c

@@ -1637,6 +1637,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 	/* Wire up PHB bus resources */
 	/* Wire up PHB bus resources */
 	pcibios_setup_phb_resources(hose, &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 */
 	/* Create an empty bus for the toplevel */
 	bus = pci_create_root_bus(hose->parent, hose->first_busno,
 	bus = pci_create_root_bus(hose->parent, hose->first_busno,
 				  hose->ops, hose, &resources);
 				  hose->ops, hose, &resources);
@@ -1646,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 		pci_free_resource_list(&resources);
 		pci_free_resource_list(&resources);
 		return;
 		return;
 	}
 	}
-	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 	hose->bus = bus;
 
 
 	/* Get probe mode and perform scan */
 	/* Get probe mode and perform scan */
@@ -1654,13 +1658,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 	if (node && ppc_md.pci_probe_mode)
 	if (node && ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
 		mode = ppc_md.pci_probe_mode(bus);
 	pr_debug("    probe mode: %d\n", mode);
 	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);
 		of_scan_bus(node, bus);
-	}
 
 
-	if (mode == PCI_PROBE_NORMAL)
-		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+	if (mode == PCI_PROBE_NORMAL) {
+		pci_bus_update_busn_res_end(bus, 255);
+		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
 	/* Platform gets a chance to do some global fixups before
 	 * we proceed to resource allocation
 	 * we proceed to resource allocation

+ 1 - 1
arch/powerpc/kernel/pci_64.c

@@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 
 
 	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
 	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
 		bus = pci_bus_b(ln);
 		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;
 			break;
 		bus = NULL;
 		bus = NULL;
 	}
 	}

+ 1 - 1
arch/powerpc/kernel/pci_of_scan.c

@@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev)
 	}
 	}
 
 
 	bus->primary = dev->bus->number;
 	bus->primary = dev->bus->number;
-	bus->subordinate = busrange[1];
+	pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
 	bus->bridge_ctl = 0;
 	bus->bridge_ctl = 0;
 
 
 	/* parse ranges property */
 	/* parse ranges property */

+ 4 - 4
arch/powerpc/platforms/powernv/pci-ioda.c

@@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
 		dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
 		dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
 		fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
 		fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
 		parent = pe->pbus->self;
 		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) {
 		switch(count) {
 		case  1: bcomp = OpalPciBusAll;		break;
 		case  1: bcomp = OpalPciBusAll;		break;
 		case  2: bcomp = OpalPciBus7Bits;	break;
 		case  2: bcomp = OpalPciBus7Bits;	break;
@@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 	pe->pdev = NULL;
 	pe->pdev = NULL;
 	pe->tce32_seg = -1;
 	pe->tce32_seg = -1;
 	pe->mve_number = -1;
 	pe->mve_number = -1;
-	pe->rid = bus->secondary << 8;
+	pe->rid = bus->busn_res.start << 8;
 	pe->dma_weight = 0;
 	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)) {
 	if (pnv_ioda_configure_pe(phb, pe)) {
 		/* XXX What do we do here ? */
 		/* XXX What do we do here ? */

+ 1 - 1
arch/powerpc/platforms/pseries/pci_dlpar.c

@@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
 		if (!num)
 		if (!num)
 			return;
 			return;
 		pcibios_setup_bus_devices(bus);
 		pcibios_setup_bus_devices(bus);
-		max = bus->secondary;
+		max = bus->busn_res.start;
 		for (pass=0; pass < 2; pass++)
 		for (pass=0; pass < 2; pass++)
 			list_for_each_entry(dev, &bus->devices, bus_list) {
 			list_for_each_entry(dev, &bus->devices, bus_list) {
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||

+ 1 - 1
arch/sh/drivers/pci/pci.c

@@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
 	need_domain_info = need_domain_info || hose->index;
 	need_domain_info = need_domain_info || hose->index;
 	hose->need_domain_info = need_domain_info;
 	hose->need_domain_info = need_domain_info;
 	if (bus) {
 	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 -
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
 		   reserve some space for bridges. */
 		if (next_busno > 224) {
 		if (next_busno > 224) {

+ 5 - 3
arch/sparc/kernel/pci.c

@@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
 	}
 	}
 
 
 	bus->primary = dev->bus->number;
 	bus->primary = dev->bus->number;
-	bus->subordinate = busrange[1];
+	pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
 	bus->bridge_ctl = 0;
 	bus->bridge_ctl = 0;
 
 
 	/* parse ranges property, or cook one up by hand for Simba */
 	/* parse ranges property, or cook one up by hand for Simba */
@@ -685,6 +685,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
 				pbm->io_space.start);
 				pbm->io_space.start);
 	pci_add_resource_offset(&resources, &pbm->mem_space,
 	pci_add_resource_offset(&resources, &pbm->mem_space,
 				pbm->mem_space.start);
 				pbm->mem_space.start);
+	pbm->busn.start = pbm->pci_first_busno;
+	pbm->busn.end	= pbm->pci_last_busno;
+	pbm->busn.flags	= IORESOURCE_BUS;
+	pci_add_resource(&resources, &pbm->busn);
 	bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
 	bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
 				  pbm, &resources);
 				  pbm, &resources);
 	if (!bus) {
 	if (!bus) {
@@ -693,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
 		pci_free_resource_list(&resources);
 		pci_free_resource_list(&resources);
 		return NULL;
 		return NULL;
 	}
 	}
-	bus->secondary = pbm->pci_first_busno;
-	bus->subordinate = pbm->pci_last_busno;
 
 
 	pci_of_scan_bus(pbm, node, bus);
 	pci_of_scan_bus(pbm, node, bus);
 	pci_bus_add_devices(bus);
 	pci_bus_add_devices(bus);

+ 1 - 0
arch/sparc/kernel/pci_impl.h

@@ -97,6 +97,7 @@ struct pci_pbm_info {
 	/* PBM I/O and Memory space resources. */
 	/* PBM I/O and Memory space resources. */
 	struct resource			io_space;
 	struct resource			io_space;
 	struct resource			mem_space;
 	struct resource			mem_space;
+	struct resource			busn;
 
 
 	/* Base of PCI Config space, can be per-PBM or shared. */
 	/* Base of PCI Config space, can be per-PBM or shared. */
 	unsigned long			config_space;
 	unsigned long			config_space;

+ 6 - 3
arch/tile/kernel/pci.c

@@ -310,6 +310,7 @@ int __init pcibios_init(void)
 		if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
 		if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
 			struct pci_controller *controller = &controllers[i];
 			struct pci_controller *controller = &controllers[i];
 			struct pci_bus *bus;
 			struct pci_bus *bus;
+			LIST_HEAD(resources);
 
 
 			if (tile_init_irqs(i, controller)) {
 			if (tile_init_irqs(i, controller)) {
 				pr_err("PCI: Could not initialize IRQs\n");
 				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
 			 * This is inlined in linux/pci.h and calls into
 			 * pci_scan_bus_parented() in probe.c.
 			 * 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->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 &&
 				if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
 					(PCI_SLOT(dev->devfn) == 0)) {
 					(PCI_SLOT(dev->devfn) == 0)) {
-					next_bus = dev->subordinate;
+					next_bus = dev->busn_res.end;
 					controllers[i].mem_resources[0] =
 					controllers[i].mem_resources[0] =
 						*next_bus->resource[0];
 						*next_bus->resource[0];
 					controllers[i].mem_resources[1] =
 					controllers[i].mem_resources[1] =

+ 5 - 4
arch/x86/pci/acpi.c

@@ -12,7 +12,6 @@ struct pci_root_info {
 	char name[16];
 	char name[16];
 	unsigned int res_num;
 	unsigned int res_num;
 	struct resource *res;
 	struct resource *res;
-	int busnum;
 	struct pci_sysdata sd;
 	struct pci_sysdata sd;
 };
 };
 
 
@@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 {
 {
 	size_t size;
 	size_t size;
 
 
+	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
 	info->bridge = device;
 	info->bridge = device;
+
 	info->res_num = 0;
 	info->res_num = 0;
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
 				info);
 				info);
@@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 	if (!info->res)
 	if (!info->res)
 		return;
 		return;
 
 
-	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
-
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 				info);
 				info);
 }
 }
@@ -426,6 +425,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 	} else {
 	} else {
 		probe_pci_root_info(info, device, busnum, domain);
 		probe_pci_root_info(info, device, busnum, domain);
 
 
+		/* insert busn res at first */
+		pci_add_resource(&resources,  &root->secondary);
 		/*
 		/*
 		 * _CRS with no apertures is normal, so only fall back to
 		 * _CRS with no apertures is normal, so only fall back to
 		 * defaults or native bridge info if we're ignoring _CRS.
 		 * defaults or native bridge info if we're ignoring _CRS.
@@ -440,7 +441,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 		bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
 		bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
 					  &resources);
 					  &resources);
 		if (bus) {
 		if (bus) {
-			bus->subordinate = pci_scan_child_bus(bus);
+			pci_scan_child_bus(bus);
 			pci_set_host_bridge_release(
 			pci_set_host_bridge_release(
 				to_pci_host_bridge(bus->bridge),
 				to_pci_host_bridge(bus->bridge),
 				release_pci_root_info, info);
 				release_pci_root_info, info);

+ 3 - 4
arch/x86/pci/amd_bus.c

@@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void)
 		link = (reg >> 8) & 0x03;
 		link = (reg >> 8) & 0x03;
 
 
 		info = alloc_pci_root_info(min_bus, max_bus, node, link);
 		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 */
 	/* get the default node and link for left over res */
@@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void)
 		int busnum;
 		int busnum;
 		struct pci_root_res *root_res;
 		struct pci_root_res *root_res;
 
 
-		busnum = info->bus_min;
-		printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
-		       info->bus_min, info->bus_max, info->node, info->link);
+		busnum = info->busn.start;
+		printk(KERN_DEBUG "bus: %pR on node %x link %x\n",
+		       &info->busn, info->node, info->link);
 		list_for_each_entry(root_res, &info->resources, list)
 		list_for_each_entry(root_res, &info->resources, list)
 			printk(KERN_DEBUG "bus: %02x %pR\n",
 			printk(KERN_DEBUG "bus: %02x %pR\n",
 				       busnum, &root_res->res);
 				       busnum, &root_res->res);

+ 19 - 3
arch/x86/pci/bus_numa.c

@@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
 		return NULL;
 		return NULL;
 
 
 	list_for_each_entry(info, &pci_root_infos, list)
 	list_for_each_entry(info, &pci_root_infos, list)
-		if (info->bus_min == bus)
+		if (info->busn.start == bus)
 			return info;
 			return info;
 
 
 	return NULL;
 	return NULL;
@@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
 {
 {
 	struct pci_root_info *info = x86_find_pci_root_info(bus);
 	struct pci_root_info *info = x86_find_pci_root_info(bus);
 	struct pci_root_res *root_res;
 	struct pci_root_res *root_res;
+	struct pci_host_bridge_window *window;
+	bool found = false;
 
 
 	if (!info)
 	if (!info)
 		goto default_resources;
 		goto default_resources;
@@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
 	printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
 	printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
 	       bus);
 	       bus);
 
 
+	/* already added by acpi ? */
+	list_for_each_entry(window, resources, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+
+	if (!found)
+		pci_add_resource(resources, &info->busn);
+
 	list_for_each_entry(root_res, &info->resources, list) {
 	list_for_each_entry(root_res, &info->resources, list) {
 		struct resource *res;
 		struct resource *res;
 		struct resource *root;
 		struct resource *root;
@@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
 	if (!info)
 	if (!info)
 		return info;
 		return info;
 
 
+	sprintf(info->name, "PCI Bus #%02x", bus_min);
+
 	INIT_LIST_HEAD(&info->resources);
 	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->node = node;
 	info->link = link;
 	info->link = link;
 
 

+ 1 - 2
arch/x86/pci/bus_numa.h

@@ -13,8 +13,7 @@ struct pci_root_info {
 	struct list_head list;
 	struct list_head list;
 	char name[12];
 	char name[12];
 	struct list_head resources;
 	struct list_head resources;
-	int bus_min;
-	int bus_max;
+	struct resource busn;
 	int node;
 	int node;
 	int link;
 	int link;
 };
 };

+ 1 - 1
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,
 		bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
 					pci_ctrl->ops, pci_ctrl, &resources);
 					pci_ctrl->ops, pci_ctrl, &resources);
 		pci_ctrl->bus = bus;
 		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)
 		if (next_busno <= pci_ctrl->last_busno)
 			next_busno = pci_ctrl->last_busno+1;
 			next_busno = pci_ctrl->last_busno+1;
 	}
 	}

+ 1 - 1
drivers/iommu/intel-iommu.c

@@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
 			if (drhd->devices[i] &&
 			if (drhd->devices[i] &&
 			    drhd->devices[i]->subordinate &&
 			    drhd->devices[i]->subordinate &&
 			    drhd->devices[i]->subordinate->number <= bus &&
 			    drhd->devices[i]->subordinate->number <= bus &&
-			    drhd->devices[i]->subordinate->subordinate >= bus)
+			    drhd->devices[i]->subordinate->busn_res.end >= bus)
 				return drhd->iommu;
 				return drhd->iommu;
 		}
 		}
 
 

+ 2 - 2
drivers/net/ethernet/broadcom/tg3.c

@@ -14168,7 +14168,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 			if (bridge->subordinate &&
 			if (bridge->subordinate &&
 			    (bridge->subordinate->number <=
 			    (bridge->subordinate->number <=
 			     tp->pdev->bus->number) &&
 			     tp->pdev->bus->number) &&
-			    (bridge->subordinate->subordinate >=
+			    (bridge->subordinate->busn_res.end >=
 			     tp->pdev->bus->number)) {
 			     tp->pdev->bus->number)) {
 				tg3_flag_set(tp, 5701_DMA_BUG);
 				tg3_flag_set(tp, 5701_DMA_BUG);
 				pci_dev_put(bridge);
 				pci_dev_put(bridge);
@@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 			if (bridge && bridge->subordinate &&
 			if (bridge && bridge->subordinate &&
 			    (bridge->subordinate->number <=
 			    (bridge->subordinate->number <=
 			     tp->pdev->bus->number) &&
 			     tp->pdev->bus->number) &&
-			    (bridge->subordinate->subordinate >=
+			    (bridge->subordinate->busn_res.end >=
 			     tp->pdev->bus->number)) {
 			     tp->pdev->bus->number)) {
 				tg3_flag_set(tp, 40BIT_DMA_BUG);
 				tg3_flag_set(tp, 40BIT_DMA_BUG);
 				pci_dev_put(bridge);
 				pci_dev_put(bridge);

+ 11 - 5
drivers/parisc/dino.c

@@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
 		int size, u32 *val)
 		int size, u32 *val)
 {
 {
 	struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
 	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);
 	u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
 	void __iomem *base_addr = d->hba.base_addr;
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
 	unsigned long flags;
@@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
 	int size, u32 val)
 	int size, u32 val)
 {
 {
 	struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
 	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);
 	u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
 	void __iomem *base_addr = d->hba.base_addr;
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
 	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));
         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",
 	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);
 	    bus->bridge->platform_data);
 
 
 	/* Firmware doesn't set up card-mode dino, so we have to */
 	/* Firmware doesn't set up card-mode dino, so we have to */
@@ -898,6 +898,7 @@ static int __init dino_probe(struct parisc_device *dev)
 	LIST_HEAD(resources);
 	LIST_HEAD(resources);
 	struct pci_bus *bus;
 	struct pci_bus *bus;
 	unsigned long hpa = dev->hpa.start;
 	unsigned long hpa = dev->hpa.start;
+	int max;
 
 
 	name = "Dino";
 	name = "Dino";
 	if (is_card_dino(&dev->id)) {
 	if (is_card_dino(&dev->id)) {
@@ -983,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev)
 	if (dino_dev->hba.gmmio_space.flags)
 	if (dino_dev->hba.gmmio_space.flags)
 		pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
 		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
 	** It's not used to avoid chicken/egg problems
 	** with configuration accessor functions.
 	** with configuration accessor functions.
@@ -998,12 +1003,13 @@ static int __init dino_probe(struct parisc_device *dev)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	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
 	/* This code *depends* on scanning being single threaded
 	 * if it isn't, this global bus number count will fail
 	 * 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_assign_resources(bus);
 	pci_bus_add_devices(bus);
 	pci_bus_add_devices(bus);
 	return 0;
 	return 0;

+ 1 - 1
drivers/parisc/iosapic.c

@@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
 		intr_slot = PCI_SLOT(pcidev->devfn);
 		intr_slot = PCI_SLOT(pcidev->devfn);
 	}
 	}
 	DBG_IRT("iosapic_xlate_pin:  bus %d slot %d pin %d\n",
 	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);
 	return irt_find_irqline(isi, intr_slot, intr_pin);
 }
 }

+ 15 - 11
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)
 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) ||
 	if ((bus < first_bus) ||
 	    (bus > last_sub_bus) ||
 	    (bus > last_sub_bus) ||
@@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
 static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
 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));
 	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);
 	u32 tok = LBA_CFG_TOK(local_bus, devfn);
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
 
@@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int
 		return 0;
 		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);
 		DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos);
 		/* either don't want to look or know device isn't present. */
 		/* either don't want to look or know device isn't present. */
 		*data = ~0U;
 		*data = ~0U;
@@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
 static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
 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));
 	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);
 	u32 tok = LBA_CFG_TOK(local_bus,devfn);
 
 
 	if ((pos > 255) || (devfn > 255))
 	if ((pos > 255) || (devfn > 255))
@@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int
 		return 0;
 		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);
 		DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data);
 		return 1; /* New Workaround */
 		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)
 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));
 	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);
 	u32 tok = LBA_CFG_TOK(local_bus, devfn);
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
 
@@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i
 {
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
 	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 	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);
 	u32 tok = LBA_CFG_TOK(local_bus,devfn);
 
 
 	if ((pos > 255) || (devfn > 255))
 	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));
 	struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
 
 
 	DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
 	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.
 	** Properly Setup MMIO resources for this bus.
@@ -989,6 +989,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 		case PAT_PBNUM:
 		case PAT_PBNUM:
 			lba_dev->hba.bus_num.start = p->start;
 			lba_dev->hba.bus_num.start = p->start;
 			lba_dev->hba.bus_num.end   = p->end;
 			lba_dev->hba.bus_num.end   = p->end;
+			lba_dev->hba.bus_num.flags = IORESOURCE_BUS;
 			break;
 			break;
 
 
 		case PAT_LMMIO:
 		case PAT_LMMIO:
@@ -1366,6 +1367,7 @@ lba_driver_probe(struct parisc_device *dev)
 	void *tmp_obj;
 	void *tmp_obj;
 	char *version;
 	char *version;
 	void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
 	void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
+	int max;
 
 
 	/* Read HW Rev First */
 	/* Read HW Rev First */
 	func_class = READ_REG32(addr + LBA_FCLASS);
 	func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1502,6 +1504,8 @@ lba_driver_probe(struct parisc_device *dev)
 	if (lba_dev->hba.gmmio_space.flags)
 	if (lba_dev->hba.gmmio_space.flags)
 		pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
 		pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
 
 
+	pci_add_resource(&resources, &lba_dev->hba.bus_num);
+
 	dev->dev.platform_data = lba_dev;
 	dev->dev.platform_data = lba_dev;
 	lba_bus = lba_dev->hba.hba_bus =
 	lba_bus = lba_dev->hba.hba_bus =
 		pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
 		pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
@@ -1511,7 +1515,7 @@ lba_driver_probe(struct parisc_device *dev)
 		return 0;
 		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() */
 	/* This is in lieu of calling pci_assign_unassigned_resources() */
 	if (is_pdc_pat()) {
 	if (is_pdc_pat()) {
@@ -1541,7 +1545,7 @@ lba_driver_probe(struct parisc_device *dev)
 		lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
 		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);
 	pci_bus_add_devices(lba_bus);
 
 
 	/* Whew! Finally done! Tell services we got this one covered. */
 	/* Whew! Finally done! Tell services we got this one covered. */

+ 19 - 11
drivers/pci/hotplug-pci.c

@@ -4,18 +4,26 @@
 #include <linux/export.h>
 #include <linux/export.h>
 #include "pci.h"
 #include "pci.h"
 
 
-
-unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+int __ref pci_hp_add_bridge(struct pci_dev *dev)
 {
 {
-	unsigned int max;
-
-	max = pci_scan_child_bus(bus);
+	struct pci_bus *parent = dev->bus;
+	int pass, busnr, start = parent->busn_res.start;
+	int end = parent->busn_res.end;
 
 
-	/*
-	 * Make the discovered devices available.
-	 */
-	pci_bus_add_devices(bus);
+	for (busnr = start; busnr <= end; busnr++) {
+		if (!pci_find_bus(pci_domain_nr(parent), busnr))
+			break;
+	}
+	if (busnr-- > end) {
+		printk(KERN_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)
+		return -1;
 
 
-	return max;
+	return 0;
 }
 }
-EXPORT_SYMBOL(pci_do_scan_bus);
+EXPORT_SYMBOL_GPL(pci_hp_add_bridge);

+ 4 - 4
drivers/pci/hotplug/acpiphp_glue.c

@@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
 			PCI_PRIMARY_BUS,
 			PCI_PRIMARY_BUS,
 			&buses);
 			&buses);
 
 
-	if (((buses >> 8) & 0xff) != bus->secondary) {
+	if (((buses >> 8) & 0xff) != bus->busn_res.start) {
 		buses = (buses & 0xff000000)
 		buses = (buses & 0xff000000)
 			| ((unsigned int)(bus->primary)     <<  0)
 			| ((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);
 		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
 	}
 	}
 	return NOTIFY_OK;
 	return NOTIFY_OK;
@@ -692,7 +692,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 	 * bus->subordinate value because it could have
 	 * bus->subordinate value because it could have
 	 * padding in it.
 	 * padding in it.
 	 */
 	 */
-	max = bus->secondary;
+	max = bus->busn_res.start;
 
 
 	list_for_each(tmp, &bus->children) {
 	list_for_each(tmp, &bus->children) {
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		n = pci_bus_max_busnr(pci_bus_b(tmp));

+ 6 - 29
drivers/pci/hotplug/cpci_hotplug_pci.c

@@ -285,42 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot)
 	for (fn = 0; fn < 8; fn++) {
 	for (fn = 0; fn < 8; fn++) {
 		struct pci_dev *dev;
 		struct pci_dev *dev;
 
 
-		dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
+		dev = pci_get_slot(parent,
+				   PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
 		if (!dev)
 		if (!dev)
 			continue;
 			continue;
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
-		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
-			/* Find an unused bus number for the new bridge */
-			struct pci_bus *child;
-			unsigned char busnr, start = parent->secondary;
-			unsigned char end = parent->subordinate;
-
-			for (busnr = start; busnr <= end; busnr++) {
-				if (!pci_find_bus(pci_domain_nr(parent),
-						  busnr))
-					break;
-			}
-			if (busnr >= end) {
-				err("No free bus for hot-added bridge\n");
-				pci_dev_put(dev);
-				continue;
-			}
-			child = pci_add_new_bus(parent, dev, busnr);
-			if (!child) {
-				err("Cannot add new bus for %s\n",
-				    pci_name(dev));
-				pci_dev_put(dev);
-				continue;
-			}
-			child->subordinate = pci_do_scan_bus(child);
-			pci_bus_size_bridges(child);
-		}
+		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+			pci_hp_add_bridge(dev);
 		pci_dev_put(dev);
 		pci_dev_put(dev);
 	}
 	}
 
 
-	pci_bus_assign_resources(parent);
+	pci_assign_unassigned_bridge_resources(parent->self);
+
 	pci_bus_add_devices(parent);
 	pci_bus_add_devices(parent);
-	pci_enable_bridges(parent);
 
 
 	dbg("%s - exit", __func__);
 	dbg("%s - exit", __func__);
 	return 0;
 	return 0;

+ 4 - 4
drivers/pci/hotplug/cpqphp_pci.c

@@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
 
 
 int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 {
 {
-	unsigned char bus;
 	struct pci_bus *child;
 	struct pci_bus *child;
 	int num;
 	int num;
 
 
@@ -106,9 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
 	}
 	}
 
 
 	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
-		child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
-		pci_do_scan_bus(child);
+		pci_hp_add_bridge(func->pci_dev);
+		child = func->pci_dev->subordinate;
+		if (child)
+			pci_bus_add_devices(child);
 	}
 	}
 
 
 	pci_dev_put(func->pci_dev);
 	pci_dev_put(func->pci_dev);

+ 4 - 4
drivers/pci/hotplug/ibmphp_core.c

@@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno)
 
 
 static int ibm_configure_device(struct pci_func *func)
 static int ibm_configure_device(struct pci_func *func)
 {
 {
-	unsigned char bus;
 	struct pci_bus *child;
 	struct pci_bus *child;
 	int num;
 	int num;
 	int flag = 0;	/* this is to make sure we don't double scan the bus,
 	int flag = 0;	/* this is to make sure we don't double scan the bus,
@@ -805,9 +804,10 @@ static int ibm_configure_device(struct pci_func *func)
 		}
 		}
 	}
 	}
 	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
 	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
-		pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus);
-		child = pci_add_new_bus(func->dev->bus, func->dev, bus);
-		pci_do_scan_bus(child);
+		pci_hp_add_bridge(func->dev);
+		child = func->dev->subordinate;
+		if (child)
+			pci_bus_add_devices(child);
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 2 - 26
drivers/pci/hotplug/pciehp_pci.c

@@ -34,29 +34,6 @@
 #include "../pci.h"
 #include "../pci.h"
 #include "pciehp.h"
 #include "pciehp.h"
 
 
-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;
-
-	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)
-		return -1;
-
-	return 0;
-}
-
 int pciehp_configure_device(struct slot *p_slot)
 int pciehp_configure_device(struct slot *p_slot)
 {
 {
 	struct pci_dev *dev;
 	struct pci_dev *dev;
@@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot)
 		if (!dev)
 		if (!dev)
 			continue;
 			continue;
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
-				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
-			pciehp_add_bridge(dev);
-		}
+				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+			pci_hp_add_bridge(dev);
 		pci_dev_put(dev);
 		pci_dev_put(dev);
 	}
 	}
 
 

+ 5 - 7
drivers/pci/hotplug/sgi_hotplug.c

@@ -397,13 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
 			else
 			else
 				sn_io_slot_fixup(dev);
 				sn_io_slot_fixup(dev);
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-				unsigned char sec_bus;
-				pci_read_config_byte(dev, PCI_SECONDARY_BUS,
-						     &sec_bus);
-				new_bus = pci_add_new_bus(dev->bus, dev,
-							  sec_bus);
-				pci_scan_child_bus(new_bus);
-				new_ppb = 1;
+				pci_hp_add_bridge(dev);
+				if (dev->subordinate) {
+					new_bus = dev->subordinate;
+					new_ppb = 1;
+				}
 			}
 			}
 			pci_dev_put(dev);
 			pci_dev_put(dev);
 		}
 		}

+ 15 - 30
drivers/pci/hotplug/shpchp_pci.c

@@ -37,9 +37,10 @@
 int __ref shpchp_configure_device(struct slot *p_slot)
 int __ref shpchp_configure_device(struct slot *p_slot)
 {
 {
 	struct pci_dev *dev;
 	struct pci_dev *dev;
-	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
-	int num, fn;
 	struct controller *ctrl = p_slot->ctrl;
 	struct controller *ctrl = p_slot->ctrl;
+	struct pci_dev *bridge = ctrl->pci_dev;
+	struct pci_bus *parent = bridge->subordinate;
+	int num, fn;
 
 
 	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 	if (dev) {
 	if (dev) {
@@ -61,39 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot)
 		if (!dev)
 		if (!dev)
 			continue;
 			continue;
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
-				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
-			/* Find an unused bus number for the new bridge */
-			struct pci_bus *child;
-			unsigned char busnr, start = parent->secondary;
-			unsigned char end = parent->subordinate;
-			for (busnr = start; busnr <= end; busnr++) {
-				if (!pci_find_bus(pci_domain_nr(parent),
-							busnr))
-					break;
-			}
-			if (busnr > end) {
-				ctrl_err(ctrl,
-					 "No free bus for hot-added bridge\n");
-				pci_dev_put(dev);
-				continue;
-			}
-			child = pci_add_new_bus(parent, dev, busnr);
-			if (!child) {
-				ctrl_err(ctrl, "Cannot add new bus for %s\n",
-					 pci_name(dev));
-				pci_dev_put(dev);
-				continue;
-			}
-			child->subordinate = pci_do_scan_bus(child);
-			pci_bus_size_bridges(child);
-		}
+		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+			pci_hp_add_bridge(dev);
+		pci_dev_put(dev);
+	}
+
+	pci_assign_unassigned_bridge_resources(bridge);
+
+	for (fn = 0; fn < 8; fn++) {
+		dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
+		if (!dev)
+			continue;
 		pci_configure_slot(dev);
 		pci_configure_slot(dev);
 		pci_dev_put(dev);
 		pci_dev_put(dev);
 	}
 	}
 
 
-	pci_bus_assign_resources(parent);
 	pci_bus_add_devices(parent);
 	pci_bus_add_devices(parent);
-	pci_enable_bridges(parent);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 3 - 3
drivers/pci/hotplug/shpchp_sysfs.c

@@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 		}
 		}
 	}
 	}
 	out += sprintf(out, "Free resources: bus numbers\n");
 	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))
 		if (!pci_find_bus(pci_domain_nr(bus), busnr))
 			break;
 			break;
 	}
 	}
-	if (busnr < bus->subordinate)
+	if (busnr < bus->busn_res.end)
 		out += sprintf(out, "start = %8.8x, length = %8.8x\n",
 		out += sprintf(out, "start = %8.8x, length = %8.8x\n",
-				busnr, (bus->subordinate - busnr));
+				busnr, (int)(bus->busn_res.end - busnr));
 
 
 	return out - buf;
 	return out - buf;
 }
 }

+ 2 - 2
drivers/pci/iov.c

@@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
 	if (!child)
 	if (!child)
 		return NULL;
 		return NULL;
 
 
-	child->subordinate = busnr;
+	pci_bus_insert_busn_res(child, busnr, busnr);
 	child->dev.parent = bus->bridge;
 	child->dev.parent = bus->bridge;
 	rc = pci_bus_add_child(child);
 	rc = pci_bus_add_child(child);
 	if (rc) {
 	if (rc) {
@@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 	iov->offset = offset;
 	iov->offset = offset;
 	iov->stride = stride;
 	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");
 		dev_err(&dev->dev, "SR-IOV: bus number out of range\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}

+ 1 - 1
drivers/pci/pci.c

@@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 	struct list_head *tmp;
 	struct list_head *tmp;
 	unsigned char max, n;
 	unsigned char max, n;
 
 
-	max = bus->subordinate;
+	max = bus->busn_res.end;
 	list_for_each(tmp, &bus->children) {
 	list_for_each(tmp, &bus->children) {
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		n = pci_bus_max_busnr(pci_bus_b(tmp));
 		if(n > max)
 		if(n > max)

+ 1 - 1
drivers/pci/pci.h

@@ -124,7 +124,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
 #endif
 #endif
 
 
 /* Functions for PCI Hotplug drivers to use */
 /* Functions for PCI Hotplug drivers to use */
-extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
+int pci_hp_add_bridge(struct pci_dev *dev);
 
 
 #ifdef HAVE_PCI_LEGACY
 #ifdef HAVE_PCI_LEGACY
 extern void pci_create_legacy_files(struct pci_bus *bus);
 extern void pci_create_legacy_files(struct pci_bus *bus);

+ 161 - 30
drivers/pci/probe.c

@@ -16,10 +16,47 @@
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
 #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. */
 /* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
 LIST_HEAD(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
 
 
+static LIST_HEAD(pci_domain_busn_res_list);
+
+struct pci_domain_busn_res {
+	struct list_head list;
+	struct resource res;
+	int domain_nr;
+};
+
+static struct resource *get_pci_domain_busn_res(int domain_nr)
+{
+	struct pci_domain_busn_res *r;
+
+	list_for_each_entry(r, &pci_domain_busn_res_list, list)
+		if (r->domain_nr == domain_nr)
+			return &r->res;
+
+	r = kzalloc(sizeof(*r), GFP_KERNEL);
+	if (!r)
+		return NULL;
+
+	r->domain_nr = domain_nr;
+	r->res.start = 0;
+	r->res.end = 0xff;
+	r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED;
+
+	list_add_tail(&r->list, &pci_domain_busn_res_list);
+
+	return &r->res;
+}
+
 static int find_anything(struct device *dev, void *data)
 static int find_anything(struct device *dev, void *data)
 {
 {
 	return 1;
 	return 1;
@@ -381,8 +418,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
 	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
 	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
 		return;
 		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)" : "");
 		 dev->transparent ? " (subtractive decode)" : "");
 
 
 	pci_bus_remove_resources(child);
 	pci_bus_remove_resources(child);
@@ -599,9 +636,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 	 * Set up the primary, secondary and subordinate
 	 * Set up the primary, secondary and subordinate
 	 * bus numbers.
 	 * bus numbers.
 	 */
 	 */
-	child->number = child->secondary = busnr;
-	child->primary = parent->secondary;
-	child->subordinate = 0xff;
+	child->number = child->busn_res.start = busnr;
+	child->primary = parent->busn_res.start;
+	child->busn_res.end = 0xff;
 
 
 	if (!bridge)
 	if (!bridge)
 		return child;
 		return child;
@@ -643,8 +680,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 	if (!pcibios_assign_all_busses())
 	if (!pcibios_assign_all_busses())
 		return;
 		return;
 
 
-	while (parent->parent && parent->subordinate < max) {
-		parent->subordinate = max;
+	while (parent->parent && parent->busn_res.end < max) {
+		parent->busn_res.end = max;
 		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
 		pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
 		parent = parent->parent;
 		parent = parent->parent;
 	}
 	}
@@ -718,15 +755,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			if (!child)
 			if (!child)
 				goto out;
 				goto out;
 			child->primary = primary;
 			child->primary = primary;
-			child->subordinate = subordinate;
+			pci_bus_insert_busn_res(child, secondary, subordinate);
 			child->bridge_ctl = bctl;
 			child->bridge_ctl = bctl;
 		}
 		}
 
 
 		cmax = pci_scan_child_bus(child);
 		cmax = pci_scan_child_bus(child);
 		if (cmax > max)
 		if (cmax > max)
 			max = cmax;
 			max = cmax;
-		if (child->subordinate > max)
-			max = child->subordinate;
+		if (child->busn_res.end > max)
+			max = child->busn_res.end;
 	} else {
 	} else {
 		/*
 		/*
 		 * We need to assign a number to this bus which we always
 		 * We need to assign a number to this bus which we always
@@ -756,11 +793,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			child = pci_add_new_bus(bus, dev, ++max);
 			child = pci_add_new_bus(bus, dev, ++max);
 			if (!child)
 			if (!child)
 				goto out;
 				goto out;
+			pci_bus_insert_busn_res(child, max, 0xff);
 		}
 		}
 		buses = (buses & 0xff000000)
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((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);
 
 
 		/*
 		/*
 		 * yenta.c forces a secondary latency timer of 176.
 		 * yenta.c forces a secondary latency timer of 176.
@@ -805,8 +843,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 					break;
 					break;
 				while (parent->parent) {
 				while (parent->parent) {
 					if ((!pcibios_assign_all_busses()) &&
 					if ((!pcibios_assign_all_busses()) &&
-					    (parent->subordinate > max) &&
-					    (parent->subordinate <= max+i)) {
+					    (parent->busn_res.end > max) &&
+					    (parent->busn_res.end <= max+i)) {
 						j = 1;
 						j = 1;
 					}
 					}
 					parent = parent->parent;
 					parent = parent->parent;
@@ -827,7 +865,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		/*
 		/*
 		 * Set the subordinate bus number to its real value.
 		 * Set the subordinate bus number to its real value.
 		 */
 		 */
-		child->subordinate = max;
+		pci_bus_update_busn_res_end(child, max);
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
 	}
 	}
 
 
@@ -837,19 +875,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 
 
 	/* Has only triggered on CardBus, fixup is in yenta_socket */
 	/* Has only triggered on CardBus, fixup is in yenta_socket */
 	while (bus->parent) {
 	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->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",
 					"wholly" : "partially",
 				bus->self->transparent ? " transparent" : "",
 				bus->self->transparent ? " transparent" : "",
 				dev_name(&bus->dev),
 				dev_name(&bus->dev),
-				bus->number, bus->subordinate);
+				&bus->busn_res);
 		}
 		}
 		bus = bus->parent;
 		bus = bus->parent;
 	}
 	}
@@ -1548,7 +1586,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
 
 
 unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 {
 {
-	unsigned int devfn, pass, max = bus->secondary;
+	unsigned int devfn, pass, max = bus->busn_res.start;
 	struct pci_dev *dev;
 	struct pci_dev *dev;
 
 
 	dev_dbg(&bus->dev, "scanning bus\n");
 	dev_dbg(&bus->dev, "scanning bus\n");
@@ -1642,7 +1680,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	/* Create legacy_io and legacy_mem files for this bus */
 	/* Create legacy_io and legacy_mem files for this bus */
 	pci_create_legacy_files(b);
 	pci_create_legacy_files(b);
 
 
-	b->number = b->secondary = bus;
+	b->number = b->busn_res.start = bus;
 
 
 	if (parent)
 	if (parent)
 		dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
 		dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
@@ -1654,7 +1692,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 		list_move_tail(&window->list, &bridge->windows);
 		list_move_tail(&window->list, &bridge->windows);
 		res = window->res;
 		res = window->res;
 		offset = window->offset;
 		offset = window->offset;
-		pci_bus_add_resource(b, res, 0);
+		if (res->flags & IORESOURCE_BUS)
+			pci_bus_insert_busn_res(b, bus, res->end);
+		else
+			pci_bus_add_resource(b, res, 0);
 		if (offset) {
 		if (offset) {
 			if (resource_type(res) == IORESOURCE_IO)
 			if (resource_type(res) == IORESOURCE_IO)
 				fmt = " (bus address [%#06llx-%#06llx])";
 				fmt = " (bus address [%#06llx-%#06llx])";
@@ -1684,16 +1725,104 @@ err_out:
 	return NULL;
 	return NULL;
 }
 }
 
 
+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, *conflict;
+
+	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;
+	}
+
+	conflict = insert_resource_conflict(parent_res, res);
+
+	if (conflict)
+		dev_printk(KERN_DEBUG, &b->dev,
+			   "busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
+			    res, pci_is_root_bus(b) ? "domain " : "",
+			    parent_res, conflict->name, conflict);
+	else
+		dev_printk(KERN_DEBUG, &b->dev,
+			   "busn_res: %pR is inserted under %s%pR\n",
+			   res, pci_is_root_bus(b) ? "domain " : "",
+			   parent_res);
+
+	return conflict == NULL;
+}
+
+int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
+{
+	struct resource *res = &b->busn_res;
+	struct resource old_res = *res;
+	resource_size_t size;
+	int ret;
+
+	if (res->start > bus_max)
+		return -EINVAL;
+
+	size = bus_max - res->start + 1;
+	ret = adjust_resource(res, res->start, size);
+	dev_printk(KERN_DEBUG, &b->dev,
+			"busn_res: %pR end %s updated to %02x\n",
+			&old_res, ret ? "can not be" : "is", bus_max);
+
+	if (!ret && !res->parent)
+		pci_bus_insert_busn_res(b, res->start, res->end);
+
+	return ret;
+}
+
+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_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 {
+	struct pci_host_bridge_window *window;
+	bool found = false;
 	struct pci_bus *b;
 	struct pci_bus *b;
+	int max;
+
+	list_for_each_entry(window, resources, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
 
 
 	b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
 	b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
 	if (!b)
 	if (!b)
 		return NULL;
 		return NULL;
 
 
-	b->subordinate = pci_scan_child_bus(b);
+	if (!found) {
+		dev_info(&b->dev,
+		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
+			bus);
+		pci_bus_insert_busn_res(b, bus, 255);
+	}
+
+	max = pci_scan_child_bus(b);
+
+	if (!found)
+		pci_bus_update_busn_res_end(b, max);
+
 	pci_bus_add_devices(b);
 	pci_bus_add_devices(b);
 	return b;
 	return b;
 }
 }
@@ -1708,9 +1837,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
 
 
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &iomem_resource);
 	pci_add_resource(&resources, &iomem_resource);
+	pci_add_resource(&resources, &busn_resource);
 	b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
 	b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
 	if (b)
 	if (b)
-		b->subordinate = pci_scan_child_bus(b);
+		pci_scan_child_bus(b);
 	else
 	else
 		pci_free_resource_list(&resources);
 		pci_free_resource_list(&resources);
 	return b;
 	return b;
@@ -1725,9 +1855,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
 
 
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &ioport_resource);
 	pci_add_resource(&resources, &iomem_resource);
 	pci_add_resource(&resources, &iomem_resource);
+	pci_add_resource(&resources, &busn_resource);
 	b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
 	b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
 	if (b) {
 	if (b) {
-		b->subordinate = pci_scan_child_bus(b);
+		pci_scan_child_bus(b);
 		pci_bus_add_devices(b);
 		pci_bus_add_devices(b);
 	} else {
 	} else {
 		pci_free_resource_list(&resources);
 		pci_free_resource_list(&resources);

+ 1 - 0
drivers/pci/remove.c

@@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
 
 
 	down_write(&pci_bus_sem);
 	down_write(&pci_bus_sem);
 	list_del(&pci_bus->node);
 	list_del(&pci_bus->node);
+	pci_bus_release_busn_res(pci_bus);
 	up_write(&pci_bus_sem);
 	up_write(&pci_bus_sem);
 	if (!pci_bus->is_added)
 	if (!pci_bus->is_added)
 		return;
 		return;

+ 12 - 12
drivers/pci/setup-bus.c

@@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus)
 	struct resource *res;
 	struct resource *res;
 	struct pci_bus_region region;
 	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];
 	res = bus->resource[0];
 	pcibios_resource_to_bus(bridge, &region, res);
 	pcibios_resource_to_bus(bridge, &region, res);
@@ -553,8 +553,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
 {
 {
 	struct pci_dev *bridge = bus->self;
 	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)
 	if (type & IORESOURCE_IO)
 		pci_setup_bridge_io(bus);
 		pci_setup_bridge_io(bus);
@@ -745,8 +745,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 	if (!size0 && !size1) {
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 			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;
 		b_res->flags = 0;
 		return;
 		return;
 	}
 	}
@@ -757,8 +757,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 	if (size1 > size0 && realloc_head) {
 	if (size1 > size0 && realloc_head) {
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
 		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 +863,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 	if (!size0 && !size1) {
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 			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;
 		b_res->flags = 0;
 		return 1;
 		return 1;
 	}
 	}
@@ -874,8 +874,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 	if (size1 > size0 && realloc_head) {
 	if (size1 > size0 && realloc_head) {
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
 		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
 		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;
 	return 1;
 }
 }

+ 1 - 1
drivers/pcmcia/cardbus.c

@@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
 	pci_fixup_cardbus(bus);
 	pci_fixup_cardbus(bus);
 
 
-	max = bus->secondary;
+	max = bus->busn_res.start;
 	for (pass = 0; pass < 2; pass++)
 	for (pass = 0; pass < 2; pass++)
 		list_for_each_entry(dev, &bus->devices, bus_list)
 		list_for_each_entry(dev, &bus->devices, bus_list)
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||

+ 13 - 13
drivers/pcmcia/yenta_socket.c

@@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket)
 	config_writeb(socket, PCI_LATENCY_TIMER, 168);
 	config_writeb(socket, PCI_LATENCY_TIMER, 168);
 	config_writel(socket, PCI_PRIMARY_BUS,
 	config_writel(socket, PCI_PRIMARY_BUS,
 		(176 << 24) |			   /* sec. latency timer */
 		(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 */
 		dev->subordinate->primary);		   /* primary bus */
 
 
 	/*
 	/*
@@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 	struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
 	struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
 
 
 	/* Check bus numbers are already set up correctly: */
 	/* Check bus numbers are already set up correctly: */
-	if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
+	if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end)
 		return; /* The subordinate number is ok, nothing to do */
 		return; /* The subordinate number is ok, nothing to do */
 
 
 	if (!bridge_to_fix->parent)
 	if (!bridge_to_fix->parent)
 		return; /* Root bridges are ok */
 		return; /* Root bridges are ok */
 
 
 	/* stay within the limits of the bus range of the parent: */
 	/* stay within the limits of the bus range of the parent: */
-	upper_limit = bridge_to_fix->parent->subordinate;
+	upper_limit = bridge_to_fix->parent->busn_res.end;
 
 
 	/* check the bus ranges of all silbling bridges to prevent overlap */
 	/* check the bus ranges of all silbling bridges to prevent overlap */
 	list_for_each(tmp, &bridge_to_fix->parent->children) {
 	list_for_each(tmp, &bridge_to_fix->parent->children) {
@@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 		 * current upper limit, set the new upper limit to
 		 * current upper limit, set the new upper limit to
 		 * the bus number below the silbling's range:
 		 * the bus number below the silbling's range:
 		 */
 		 */
-		if (silbling->secondary > bridge_to_fix->subordinate
-		    && silbling->secondary <= upper_limit)
-			upper_limit = silbling->secondary - 1;
+		if (silbling->busn_res.start > bridge_to_fix->busn_res.end
+		    && silbling->busn_res.start <= upper_limit)
+			upper_limit = silbling->busn_res.start - 1;
 	}
 	}
 
 
 	/* Show that the wanted subordinate number is not possible: */
 	/* Show that the wanted subordinate number is not possible: */
-	if (cardbus_bridge->subordinate > upper_limit)
+	if (cardbus_bridge->busn_res.end > upper_limit)
 		dev_printk(KERN_WARNING, &cardbus_bridge->dev,
 		dev_printk(KERN_WARNING, &cardbus_bridge->dev,
 			   "Upper limit for fixing this "
 			   "Upper limit for fixing this "
 			   "bridge's parent bridge: #%02x\n", upper_limit);
 			   "bridge's parent bridge: #%02x\n", upper_limit);
 
 
 	/* If we have room to increase the bridge's subordinate number, */
 	/* If we have room to increase the bridge's subordinate number, */
-	if (bridge_to_fix->subordinate < upper_limit) {
+	if (bridge_to_fix->busn_res.end < upper_limit) {
 
 
 		/* use the highest number of the hidden bus, within limits */
 		/* use the highest number of the hidden bus, within limits */
 		unsigned char subordinate_to_assign =
 		unsigned char subordinate_to_assign =
-			min(cardbus_bridge->subordinate, upper_limit);
+			min_t(int, cardbus_bridge->busn_res.end, upper_limit);
 
 
 		dev_printk(KERN_INFO, &bridge_to_fix->dev,
 		dev_printk(KERN_INFO, &bridge_to_fix->dev,
 			   "Raising subordinate bus# of parent "
 			   "Raising subordinate bus# of parent "
 			   "bus (#%02x) from #%02x to #%02x\n",
 			   "bus (#%02x) from #%02x to #%02x\n",
 			   bridge_to_fix->number,
 			   bridge_to_fix->number,
-			   bridge_to_fix->subordinate, subordinate_to_assign);
+			   (int)bridge_to_fix->busn_res.end, subordinate_to_assign);
 
 
 		/* Save the new subordinate in the bus struct of the bridge */
 		/* Save the new subordinate in the bus struct of the bridge */
-		bridge_to_fix->subordinate = subordinate_to_assign;
+		bridge_to_fix->busn_res.end = subordinate_to_assign;
 
 
 		/* and update the PCI config space with the new subordinate */
 		/* and update the PCI config space with the new subordinate */
 		pci_write_config_byte(bridge_to_fix->self,
 		pci_write_config_byte(bridge_to_fix->self,
-			PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
+			PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end);
 	}
 	}
 }
 }
 
 

+ 6 - 2
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);
 	return (pdev->error_state != pci_channel_io_normal);
 }
 }
 
 
+extern struct resource busn_resource;
+
 struct pci_host_bridge_window {
 struct pci_host_bridge_window {
 	struct list_head list;
 	struct list_head list;
 	struct resource *res;		/* host bridge aperture (CPU address) */
 	struct resource *res;		/* host bridge aperture (CPU address) */
@@ -419,6 +421,7 @@ struct pci_bus {
 	struct list_head slots;		/* list of slots on this bus */
 	struct list_head slots;		/* list of slots on this bus */
 	struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
 	struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
 	struct list_head resources;	/* address space routed to this bus */
 	struct list_head resources;	/* address space routed to this bus */
+	struct resource busn_res;	/* bus numbers routed to this bus */
 
 
 	struct pci_ops	*ops;		/* configuration access functions */
 	struct pci_ops	*ops;		/* configuration access functions */
 	void		*sysdata;	/* hook for sys-specific extension */
 	void		*sysdata;	/* hook for sys-specific extension */
@@ -426,8 +429,6 @@ struct pci_bus {
 
 
 	unsigned char	number;		/* bus number */
 	unsigned char	number;		/* bus number */
 	unsigned char	primary;	/* number of primary bridge */
 	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	max_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
 
 
@@ -668,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_bus *pci_create_root_bus(struct device *parent, int bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
 				    struct list_head *resources);
+int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
+int 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_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
 					     struct list_head *resources);

+ 8 - 5
kernel/resource.c

@@ -722,14 +722,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
 
 
 	write_lock(&resource_lock);
 	write_lock(&resource_lock);
 
 
+	if (!parent)
+		goto skip;
+
 	if ((start < parent->start) || (end > parent->end))
 	if ((start < parent->start) || (end > parent->end))
 		goto out;
 		goto out;
 
 
-	for (tmp = res->child; tmp; tmp = tmp->sibling) {
-		if ((tmp->start < start) || (tmp->end > end))
-			goto out;
-	}
-
 	if (res->sibling && (res->sibling->start <= end))
 	if (res->sibling && (res->sibling->start <= end))
 		goto out;
 		goto out;
 
 
@@ -741,6 +739,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
 			goto out;
 			goto out;
 	}
 	}
 
 
+skip:
+	for (tmp = res->child; tmp; tmp = tmp->sibling)
+		if ((tmp->start < start) || (tmp->end > end))
+			goto out;
+
 	res->start = start;
 	res->start = start;
 	res->end = end;
 	res->end = end;
 	result = 0;
 	result = 0;