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

Commit a97a6be4 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sched: Ensure watchdog is enabled before disabling"

parents 5a1e6a8d af04b3a2
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -446,6 +446,7 @@ extern unsigned int hardlockup_panic;
void lockup_detector_init(void);
extern void watchdog_enable(unsigned int cpu);
extern void watchdog_disable(unsigned int cpu);
extern bool watchdog_configured(unsigned int cpu);
#else
static inline void touch_softlockup_watchdog_sched(void)
{
@@ -468,6 +469,14 @@ static inline void watchdog_enable(unsigned int cpu)
static inline void watchdog_disable(unsigned int cpu)
{
}
static inline bool watchdog_configured(unsigned int cpu)
{
	/*
	 * Predend the watchdog is always configured.
	 * We will be waiting for the watchdog to be enabled in core isolation
	 */
	return true;
}
#endif

#ifdef CONFIG_DETECT_HUNG_TASK
+16 −0
Original line number Diff line number Diff line
@@ -5696,6 +5696,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
@@ -588,17 +588,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 = raw_cpu_ptr(&watchdog_hrtimer);
	unsigned int *enabled = raw_cpu_ptr(&watchdog_en);

	lock_device_hotplug_assert();

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

	/* kick off the timer for the hardlockup detector */
	hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -614,24 +610,40 @@ void watchdog_enable(unsigned int cpu)
	/* initialize timestamp */
	watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);
	__touch_watchdog();

	/*
	 * 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 = raw_cpu_ptr(&watchdog_hrtimer);
	unsigned int *enabled = raw_cpu_ptr(&watchdog_en);

	lock_device_hotplug_assert();

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

	watchdog_set_prio(SCHED_NORMAL, 0);
	hrtimer_cancel(hrtimer);
	/* disable the perf event */
	watchdog_nmi_disable(cpu);

	/*
	 * 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)