Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }