diff options
Diffstat (limited to 'drivers/remoteproc/remoteproc_debugfs.c')
-rw-r--r-- | drivers/remoteproc/remoteproc_debugfs.c | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 03833850f214..157a57309601 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/debugfs.h> | 28 | #include <linux/debugfs.h> |
29 | #include <linux/remoteproc.h> | 29 | #include <linux/remoteproc.h> |
30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
31 | #include <linux/uaccess.h> | ||
32 | |||
33 | #include "remoteproc_internal.h" | ||
31 | 34 | ||
32 | /* remoteproc debugfs parent dir */ | 35 | /* remoteproc debugfs parent dir */ |
33 | static struct dentry *rproc_dbg; | 36 | static struct dentry *rproc_dbg; |
@@ -79,7 +82,7 @@ static ssize_t rproc_state_read(struct file *filp, char __user *userbuf, | |||
79 | 82 | ||
80 | state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state; | 83 | state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state; |
81 | 84 | ||
82 | i = snprintf(buf, 30, "%.28s (%d)\n", rproc_state_string[state], | 85 | i = scnprintf(buf, 30, "%.28s (%d)\n", rproc_state_string[state], |
83 | rproc->state); | 86 | rproc->state); |
84 | 87 | ||
85 | return simple_read_from_buffer(userbuf, count, ppos, buf, i); | 88 | return simple_read_from_buffer(userbuf, count, ppos, buf, i); |
@@ -100,7 +103,7 @@ static ssize_t rproc_name_read(struct file *filp, char __user *userbuf, | |||
100 | char buf[100]; | 103 | char buf[100]; |
101 | int i; | 104 | int i; |
102 | 105 | ||
103 | i = snprintf(buf, sizeof(buf), "%.98s\n", rproc->name); | 106 | i = scnprintf(buf, sizeof(buf), "%.98s\n", rproc->name); |
104 | 107 | ||
105 | return simple_read_from_buffer(userbuf, count, ppos, buf, i); | 108 | return simple_read_from_buffer(userbuf, count, ppos, buf, i); |
106 | } | 109 | } |
@@ -111,6 +114,82 @@ static const struct file_operations rproc_name_ops = { | |||
111 | .llseek = generic_file_llseek, | 114 | .llseek = generic_file_llseek, |
112 | }; | 115 | }; |
113 | 116 | ||
117 | /* expose recovery flag via debugfs */ | ||
118 | static ssize_t rproc_recovery_read(struct file *filp, char __user *userbuf, | ||
119 | size_t count, loff_t *ppos) | ||
120 | { | ||
121 | struct rproc *rproc = filp->private_data; | ||
122 | char *buf = rproc->recovery_disabled ? "disabled\n" : "enabled\n"; | ||
123 | |||
124 | return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * By writing to the 'recovery' debugfs entry, we control the behavior of the | ||
129 | * recovery mechanism dynamically. The default value of this entry is "enabled". | ||
130 | * | ||
131 | * The 'recovery' debugfs entry supports these commands: | ||
132 | * | ||
133 | * enabled: When enabled, the remote processor will be automatically | ||
134 | * recovered whenever it crashes. Moreover, if the remote | ||
135 | * processor crashes while recovery is disabled, it will | ||
136 | * be automatically recovered too as soon as recovery is enabled. | ||
137 | * | ||
138 | * disabled: When disabled, a remote processor will remain in a crashed | ||
139 | * state if it crashes. This is useful for debugging purposes; | ||
140 | * without it, debugging a crash is substantially harder. | ||
141 | * | ||
142 | * recover: This function will trigger an immediate recovery if the | ||
143 | * remote processor is in a crashed state, without changing | ||
144 | * or checking the recovery state (enabled/disabled). | ||
145 | * This is useful during debugging sessions, when one expects | ||
146 | * additional crashes to happen after enabling recovery. In this | ||
147 | * case, enabling recovery will make it hard to debug subsequent | ||
148 | * crashes, so it's recommended to keep recovery disabled, and | ||
149 | * instead use the "recover" command as needed. | ||
150 | */ | ||
151 | static ssize_t | ||
152 | rproc_recovery_write(struct file *filp, const char __user *user_buf, | ||
153 | size_t count, loff_t *ppos) | ||
154 | { | ||
155 | struct rproc *rproc = filp->private_data; | ||
156 | char buf[10]; | ||
157 | int ret; | ||
158 | |||
159 | if (count > sizeof(buf)) | ||
160 | return count; | ||
161 | |||
162 | ret = copy_from_user(buf, user_buf, count); | ||
163 | if (ret) | ||
164 | return -EFAULT; | ||
165 | |||
166 | /* remove end of line */ | ||
167 | if (buf[count - 1] == '\n') | ||
168 | buf[count - 1] = '\0'; | ||
169 | |||
170 | if (!strncmp(buf, "enabled", count)) { | ||
171 | rproc->recovery_disabled = false; | ||
172 | /* if rproc has crashed, trigger recovery */ | ||
173 | if (rproc->state == RPROC_CRASHED) | ||
174 | rproc_trigger_recovery(rproc); | ||
175 | } else if (!strncmp(buf, "disabled", count)) { | ||
176 | rproc->recovery_disabled = true; | ||
177 | } else if (!strncmp(buf, "recover", count)) { | ||
178 | /* if rproc has crashed, trigger recovery */ | ||
179 | if (rproc->state == RPROC_CRASHED) | ||
180 | rproc_trigger_recovery(rproc); | ||
181 | } | ||
182 | |||
183 | return count; | ||
184 | } | ||
185 | |||
186 | static const struct file_operations rproc_recovery_ops = { | ||
187 | .read = rproc_recovery_read, | ||
188 | .write = rproc_recovery_write, | ||
189 | .open = simple_open, | ||
190 | .llseek = generic_file_llseek, | ||
191 | }; | ||
192 | |||
114 | void rproc_remove_trace_file(struct dentry *tfile) | 193 | void rproc_remove_trace_file(struct dentry *tfile) |
115 | { | 194 | { |
116 | debugfs_remove(tfile); | 195 | debugfs_remove(tfile); |
@@ -154,6 +233,8 @@ void rproc_create_debug_dir(struct rproc *rproc) | |||
154 | rproc, &rproc_name_ops); | 233 | rproc, &rproc_name_ops); |
155 | debugfs_create_file("state", 0400, rproc->dbg_dir, | 234 | debugfs_create_file("state", 0400, rproc->dbg_dir, |
156 | rproc, &rproc_state_ops); | 235 | rproc, &rproc_state_ops); |
236 | debugfs_create_file("recovery", 0400, rproc->dbg_dir, | ||
237 | rproc, &rproc_recovery_ops); | ||
157 | } | 238 | } |
158 | 239 | ||
159 | void __init rproc_init_debugfs(void) | 240 | void __init rproc_init_debugfs(void) |