aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorMiguel Vadillo <vadillo@ti.com>2011-09-07 21:14:18 -0500
committerIliyan Malchev <malchev@google.com>2011-09-09 12:12:29 -0700
commit8a8569a0561cba735355a46c52bb155232c8fbf4 (patch)
treedb487d2f663c048edfebae7a2d36c5e466036132 /drivers/remoteproc
parent4be6fc8085f231a37772a9732819dbffd534629a (diff)
downloadkernel_samsung_tuna-8a8569a0561cba735355a46c52bb155232c8fbf4.zip
kernel_samsung_tuna-8a8569a0561cba735355a46c52bb155232c8fbf4.tar.gz
kernel_samsung_tuna-8a8569a0561cba735355a46c52bb155232c8fbf4.tar.bz2
drivers: remoteproc: save last traces in sysfs in case of crash
When an error is detected copy the last trace buffer content of each core to an entry in sysfs, this is to provide a way to see the last ducati traces after a crash. After a recovery the last buffer traces can be cat'ed reading trace0_last and trace1_last. Signed-off-by: Miguel Vadillo <vadillo@ti.com>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/remoteproc.c78
1 files changed, 58 insertions, 20 deletions
diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c
index 4124011..05c0c98 100644
--- a/drivers/remoteproc/remoteproc.c
+++ b/drivers/remoteproc/remoteproc.c
@@ -55,8 +55,8 @@ static ssize_t rproc_format_trace_buf(char __user *userbuf, size_t count,
int i, w_pos;
/* Assume write_idx is the penultimate byte in the buffer trace*/
- w_idx = (int *)(buf + (size - (sizeof(u32) * 2)));
size = size - (sizeof(u32) * 2);
+ w_idx = (int *)(buf + size);
w_pos = *w_idx;
if (from_beg)
@@ -127,6 +127,10 @@ static const struct file_operations rproc_name_ops = {
DEBUGFS_READONLY_FILE(trace0, rproc->trace_buf0, rproc->trace_len0);
DEBUGFS_READONLY_FILE(trace1, rproc->trace_buf1, rproc->trace_len1);
+DEBUGFS_READONLY_FILE(trace0_last, rproc->last_trace_buf0,
+ rproc->last_trace_len0);
+DEBUGFS_READONLY_FILE(trace1_last, rproc->last_trace_buf1,
+ rproc->last_trace_len1);
#define DEBUGFS_ADD(name) \
debugfs_create_file(#name, 0400, rproc->dbg_dir, \
@@ -211,6 +215,12 @@ static int _event_notify(struct rproc *rproc, int type, void *data)
init_completion(&rproc->error_comp);
rproc->state = RPROC_CRASHED;
mutex_unlock(&rproc->lock);
+ if (rproc->trace_buf0 && rproc->last_trace_buf0)
+ memcpy(rproc->last_trace_buf0, rproc->trace_buf0,
+ rproc->last_trace_len0);
+ if (rproc->trace_buf1 && rproc->last_trace_buf1)
+ memcpy(rproc->last_trace_buf1, rproc->trace_buf1,
+ rproc->last_trace_len1);
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
pm_runtime_dont_use_autosuspend(rproc->dev);
#endif
@@ -393,9 +403,11 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
/* store the da for processing at the end */
if (!trace_da0) {
rproc->trace_len0 = rsc->len;
+ rproc->last_trace_len0 = rsc->len;
trace_da0 = da;
} else {
rproc->trace_len1 = rsc->len;
+ rproc->last_trace_len1 = rsc->len;
trace_da1 = da;
}
break;
@@ -446,6 +458,9 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
len -= sizeof(*rsc);
}
+ if (ret)
+ goto error;
+
/*
* post-process trace buffers, as we cannot rely on the order of the
* trace section and the carveout sections.
@@ -453,33 +468,54 @@ static int rproc_handle_resources(struct rproc *rproc, struct fw_resource *rsc,
* trace buffer memory _is_ normal memory, so we cast away the
* __iomem to make sparse happy
*/
- if (!ret && trace_da0) {
+ if (trace_da0) {
ret = rproc_da_to_pa(rproc->memory_maps, trace_da0, &pa);
- if (!ret) {
- rproc->trace_buf0 = (__force void *)
- ioremap_nocache(pa, rproc->trace_len0);
- if (rproc->trace_buf0)
- DEBUGFS_ADD(trace0);
- else {
- dev_err(dev, "can't ioremap trace buffer0\n");
- ret = -EIO;
+ if (ret)
+ goto error;
+ rproc->trace_buf0 = (__force void *)
+ ioremap_nocache(pa, rproc->trace_len0);
+ if (rproc->trace_buf0) {
+ DEBUGFS_ADD(trace0);
+ if (!rproc->last_trace_buf0) {
+ rproc->last_trace_buf0 = kzalloc(sizeof(u32) *
+ rproc->last_trace_len0,
+ GFP_KERNEL);
+ if (!rproc->last_trace_buf0) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ DEBUGFS_ADD(trace0_last);
}
+ } else {
+ dev_err(dev, "can't ioremap trace buffer0\n");
+ ret = -EIO;
+ goto error;
}
}
- if (!ret && trace_da1) {
+ if (trace_da1) {
ret = rproc_da_to_pa(rproc->memory_maps, trace_da1, &pa);
- if (!ret) {
- rproc->trace_buf1 = (__force void *)
- ioremap_nocache(pa, rproc->trace_len1);
- if (rproc->trace_buf1)
- DEBUGFS_ADD(trace1);
- else {
- dev_err(dev, "can't ioremap trace buffer1\n");
- ret = -EIO;
+ if (ret)
+ goto error;
+ rproc->trace_buf1 = (__force void *)
+ ioremap_nocache(pa, rproc->trace_len1);
+ if (rproc->trace_buf1) {
+ DEBUGFS_ADD(trace1);
+ if (!rproc->last_trace_buf1) {
+ rproc->last_trace_buf1 = kzalloc(sizeof(u32) *
+ rproc->last_trace_len1,
+ GFP_KERNEL);
+ if (!rproc->last_trace_buf1) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ DEBUGFS_ADD(trace1_last);
}
+ } else {
+ dev_err(dev, "can't ioremap trace buffer1\n");
+ ret = -EIO;
}
}
-
+error:
return ret;
}
@@ -1160,6 +1196,8 @@ int rproc_unregister(const char *name)
pm_qos_remove_request(rproc->qos_request);
kfree(rproc->qos_request);
+ kfree(rproc->last_trace_buf0);
+ kfree(rproc->last_trace_buf1);
kfree(rproc);
return 0;