^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Remote Processor Framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/remoteproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <trace/hooks/remoteproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "remoteproc_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define to_rproc(d) container_of(d, struct rproc, dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static ssize_t recovery_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return sprintf(buf, "%s", rproc->recovery_disabled ? "disabled\n" : "enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * By writing to the 'recovery' sysfs entry, we control the behavior of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * recovery mechanism dynamically. The default value of this entry is "enabled".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * The 'recovery' sysfs entry supports these commands:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * enabled: When enabled, the remote processor will be automatically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * recovered whenever it crashes. Moreover, if the remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * processor crashes while recovery is disabled, it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * be automatically recovered too as soon as recovery is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * disabled: When disabled, a remote processor will remain in a crashed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * state if it crashes. This is useful for debugging purposes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * without it, debugging a crash is substantially harder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * recover: This function will trigger an immediate recovery if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * remote processor is in a crashed state, without changing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * or checking the recovery state (enabled/disabled).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * This is useful during debugging sessions, when one expects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * additional crashes to happen after enabling recovery. In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * case, enabling recovery will make it hard to debug subsequent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * crashes, so it's recommended to keep recovery disabled, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * instead use the "recover" command as needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static ssize_t recovery_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (sysfs_streq(buf, "enabled")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* change the flag and begin the recovery process if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rproc->recovery_disabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) trace_android_vh_rproc_recovery_set(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) rproc_trigger_recovery(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) } else if (sysfs_streq(buf, "disabled")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rproc->recovery_disabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) trace_android_vh_rproc_recovery_set(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) } else if (sysfs_streq(buf, "recover")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* begin the recovery process without changing the flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) rproc_trigger_recovery(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static DEVICE_ATTR_RW(recovery);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * A coredump-configuration-to-string lookup table, for exposing a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * human readable configuration via sysfs. Always keep in sync with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * enum rproc_coredump_mechanism
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const char * const rproc_coredump_str[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [RPROC_COREDUMP_DISABLED] = "disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) [RPROC_COREDUMP_ENABLED] = "enabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) [RPROC_COREDUMP_INLINE] = "inline",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Expose the current coredump configuration via debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static ssize_t coredump_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return sprintf(buf, "%s\n", rproc_coredump_str[rproc->dump_conf]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * By writing to the 'coredump' sysfs entry, we control the behavior of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * coredump mechanism dynamically. The default value of this entry is "default".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * The 'coredump' sysfs entry supports these commands:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * disabled: This is the default coredump mechanism. Recovery will proceed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * without collecting any dump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * default: When the remoteproc crashes the entire coredump will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * copied to a separate buffer and exposed to userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * inline: The coredump will not be copied to a separate buffer and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * recovery process will have to wait until data is read by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * userspace. But this avoid usage of extra memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static ssize_t coredump_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (rproc->state == RPROC_CRASHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dev_err(&rproc->dev, "can't change coredump configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (sysfs_streq(buf, "disabled")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) rproc->dump_conf = RPROC_COREDUMP_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } else if (sysfs_streq(buf, "enabled")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) rproc->dump_conf = RPROC_COREDUMP_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) } else if (sysfs_streq(buf, "inline")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rproc->dump_conf = RPROC_COREDUMP_INLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dev_err(&rproc->dev, "Invalid coredump configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static DEVICE_ATTR_RW(coredump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Expose the loaded / running firmware name via sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) const char *firmware = rproc->firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * If the remote processor has been started by an external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * entity we have no idea of what image it is running. As such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * simply display a generic string rather then rproc->firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Here we rely on the autonomous flag because a remote processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * may have been attached to and currently in a running state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (rproc->autonomous)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) firmware = "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return sprintf(buf, "%s\n", firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Change firmware name via sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static ssize_t firmware_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) err = rproc_set_firmware(rproc, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return err ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static DEVICE_ATTR_RW(firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * A state-to-string lookup table, for exposing a human readable state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * via sysfs. Always keep in sync with enum rproc_state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static const char * const rproc_state_string[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) [RPROC_OFFLINE] = "offline",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) [RPROC_SUSPENDED] = "suspended",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) [RPROC_RUNNING] = "running",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) [RPROC_CRASHED] = "crashed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) [RPROC_DELETED] = "deleted",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) [RPROC_DETACHED] = "detached",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) [RPROC_LAST] = "invalid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* Expose the state of the remote processor via sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static ssize_t state_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return sprintf(buf, "%s\n", rproc_state_string[state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* Change remote processor state via sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static ssize_t state_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (sysfs_streq(buf, "start")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (rproc->state == RPROC_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = rproc_boot(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) dev_err(&rproc->dev, "Boot failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else if (sysfs_streq(buf, "stop")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (rproc->state != RPROC_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) rproc_shutdown(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static DEVICE_ATTR_RW(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* Expose the name of the remote processor via sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static ssize_t name_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct rproc *rproc = to_rproc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return sprintf(buf, "%s\n", rproc->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static DEVICE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static struct attribute *rproc_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) &dev_attr_coredump.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) &dev_attr_recovery.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) &dev_attr_firmware.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) &dev_attr_state.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) &dev_attr_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct attribute_group rproc_devgroup = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .attrs = rproc_attrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static const struct attribute_group *rproc_devgroups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) &rproc_devgroup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct class rproc_class = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .name = "remoteproc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .dev_groups = rproc_devgroups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int __init rproc_init_sysfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* create remoteproc device class for sysfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int err = class_register(&rproc_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pr_err("remoteproc: unable to register class\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) void __exit rproc_exit_sysfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) class_unregister(&rproc_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }