root/drivers/remoteproc/remoteproc_sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. firmware_show
  2. firmware_store
  3. state_show
  4. state_store
  5. name_show
  6. rproc_init_sysfs
  7. rproc_exit_sysfs

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Remote Processor Framework
   4  */
   5 
   6 #include <linux/remoteproc.h>
   7 
   8 #include "remoteproc_internal.h"
   9 
  10 #define to_rproc(d) container_of(d, struct rproc, dev)
  11 
  12 /* Expose the loaded / running firmware name via sysfs */
  13 static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
  14                           char *buf)
  15 {
  16         struct rproc *rproc = to_rproc(dev);
  17 
  18         return sprintf(buf, "%s\n", rproc->firmware);
  19 }
  20 
  21 /* Change firmware name via sysfs */
  22 static ssize_t firmware_store(struct device *dev,
  23                               struct device_attribute *attr,
  24                               const char *buf, size_t count)
  25 {
  26         struct rproc *rproc = to_rproc(dev);
  27         char *p;
  28         int err, len = count;
  29 
  30         err = mutex_lock_interruptible(&rproc->lock);
  31         if (err) {
  32                 dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, err);
  33                 return -EINVAL;
  34         }
  35 
  36         if (rproc->state != RPROC_OFFLINE) {
  37                 dev_err(dev, "can't change firmware while running\n");
  38                 err = -EBUSY;
  39                 goto out;
  40         }
  41 
  42         len = strcspn(buf, "\n");
  43         if (!len) {
  44                 dev_err(dev, "can't provide a NULL firmware\n");
  45                 err = -EINVAL;
  46                 goto out;
  47         }
  48 
  49         p = kstrndup(buf, len, GFP_KERNEL);
  50         if (!p) {
  51                 err = -ENOMEM;
  52                 goto out;
  53         }
  54 
  55         kfree(rproc->firmware);
  56         rproc->firmware = p;
  57 out:
  58         mutex_unlock(&rproc->lock);
  59 
  60         return err ? err : count;
  61 }
  62 static DEVICE_ATTR_RW(firmware);
  63 
  64 /*
  65  * A state-to-string lookup table, for exposing a human readable state
  66  * via sysfs. Always keep in sync with enum rproc_state
  67  */
  68 static const char * const rproc_state_string[] = {
  69         [RPROC_OFFLINE]         = "offline",
  70         [RPROC_SUSPENDED]       = "suspended",
  71         [RPROC_RUNNING]         = "running",
  72         [RPROC_CRASHED]         = "crashed",
  73         [RPROC_DELETED]         = "deleted",
  74         [RPROC_LAST]            = "invalid",
  75 };
  76 
  77 /* Expose the state of the remote processor via sysfs */
  78 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
  79                           char *buf)
  80 {
  81         struct rproc *rproc = to_rproc(dev);
  82         unsigned int state;
  83 
  84         state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
  85         return sprintf(buf, "%s\n", rproc_state_string[state]);
  86 }
  87 
  88 /* Change remote processor state via sysfs */
  89 static ssize_t state_store(struct device *dev,
  90                               struct device_attribute *attr,
  91                               const char *buf, size_t count)
  92 {
  93         struct rproc *rproc = to_rproc(dev);
  94         int ret = 0;
  95 
  96         if (sysfs_streq(buf, "start")) {
  97                 if (rproc->state == RPROC_RUNNING)
  98                         return -EBUSY;
  99 
 100                 ret = rproc_boot(rproc);
 101                 if (ret)
 102                         dev_err(&rproc->dev, "Boot failed: %d\n", ret);
 103         } else if (sysfs_streq(buf, "stop")) {
 104                 if (rproc->state != RPROC_RUNNING)
 105                         return -EINVAL;
 106 
 107                 rproc_shutdown(rproc);
 108         } else {
 109                 dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
 110                 ret = -EINVAL;
 111         }
 112         return ret ? ret : count;
 113 }
 114 static DEVICE_ATTR_RW(state);
 115 
 116 /* Expose the name of the remote processor via sysfs */
 117 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 118                          char *buf)
 119 {
 120         struct rproc *rproc = to_rproc(dev);
 121 
 122         return sprintf(buf, "%s\n", rproc->name);
 123 }
 124 static DEVICE_ATTR_RO(name);
 125 
 126 static struct attribute *rproc_attrs[] = {
 127         &dev_attr_firmware.attr,
 128         &dev_attr_state.attr,
 129         &dev_attr_name.attr,
 130         NULL
 131 };
 132 
 133 static const struct attribute_group rproc_devgroup = {
 134         .attrs = rproc_attrs
 135 };
 136 
 137 static const struct attribute_group *rproc_devgroups[] = {
 138         &rproc_devgroup,
 139         NULL
 140 };
 141 
 142 struct class rproc_class = {
 143         .name           = "remoteproc",
 144         .dev_groups     = rproc_devgroups,
 145 };
 146 
 147 int __init rproc_init_sysfs(void)
 148 {
 149         /* create remoteproc device class for sysfs */
 150         int err = class_register(&rproc_class);
 151 
 152         if (err)
 153                 pr_err("remoteproc: unable to register class\n");
 154         return err;
 155 }
 156 
 157 void __exit rproc_exit_sysfs(void)
 158 {
 159         class_unregister(&rproc_class);
 160 }

/* [<][>][^][v][top][bottom][index][help] */