Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1739925 > unrolled thread
| Started by | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| First post | 2017-09-26 16:20 +0200 |
| Last post | 2017-09-26 16:20 +0200 |
| Articles | 6 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/7] PCI: Improvements for native PCIe hotplug Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
[PATCH 7/7] PCI: pciehp: Check that the device is really present before touching it Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
[PATCH 5/7] PCI: pciehp: Fix race condition handling surprise link down Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
[PATCH 6/7] PCI: pciehp: Do not clear Presence Detect Changed during initialization Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
[PATCH 4/7] PCI: Distribute available resources to hotplug capable PCIe downstream ports Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
[PATCH 1/7] PCI: Do not allocate more buses than available in parent Mika Westerberg <mika.westerberg@linux.intel.com> - 2017-09-26 16:20 +0200
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 0/7] PCI: Improvements for native PCIe hotplug |
| Message-ID | <utYSl-5Rt-5@gated-at.bofh.it> |
Hi,
Currently when plugging PCIe device using native PCIe hotplug Linux PCI
core tries to allocate bus space and resources so that the newly enumerated
topology barely fits there. Now, if the PCIe topology that was just plugged
in has more PCIe hotplug ports we will run out of bus space and resources
pretty quickly. There is a workaround for this by passing pci=hpbussize=N
in the kernel command line but it runs to the same situation after next
hotplug.
A good example where this is a problem is Thunderbolt where each
Thunderbolt device includes PCIe switch and the topology can be extended up
to 6 chained devices.
Future platforms will move from BIOS assisted (ACPI) hotplug from native
PCIe hotplug because then it is possible to power down PCIe hotplug ports
without confusing the SMI handler which is not necessary when native PCIe
hotplug is used. Also Macs have been using native PCIe hotplug from the
beginning. The upcoming Windows already learned how to handle these complex
PCIe topologies and we will reuse the same knowledge in Linux with this
patch series.
The idea is to distribute available bus space and resources to hotplug PCIe
downstream ports so that the PCIe chain can be extended from those points.
The initial available space is configured by the BIOS to the root port in
question.
This series first teaches the Linux PCI core to distribute available bus
space and resources if PCIe hotplug is used. Then following are fixes for
issues found while testing.
With this series applied I can connect the maximum length Thunderbolt PCIe
chain (6 devices) to a Macbook Pro as can be seen from the 'lspci -t'
output below:
-[0000:00]-+-00.0
+-02.0
+-14.0
+-16.0
+-19.0
+-1c.0-[01]----00.0
+-1c.4-[03-78]----00.0-[04-78]--+-00.0-[05]----00.0
| +-01.0-[07-3f]----00.0-[08-3f]--+-01.0-[09]----00.0
| | \-04.0-[0a-3f]----00.0-[0b-3f]--+-01.0-[0c]----00.0
| | \-04.0-[0d-3f]----00.0-[0e-3f]--+-01.0-[0f]--
| | \-04.0-[10-3f]----00.0-[11-3f]--+-01.0-[12]----00.0
| | \-04.0-[13-3f]----00.0-[14-3f]--+-01.0-[15]----00.0
| | \-04.0-[16-3f]----00.0-[17-3f]----00.0-[18-3f]----00.0
| +-02.0-[06]----00.0
| \-04.0-[40-78]--
+-1d.0-[79-ee]----00.0-[7a-ee]--+-00.0-[7b]----00.0
| +-01.0-[7d-b5]--
| +-02.0-[7c]----00.0
| \-04.0-[b6-ee]--
+-1d.3-[02]----00.0
+-1e.0
+-1e.1
+-1e.3
+-1f.0
+-1f.2
+-1f.3
\-1f.4
Mika Westerberg (7):
PCI: Do not allocate more buses than available in parent
PCI: Introduce pcie_upstream_port()
PCI: Distribute available buses to hotplug capable PCIe downstream ports
PCI: Distribute available resources to hotplug capable PCIe downstream ports
PCI: pciehp: Fix race condition handling surprise link down
PCI: pciehp: Do not clear Presence Detect Changed during initialization
PCI: pciehp: Check that the device is really present before touching it
drivers/pci/hotplug-pci.c | 13 ++-
drivers/pci/hotplug/pciehp_ctrl.c | 7 +-
drivers/pci/hotplug/pciehp_hpc.c | 13 ++-
drivers/pci/hotplug/pciehp_pci.c | 18 +++-
drivers/pci/probe.c | 113 +++++++++++++++++++++----
drivers/pci/setup-bus.c | 169 ++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 30 ++++++-
7 files changed, 332 insertions(+), 31 deletions(-)
--
2.14.1
[toc] | [next] | [standalone]
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 7/7] PCI: pciehp: Check that the device is really present before touching it |
| Message-ID | <utYSm-5Rt-27@gated-at.bofh.it> |
| In reply to | #1739925 |
During surprise hot-unplug the device is not there anymore. When that
happens we read 0xffffffff from the registers and pciehp_unconfigure_device()
inadvertently thinks the device is a display device because bridge
control register returns 0xff refusing to remove it:
pciehp 0000:00:1c.0:pcie004: Slot(0): Link Down
pciehp 0000:00:1c.0:pcie004: Slot(0): Card present
pciehp 0000:00:1c.0:pcie004: Cannot remove display device 0000:01:00.0
This causes the hotplug functionality to leave the hierarcy untouched
preventing further hotplug operations.
To fix this verify presence of a device by calling pci_device_is_present()
for it before we touch it any further.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/pci/hotplug/pciehp_pci.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index b31702f76149..2a3a62393ba9 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -101,8 +101,14 @@ int pciehp_unconfigure_device(struct slot *p_slot)
*/
list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
bus_list) {
+ bool present;
+
pci_dev_get(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+
+ /* Check if the device is really there anymore */
+ present = presence ? pci_device_is_present(dev) : false;
+
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && present) {
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
ctrl_err(ctrl,
@@ -113,7 +119,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
break;
}
}
- if (!presence) {
+ if (!present) {
pci_dev_set_disconnected(dev, NULL);
if (pci_has_subordinate(dev))
pci_walk_bus(dev->subordinate,
@@ -124,7 +130,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
* Ensure that no new Requests will be generated from
* the device.
*/
- if (presence) {
+ if (present) {
pci_read_config_word(dev, PCI_COMMAND, &command);
command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
command |= PCI_COMMAND_INTX_DISABLE;
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 5/7] PCI: pciehp: Fix race condition handling surprise link down |
| Message-ID | <utYSm-5Rt-23@gated-at.bofh.it> |
| In reply to | #1739925 |
A surprise link down may retrain very quickly causing the same slot
generate a link up event before handling the link down event completes.
Since the link is active, the power off work queued from the first link
down will cause a second down event when power is disabled. However, the
link up event sets the slot state to POWERON_STATE before the event to
handle this is enqueued, making the second down event believe it needs
to do something.
This creates constant link up and down event cycle.
To prevent this it is better to handle each event at the time in order
it occurred, so change the driver to use ordered workqueue instead.
A normal device hotplug triggers two events (presense detect and link
up) that are already handled properly in the driver but we currently log
an error if we find an existing device in the slot. Since this is not an
error change the log level to be debug instead to avoid scaring users.
This is based on the original work by Ashok Raj.
Link: https://patchwork.kernel.org/patch/9469023
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/pci/hotplug/pciehp_ctrl.c | 7 ++++---
drivers/pci/hotplug/pciehp_hpc.c | 2 +-
drivers/pci/hotplug/pciehp_pci.c | 6 +++++-
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index ec0b4c11ccd9..83f3d4af3677 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -113,10 +113,11 @@ static int board_added(struct slot *p_slot)
retval = pciehp_configure_device(p_slot);
if (retval) {
- ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
- pci_domain_nr(parent), parent->number);
- if (retval != -EEXIST)
+ if (retval != -EEXIST) {
+ ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
+ pci_domain_nr(parent), parent->number);
goto err_exit;
+ }
}
pciehp_green_led_on(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index e5d5ce9e3010..83c93f9da65a 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -795,7 +795,7 @@ static int pcie_init_slot(struct controller *ctrl)
if (!slot)
return -ENOMEM;
- slot->wq = alloc_workqueue("pciehp-%u", 0, 0, PSN(ctrl));
+ slot->wq = alloc_ordered_workqueue("pciehp-%u", 0, PSN(ctrl));
if (!slot->wq)
goto abort;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 19f30a9f461d..b31702f76149 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -46,7 +46,11 @@ int pciehp_configure_device(struct slot *p_slot)
dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
if (dev) {
- ctrl_err(ctrl, "Device %s already exists at %04x:%02x:00, cannot hot-add\n",
+ /*
+ * The device is already there. Either configured by the
+ * boot firmware or a previous hotplug event.
+ */
+ ctrl_dbg(ctrl, "Device %s already exists at %04x:%02x:00, skipping hot-add\n",
pci_name(dev), pci_domain_nr(parent), parent->number);
pci_dev_put(dev);
ret = -EEXIST;
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 6/7] PCI: pciehp: Do not clear Presence Detect Changed during initialization |
| Message-ID | <utYSm-5Rt-29@gated-at.bofh.it> |
| In reply to | #1739925 |
It is possible that the hotplug event has already happened before the driver is attached to a PCIe hotplug downstream port. If we just clear the status we never get the hotplug interrupt and thus the event will be missed. To make sure that does not happen, we leave Presence Detect Changed bit untouched during initialization. Then once the event is unmasked we get an interrupt and handle the hotplug event properly. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> --- drivers/pci/hotplug/pciehp_hpc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 83c93f9da65a..bc1622aa7a05 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -862,11 +862,16 @@ struct controller *pcie_init(struct pcie_device *dev) if (link_cap & PCI_EXP_LNKCAP_DLLLARC) ctrl->link_active_reporting = 1; - /* Clear all remaining event bits in Slot Status register */ + /* + * Clear all remaining event bits in Slot Status register except + * Presence Detect Changed. We want to make sure possible + * hotplug event is triggered when the interrupt is unmasked so + * that we don't lose that event. + */ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | - PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | - PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); + PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_CC | + PCI_EXP_SLTSTA_DLLSC); ctrl_info(ctrl, "Slot #%d AttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c Interlock%c NoCompl%c LLActRep%c\n", (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, -- 2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 4/7] PCI: Distribute available resources to hotplug capable PCIe downstream ports |
| Message-ID | <utYSm-5Rt-31@gated-at.bofh.it> |
| In reply to | #1739925 |
The same problem that we have with bus space, applies to other resources
as well. Linux only allocates the minimal amount of resources so that
the devices currently present barely fit there. This prevents extending
the chain later on because the resource windows allocated for hotplug
downstream ports are too small.
Here we follow what we already did for bus number and assign all
available extra resources to hotplug capable PCIe downstream ports. This
makes it possible to extend the hierarchy later.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/pci/setup-bus.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 958da7db9033..5df6cbcfbf54 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1853,6 +1853,167 @@ void __init pci_assign_unassigned_resources(void)
}
}
+static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
+ struct list_head *add_list, resource_size_t available)
+{
+ struct pci_dev_resource *dev_res;
+
+ if (res->parent)
+ return;
+
+ if (resource_size(res) >= available)
+ return;
+
+ dev_res = res_to_dev_res(add_list, res);
+ if (!dev_res)
+ return;
+
+ /* Is there room to extend the window */
+ if (available - resource_size(res) <= dev_res->add_size)
+ return;
+
+ dev_res->add_size = available - resource_size(res);
+ dev_dbg(&bridge->dev, "bridge window %pR extended by %pa\n", res,
+ &dev_res->add_size);
+}
+
+static void pci_bus_distribute_available_resources(struct pci_bus *bus,
+ struct list_head *add_list, resource_size_t available_io,
+ resource_size_t available_mmio, resource_size_t available_mmio_pref)
+{
+ resource_size_t remaining_io, remaining_mmio, remaining_mmio_pref;
+ struct resource *io_res, *mmio_res, *mmio_pref_res;
+ struct pci_dev *dev, *bridge = bus->self;
+ unsigned int hotplug_bridges = 0;
+
+ io_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
+ mmio_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
+ mmio_pref_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
+
+ /*
+ * Update additional resource list (add_list) to fill all the
+ * extra resource space available for this port except the space
+ * calculated in __pci_bus_size_bridges() which covers all the
+ * devices currently connected to the port and below.
+ */
+ extend_bridge_window(bridge, io_res, add_list, available_io);
+ extend_bridge_window(bridge, mmio_res, add_list, available_mmio);
+ extend_bridge_window(bridge, mmio_pref_res, add_list,
+ available_mmio_pref);
+
+ /*
+ * Calculate the total amount of extra resource space we can
+ * pass the to bridges below this one. This is basically the
+ * extra space substracted by the minimal required space for the
+ * non-hotplug bridges.
+ */
+ remaining_io = available_io;
+ remaining_mmio = available_mmio;
+ remaining_mmio_pref = available_mmio_pref;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ const struct resource *res;
+
+ if (!pci_is_bridge(dev))
+ continue;
+
+ /* Keep track how many hotplug bridges this bus has */
+ if (dev->is_hotplug_bridge) {
+ hotplug_bridges++;
+ } else {
+ /*
+ * Reduce the available resource space by what
+ * the bridge and devices below it occupy.
+ */
+ res = &dev->resource[PCI_BRIDGE_RESOURCES + 0];
+ if (!res->parent && available_io > resource_size(res))
+ remaining_io -= resource_size(res);
+
+ res = &dev->resource[PCI_BRIDGE_RESOURCES + 1];
+ if (!res->parent && available_mmio > resource_size(res))
+ remaining_mmio -= resource_size(res);
+
+ res = &dev->resource[PCI_BRIDGE_RESOURCES + 2];
+ if (!res->parent &&
+ available_mmio_pref > resource_size(res))
+ remaining_mmio_pref -= resource_size(res);
+ }
+ }
+
+ /*
+ * Go over devices on this bus and distribute the remaining
+ * resource space between hotplug bridges.
+ */
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ struct pci_bus *b;
+
+ b = dev->subordinate;
+ if (!b || !pci_is_bridge(dev))
+ continue;
+
+ if (pcie_upstream_port(dev)) {
+ /*
+ * Upstream port gets all resources directly
+ * from the downstream port.
+ */
+ pci_bus_distribute_available_resources(b, add_list,
+ available_io, available_mmio,
+ available_mmio_pref);
+ } else if (dev->is_hotplug_bridge) {
+ resource_size_t align, io, mmio, mmio_pref;
+
+ /*
+ * Distribute available extra resources equally
+ * between hotplug capable downstream ports
+ * taking alignment into account.
+ *
+ * Here hotplug_bridges is always != 0.
+ */
+ align = pci_resource_alignment(bridge, io_res);
+ io = div64_ul(available_io, hotplug_bridges);
+ io = min(ALIGN(io, align), remaining_io);
+ remaining_io -= io;
+
+ align = pci_resource_alignment(bridge, mmio_res);
+ mmio = div64_ul(available_mmio, hotplug_bridges);
+ mmio = min(ALIGN(mmio, align), remaining_mmio);
+ remaining_mmio -= mmio;
+
+ align = pci_resource_alignment(bridge, mmio_pref_res);
+ mmio_pref = div64_ul(available_mmio_pref,
+ hotplug_bridges);
+ mmio_pref = min(ALIGN(mmio_pref, align),
+ remaining_mmio_pref);
+ remaining_mmio_pref -= mmio_pref;
+
+ pci_bus_distribute_available_resources(b, add_list, io,
+ mmio, mmio_pref);
+ }
+ }
+}
+
+static void
+pci_bridge_distribute_available_resources(struct pci_dev *bridge,
+ struct list_head *add_list)
+{
+ resource_size_t available_io, available_mmio, available_mmio_pref;
+ const struct resource *res;
+
+ if (!bridge->is_hotplug_bridge)
+ return;
+
+ /* Take the initial extra resources from the hotplug port */
+ res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
+ available_io = resource_size(res);
+ res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
+ available_mmio = resource_size(res);
+ res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
+ available_mmio_pref = resource_size(res);
+
+ pci_bus_distribute_available_resources(bridge->subordinate,
+ add_list, available_io, available_mmio, available_mmio_pref);
+}
+
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{
struct pci_bus *parent = bridge->subordinate;
@@ -1867,6 +2028,14 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
again:
__pci_bus_size_bridges(parent, &add_list);
+
+ /*
+ * Distribute remaining resources (if any) equally between
+ * hotplug bridges below. This makes it possible to extend the
+ * hierarchy later without running out of resources.
+ */
+ pci_bridge_distribute_available_resources(bridge, &add_list);
+
__pci_bridge_assign_resources(bridge, &add_list, &fail_head);
BUG_ON(!list_empty(&add_list));
tried_times++;
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|---|
| Date | 2017-09-26 16:20 +0200 |
| Subject | [PATCH 1/7] PCI: Do not allocate more buses than available in parent |
| Message-ID | <utYSm-5Rt-35@gated-at.bofh.it> |
| In reply to | #1739925 |
One can ask more buses to be reserved for hotplug bridges by passing
pci=hpbussize=N in the kernel command line. However, if the parent bus
does not have enough bus space available we still create child bus with
the requested number of subordinate buses.
In the example below hpbussize is set to one more than we have available
buses in the root port:
pci 0000:07:00.0: [8086:1578] type 01 class 0x060400
pci 0000:07:00.0: calling pci_fixup_transparent_bridge+0x0/0x20
pci 0000:07:00.0: supports D1 D2
pci 0000:07:00.0: PME# supported from D0 D1 D2 D3hot D3cold
pci 0000:07:00.0: PME# disabled
pci 0000:07:00.0: scanning [bus 00-00] behind bridge, pass 0
pci 0000:07:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
pci 0000:07:00.0: scanning [bus 00-00] behind bridge, pass 1
pci_bus 0000:08: busn_res: can not insert [bus 08-ff] under [bus 07-3f] (conflicts with (null) [bus 07-3f])
pci_bus 0000:08: scanning bus
...
pci_bus 0000:0a: bus scan returning with max=40
pci_bus 0000:0a: busn_res: [bus 0a-ff] end is updated to 40
pci_bus 0000:0a: [bus 0a-40] partially hidden behind bridge 0000:07 [bus 07-3f]
pci_bus 0000:08: bus scan returning with max=40
pci_bus 0000:08: busn_res: [bus 08-ff] end is updated to 40
Instead of allowing this we limit the subordinate number to be less than
or equal the maximum subordinate number allocated for the parent bus (if
it has any).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/pci/probe.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ff94b69738a8..f285cd74088e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1076,7 +1076,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
child = pci_add_new_bus(bus, dev, max+1);
if (!child)
goto out;
- pci_bus_insert_busn_res(child, max+1, 0xff);
+ pci_bus_insert_busn_res(child, max+1,
+ bus->busn_res.end);
}
max++;
buses = (buses & 0xff000000)
@@ -2433,6 +2434,10 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
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;
+
+ /* Do not allocate more buses than we have room left */
+ if (max > bus->busn_res.end)
+ max = bus->busn_res.end;
}
/*
--
2.14.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web