Skip to content

Commit 08d72bd

Browse files
committed
Merge tag 'smp-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull CPU hotplug updates from Thomas Gleixner: "A small set of updates for CPU hotplug: - Prevent stale CPU hotplug state in the cpu_down() path which was detected by stress testing the sysfs interface - Ensure that the target CPU hotplug state for the boot CPU is CPUHP_ONLINE instead of the compile time init value CPUHP_OFFLINE. - Switch back to the original behaviour of warning when a CPU hotplug callback in the DYING/STARTING section returns an error code. Otherwise a buggy callback can leave the CPUs in an non recoverable state" * tag 'smp-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: cpu/hotplug: Do not bail-out in DYING/STARTING sections cpu/hotplug: Set cpuhp target for boot cpu cpu/hotplug: Make target_store() a nop when target == state
2 parents 9d33edb + 6f855b3 commit 08d72bd

1 file changed

Lines changed: 44 additions & 17 deletions

File tree

kernel/cpu.c

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -663,21 +663,51 @@ static bool cpuhp_next_state(bool bringup,
663663
return true;
664664
}
665665

666-
static int cpuhp_invoke_callback_range(bool bringup,
667-
unsigned int cpu,
668-
struct cpuhp_cpu_state *st,
669-
enum cpuhp_state target)
666+
static int __cpuhp_invoke_callback_range(bool bringup,
667+
unsigned int cpu,
668+
struct cpuhp_cpu_state *st,
669+
enum cpuhp_state target,
670+
bool nofail)
670671
{
671672
enum cpuhp_state state;
672-
int err = 0;
673+
int ret = 0;
673674

674675
while (cpuhp_next_state(bringup, &state, st, target)) {
676+
int err;
677+
675678
err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL);
676-
if (err)
679+
if (!err)
680+
continue;
681+
682+
if (nofail) {
683+
pr_warn("CPU %u %s state %s (%d) failed (%d)\n",
684+
cpu, bringup ? "UP" : "DOWN",
685+
cpuhp_get_step(st->state)->name,
686+
st->state, err);
687+
ret = -1;
688+
} else {
689+
ret = err;
677690
break;
691+
}
678692
}
679693

680-
return err;
694+
return ret;
695+
}
696+
697+
static inline int cpuhp_invoke_callback_range(bool bringup,
698+
unsigned int cpu,
699+
struct cpuhp_cpu_state *st,
700+
enum cpuhp_state target)
701+
{
702+
return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false);
703+
}
704+
705+
static inline void cpuhp_invoke_callback_range_nofail(bool bringup,
706+
unsigned int cpu,
707+
struct cpuhp_cpu_state *st,
708+
enum cpuhp_state target)
709+
{
710+
__cpuhp_invoke_callback_range(bringup, cpu, st, target, true);
681711
}
682712

683713
static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st)
@@ -999,7 +1029,6 @@ static int take_cpu_down(void *_param)
9991029
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
10001030
enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
10011031
int err, cpu = smp_processor_id();
1002-
int ret;
10031032

10041033
/* Ensure this CPU doesn't handle any more interrupts. */
10051034
err = __cpu_disable();
@@ -1012,13 +1041,10 @@ static int take_cpu_down(void *_param)
10121041
*/
10131042
WARN_ON(st->state != (CPUHP_TEARDOWN_CPU - 1));
10141043

1015-
/* Invoke the former CPU_DYING callbacks */
1016-
ret = cpuhp_invoke_callback_range(false, cpu, st, target);
1017-
10181044
/*
1019-
* DYING must not fail!
1045+
* Invoke the former CPU_DYING callbacks. DYING must not fail!
10201046
*/
1021-
WARN_ON_ONCE(ret);
1047+
cpuhp_invoke_callback_range_nofail(false, cpu, st, target);
10221048

10231049
/* Give up timekeeping duties */
10241050
tick_handover_do_timer();
@@ -1296,16 +1322,14 @@ void notify_cpu_starting(unsigned int cpu)
12961322
{
12971323
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
12981324
enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
1299-
int ret;
13001325

13011326
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
13021327
cpumask_set_cpu(cpu, &cpus_booted_once_mask);
1303-
ret = cpuhp_invoke_callback_range(true, cpu, st, target);
13041328

13051329
/*
13061330
* STARTING must not fail!
13071331
*/
1308-
WARN_ON_ONCE(ret);
1332+
cpuhp_invoke_callback_range_nofail(true, cpu, st, target);
13091333
}
13101334

13111335
/*
@@ -2326,8 +2350,10 @@ static ssize_t target_store(struct device *dev, struct device_attribute *attr,
23262350

23272351
if (st->state < target)
23282352
ret = cpu_up(dev->id, target);
2329-
else
2353+
else if (st->state > target)
23302354
ret = cpu_down(dev->id, target);
2355+
else if (WARN_ON(st->target != target))
2356+
st->target = target;
23312357
out:
23322358
unlock_device_hotplug();
23332359
return ret ? ret : count;
@@ -2688,6 +2714,7 @@ void __init boot_cpu_hotplug_init(void)
26882714
cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
26892715
#endif
26902716
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
2717+
this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
26912718
}
26922719

26932720
/*

0 commit comments

Comments
 (0)