[Skiboot] [PATCH 2/2] pci: Make fast reboot creset PHBs in parallel

Michael Neuling mikey at neuling.org
Thu Feb 22 11:26:52 AEDT 2018


In this patch, we added a creset to the fast reboot path:

  commit a1eba9d29d17ff44fca1293b071023a9fbf4b938
  Author: Andrew Donnellan <andrew.donnellan at au1.ibm.com>
  fast-reboot: creset PHBs on fast reboot

Unfortunately, this does the creset in serial rather than in
parallel.

This patch changes the creset on fast reboot to operate in
parallel. It simplifies the code by abstracting pci_init_slots() so
that it can be used on boot and fast reboot to perform all the PCI
retraining.

This improves fast reboot PCI training on a dual chip P9 from ~12
seconds down to ~2 seconds. Similar improvements for P8 are achieved
as well.

This means the time to download the BOOTKERNEL is the bottleneck for
fast reboot.

Signed-off-by: Michael Neuling <mikey at neuling.org>
---
 core/pci.c | 51 +++++++++++++++++++++------------------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/core/pci.c b/core/pci.c
index 2ed3e05d15..e4b824aa9b 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -973,13 +973,13 @@ static void pci_reset_phb(void *data)
 	struct pci_slot *slot = phb->slot;
 	int64_t rc;
 
-	if (!slot || !slot->ops.freset) {
-		PCINOTICE(phb, 0, "Cannot issue fundamental reset\n");
+	if (!slot || !slot->ops.run_sm) {
+		PCINOTICE(phb, 0, "Cannot issue reset\n");
 		return;
 	}
 
 	pci_slot_add_flags(slot, PCI_SLOT_FLAG_BOOTUP);
-	rc = slot->ops.freset(slot);
+	rc = slot->ops.run_sm(slot);
 	while (rc > 0) {
 		PCITRACE(phb, 0, "Waiting %ld ms\n", tb_to_msecs(rc));
 		time_wait(rc);
@@ -987,7 +987,7 @@ static void pci_reset_phb(void *data)
 	}
 	pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
 	if (rc < 0)
-		PCIERR(phb, 0, "Error %lld fundamental resetting\n", rc);
+		PCIERR(phb, 0, "Error %lld resetting\n", rc);
 }
 
 static void pci_scan_phb(void *data)
@@ -1680,7 +1680,7 @@ static void pci_do_jobs(void (*fn)(void *))
 	free(jobs);
 }
 
-void pci_init_slots(void)
+static void __pci_init_slots(void)
 {
 	unsigned int i;
 
@@ -1748,46 +1748,37 @@ static void __pci_reset(struct list_head *list)
 int64_t pci_reset(void)
 {
 	unsigned int i;
-	struct pci_slot *slot;
-	int64_t rc;
 
 	prlog(PR_NOTICE, "PCI: Clearing all devices...\n");
 
-	/* XXX Do those in parallel (at least the power up
-	 * state machine could be done in parallel)
-	 */
 	for (i = 0; i < ARRAY_SIZE(phbs); i++) {
 		struct phb *phb = phbs[i];
 		if (!phb)
 			continue;
 		__pci_reset(&phb->devices);
 
-		slot = phb->slot;
-		if (!slot || !slot->ops.creset) {
-			PCINOTICE(phb, 0, "Can't do complete reset\n");
-		} else {
-			rc = slot->ops.creset(slot);
-			while (rc > 0) {
-				time_wait(rc);
-				rc = slot->ops.run_sm(slot);
-			}
-			if (rc < 0) {
-				PCIERR(phb, 0, "Complete reset failed "
-				               "(rc=%lld)\n", rc);
-				return rc;
-			}
-		}
-
-		if (phb->ops->ioda_reset)
-			phb->ops->ioda_reset(phb, true);
+		pci_slot_set_state(phb->slot, PCI_SLOT_STATE_CRESET_START);
 	}
 
-	/* Re-Initialize all discovered PCI slots */
-	pci_init_slots();
+	/* Do init and discovery of PCI slots in parallel */
+	__pci_init_slots();
 
 	return 0;
 }
 
+void pci_init_slots(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(phbs); i++) {
+		struct phb *phb = phbs[i];
+		if (!phb)
+			continue;
+		pci_slot_set_state(phb->slot, PCI_SLOT_STATE_FRESET_POWER_OFF);
+	}
+	__pci_init_slots();
+}
+
 /*
  * Complete iteration on current level before switching to
  * child level, which is the proper order for restoring
-- 
2.14.1



More information about the Skiboot mailing list