diff options
-rw-r--r-- | drivers/soc/qcom/pil-q6v5-mss.c | 5 | ||||
-rw-r--r-- | drivers/soc/qcom/subsys-pil-tz.c | 5 | ||||
-rw-r--r-- | drivers/soc/qcom/subsystem_restart.c | 33 | ||||
-rw-r--r-- | include/soc/qcom/subsystem_restart.h | 3 |
4 files changed, 46 insertions, 0 deletions
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c index 2ff8e7e8739..f49805da7f9 100644 --- a/drivers/soc/qcom/pil-q6v5-mss.c +++ b/drivers/soc/qcom/pil-q6v5-mss.c @@ -186,7 +186,12 @@ static irqreturn_t modem_wdog_bite_intr_handler(int irq, void *dev_id) struct modem_data *drv = subsys_to_drv(dev_id); if (drv->ignore_errors) return IRQ_HANDLED; + pr_err("Watchdog bite received from modem software!\n"); + if (drv->subsys_desc.system_debug && + !gpio_get_value(drv->subsys_desc.err_fatal_gpio)) + panic("%s: System ramdump requested. Triggering device restart!\n", + __func__); subsys_set_crash_status(drv->subsys, true); restart_modem(drv); return IRQ_HANDLED; diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index 350214771d8..c3fab26fe2d 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -849,6 +849,11 @@ static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) d->subsys_desc.name); return IRQ_HANDLED; } + + if (d->subsys_desc.system_debug && + !gpio_get_value(d->subsys_desc.err_fatal_gpio)) + panic("%s: System ramdump requested. Triggering device restart!\n", + __func__); subsys_set_crash_status(d->subsys, true); log_failure_reason(d); subsystem_restart_dev(d->subsys); diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index 64e79074a2b..51af0ed814b 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -226,6 +226,38 @@ static ssize_t restart_level_store(struct device *dev, return -EPERM; } +static ssize_t system_debug_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct subsys_device *subsys = to_subsys(dev); + char p[6] = "set"; + + if (!subsys->desc->system_debug) + strlcpy(p, "reset", sizeof(p)); + + return snprintf(buf, PAGE_SIZE, "%s\n", p); +} + +static ssize_t system_debug_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct subsys_device *subsys = to_subsys(dev); + const char *p; + + p = memchr(buf, '\n', count); + if (p) + count = p - buf; + + if (!strncasecmp(buf, "set", count)) + subsys->desc->system_debug = true; + else if (!strncasecmp(buf, "reset", count)) + subsys->desc->system_debug = false; + else + return -EPERM; + return count; +} + int subsys_get_restart_level(struct subsys_device *dev) { return dev->restart_level; @@ -266,6 +298,7 @@ static struct device_attribute subsys_attrs[] = { __ATTR_RO(state), __ATTR_RO(crash_count), __ATTR(restart_level, 0644, restart_level_show, restart_level_store), + __ATTR(system_debug, 0644, system_debug_show, system_debug_store), __ATTR_NULL, }; diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h index 61007a32528..3c0fc0102e9 100644 --- a/include/soc/qcom/subsystem_restart.h +++ b/include/soc/qcom/subsystem_restart.h @@ -45,6 +45,8 @@ struct module; * @ssctl_instance_id: Instance id used to connect with SSCTL service * @sysmon_pid: pdev id that sysmon is probed with for the subsystem * @sysmon_shutdown_ret: Return value for the call to sysmon_send_shutdown + * @system_debug: If "set", triggers a device restart when the + * subsystem's wdog bite handler is invoked. */ struct subsys_desc { const char *name; @@ -72,6 +74,7 @@ struct subsys_desc { int ssctl_instance_id; u32 sysmon_pid; int sysmon_shutdown_ret; + bool system_debug; }; /** |