Commit e16b4660 authored by Keith Busch's avatar Keith Busch Committed by Bjorn Helgaas
Browse files

PCI: Allow additional bus numbers for hotplug bridges



A user may hot add a switch requiring more than one bus to enumerate.  This
previously required a system reboot if BIOS did not sufficiently pad the
bus resource, which they frequently don't do.

Add a kernel parameter so a user can specify the minimum number of bus
numbers to reserve for a hotplug bridge's subordinate buses so rebooting
won't be necessary.

The default is 1, which is equivalent to previous behavior.

Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent af8c34ce
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3016,6 +3016,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
		hpmemsize=nn[KMG]	The fixed amount of bus space which is
				reserved for hotplug bridge's memory window.
				Default size is 2 megabytes.
		hpbussize=nn	The minimum amount of additional bus numbers
				reserved for buses below a hotplug bridge.
				Default is 1.
		realloc=	Enable/disable reallocating PCI bridge resources
				if allocations done by BIOS are too small to
				accommodate resources required by all child
+8 −0
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;

#define DEFAULT_HOTPLUG_BUS_SIZE	1
unsigned long pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;

enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;

/*
@@ -5021,6 +5024,11 @@ static int __init pci_setup(char *str)
				pci_hotplug_io_size = memparse(str + 9, &str);
			} else if (!strncmp(str, "hpmemsize=", 10)) {
				pci_hotplug_mem_size = memparse(str + 10, &str);
			} else if (!strncmp(str, "hpbussize=", 10)) {
				pci_hotplug_bus_size =
					simple_strtoul(str + 10, &str, 0);
				if (pci_hotplug_bus_size > 0xff)
					pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
			} else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
				pcie_bus_config = PCIE_BUS_TUNE_OFF;
			} else if (!strncmp(str, "pcie_bus_safe", 13)) {
+9 −0
Original line number Diff line number Diff line
@@ -2076,6 +2076,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
				max = pci_scan_bridge(bus, dev, max, pass);
		}

	/*
	 * Make sure a hotplug bridge has at least the minimum requested
	 * number of buses.
	 */
	if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) {
		if (max - bus->busn_res.start < pci_hotplug_bus_size - 1)
			max = bus->busn_res.start + pci_hotplug_bus_size - 1;
	}

	/*
	 * We've scanned the bus and so we know all about what's on
	 * the other side of any bridges that may be on this bus plus
+1 −0
Original line number Diff line number Diff line
@@ -1706,6 +1706,7 @@ extern u8 pci_cache_line_size;

extern unsigned long pci_hotplug_io_size;
extern unsigned long pci_hotplug_mem_size;
extern unsigned long pci_hotplug_bus_size;

/* Architecture-specific versions may override these (weak) */
void pcibios_disable_device(struct pci_dev *dev);