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

Commit 267538c2 authored by Olav Haugan's avatar Olav Haugan Committed by Satya Durga Srinivasu Prabhala
Browse files

watchdog: Add support for cpu isolation



Open up interface to allow external subsystem to enable and disable hard
lockup detector.

Change-Id: I42b82e7c7869be1df0837c86d3d97aafb4b064bb
Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
[markivx: Forward port to 4.14 and moved sched.h diff to nmi.h]
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
[satyap@codeaurora.org: Port to 4.19 and fix merge conflicts]
Signed-off-by: default avatarSatya Durga Srinivasu Prabhala <satyap@codeaurora.org>
parent 3832c3d3
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -716,6 +716,11 @@ int lock_device_hotplug_sysfs(void)
	return restart_syscall();
}

void lock_device_hotplug_assert(void)
{
	lockdep_assert_held(&device_hotplug_lock);
}

#ifdef CONFIG_BLOCK
static inline int device_is_not_partition(struct device *dev)
{
+1 −0
Original line number Diff line number Diff line
@@ -1203,6 +1203,7 @@ static inline bool device_supports_offline(struct device *dev)
extern void lock_device_hotplug(void);
extern void unlock_device_hotplug(void);
extern int lock_device_hotplug_sysfs(void);
extern void lock_device_hotplug_assert(void);
extern int device_offline(struct device *dev);
extern int device_online(struct device *dev);
extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
+17 −0
Original line number Diff line number Diff line
@@ -13,6 +13,9 @@

#ifdef CONFIG_LOCKUP_DETECTOR
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);
void lockup_detector_soft_poweroff(void);
void lockup_detector_cleanup(void);
bool is_hardlockup(void);
@@ -37,6 +40,20 @@ extern int sysctl_hardlockup_all_cpu_backtrace;
static inline void lockup_detector_init(void) { }
static inline void lockup_detector_soft_poweroff(void) { }
static inline void lockup_detector_cleanup(void) { }
static inline void watchdog_enable(unsigned int cpu)
{
}
static inline void watchdog_disable(unsigned int cpu)
{
}
static inline bool watchdog_configured(unsigned int cpu)
{
	/*
	 * Pretend the watchdog is always configured.
	 * We will be waiting for the watchdog to be enabled in core isolation
	 */
	return true;
}
#endif /* !CONFIG_LOCKUP_DETECTOR */

#ifdef CONFIG_SOFTLOCKUP_DETECTOR
+20 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#include <linux/mm.h>
#include <linux/cpu.h>
#include <linux/device.h>
#include <linux/nmi.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -170,6 +171,7 @@ static u64 __read_mostly sample_period;

static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer);
static DEFINE_PER_CPU(unsigned int, watchdog_en);
static DEFINE_PER_CPU(bool, softlockup_touch_sync);
static DEFINE_PER_CPU(bool, soft_watchdog_warn);
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
@@ -469,16 +471,24 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
	return HRTIMER_RESTART;
}

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

	WARN_ON_ONCE(cpu != smp_processor_id());

	init_completion(done);
	complete(done);

	lock_device_hotplug_assert();

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

	/*
	 * Start the timer first to prevent the NMI watchdog triggering
	 * before the timer has a chance to fire.
@@ -495,9 +505,17 @@ static void watchdog_enable(unsigned int cpu)
		watchdog_nmi_enable(cpu);
}

static void watchdog_disable(unsigned int cpu)
/* 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;

	WARN_ON_ONCE(cpu != smp_processor_id());