aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorIliyan Malchev <malchev@google.com>2011-09-15 17:04:16 -0700
committerIliyan Malchev <malchev@google.com>2011-09-23 14:44:54 -0700
commit21c623210684840ad05241e8fc3f8941d95308be (patch)
tree1e3cbeb28c0ea89e243b618ef930eb6181935ea5 /drivers/remoteproc
parentddbb0c5faf3eed37d1d6a578d01a770d2586fe54 (diff)
downloadkernel_samsung_tuna-21c623210684840ad05241e8fc3f8941d95308be.zip
kernel_samsung_tuna-21c623210684840ad05241e8fc3f8941d95308be.tar.gz
kernel_samsung_tuna-21c623210684840ad05241e8fc3f8941d95308be.tar.bz2
remoteproc: enable halt-on-crash for core dumps
This patch allows you to cause the respecive remoteproc instance to halt when crashing by writing the string "enable" to the core file: echo enable > /<debugfs>/remoteproc/<remoteproc>/core. After this, if the remoteproc crashes, you can extract the core by reading the same file. You can then resume crash recovery by writing "continue" to the file. The halt-on-crash will remain enabled, so that subsequent crashes can be analyzed by pulling the core file again. Writing "disable" will turn off halt-on-crash so that crash recovery happens immediately. (This means copying of trace{0,1} to trace{0,1}_last, and resetting the remoteproc.) Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/remoteproc.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c
index 17543eb..3203af4 100644
--- a/drivers/remoteproc/remoteproc.c
+++ b/drivers/remoteproc/remoteproc.c
@@ -347,6 +347,49 @@ static int rproc_memory_map_index(const struct rproc *rproc, loff_t *off)
return -1;
}
+ssize_t core_rproc_write(struct file *filp,
+ const char __user *buffer, size_t count, loff_t *off)
+{
+ char cmd[100];
+ int cmdlen;
+ struct core_rproc *d = filp->private_data;
+ struct rproc *rproc = d->rproc;
+
+ cmdlen = min(sizeof(cmd) - 1, count);
+ if (copy_from_user(cmd, buffer, cmdlen))
+ return -EFAULT;
+ cmd[cmdlen] = 0;
+
+ if (!strncmp(cmd, "enable", 6)) {
+ pr_info("remoteproc %s halt on crash ENABLED\n", rproc->name);
+ rproc->halt_on_crash = true;
+ goto done;
+ } else if (!strncmp(cmd, "disable", 7)) {
+ pr_info("remoteproc %s halt on crash DISABLED\n", rproc->name);
+ rproc->halt_on_crash = false;
+ /* If you disable halt-on-crashed after the remote processor
+ * has already crashed, we will let it continue crashing (so it
+ * can get handled otherwise) as well.
+ */
+ if (rproc->state != RPROC_CRASHED)
+ goto done;
+ } else if (strncmp(cmd, "continue", 8)) {
+ pr_err("%s: invalid command: expecting \"enable\"," \
+ "\"disable\", or \"continue\"\n", __func__);
+ return -EINVAL;
+ }
+
+ if (rproc->state == RPROC_CRASHED) {
+ pr_info("remoteproc %s: resuming crash recovery\n",
+ rproc->name);
+ complete_remoteproc_crash(rproc);
+ }
+
+done:
+ *off += count;
+ return count;
+}
+
static ssize_t core_rproc_read(struct file *filp,
char __user *userbuf, size_t count, loff_t *ppos)
{
@@ -423,6 +466,7 @@ static ssize_t core_rproc_read(struct file *filp,
static const struct file_operations core_rproc_ops = {
.read = core_rproc_read,
+ .write = core_rproc_write,
.open = core_rproc_open,
.release = core_rproc_release,
.llseek = generic_file_llseek,
@@ -525,9 +569,15 @@ static int rproc_mmu_fault_isr(struct rproc *rproc, u64 da, u32 flags)
static int rproc_watchdog_isr(struct rproc *rproc)
{
- dev_err(rproc->dev, "Enter %s\n", __func__);
- schedule_work(&rproc->error_work);
+ /* If the ducati is suspended in a crash, do nothing. */
+ if (rproc->state == RPROC_CRASHED) {
+ pr_info("remoteproc %s is already in the crashed state\n",
+ rproc->name);
+ return 0;
+ }
+ dev_err(rproc->dev, "%s\n", __func__);
+ schedule_work(&rproc->error_work);
return 0;
}
@@ -583,6 +633,13 @@ static int _event_notify(struct rproc *rproc, int type, void *data)
return -EINVAL;
}
+ if (type == RPROC_ERROR) {
+ /* FIXME: send uevent here */
+ pr_info("remoteproc: %s has crashed (core dump available)\n",
+ rproc->name);
+ return 0;
+ }
+
return blocking_notifier_call_chain(nh, type, data);
}