aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/soc/qcom/pil-q6v5-mss.c5
-rw-r--r--drivers/soc/qcom/subsys-pil-tz.c5
-rw-r--r--drivers/soc/qcom/subsystem_restart.c33
-rw-r--r--include/soc/qcom/subsystem_restart.h3
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;
};
/**