diff options
author | Michael Neuling <mikey@neuling.org> | 2018-02-22 11:26:52 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2018-02-28 20:28:28 -0600 |
commit | fe6d86b92a0054f7f063cd957091889f4ccd853a (patch) | |
tree | a4f86b02516bb0d8b24970b4691ad0862a3f1ea8 /core/pci.c | |
parent | fa03921a9aa6296b6019c79127db7d009705be2d (diff) | |
download | talos-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.c | 51 |
1 files changed, 21 insertions, 30 deletions
@@ -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 |