Commit 08d72bd2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 9d33edb2 6f855b39
Loading
Loading
Loading
Loading
+44 −17
Original line number Diff line number Diff line
@@ -663,21 +663,51 @@ static bool cpuhp_next_state(bool bringup,
	return true;
}

static int cpuhp_invoke_callback_range(bool bringup,
static int __cpuhp_invoke_callback_range(bool bringup,
					 unsigned int cpu,
					 struct cpuhp_cpu_state *st,
				       enum cpuhp_state target)
					 enum cpuhp_state target,
					 bool nofail)
{
	enum cpuhp_state state;
	int err = 0;
	int ret = 0;

	while (cpuhp_next_state(bringup, &state, st, target)) {
		int err;

		err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL);
		if (err)
		if (!err)
			continue;

		if (nofail) {
			pr_warn("CPU %u %s state %s (%d) failed (%d)\n",
				cpu, bringup ? "UP" : "DOWN",
				cpuhp_get_step(st->state)->name,
				st->state, err);
			ret = -1;
		} else {
			ret = err;
			break;
		}
	}

	return err;
	return ret;
}

static inline int cpuhp_invoke_callback_range(bool bringup,
					      unsigned int cpu,
					      struct cpuhp_cpu_state *st,
					      enum cpuhp_state target)
{
	return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false);
}

static inline void cpuhp_invoke_callback_range_nofail(bool bringup,
						      unsigned int cpu,
						      struct cpuhp_cpu_state *st,
						      enum cpuhp_state target)
{
	__cpuhp_invoke_callback_range(bringup, cpu, st, target, true);
}

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

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

	/* Invoke the former CPU_DYING callbacks */
	ret = cpuhp_invoke_callback_range(false, cpu, st, target);

	/*
	 * DYING must not fail!
	 * Invoke the former CPU_DYING callbacks. DYING must not fail!
	 */
	WARN_ON_ONCE(ret);
	cpuhp_invoke_callback_range_nofail(false, cpu, st, target);

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

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

	/*
	 * STARTING must not fail!
	 */
	WARN_ON_ONCE(ret);
	cpuhp_invoke_callback_range_nofail(true, cpu, st, target);
}

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

	if (st->state < target)
		ret = cpu_up(dev->id, target);
	else
	else if (st->state > target)
		ret = cpu_down(dev->id, target);
	else if (WARN_ON(st->target != target))
		st->target = target;
out:
	unlock_device_hotplug();
	return ret ? ret : count;
@@ -2688,6 +2714,7 @@ void __init boot_cpu_hotplug_init(void)
	cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
#endif
	this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
	this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
}

/*