diff options
author | Iliyan Malchev <malchev@google.com> | 2011-09-15 17:04:16 -0700 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-09-23 14:44:54 -0700 |
commit | 21c623210684840ad05241e8fc3f8941d95308be (patch) | |
tree | 1e3cbeb28c0ea89e243b618ef930eb6181935ea5 /drivers/remoteproc | |
parent | ddbb0c5faf3eed37d1d6a578d01a770d2586fe54 (diff) | |
download | kernel_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.c | 61 |
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); } |