From: Vincent Donnefort <[email protected]>

After the AP brought itself down to CPUHP_TEARDOWN_CPU, the BP will finish
the job. The steps left are as followed:

   +--------------------+
   | CPUHP_TEARDOWN_CPU |  -> If fails state is CPUHP_TEARDOWN_CPU
   +--------------------+
   |   ATOMIC STATES    |  -> Cannot Fail
   +--------------------+
   |  CPUHP_BRINGUP_CPU |  -> Cannot fail
   +--------------------+
   |        ...         |
   |        ...         |  -> Can fail and rollback
   |   CPUHP_OFFLINE    |
   +--------------------+

There are, in case of failure two possibilities:

  1. Failure in CPUHP_TEARDOWN_CPU, then st->state will still be
     CPUHP_TEARDOWN_CPU

  2. Failure between CPUHP_OFFLINE and CPUHP_BRINGUP_CPU.

For 2. The rollback will always run in the CPUHP_BRINGUP_CPU bringup
callback (bringup_cpu()) which kicks the AP back on. The latter will then
end-up setting st->state to CPUHP_AP_ONLINE_IDLE.

Checking for CPUHP_AP_ONLINE_IDLE allows then to rollback in all cases.

Signed-off-by: Vincent Donnefort <[email protected]>
---
 kernel/cpu.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/kernel/cpu.c b/kernel/cpu.c
index aebec3a..8b3f84e 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1078,7 +1078,14 @@ static int __ref _cpu_down(unsigned int cpu, int 
tasks_frozen,
         * to do the further cleanups.
         */
        ret = cpuhp_down_callbacks(cpu, st, target);
-       if (ret && st->state == CPUHP_TEARDOWN_CPU && st->state < prev_state) {
+       if (ret && (st->state == CPUHP_AP_ONLINE_IDLE ||
+                   st->state == CPUHP_TEARDOWN_CPU) &&
+           st->state < prev_state) {
+               /*
+                * After an error the state can be either:
+                *  - CPUHP_TEARDOWN_CPU if this step failed.
+                *  - CPUHP_AP_ONLINE_IDLE if any other failed.
+                */
                cpuhp_reset_state(st, prev_state);
                __cpuhp_kick_ap(st);
        }
-- 
2.7.4

Reply via email to