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 Original line Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/security.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/delay.h>


#include <linux/kthread.h>
#include <linux/kthread.h>


@@ -5985,6 +5986,22 @@ int sched_isolate_cpu(int cpu)
	if (++cpu_isolation_vote[cpu] > 1)
	if (++cpu_isolation_vote[cpu] > 1)
		goto out;
		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);
	set_cpu_isolated(cpu, true);
	cpumask_clear_cpu(cpu, &avail_cpus);
	cpumask_clear_cpu(cpu, &avail_cpus);


+20 −8
Original line number Original line 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);
	sched_setscheduler(current, policy, &param);
}
}


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


	lock_device_hotplug_assert();

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


	/*
	/*
	 * Start the timer first to prevent the NMI watchdog triggering
	 * 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_nmi_enable(cpu);


	watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);
	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)
void watchdog_disable(unsigned int cpu)
{
{
	struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
	struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
	unsigned int *enabled = this_cpu_ptr(&watchdog_en);
	unsigned int *enabled = this_cpu_ptr(&watchdog_en);


	lock_device_hotplug_assert();

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


	watchdog_set_prio(SCHED_NORMAL, 0);
	watchdog_set_prio(SCHED_NORMAL, 0);
	/*
	/*
@@ -506,6 +507,17 @@ void watchdog_disable(unsigned int cpu)
	 */
	 */
	watchdog_nmi_disable(cpu);
	watchdog_nmi_disable(cpu);
	hrtimer_cancel(hrtimer);
	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)
static void watchdog_cleanup(unsigned int cpu, bool online)