@@ -7,6 +7,7 @@
#include <skiboot.h>
#include <cpu.h>
+#include <chip.h>
#include <pci.h>
#include <pci-cfg.h>
#include <pci-slot.h>
@@ -21,6 +22,23 @@ int last_phb_id = 0;
/*
* Generic PCI utilities
*/
+static void pci_time_wait(unsigned long duration)
+{
+ /* QEMU doesn't need to wait */
+ if (!chip_quirk(QUIRK_QEMU)) {
+ backtrace();
+ time_wait(duration);
+ }
+}
+
+static void pci_time_wait_ms(unsigned long ms)
+{
+ /* QEMU doesn't need to wait */
+ if (!chip_quirk(QUIRK_QEMU)) {
+ backtrace();
+ time_wait_ms(ms);
+ }
+}
static int64_t __pci_find_cap(struct phb *phb, uint16_t bdfn,
uint8_t want, bool check_cap_indicator)
@@ -205,7 +223,7 @@ bool pci_wait_crs(struct phb *phb, uint16_t bdfn, uint32_t *out_vdid)
if (vdid != 0xffff0001)
break;
had_crs = true;
- time_wait_ms(100);
+ pci_time_wait_ms(100);
}
if (vdid == 0xffff0001) {
PCIERR(phb, bdfn, "CRS timeout !\n");
@@ -412,7 +430,7 @@ static void pci_slot_set_power_state(struct phb *phb,
break;
check_timers(false);
- time_wait_ms(10);
+ pci_time_wait_ms(10);
} while (--wait >= 0);
if (wait < 0) {
@@ -497,7 +515,7 @@ static bool pci_bridge_power_on(struct phb *phb, struct pci_device *pd)
ecap + PCICAP_EXP_SLOTCTL, slot_ctl);
/* Wait a couple of seconds */
- time_wait_ms(2000);
+ pci_time_wait_ms(2000);
}
/* Enable link */
@@ -528,7 +546,7 @@ static bool pci_bridge_wait_link(struct phb *phb,
*/
if (!(link_cap & PCICAP_EXP_LCAP_DL_ACT_REP)) {
if (was_reset)
- time_wait_ms(1000);
+ pci_time_wait_ms(1000);
return true;
}
@@ -544,7 +562,7 @@ static bool pci_bridge_wait_link(struct phb *phb,
if (link_sts & PCICAP_EXP_LSTAT_DLLL_ACT)
break;
- time_wait_ms(100);
+ pci_time_wait_ms(100);
}
if (!(link_sts & PCICAP_EXP_LSTAT_DLLL_ACT)) {
@@ -553,7 +571,7 @@ static bool pci_bridge_wait_link(struct phb *phb,
}
/* Need another 100ms before touching the config space */
- time_wait_ms(100);
+ pci_time_wait_ms(100);
PCIDBG(phb, pd->bdfn, "link is up\n");
return true;
@@ -623,7 +641,7 @@ static bool pci_enable_bridge(struct phb *phb, struct pci_device *pd)
"Bridge secondary reset is on, clearing it ...\n");
bctl &= ~PCI_CFG_BRCTL_SECONDARY_RESET;
pci_cfg_write16(phb, pd->bdfn, PCI_CFG_BRCTL, bctl);
- time_wait_ms(1000);
+ pci_time_wait_ms(1000);
was_reset = true;
}
@@ -973,7 +991,7 @@ static void pci_reset_phb(void *data)
rc = slot->ops.run_sm(slot);
while (rc > 0) {
PCITRACE(phb, 0, "Waiting %ld ms\n", tb_to_msecs(rc));
- time_wait(rc);
+ pci_time_wait(rc);
rc = slot->ops.run_sm(slot);
}
pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
@@ -1675,7 +1693,7 @@ static void __pci_init_slots(void)
*/
for (i = 0; i < ARRAY_SIZE(phbs); i++) {
if (phbs[i]) {
- time_wait_ms(20);
+ pci_time_wait_ms(20);
break;
}
}
@@ -5,6 +5,7 @@
#define __PCI_SLOT_H
#include <opal.h>
+#include <chip.h>
#include <device.h>
#include <timebase.h>
#include <timer.h>
@@ -233,6 +234,9 @@ static inline void pci_slot_set_state(struct pci_slot *slot, uint32_t state)
static inline uint64_t pci_slot_set_sm_timeout(struct pci_slot *slot,
uint64_t dur)
{
+ /* QEMU doesn't need to wait */
+ if (chip_quirk(QUIRK_QEMU))
+ return 0;
if (slot)
slot->delay_tgt_tb = mftb() + dur;
return dur;
Waiting for PCI reset is the most costly component of a QEMU boot, mostly due to 1s delay between PERST deassert and device config space access. These PCI hardware delays are not required with QEMU, so skip them on that platform. On a single-CPU QEMU powernv10 machine where PCI probing is not well parallelised, this reduces skiboot boot time from 6.3s to 0.4s. This is important for testing and CI. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- core/pci.c | 36 +++++++++++++++++++++++++++--------- include/pci-slot.h | 4 ++++ 2 files changed, 31 insertions(+), 9 deletions(-)