soc: qcom: Add watchdog bite in panic

Add watchdog bite in panic by registering a restart handler. Also add
support for an earlier watchdog bite in the panic handler itself, which
should provide a better context for post-mortem analysis.

Change-Id: Ib6530fa754b78fd26a9f7d5a348b1e7ceb3c1f96
Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
Elliot Berman 2019-10-18 11:19:58 -07:00
parent 205d6619be
commit ad4ce8c7d2
4 changed files with 45 additions and 8 deletions

View File

@ -502,13 +502,6 @@ static int do_msm_restart(struct notifier_block *unused, unsigned long action,
msm_restart_prepare(cmd);
/*
* Trigger a watchdog bite here and if this fails,
* device will take the usual restart path.
*/
if (WDOG_BITE_ON_PANIC && in_panic)
msm_trigger_wdog_bite();
qcom_scm_disable_sdi();
qcom_scm_halt_spmi_pmic_arbiter();
deassert_ps_hold();

View File

@ -783,7 +783,7 @@ config QCOM_WATCHDOG
not catch any early lockups.
config QCOM_FORCE_WDOG_BITE_ON_PANIC
bool "QCOM force watchdog bite"
bool "QCOM force watchdog bite on panic"
depends on QCOM_WATCHDOG
help
This forces a watchdog bite when the device restarts
@ -791,6 +791,16 @@ config QCOM_FORCE_WDOG_BITE_ON_PANIC
this provides additional debugging
information.
config QCOM_WDOG_BITE_EARLY_PANIC
bool "QCOM early panic watchdog bite"
depends on QCOM_WATCHDOG && QCOM_FORCE_WDOG_BITE_ON_PANIC
help
This forces a watchdog bite early in panic sequence. On certain
MSM SoCs, this provides us additional debugging information at the
context of the crash. If this option is disabled, then bite occurs
later in panic, which permits more of the restart sequence to run
(e.g. more dmesg to flushed to console).
config MSM_SPCOM
depends on QCOM_GLINK
tristate "Secure Processor Communication over RPMSG"

View File

@ -18,6 +18,7 @@
#include <linux/cpu_pm.h>
#include <linux/platform_device.h>
#include <linux/wait.h>
#include <linux/reboot.h>
#include <linux/qcom_scm.h>
#include <soc/qcom/minidump.h>
#include <soc/qcom/watchdog.h>
@ -68,8 +69,10 @@ struct msm_watchdog_data {
cpumask_t alive_mask;
struct mutex disable_lock;
bool irq_ppi;
bool in_panic;
struct msm_watchdog_data __percpu **wdog_cpu_dd;
struct notifier_block panic_blk;
struct notifier_block restart_blk;
bool enabled;
bool user_pet_enabled;
@ -168,6 +171,11 @@ static int panic_wdog_handler(struct notifier_block *this,
{
struct msm_watchdog_data *wdog_dd = container_of(this,
struct msm_watchdog_data, panic_blk);
wdog_dd->in_panic = true;
if (WDOG_BITE_EARLY_PANIC) {
pr_info("Triggering early bite\n");
msm_trigger_wdog_bite();
}
if (panic_timeout == 0) {
__raw_writel(0, wdog_dd->base + WDT0_EN);
/* Make sure watchdog is enabled before notifying the caller */
@ -206,6 +214,22 @@ static void wdog_disable(struct msm_watchdog_data *wdog_dd)
dev_err(wdog_dd->dev, "MSM Apps Watchdog deactivated\n");
}
static int restart_wdog_handler(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct msm_watchdog_data *wdog_dd = container_of(this,
struct msm_watchdog_data, restart_blk);
if (WDOG_BITE_ON_PANIC && wdog_dd->in_panic) {
/*
* Trigger a watchdog bite here and if this fails,
* device will take the usual restart path.
*/
pr_info("Triggering late bite\n");
msm_trigger_wdog_bite();
}
return NOTIFY_DONE;
}
static ssize_t wdog_disable_get(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -587,9 +611,13 @@ static void init_watchdog_data(struct msm_watchdog_data *wdog_dd)
__raw_writel(timeout, wdog_dd->base + WDT0_BARK_TIME);
__raw_writel(timeout + 3*WDT_HZ, wdog_dd->base + WDT0_BITE_TIME);
wdog_dd->panic_blk.priority = WDOG_BITE_EARLY_PANIC ? INT_MAX - 1 : 0;
wdog_dd->panic_blk.notifier_call = panic_wdog_handler;
atomic_notifier_chain_register(&panic_notifier_list,
&wdog_dd->panic_blk);
wdog_dd->restart_blk.priority = 255;
wdog_dd->restart_blk.notifier_call = restart_wdog_handler;
register_restart_handler(&wdog_dd->restart_blk);
mutex_init(&wdog_dd->disable_lock);
init_waitqueue_head(&wdog_dd->pet_complete);
wdog_dd->timer_expired = false;

View File

@ -12,6 +12,12 @@
#define WDOG_BITE_ON_PANIC 0
#endif
#ifdef CONFIG_QCOM_WDOG_BITE_EARLY_PANIC
#define WDOG_BITE_EARLY_PANIC 1
#else
#define WDOG_BITE_EARLY_PANIC 0
#endif
#if IS_ENABLED(CONFIG_QCOM_WATCHDOG)
void msm_trigger_wdog_bite(void);
#else