0001
0002
0003
0004
0005
0006 #include <linux/remoteproc.h>
0007 #include <linux/slab.h>
0008
0009 #include "remoteproc_internal.h"
0010
0011 #define to_rproc(d) container_of(d, struct rproc, dev)
0012
0013 static ssize_t recovery_show(struct device *dev,
0014 struct device_attribute *attr, char *buf)
0015 {
0016 struct rproc *rproc = to_rproc(dev);
0017
0018 return sysfs_emit(buf, "%s", rproc->recovery_disabled ? "disabled\n" : "enabled\n");
0019 }
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 static ssize_t recovery_store(struct device *dev,
0046 struct device_attribute *attr,
0047 const char *buf, size_t count)
0048 {
0049 struct rproc *rproc = to_rproc(dev);
0050
0051 if (sysfs_streq(buf, "enabled")) {
0052
0053 rproc->recovery_disabled = false;
0054 rproc_trigger_recovery(rproc);
0055 } else if (sysfs_streq(buf, "disabled")) {
0056 rproc->recovery_disabled = true;
0057 } else if (sysfs_streq(buf, "recover")) {
0058
0059 rproc_trigger_recovery(rproc);
0060 } else {
0061 return -EINVAL;
0062 }
0063
0064 return count;
0065 }
0066 static DEVICE_ATTR_RW(recovery);
0067
0068
0069
0070
0071
0072
0073 static const char * const rproc_coredump_str[] = {
0074 [RPROC_COREDUMP_DISABLED] = "disabled",
0075 [RPROC_COREDUMP_ENABLED] = "enabled",
0076 [RPROC_COREDUMP_INLINE] = "inline",
0077 };
0078
0079
0080 static ssize_t coredump_show(struct device *dev,
0081 struct device_attribute *attr, char *buf)
0082 {
0083 struct rproc *rproc = to_rproc(dev);
0084
0085 return sysfs_emit(buf, "%s\n", rproc_coredump_str[rproc->dump_conf]);
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static ssize_t coredump_store(struct device *dev,
0105 struct device_attribute *attr,
0106 const char *buf, size_t count)
0107 {
0108 struct rproc *rproc = to_rproc(dev);
0109
0110 if (rproc->state == RPROC_CRASHED) {
0111 dev_err(&rproc->dev, "can't change coredump configuration\n");
0112 return -EBUSY;
0113 }
0114
0115 if (sysfs_streq(buf, "disabled")) {
0116 rproc->dump_conf = RPROC_COREDUMP_DISABLED;
0117 } else if (sysfs_streq(buf, "enabled")) {
0118 rproc->dump_conf = RPROC_COREDUMP_ENABLED;
0119 } else if (sysfs_streq(buf, "inline")) {
0120 rproc->dump_conf = RPROC_COREDUMP_INLINE;
0121 } else {
0122 dev_err(&rproc->dev, "Invalid coredump configuration\n");
0123 return -EINVAL;
0124 }
0125
0126 return count;
0127 }
0128 static DEVICE_ATTR_RW(coredump);
0129
0130
0131 static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
0132 char *buf)
0133 {
0134 struct rproc *rproc = to_rproc(dev);
0135 const char *firmware = rproc->firmware;
0136
0137
0138
0139
0140
0141
0142 if (rproc->state == RPROC_ATTACHED)
0143 firmware = "unknown";
0144
0145 return sprintf(buf, "%s\n", firmware);
0146 }
0147
0148
0149 static ssize_t firmware_store(struct device *dev,
0150 struct device_attribute *attr,
0151 const char *buf, size_t count)
0152 {
0153 struct rproc *rproc = to_rproc(dev);
0154 int err;
0155
0156 err = rproc_set_firmware(rproc, buf);
0157
0158 return err ? err : count;
0159 }
0160 static DEVICE_ATTR_RW(firmware);
0161
0162
0163
0164
0165
0166 static const char * const rproc_state_string[] = {
0167 [RPROC_OFFLINE] = "offline",
0168 [RPROC_SUSPENDED] = "suspended",
0169 [RPROC_RUNNING] = "running",
0170 [RPROC_CRASHED] = "crashed",
0171 [RPROC_DELETED] = "deleted",
0172 [RPROC_ATTACHED] = "attached",
0173 [RPROC_DETACHED] = "detached",
0174 [RPROC_LAST] = "invalid",
0175 };
0176
0177
0178 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
0179 char *buf)
0180 {
0181 struct rproc *rproc = to_rproc(dev);
0182 unsigned int state;
0183
0184 state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
0185 return sprintf(buf, "%s\n", rproc_state_string[state]);
0186 }
0187
0188
0189 static ssize_t state_store(struct device *dev,
0190 struct device_attribute *attr,
0191 const char *buf, size_t count)
0192 {
0193 struct rproc *rproc = to_rproc(dev);
0194 int ret = 0;
0195
0196 if (sysfs_streq(buf, "start")) {
0197 ret = rproc_boot(rproc);
0198 if (ret)
0199 dev_err(&rproc->dev, "Boot failed: %d\n", ret);
0200 } else if (sysfs_streq(buf, "stop")) {
0201 ret = rproc_shutdown(rproc);
0202 } else if (sysfs_streq(buf, "detach")) {
0203 ret = rproc_detach(rproc);
0204 } else {
0205 dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
0206 ret = -EINVAL;
0207 }
0208 return ret ? ret : count;
0209 }
0210 static DEVICE_ATTR_RW(state);
0211
0212
0213 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
0214 char *buf)
0215 {
0216 struct rproc *rproc = to_rproc(dev);
0217
0218 return sprintf(buf, "%s\n", rproc->name);
0219 }
0220 static DEVICE_ATTR_RO(name);
0221
0222 static umode_t rproc_is_visible(struct kobject *kobj, struct attribute *attr,
0223 int n)
0224 {
0225 struct device *dev = kobj_to_dev(kobj);
0226 struct rproc *rproc = to_rproc(dev);
0227 umode_t mode = attr->mode;
0228
0229 if (rproc->sysfs_read_only && (attr == &dev_attr_recovery.attr ||
0230 attr == &dev_attr_firmware.attr ||
0231 attr == &dev_attr_state.attr ||
0232 attr == &dev_attr_coredump.attr))
0233 mode = 0444;
0234
0235 return mode;
0236 }
0237
0238 static struct attribute *rproc_attrs[] = {
0239 &dev_attr_coredump.attr,
0240 &dev_attr_recovery.attr,
0241 &dev_attr_firmware.attr,
0242 &dev_attr_state.attr,
0243 &dev_attr_name.attr,
0244 NULL
0245 };
0246
0247 static const struct attribute_group rproc_devgroup = {
0248 .attrs = rproc_attrs,
0249 .is_visible = rproc_is_visible,
0250 };
0251
0252 static const struct attribute_group *rproc_devgroups[] = {
0253 &rproc_devgroup,
0254 NULL
0255 };
0256
0257 struct class rproc_class = {
0258 .name = "remoteproc",
0259 .dev_groups = rproc_devgroups,
0260 };
0261
0262 int __init rproc_init_sysfs(void)
0263 {
0264
0265 int err = class_register(&rproc_class);
0266
0267 if (err)
0268 pr_err("remoteproc: unable to register class\n");
0269 return err;
0270 }
0271
0272 void __exit rproc_exit_sysfs(void)
0273 {
0274 class_unregister(&rproc_class);
0275 }