@@ -1886,6 +1886,22 @@ void pci_restore_bridge_buses(struct phb *phb, struct pci_device *pd)
pci_walk_dev(phb, pd, __pci_restore_bridge_buses, NULL);
}
+void pci_restore_slot_bus_configs(struct pci_slot *slot)
+{
+ /*
+ * We might lose the bus numbers during the reset operation
+ * and we need to restore them. Otherwise, some adapters (e.g.
+ * IPR) can't be probed properly by the kernel. We don't need
+ * to restore bus numbers for every kind of reset, however,
+ * it's not harmful to always restore the bus numbers, which
+ * simplifies the logic.
+ */
+ pci_restore_bridge_buses(slot->phb, slot->pd);
+ if (slot->phb->ops->device_init)
+ pci_walk_dev(slot->phb, slot->pd,
+ slot->phb->ops->device_init, NULL);
+}
+
struct pci_cfg_reg_filter *pci_find_cfg_reg_filter(struct pci_device *pd,
uint32_t start, uint32_t len)
{
@@ -2146,18 +2146,6 @@ static void phb4_prepare_link_change(struct pci_slot *slot, bool is_up)
out_be64(p->regs + PHB_REGB_ERR_FAT_ENABLE,
0xde0fff91035743ffull);
- /*
- * We might lose the bus numbers during the reset operation
- * and we need to restore them. Otherwise, some adapters (e.g.
- * IPR) can't be probed properly by the kernel. We don't need
- * to restore bus numbers for every kind of reset, however,
- * it's not harmful to always restore the bus numbers, which
- * simplifies the logic.
- */
- pci_restore_bridge_buses(slot->phb, slot->pd);
- if (slot->phb->ops->device_init)
- pci_walk_dev(slot->phb, slot->pd,
- slot->phb->ops->device_init, NULL);
} else {
/* Mask AER receiver error */
phb4_pcicfg_read32(&p->phb, 0, p->aercap +
@@ -2691,6 +2679,7 @@ static int64_t phb4_poll_link(struct pci_slot *slot)
*/
PHBERR(p, "LINK: Degraded but no more retries\n");
}
+ pci_restore_slot_bus_configs(slot);
pci_slot_set_state(slot, PHB4_SLOT_NORMAL);
return OPAL_SUCCESS;
}
@@ -436,6 +436,7 @@ extern int64_t pci_find_ecap(struct phb *phb, uint16_t bdfn, uint16_t cap,
uint8_t *version);
extern void pci_init_capabilities(struct phb *phb, struct pci_device *pd);
extern bool pci_wait_crs(struct phb *phb, uint16_t bdfn, uint32_t *out_vdid);
+extern void pci_restore_slot_bus_configs(struct pci_slot *slot);
extern void pci_device_init(struct phb *phb, struct pci_device *pd);
extern struct pci_device *pci_walk_dev(struct phb *phb,
struct pci_device *pd,
Currently we restore PCIe bus numbers right after the link is up. Unfortunately as this point we haven't done CRS so config space may not be accessible. This moves the bus number restore till after CRS has happened. Signed-off-by: Michael Neuling <mikey@neuling.org> --- core/pci.c | 16 ++++++++++++++++ hw/phb4.c | 13 +------------ include/pci.h | 1 + 3 files changed, 18 insertions(+), 12 deletions(-)