diff options
author | Marc Zyngier <maz@kernel.org> | 2022-04-19 19:27:55 +0100 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2022-04-20 13:24:44 +0100 |
commit | 7d26b0516a0df5888fd1486054bc5159f6c0b88f (patch) | |
tree | 4b334316f4569a701315f196892c861b1b0cf305 | |
parent | 9eae588529751f95834bca775b30b66291def7f6 (diff) | |
download | linux-7d26b0516a0df5888fd1486054bc5159f6c0b88f.tar.gz linux-7d26b0516a0df5888fd1486054bc5159f6c0b88f.tar.bz2 linux-7d26b0516a0df5888fd1486054bc5159f6c0b88f.zip |
arm64: Use WFxT for __delay() when possible
Marginally optimise __delay() by using a WFIT/WFET sequence.
It probably is a win if no interrupt fires during the delay.
Signed-off-by: Marc Zyngier <maz@kernel.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20220419182755.601427-11-maz@kernel.org
-rw-r--r-- | arch/arm64/lib/delay.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c index 1688af0a4c97..5b7890139bc2 100644 --- a/arch/arm64/lib/delay.c +++ b/arch/arm64/lib/delay.c @@ -27,7 +27,17 @@ void __delay(unsigned long cycles) { cycles_t start = get_cycles(); - if (arch_timer_evtstrm_available()) { + if (cpus_have_const_cap(ARM64_HAS_WFXT)) { + u64 end = start + cycles; + + /* + * Start with WFIT. If an interrupt makes us resume + * early, use a WFET loop to complete the delay. + */ + wfit(end); + while ((get_cycles() - start) < cycles) + wfet(end); + } else if (arch_timer_evtstrm_available()) { const cycles_t timer_evt_period = USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US); |