diff options
| -rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 3 | ||||
| -rw-r--r-- | drivers/remoteproc/remoteproc_debugfs.c | 81 | ||||
| -rw-r--r-- | include/linux/remoteproc.h | 2 |
3 files changed, 85 insertions, 1 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 5000d7589cf5..29fc8236cac9 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c | |||
| @@ -965,7 +965,8 @@ static void rproc_crash_handler_work(struct work_struct *work) | |||
| 965 | 965 | ||
| 966 | mutex_unlock(&rproc->lock); | 966 | mutex_unlock(&rproc->lock); |
| 967 | 967 | ||
| 968 | rproc_trigger_recovery(rproc); | 968 | if (!rproc->recovery_disabled) |
| 969 | rproc_trigger_recovery(rproc); | ||
| 969 | } | 970 | } |
| 970 | 971 | ||
| 971 | /** | 972 | /** |
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 03833850f214..10a38258e31d 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; |
| @@ -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 ret; | ||
| 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) |
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 0c1a2f95be76..2ccc3fe2046d 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h | |||
| @@ -399,6 +399,7 @@ enum rproc_crash_type { | |||
| 399 | * @crash_handler: workqueue for handling a crash | 399 | * @crash_handler: workqueue for handling a crash |
| 400 | * @crash_cnt: crash counter | 400 | * @crash_cnt: crash counter |
| 401 | * @crash_comp: completion used to sync crash handler and the rproc reload | 401 | * @crash_comp: completion used to sync crash handler and the rproc reload |
| 402 | * @recovery_disabled: flag that state if recovery was disabled | ||
| 402 | */ | 403 | */ |
| 403 | struct rproc { | 404 | struct rproc { |
| 404 | struct klist_node node; | 405 | struct klist_node node; |
| @@ -425,6 +426,7 @@ struct rproc { | |||
| 425 | struct work_struct crash_handler; | 426 | struct work_struct crash_handler; |
| 426 | unsigned crash_cnt; | 427 | unsigned crash_cnt; |
| 427 | struct completion crash_comp; | 428 | struct completion crash_comp; |
| 429 | bool recovery_disabled; | ||
| 428 | }; | 430 | }; |
| 429 | 431 | ||
| 430 | /* we currently support only two vrings per rvdev */ | 432 | /* we currently support only two vrings per rvdev */ |
