aboutsummaryrefslogtreecommitdiff
path: root/core/pci.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2016-10-14 15:26:04 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-10-17 10:33:56 +1100
commit481ad7330e332770b1dcd2c9f56d0a2caac67755 (patch)
treec33454a0d6a6420c46c7ecf07a4a8a1b8586d9c2 /core/pci.c
parent39aad95618fea977464bfc38ec0c190075a26304 (diff)
downloadskiboot-481ad7330e332770b1dcd2c9f56d0a2caac67755.zip
skiboot-481ad7330e332770b1dcd2c9f56d0a2caac67755.tar.gz
skiboot-481ad7330e332770b1dcd2c9f56d0a2caac67755.tar.bz2
core/pci: Reserve PCI buses for RC's slot
When RC's downstream link is down, we need reserve spare PCI buses if it has an associated PCI hotplug slot. Otherwise, the adapter behind it can't be probed successfully in PCI hot add scenario. This reserves all available buses (to 255) for RC's hotplug slot when its downstream is down so that PCI adapter can be hot added to the slot afterwards. Cc: stable # 5.3.0+ Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pci.c')
-rw-r--r--core/pci.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/core/pci.c b/core/pci.c
index 07b15d8..ba7cd9d 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -558,9 +558,10 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus, uint8_t max_bus,
struct list_head *list, struct pci_device *parent,
bool scan_downstream)
{
- struct pci_device *pd = NULL;
+ struct pci_device *pd = NULL, *rc = NULL;
uint8_t dev, fn, next_bus, max_sub, save_max;
uint32_t scan_map;
+ bool use_max;
/* Decide what to scan */
scan_map = parent ? parent->scan_map : phb->scan_map;
@@ -576,6 +577,10 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus, uint8_t max_bus,
if (!pd)
continue;
+ /* Record RC when its downstream link is down */
+ if (!scan_downstream && dev == 0 && !rc)
+ rc = pd;
+
/* XXX Handle ARI */
if (!pd->is_multifunction)
continue;
@@ -586,6 +591,20 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus, uint8_t max_bus,
}
}
+ /* Reserve all possible buses if RC's downstream link is down
+ * if PCI hotplug is supported.
+ */
+ if (rc && rc->slot && rc->slot->pluggable) {
+ next_bus = phb->ops->choose_bus(phb, rc, bus + 1,
+ &max_bus, &use_max);
+ rc->secondary_bus = next_bus;
+ rc->subordinate_bus = max_bus;
+ pci_cfg_write8(phb, rc->bdfn, PCI_CFG_SECONDARY_BUS,
+ rc->secondary_bus);
+ pci_cfg_write8(phb, rc->bdfn, PCI_CFG_SUBORDINATE_BUS,
+ rc->subordinate_bus);
+ }
+
/*
* We only scan downstream if instructed to do so by the
* caller. Typically we avoid the scan when we know the
@@ -605,7 +624,7 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus, uint8_t max_bus,
/* Scan down bridges */
list_for_each(list, pd, link) {
- bool use_max, do_scan;
+ bool do_scan;
if (!pd->is_bridge)
continue;