Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 527706a7 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sched: Ensure watchdog is enabled before disabling"

parents e1e01a17 42ea2119
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <linux/delay.h>

#include <linux/kthread.h>

@@ -5985,6 +5986,22 @@ int sched_isolate_cpu(int cpu)
	if (++cpu_isolation_vote[cpu] > 1)
		goto out;

	/*
	 * There is a race between watchdog being enabled by hotplug and
	 * core isolation disabling the watchdog. When a CPU is hotplugged in
	 * and the hotplug lock has been released the watchdog thread might
	 * not have run yet to enable the watchdog.
	 * We have to wait for the watchdog to be enabled before proceeding.
	 */
	if (!watchdog_configured(cpu)) {
		msleep(20);
		if (!watchdog_configured(cpu)) {
			--cpu_isolation_vote[cpu];
			ret_code = -EBUSY;
			goto out;
		}
	}

	set_cpu_isolated(cpu, true);
	cpumask_clear_cpu(cpu, &avail_cpus);

+20 −8
Original line number Diff line number Diff line
@@ -456,17 +456,13 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio)
	sched_setscheduler(current, policy, &param);
}

/* Must be called with hotplug lock (lock_device_hotplug()) held. */
void watchdog_enable(unsigned int cpu)
{
	struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
	unsigned int *enabled = this_cpu_ptr(&watchdog_en);

	lock_device_hotplug_assert();

	if (*enabled)
		return;
	*enabled = 1;

	/*
	 * Start the timer first to prevent the NMI watchdog triggering
@@ -484,19 +480,24 @@ void watchdog_enable(unsigned int cpu)
		watchdog_nmi_enable(cpu);

	watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);

	/*
	 * Need to ensure above operations are observed by other CPUs before
	 * indicating that timer is enabled. This is to synchronize core
	 * isolation and hotplug. Core isolation will wait for this flag to be
	 * set.
	 */
	mb();
	*enabled = 1;
}

/* Must be called with hotplug lock (lock_device_hotplug()) held. */
void watchdog_disable(unsigned int cpu)
{
	struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
	unsigned int *enabled = this_cpu_ptr(&watchdog_en);

	lock_device_hotplug_assert();

	if (!*enabled)
		return;
	*enabled = 0;

	watchdog_set_prio(SCHED_NORMAL, 0);
	/*
@@ -506,6 +507,17 @@ void watchdog_disable(unsigned int cpu)
	 */
	watchdog_nmi_disable(cpu);
	hrtimer_cancel(hrtimer);

	/*
	 * No need for barrier here since disabling the watchdog is
	 * synchronized with hotplug lock
	 */
	*enabled = 0;
}

bool watchdog_configured(unsigned int cpu)
{
	return *per_cpu_ptr(&watchdog_en, cpu);
}

static void watchdog_cleanup(unsigned int cpu, bool online)