summaryrefslogtreecommitdiffstats
path: root/core/pci.c
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2018-02-22 11:26:52 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2018-02-28 20:28:28 -0600
commitfe6d86b92a0054f7f063cd957091889f4ccd853a (patch)
treea4f86b02516bb0d8b24970b4691ad0862a3f1ea8 /core/pci.c
parentfa03921a9aa6296b6019c79127db7d009705be2d (diff)
downloadtalos-skiboot-fe6d86b92a0054f7f063cd957091889f4ccd853a.tar.gz
talos-skiboot-fe6d86b92a0054f7f063cd957091889f4ccd853a.zip
pci: Make fast reboot creset PHBs in parallel
In this patch, we added a creset to the fast reboot path: commit a1eba9d29d17ff44fca1293b071023a9fbf4b938 Author: Andrew Donnellan <andrew.donnellan@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@neuling.org> Reviewed-by: Russell Currey <ruscur@russell.cc> Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pci.c')
-rw-r--r--core/pci.c51
1 files changed, 21 insertions, 30 deletions
diff --git a/core/pci.c b/core/pci.c
index 2ed3e05d..e4b824aa 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
OpenPOWER on IntegriCloud