LCOV - code coverage report
Current view: top level - drivers/remoteproc - remoteproc_sysfs.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 4 59 6.8 %
Date: 2022-03-28 13:20:08 Functions: 1 7 14.3 %
Branches: 1 24 4.2 %

           Branch data     Line data    Source code
       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                 :          0 : static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
      14                 :            :                           char *buf)
      15                 :            : {
      16                 :          0 :         struct rproc *rproc = to_rproc(dev);
      17                 :            : 
      18                 :          0 :         return sprintf(buf, "%s\n", rproc->firmware);
      19                 :            : }
      20                 :            : 
      21                 :            : /* Change firmware name via sysfs */
      22                 :          0 : static ssize_t firmware_store(struct device *dev,
      23                 :            :                               struct device_attribute *attr,
      24                 :            :                               const char *buf, size_t count)
      25                 :            : {
      26                 :          0 :         struct rproc *rproc = to_rproc(dev);
      27                 :          0 :         char *p;
      28                 :          0 :         int err, len = count;
      29                 :            : 
      30                 :          0 :         err = mutex_lock_interruptible(&rproc->lock);
      31         [ #  # ]:          0 :         if (err) {
      32                 :          0 :                 dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, err);
      33                 :          0 :                 return -EINVAL;
      34                 :            :         }
      35                 :            : 
      36         [ #  # ]:          0 :         if (rproc->state != RPROC_OFFLINE) {
      37                 :          0 :                 dev_err(dev, "can't change firmware while running\n");
      38                 :          0 :                 err = -EBUSY;
      39                 :          0 :                 goto out;
      40                 :            :         }
      41                 :            : 
      42                 :          0 :         len = strcspn(buf, "\n");
      43         [ #  # ]:          0 :         if (!len) {
      44                 :          0 :                 dev_err(dev, "can't provide a NULL firmware\n");
      45                 :          0 :                 err = -EINVAL;
      46                 :          0 :                 goto out;
      47                 :            :         }
      48                 :            : 
      49                 :          0 :         p = kstrndup(buf, len, GFP_KERNEL);
      50         [ #  # ]:          0 :         if (!p) {
      51                 :          0 :                 err = -ENOMEM;
      52                 :          0 :                 goto out;
      53                 :            :         }
      54                 :            : 
      55                 :          0 :         kfree(rproc->firmware);
      56                 :          0 :         rproc->firmware = p;
      57                 :          0 : out:
      58                 :          0 :         mutex_unlock(&rproc->lock);
      59                 :            : 
      60         [ #  # ]:          0 :         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                 :          0 : static ssize_t state_show(struct device *dev, struct device_attribute *attr,
      79                 :            :                           char *buf)
      80                 :            : {
      81                 :          0 :         struct rproc *rproc = to_rproc(dev);
      82                 :          0 :         unsigned int state;
      83                 :            : 
      84                 :          0 :         state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
      85                 :          0 :         return sprintf(buf, "%s\n", rproc_state_string[state]);
      86                 :            : }
      87                 :            : 
      88                 :            : /* Change remote processor state via sysfs */
      89                 :          0 : static ssize_t state_store(struct device *dev,
      90                 :            :                               struct device_attribute *attr,
      91                 :            :                               const char *buf, size_t count)
      92                 :            : {
      93                 :          0 :         struct rproc *rproc = to_rproc(dev);
      94                 :          0 :         int ret = 0;
      95                 :            : 
      96         [ #  # ]:          0 :         if (sysfs_streq(buf, "start")) {
      97         [ #  # ]:          0 :                 if (rproc->state == RPROC_RUNNING)
      98                 :            :                         return -EBUSY;
      99                 :            : 
     100                 :          0 :                 ret = rproc_boot(rproc);
     101         [ #  # ]:          0 :                 if (ret)
     102                 :          0 :                         dev_err(&rproc->dev, "Boot failed: %d\n", ret);
     103         [ #  # ]:          0 :         } else if (sysfs_streq(buf, "stop")) {
     104         [ #  # ]:          0 :                 if (rproc->state != RPROC_RUNNING)
     105                 :            :                         return -EINVAL;
     106                 :            : 
     107                 :          0 :                 rproc_shutdown(rproc);
     108                 :            :         } else {
     109                 :          0 :                 dev_err(&rproc->dev, "Unrecognised option: %s\n", buf);
     110                 :          0 :                 ret = -EINVAL;
     111                 :            :         }
     112         [ #  # ]:          0 :         return ret ? ret : count;
     113                 :            : }
     114                 :            : static DEVICE_ATTR_RW(state);
     115                 :            : 
     116                 :            : /* Expose the name of the remote processor via sysfs */
     117                 :          0 : static ssize_t name_show(struct device *dev, struct device_attribute *attr,
     118                 :            :                          char *buf)
     119                 :            : {
     120                 :          0 :         struct rproc *rproc = to_rproc(dev);
     121                 :            : 
     122                 :          0 :         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                 :         30 : int __init rproc_init_sysfs(void)
     148                 :            : {
     149                 :            :         /* create remoteproc device class for sysfs */
     150                 :         30 :         int err = class_register(&rproc_class);
     151                 :            : 
     152         [ -  + ]:         30 :         if (err)
     153                 :          0 :                 pr_err("remoteproc: unable to register class\n");
     154                 :         30 :         return err;
     155                 :            : }
     156                 :            : 
     157                 :          0 : void __exit rproc_exit_sysfs(void)
     158                 :            : {
     159                 :          0 :         class_unregister(&rproc_class);
     160                 :          0 : }

Generated by: LCOV version 1.14