提交 e16b4660 编写于 作者: K Keith Busch 提交者: Bjorn Helgaas

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: NKeith Busch <keith.busch@intel.com>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
上级 af8c34ce
...@@ -3016,6 +3016,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -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 hpmemsize=nn[KMG] The fixed amount of bus space which is
reserved for hotplug bridge's memory window. reserved for hotplug bridge's memory window.
Default size is 2 megabytes. 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 realloc= Enable/disable reallocating PCI bridge resources
if allocations done by BIOS are too small to if allocations done by BIOS are too small to
accommodate resources required by all child accommodate resources required by all child
......
...@@ -81,6 +81,9 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; ...@@ -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_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_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; enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
/* /*
...@@ -5021,6 +5024,11 @@ static int __init pci_setup(char *str) ...@@ -5021,6 +5024,11 @@ static int __init pci_setup(char *str)
pci_hotplug_io_size = memparse(str + 9, &str); pci_hotplug_io_size = memparse(str + 9, &str);
} else if (!strncmp(str, "hpmemsize=", 10)) { } else if (!strncmp(str, "hpmemsize=", 10)) {
pci_hotplug_mem_size = memparse(str + 10, &str); 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)) { } else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
pcie_bus_config = PCIE_BUS_TUNE_OFF; pcie_bus_config = PCIE_BUS_TUNE_OFF;
} else if (!strncmp(str, "pcie_bus_safe", 13)) { } else if (!strncmp(str, "pcie_bus_safe", 13)) {
......
...@@ -2076,6 +2076,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) ...@@ -2076,6 +2076,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
max = pci_scan_bridge(bus, dev, max, pass); 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 * 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 * the other side of any bridges that may be on this bus plus
......
...@@ -1706,6 +1706,7 @@ extern u8 pci_cache_line_size; ...@@ -1706,6 +1706,7 @@ extern u8 pci_cache_line_size;
extern unsigned long pci_hotplug_io_size; extern unsigned long pci_hotplug_io_size;
extern unsigned long pci_hotplug_mem_size; extern unsigned long pci_hotplug_mem_size;
extern unsigned long pci_hotplug_bus_size;
/* Architecture-specific versions may override these (weak) */ /* Architecture-specific versions may override these (weak) */
void pcibios_disable_device(struct pci_dev *dev); void pcibios_disable_device(struct pci_dev *dev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册