aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/psci/psci.c
diff options
context:
space:
mode:
authorMarc Zyngier <[email protected]>2021-06-15 11:12:26 +0000
committerWill Deacon <[email protected]>2021-06-17 17:00:39 +0000
commitc9223b616298c3d0e6ff5dd20d14d65c2131c535 (patch)
tree2ccdd6c72704403c9de79d46f01eb463f92e9dd9 /drivers/firmware/psci/psci.c
parentarm64: Convert cpu_do_idle() to using cpuidle context helpers (diff)
downloadkernel-c9223b616298c3d0e6ff5dd20d14d65c2131c535.tar.gz
kernel-c9223b616298c3d0e6ff5dd20d14d65c2131c535.zip
PSCI: Use cpuidle context helpers in psci_cpu_suspend_enter()
The PSCI CPU suspend code isn't aware of the PMR vs DAIF game, resulting in a system that locks up if entering CPU suspend with GICv3 pNMI enabled. To save the day, teach the suspend code about our new cpuidle context helpers, which will do everything that's required just like the usual WFI cpuidle code. This fixes my Altra system, which would otherwise lock-up at boot time when booted with irqchip.gicv3_pseudo_nmi=1. Tested-by: Valentin Schneider <[email protected]> Reviewed-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
Diffstat (limited to 'drivers/firmware/psci/psci.c')
-rw-r--r--drivers/firmware/psci/psci.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 3c1c5daf6df2..e3da38e15c5b 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -335,10 +335,15 @@ int psci_cpu_suspend_enter(u32 state)
{
int ret;
- if (!psci_power_state_loses_context(state))
+ if (!psci_power_state_loses_context(state)) {
+ struct arm_cpuidle_irq_context context;
+
+ arm_cpuidle_save_irq_context(&context);
ret = psci_ops.cpu_suspend(state, 0);
- else
+ arm_cpuidle_restore_irq_context(&context);
+ } else {
ret = cpu_suspend(state, psci_suspend_finisher);
+ }
return ret;
}