LCOV - code coverage report
Current view: top level - drivers/edac - edac_device_sysfs.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 225 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 30 0.0 %
Branches: 0 62 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * file for managing the edac_device subsystem of devices for EDAC
       3                 :            :  *
       4                 :            :  * (C) 2007 SoftwareBitMaker
       5                 :            :  *
       6                 :            :  * This file may be distributed under the terms of the
       7                 :            :  * GNU General Public License.
       8                 :            :  *
       9                 :            :  * Written Doug Thompson <norsk5@xmission.com>
      10                 :            :  *
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/ctype.h>
      14                 :            : #include <linux/module.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/edac.h>
      17                 :            : 
      18                 :            : #include "edac_device.h"
      19                 :            : #include "edac_module.h"
      20                 :            : 
      21                 :            : #define EDAC_DEVICE_SYMLINK     "device"
      22                 :            : 
      23                 :            : #define to_edacdev(k) container_of(k, struct edac_device_ctl_info, kobj)
      24                 :            : #define to_edacdev_attr(a) container_of(a, struct edacdev_attribute, attr)
      25                 :            : 
      26                 :            : 
      27                 :            : /*
      28                 :            :  * Set of edac_device_ctl_info attribute store/show functions
      29                 :            :  */
      30                 :            : 
      31                 :            : /* 'log_ue' */
      32                 :          0 : static ssize_t edac_device_ctl_log_ue_show(struct edac_device_ctl_info
      33                 :            :                                         *ctl_info, char *data)
      34                 :            : {
      35                 :          0 :         return sprintf(data, "%u\n", ctl_info->log_ue);
      36                 :            : }
      37                 :            : 
      38                 :          0 : static ssize_t edac_device_ctl_log_ue_store(struct edac_device_ctl_info
      39                 :            :                                         *ctl_info, const char *data,
      40                 :            :                                         size_t count)
      41                 :            : {
      42                 :            :         /* if parameter is zero, turn off flag, if non-zero turn on flag */
      43                 :          0 :         ctl_info->log_ue = (simple_strtoul(data, NULL, 0) != 0);
      44                 :            : 
      45                 :          0 :         return count;
      46                 :            : }
      47                 :            : 
      48                 :            : /* 'log_ce' */
      49                 :          0 : static ssize_t edac_device_ctl_log_ce_show(struct edac_device_ctl_info
      50                 :            :                                         *ctl_info, char *data)
      51                 :            : {
      52                 :          0 :         return sprintf(data, "%u\n", ctl_info->log_ce);
      53                 :            : }
      54                 :            : 
      55                 :          0 : static ssize_t edac_device_ctl_log_ce_store(struct edac_device_ctl_info
      56                 :            :                                         *ctl_info, const char *data,
      57                 :            :                                         size_t count)
      58                 :            : {
      59                 :            :         /* if parameter is zero, turn off flag, if non-zero turn on flag */
      60                 :          0 :         ctl_info->log_ce = (simple_strtoul(data, NULL, 0) != 0);
      61                 :            : 
      62                 :          0 :         return count;
      63                 :            : }
      64                 :            : 
      65                 :            : /* 'panic_on_ue' */
      66                 :          0 : static ssize_t edac_device_ctl_panic_on_ue_show(struct edac_device_ctl_info
      67                 :            :                                                 *ctl_info, char *data)
      68                 :            : {
      69                 :          0 :         return sprintf(data, "%u\n", ctl_info->panic_on_ue);
      70                 :            : }
      71                 :            : 
      72                 :          0 : static ssize_t edac_device_ctl_panic_on_ue_store(struct edac_device_ctl_info
      73                 :            :                                                  *ctl_info, const char *data,
      74                 :            :                                                  size_t count)
      75                 :            : {
      76                 :            :         /* if parameter is zero, turn off flag, if non-zero turn on flag */
      77                 :          0 :         ctl_info->panic_on_ue = (simple_strtoul(data, NULL, 0) != 0);
      78                 :            : 
      79                 :          0 :         return count;
      80                 :            : }
      81                 :            : 
      82                 :            : /* 'poll_msec' show and store functions*/
      83                 :          0 : static ssize_t edac_device_ctl_poll_msec_show(struct edac_device_ctl_info
      84                 :            :                                         *ctl_info, char *data)
      85                 :            : {
      86                 :          0 :         return sprintf(data, "%u\n", ctl_info->poll_msec);
      87                 :            : }
      88                 :            : 
      89                 :          0 : static ssize_t edac_device_ctl_poll_msec_store(struct edac_device_ctl_info
      90                 :            :                                         *ctl_info, const char *data,
      91                 :            :                                         size_t count)
      92                 :            : {
      93                 :          0 :         unsigned long value;
      94                 :            : 
      95                 :            :         /* get the value and enforce that it is non-zero, must be at least
      96                 :            :          * one millisecond for the delay period, between scans
      97                 :            :          * Then cancel last outstanding delay for the work request
      98                 :            :          * and set a new one.
      99                 :            :          */
     100                 :          0 :         value = simple_strtoul(data, NULL, 0);
     101                 :          0 :         edac_device_reset_delay_period(ctl_info, value);
     102                 :            : 
     103                 :          0 :         return count;
     104                 :            : }
     105                 :            : 
     106                 :            : /* edac_device_ctl_info specific attribute structure */
     107                 :            : struct ctl_info_attribute {
     108                 :            :         struct attribute attr;
     109                 :            :         ssize_t(*show) (struct edac_device_ctl_info *, char *);
     110                 :            :         ssize_t(*store) (struct edac_device_ctl_info *, const char *, size_t);
     111                 :            : };
     112                 :            : 
     113                 :            : #define to_ctl_info(k) container_of(k, struct edac_device_ctl_info, kobj)
     114                 :            : #define to_ctl_info_attr(a) container_of(a,struct ctl_info_attribute,attr)
     115                 :            : 
     116                 :            : /* Function to 'show' fields from the edac_dev 'ctl_info' structure */
     117                 :          0 : static ssize_t edac_dev_ctl_info_show(struct kobject *kobj,
     118                 :            :                                 struct attribute *attr, char *buffer)
     119                 :            : {
     120                 :          0 :         struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
     121                 :          0 :         struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
     122                 :            : 
     123         [ #  # ]:          0 :         if (ctl_info_attr->show)
     124                 :          0 :                 return ctl_info_attr->show(edac_dev, buffer);
     125                 :            :         return -EIO;
     126                 :            : }
     127                 :            : 
     128                 :            : /* Function to 'store' fields into the edac_dev 'ctl_info' structure */
     129                 :          0 : static ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
     130                 :            :                                 struct attribute *attr,
     131                 :            :                                 const char *buffer, size_t count)
     132                 :            : {
     133                 :          0 :         struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
     134                 :          0 :         struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
     135                 :            : 
     136         [ #  # ]:          0 :         if (ctl_info_attr->store)
     137                 :          0 :                 return ctl_info_attr->store(edac_dev, buffer, count);
     138                 :            :         return -EIO;
     139                 :            : }
     140                 :            : 
     141                 :            : /* edac_dev file operations for an 'ctl_info' */
     142                 :            : static const struct sysfs_ops device_ctl_info_ops = {
     143                 :            :         .show = edac_dev_ctl_info_show,
     144                 :            :         .store = edac_dev_ctl_info_store
     145                 :            : };
     146                 :            : 
     147                 :            : #define CTL_INFO_ATTR(_name,_mode,_show,_store)        \
     148                 :            : static struct ctl_info_attribute attr_ctl_info_##_name = {      \
     149                 :            :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     150                 :            :         .show   = _show,                                        \
     151                 :            :         .store  = _store,                                       \
     152                 :            : };
     153                 :            : 
     154                 :            : /* Declare the various ctl_info attributes here and their respective ops */
     155                 :            : CTL_INFO_ATTR(log_ue, S_IRUGO | S_IWUSR,
     156                 :            :         edac_device_ctl_log_ue_show, edac_device_ctl_log_ue_store);
     157                 :            : CTL_INFO_ATTR(log_ce, S_IRUGO | S_IWUSR,
     158                 :            :         edac_device_ctl_log_ce_show, edac_device_ctl_log_ce_store);
     159                 :            : CTL_INFO_ATTR(panic_on_ue, S_IRUGO | S_IWUSR,
     160                 :            :         edac_device_ctl_panic_on_ue_show,
     161                 :            :         edac_device_ctl_panic_on_ue_store);
     162                 :            : CTL_INFO_ATTR(poll_msec, S_IRUGO | S_IWUSR,
     163                 :            :         edac_device_ctl_poll_msec_show, edac_device_ctl_poll_msec_store);
     164                 :            : 
     165                 :            : /* Base Attributes of the EDAC_DEVICE ECC object */
     166                 :            : static struct ctl_info_attribute *device_ctrl_attr[] = {
     167                 :            :         &attr_ctl_info_panic_on_ue,
     168                 :            :         &attr_ctl_info_log_ue,
     169                 :            :         &attr_ctl_info_log_ce,
     170                 :            :         &attr_ctl_info_poll_msec,
     171                 :            :         NULL,
     172                 :            : };
     173                 :            : 
     174                 :            : /*
     175                 :            :  * edac_device_ctrl_master_release
     176                 :            :  *
     177                 :            :  *      called when the reference count for the 'main' kobj
     178                 :            :  *      for a edac_device control struct reaches zero
     179                 :            :  *
     180                 :            :  *      Reference count model:
     181                 :            :  *              One 'main' kobject for each control structure allocated.
     182                 :            :  *              That main kobj is initially set to one AND
     183                 :            :  *              the reference count for the EDAC 'core' module is
     184                 :            :  *              bumped by one, thus added 'keep in memory' dependency.
     185                 :            :  *
     186                 :            :  *              Each new internal kobj (in instances and blocks) then
     187                 :            :  *              bumps the 'main' kobject.
     188                 :            :  *
     189                 :            :  *              When they are released their release functions decrement
     190                 :            :  *              the 'main' kobj.
     191                 :            :  *
     192                 :            :  *              When the main kobj reaches zero (0) then THIS function
     193                 :            :  *              is called which then decrements the EDAC 'core' module.
     194                 :            :  *              When the module reference count reaches zero then the
     195                 :            :  *              module no longer has dependency on keeping the release
     196                 :            :  *              function code in memory and module can be unloaded.
     197                 :            :  *
     198                 :            :  *              This will support several control objects as well, each
     199                 :            :  *              with its own 'main' kobj.
     200                 :            :  */
     201                 :          0 : static void edac_device_ctrl_master_release(struct kobject *kobj)
     202                 :            : {
     203                 :          0 :         struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
     204                 :            : 
     205                 :          0 :         edac_dbg(4, "control index=%d\n", edac_dev->dev_idx);
     206                 :            : 
     207                 :            :         /* decrement the EDAC CORE module ref count */
     208                 :          0 :         module_put(edac_dev->owner);
     209                 :            : 
     210                 :            :         /* free the control struct containing the 'main' kobj
     211                 :            :          * passed in to this routine
     212                 :            :          */
     213                 :          0 :         kfree(edac_dev);
     214                 :          0 : }
     215                 :            : 
     216                 :            : /* ktype for the main (master) kobject */
     217                 :            : static struct kobj_type ktype_device_ctrl = {
     218                 :            :         .release = edac_device_ctrl_master_release,
     219                 :            :         .sysfs_ops = &device_ctl_info_ops,
     220                 :            :         .default_attrs = (struct attribute **)device_ctrl_attr,
     221                 :            : };
     222                 :            : 
     223                 :            : /*
     224                 :            :  * edac_device_register_sysfs_main_kobj
     225                 :            :  *
     226                 :            :  *      perform the high level setup for the new edac_device instance
     227                 :            :  *
     228                 :            :  * Return:  0 SUCCESS
     229                 :            :  *         !0 FAILURE
     230                 :            :  */
     231                 :          0 : int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
     232                 :            : {
     233                 :          0 :         struct bus_type *edac_subsys;
     234                 :          0 :         int err;
     235                 :            : 
     236                 :          0 :         edac_dbg(1, "\n");
     237                 :            : 
     238                 :            :         /* get the /sys/devices/system/edac reference */
     239                 :          0 :         edac_subsys = edac_get_sysfs_subsys();
     240                 :            : 
     241                 :            :         /* Point to the 'edac_subsys' this instance 'reports' to */
     242                 :          0 :         edac_dev->edac_subsys = edac_subsys;
     243                 :            : 
     244                 :            :         /* Init the devices's kobject */
     245                 :          0 :         memset(&edac_dev->kobj, 0, sizeof(struct kobject));
     246                 :            : 
     247                 :            :         /* Record which module 'owns' this control structure
     248                 :            :          * and bump the ref count of the module
     249                 :            :          */
     250                 :          0 :         edac_dev->owner = THIS_MODULE;
     251                 :            : 
     252         [ #  # ]:          0 :         if (!try_module_get(edac_dev->owner)) {
     253                 :          0 :                 err = -ENODEV;
     254                 :          0 :                 goto err_out;
     255                 :            :         }
     256                 :            : 
     257                 :            :         /* register */
     258                 :          0 :         err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
     259                 :          0 :                                    &edac_subsys->dev_root->kobj,
     260                 :          0 :                                    "%s", edac_dev->name);
     261         [ #  # ]:          0 :         if (err) {
     262                 :          0 :                 edac_dbg(1, "Failed to register '.../edac/%s'\n",
     263                 :            :                          edac_dev->name);
     264                 :          0 :                 goto err_kobj_reg;
     265                 :            :         }
     266                 :          0 :         kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
     267                 :            : 
     268                 :            :         /* At this point, to 'free' the control struct,
     269                 :            :          * edac_device_unregister_sysfs_main_kobj() must be used
     270                 :            :          */
     271                 :            : 
     272                 :          0 :         edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name);
     273                 :            : 
     274                 :          0 :         return 0;
     275                 :            : 
     276                 :            :         /* Error exit stack */
     277                 :            : err_kobj_reg:
     278                 :          0 :         module_put(edac_dev->owner);
     279                 :            : 
     280                 :            : err_out:
     281                 :            :         return err;
     282                 :            : }
     283                 :            : 
     284                 :            : /*
     285                 :            :  * edac_device_unregister_sysfs_main_kobj:
     286                 :            :  *      the '..../edac/<name>' kobject
     287                 :            :  */
     288                 :          0 : void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
     289                 :            : {
     290                 :          0 :         edac_dbg(0, "\n");
     291                 :          0 :         edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj));
     292                 :            : 
     293                 :            :         /*
     294                 :            :          * Unregister the edac device's kobject and
     295                 :            :          * allow for reference count to reach 0 at which point
     296                 :            :          * the callback will be called to:
     297                 :            :          *   a) module_put() this module
     298                 :            :          *   b) 'kfree' the memory
     299                 :            :          */
     300                 :          0 :         kobject_put(&dev->kobj);
     301                 :          0 : }
     302                 :            : 
     303                 :            : /* edac_dev -> instance information */
     304                 :            : 
     305                 :            : /*
     306                 :            :  * Set of low-level instance attribute show functions
     307                 :            :  */
     308                 :          0 : static ssize_t instance_ue_count_show(struct edac_device_instance *instance,
     309                 :            :                                 char *data)
     310                 :            : {
     311                 :          0 :         return sprintf(data, "%u\n", instance->counters.ue_count);
     312                 :            : }
     313                 :            : 
     314                 :          0 : static ssize_t instance_ce_count_show(struct edac_device_instance *instance,
     315                 :            :                                 char *data)
     316                 :            : {
     317                 :          0 :         return sprintf(data, "%u\n", instance->counters.ce_count);
     318                 :            : }
     319                 :            : 
     320                 :            : #define to_instance(k) container_of(k, struct edac_device_instance, kobj)
     321                 :            : #define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
     322                 :            : 
     323                 :            : /* DEVICE instance kobject release() function */
     324                 :          0 : static void edac_device_ctrl_instance_release(struct kobject *kobj)
     325                 :            : {
     326                 :          0 :         struct edac_device_instance *instance;
     327                 :            : 
     328                 :          0 :         edac_dbg(1, "\n");
     329                 :            : 
     330                 :            :         /* map from this kobj to the main control struct
     331                 :            :          * and then dec the main kobj count
     332                 :            :          */
     333                 :          0 :         instance = to_instance(kobj);
     334                 :          0 :         kobject_put(&instance->ctl->kobj);
     335                 :          0 : }
     336                 :            : 
     337                 :            : /* instance specific attribute structure */
     338                 :            : struct instance_attribute {
     339                 :            :         struct attribute attr;
     340                 :            :         ssize_t(*show) (struct edac_device_instance *, char *);
     341                 :            :         ssize_t(*store) (struct edac_device_instance *, const char *, size_t);
     342                 :            : };
     343                 :            : 
     344                 :            : /* Function to 'show' fields from the edac_dev 'instance' structure */
     345                 :          0 : static ssize_t edac_dev_instance_show(struct kobject *kobj,
     346                 :            :                                 struct attribute *attr, char *buffer)
     347                 :            : {
     348                 :          0 :         struct edac_device_instance *instance = to_instance(kobj);
     349                 :          0 :         struct instance_attribute *instance_attr = to_instance_attr(attr);
     350                 :            : 
     351         [ #  # ]:          0 :         if (instance_attr->show)
     352                 :          0 :                 return instance_attr->show(instance, buffer);
     353                 :            :         return -EIO;
     354                 :            : }
     355                 :            : 
     356                 :            : /* Function to 'store' fields into the edac_dev 'instance' structure */
     357                 :          0 : static ssize_t edac_dev_instance_store(struct kobject *kobj,
     358                 :            :                                 struct attribute *attr,
     359                 :            :                                 const char *buffer, size_t count)
     360                 :            : {
     361                 :          0 :         struct edac_device_instance *instance = to_instance(kobj);
     362                 :          0 :         struct instance_attribute *instance_attr = to_instance_attr(attr);
     363                 :            : 
     364         [ #  # ]:          0 :         if (instance_attr->store)
     365                 :          0 :                 return instance_attr->store(instance, buffer, count);
     366                 :            :         return -EIO;
     367                 :            : }
     368                 :            : 
     369                 :            : /* edac_dev file operations for an 'instance' */
     370                 :            : static const struct sysfs_ops device_instance_ops = {
     371                 :            :         .show = edac_dev_instance_show,
     372                 :            :         .store = edac_dev_instance_store
     373                 :            : };
     374                 :            : 
     375                 :            : #define INSTANCE_ATTR(_name,_mode,_show,_store)        \
     376                 :            : static struct instance_attribute attr_instance_##_name = {      \
     377                 :            :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     378                 :            :         .show   = _show,                                        \
     379                 :            :         .store  = _store,                                       \
     380                 :            : };
     381                 :            : 
     382                 :            : /*
     383                 :            :  * Define attributes visible for the edac_device instance object
     384                 :            :  *      Each contains a pointer to a show and an optional set
     385                 :            :  *      function pointer that does the low level output/input
     386                 :            :  */
     387                 :            : INSTANCE_ATTR(ce_count, S_IRUGO, instance_ce_count_show, NULL);
     388                 :            : INSTANCE_ATTR(ue_count, S_IRUGO, instance_ue_count_show, NULL);
     389                 :            : 
     390                 :            : /* list of edac_dev 'instance' attributes */
     391                 :            : static struct instance_attribute *device_instance_attr[] = {
     392                 :            :         &attr_instance_ce_count,
     393                 :            :         &attr_instance_ue_count,
     394                 :            :         NULL,
     395                 :            : };
     396                 :            : 
     397                 :            : /* The 'ktype' for each edac_dev 'instance' */
     398                 :            : static struct kobj_type ktype_instance_ctrl = {
     399                 :            :         .release = edac_device_ctrl_instance_release,
     400                 :            :         .sysfs_ops = &device_instance_ops,
     401                 :            :         .default_attrs = (struct attribute **)device_instance_attr,
     402                 :            : };
     403                 :            : 
     404                 :            : /* edac_dev -> instance -> block information */
     405                 :            : 
     406                 :            : #define to_block(k) container_of(k, struct edac_device_block, kobj)
     407                 :            : #define to_block_attr(a) \
     408                 :            :         container_of(a, struct edac_dev_sysfs_block_attribute, attr)
     409                 :            : 
     410                 :            : /*
     411                 :            :  * Set of low-level block attribute show functions
     412                 :            :  */
     413                 :          0 : static ssize_t block_ue_count_show(struct kobject *kobj,
     414                 :            :                                         struct attribute *attr, char *data)
     415                 :            : {
     416                 :          0 :         struct edac_device_block *block = to_block(kobj);
     417                 :            : 
     418                 :          0 :         return sprintf(data, "%u\n", block->counters.ue_count);
     419                 :            : }
     420                 :            : 
     421                 :          0 : static ssize_t block_ce_count_show(struct kobject *kobj,
     422                 :            :                                         struct attribute *attr, char *data)
     423                 :            : {
     424                 :          0 :         struct edac_device_block *block = to_block(kobj);
     425                 :            : 
     426                 :          0 :         return sprintf(data, "%u\n", block->counters.ce_count);
     427                 :            : }
     428                 :            : 
     429                 :            : /* DEVICE block kobject release() function */
     430                 :          0 : static void edac_device_ctrl_block_release(struct kobject *kobj)
     431                 :            : {
     432                 :          0 :         struct edac_device_block *block;
     433                 :            : 
     434                 :          0 :         edac_dbg(1, "\n");
     435                 :            : 
     436                 :            :         /* get the container of the kobj */
     437                 :          0 :         block = to_block(kobj);
     438                 :            : 
     439                 :            :         /* map from 'block kobj' to 'block->instance->controller->main_kobj'
     440                 :            :          * now 'release' the block kobject
     441                 :            :          */
     442                 :          0 :         kobject_put(&block->instance->ctl->kobj);
     443                 :          0 : }
     444                 :            : 
     445                 :            : 
     446                 :            : /* Function to 'show' fields from the edac_dev 'block' structure */
     447                 :          0 : static ssize_t edac_dev_block_show(struct kobject *kobj,
     448                 :            :                                 struct attribute *attr, char *buffer)
     449                 :            : {
     450                 :          0 :         struct edac_dev_sysfs_block_attribute *block_attr =
     451                 :          0 :                                                 to_block_attr(attr);
     452                 :            : 
     453         [ #  # ]:          0 :         if (block_attr->show)
     454                 :          0 :                 return block_attr->show(kobj, attr, buffer);
     455                 :            :         return -EIO;
     456                 :            : }
     457                 :            : 
     458                 :            : /* Function to 'store' fields into the edac_dev 'block' structure */
     459                 :          0 : static ssize_t edac_dev_block_store(struct kobject *kobj,
     460                 :            :                                 struct attribute *attr,
     461                 :            :                                 const char *buffer, size_t count)
     462                 :            : {
     463                 :          0 :         struct edac_dev_sysfs_block_attribute *block_attr;
     464                 :            : 
     465                 :          0 :         block_attr = to_block_attr(attr);
     466                 :            : 
     467         [ #  # ]:          0 :         if (block_attr->store)
     468                 :          0 :                 return block_attr->store(kobj, attr, buffer, count);
     469                 :            :         return -EIO;
     470                 :            : }
     471                 :            : 
     472                 :            : /* edac_dev file operations for a 'block' */
     473                 :            : static const struct sysfs_ops device_block_ops = {
     474                 :            :         .show = edac_dev_block_show,
     475                 :            :         .store = edac_dev_block_store
     476                 :            : };
     477                 :            : 
     478                 :            : #define BLOCK_ATTR(_name,_mode,_show,_store)        \
     479                 :            : static struct edac_dev_sysfs_block_attribute attr_block_##_name = {     \
     480                 :            :         .attr = {.name = __stringify(_name), .mode = _mode },   \
     481                 :            :         .show   = _show,                                        \
     482                 :            :         .store  = _store,                                       \
     483                 :            : };
     484                 :            : 
     485                 :            : BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
     486                 :            : BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
     487                 :            : 
     488                 :            : /* list of edac_dev 'block' attributes */
     489                 :            : static struct edac_dev_sysfs_block_attribute *device_block_attr[] = {
     490                 :            :         &attr_block_ce_count,
     491                 :            :         &attr_block_ue_count,
     492                 :            :         NULL,
     493                 :            : };
     494                 :            : 
     495                 :            : /* The 'ktype' for each edac_dev 'block' */
     496                 :            : static struct kobj_type ktype_block_ctrl = {
     497                 :            :         .release = edac_device_ctrl_block_release,
     498                 :            :         .sysfs_ops = &device_block_ops,
     499                 :            :         .default_attrs = (struct attribute **)device_block_attr,
     500                 :            : };
     501                 :            : 
     502                 :            : /* block ctor/dtor  code */
     503                 :            : 
     504                 :            : /*
     505                 :            :  * edac_device_create_block
     506                 :            :  */
     507                 :          0 : static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
     508                 :            :                                 struct edac_device_instance *instance,
     509                 :            :                                 struct edac_device_block *block)
     510                 :            : {
     511                 :          0 :         int i;
     512                 :          0 :         int err;
     513                 :          0 :         struct edac_dev_sysfs_block_attribute *sysfs_attrib;
     514                 :          0 :         struct kobject *main_kobj;
     515                 :            : 
     516                 :          0 :         edac_dbg(4, "Instance '%s' inst_p=%p  block '%s'  block_p=%p\n",
     517                 :            :                  instance->name, instance, block->name, block);
     518                 :          0 :         edac_dbg(4, "block kobj=%p  block kobj->parent=%p\n",
     519                 :            :                  &block->kobj, &block->kobj.parent);
     520                 :            : 
     521                 :            :         /* init this block's kobject */
     522                 :          0 :         memset(&block->kobj, 0, sizeof(struct kobject));
     523                 :            : 
     524                 :            :         /* bump the main kobject's reference count for this controller
     525                 :            :          * and this instance is dependent on the main
     526                 :            :          */
     527                 :          0 :         main_kobj = kobject_get(&edac_dev->kobj);
     528         [ #  # ]:          0 :         if (!main_kobj) {
     529                 :          0 :                 err = -ENODEV;
     530                 :          0 :                 goto err_out;
     531                 :            :         }
     532                 :            : 
     533                 :            :         /* Add this block's kobject */
     534                 :          0 :         err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
     535                 :            :                                    &instance->kobj,
     536                 :          0 :                                    "%s", block->name);
     537         [ #  # ]:          0 :         if (err) {
     538                 :          0 :                 edac_dbg(1, "Failed to register instance '%s'\n", block->name);
     539                 :          0 :                 kobject_put(main_kobj);
     540                 :          0 :                 err = -ENODEV;
     541                 :          0 :                 goto err_out;
     542                 :            :         }
     543                 :            : 
     544                 :            :         /* If there are driver level block attributes, then added them
     545                 :            :          * to the block kobject
     546                 :            :          */
     547                 :          0 :         sysfs_attrib = block->block_attributes;
     548   [ #  #  #  # ]:          0 :         if (sysfs_attrib && block->nr_attribs) {
     549         [ #  # ]:          0 :                 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
     550                 :            : 
     551                 :          0 :                         edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n",
     552                 :            :                                  sysfs_attrib->attr.name,
     553                 :            :                                  sysfs_attrib, &block->kobj);
     554                 :            : 
     555                 :            :                         /* Create each block_attribute file */
     556                 :          0 :                         err = sysfs_create_file(&block->kobj,
     557                 :          0 :                                 &sysfs_attrib->attr);
     558         [ #  # ]:          0 :                         if (err)
     559                 :          0 :                                 goto err_on_attrib;
     560                 :            :                 }
     561                 :            :         }
     562                 :          0 :         kobject_uevent(&block->kobj, KOBJ_ADD);
     563                 :            : 
     564                 :          0 :         return 0;
     565                 :            : 
     566                 :            :         /* Error unwind stack */
     567                 :            : err_on_attrib:
     568                 :          0 :         kobject_put(&block->kobj);
     569                 :            : 
     570                 :            : err_out:
     571                 :            :         return err;
     572                 :            : }
     573                 :            : 
     574                 :            : /*
     575                 :            :  * edac_device_delete_block(edac_dev,block);
     576                 :            :  */
     577                 :            : static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
     578                 :            :                                 struct edac_device_block *block)
     579                 :            : {
     580                 :            :         struct edac_dev_sysfs_block_attribute *sysfs_attrib;
     581                 :            :         int i;
     582                 :            : 
     583                 :            :         /* if this block has 'attributes' then we need to iterate over the list
     584                 :            :          * and 'remove' the attributes on this block
     585                 :            :          */
     586                 :            :         sysfs_attrib = block->block_attributes;
     587                 :            :         if (sysfs_attrib && block->nr_attribs) {
     588                 :            :                 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
     589                 :            : 
     590                 :            :                         /* remove each block_attrib file */
     591                 :            :                         sysfs_remove_file(&block->kobj,
     592                 :            :                                 (struct attribute *) sysfs_attrib);
     593                 :            :                 }
     594                 :            :         }
     595                 :            : 
     596                 :            :         /* unregister this block's kobject, SEE:
     597                 :            :          *      edac_device_ctrl_block_release() callback operation
     598                 :            :          */
     599                 :            :         kobject_put(&block->kobj);
     600                 :            : }
     601                 :            : 
     602                 :            : /* instance ctor/dtor code */
     603                 :            : 
     604                 :            : /*
     605                 :            :  * edac_device_create_instance
     606                 :            :  *      create just one instance of an edac_device 'instance'
     607                 :            :  */
     608                 :          0 : static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
     609                 :            :                                 int idx)
     610                 :            : {
     611                 :          0 :         int i, j;
     612                 :          0 :         int err;
     613                 :          0 :         struct edac_device_instance *instance;
     614                 :          0 :         struct kobject *main_kobj;
     615                 :            : 
     616                 :          0 :         instance = &edac_dev->instances[idx];
     617                 :            : 
     618                 :            :         /* Init the instance's kobject */
     619                 :          0 :         memset(&instance->kobj, 0, sizeof(struct kobject));
     620                 :            : 
     621                 :          0 :         instance->ctl = edac_dev;
     622                 :            : 
     623                 :            :         /* bump the main kobject's reference count for this controller
     624                 :            :          * and this instance is dependent on the main
     625                 :            :          */
     626                 :          0 :         main_kobj = kobject_get(&edac_dev->kobj);
     627         [ #  # ]:          0 :         if (!main_kobj) {
     628                 :          0 :                 err = -ENODEV;
     629                 :          0 :                 goto err_out;
     630                 :            :         }
     631                 :            : 
     632                 :            :         /* Formally register this instance's kobject under the edac_device */
     633                 :          0 :         err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
     634                 :          0 :                                    &edac_dev->kobj, "%s", instance->name);
     635         [ #  # ]:          0 :         if (err != 0) {
     636                 :          0 :                 edac_dbg(2, "Failed to register instance '%s'\n",
     637                 :            :                          instance->name);
     638                 :          0 :                 kobject_put(main_kobj);
     639                 :          0 :                 goto err_out;
     640                 :            :         }
     641                 :            : 
     642                 :            :         edac_dbg(4, "now register '%d' blocks for instance %d\n",
     643                 :            :                  instance->nr_blocks, idx);
     644                 :            : 
     645                 :            :         /* register all blocks of this instance */
     646         [ #  # ]:          0 :         for (i = 0; i < instance->nr_blocks; i++) {
     647                 :          0 :                 err = edac_device_create_block(edac_dev, instance,
     648                 :          0 :                                                 &instance->blocks[i]);
     649         [ #  # ]:          0 :                 if (err) {
     650                 :            :                         /* If any fail, remove all previous ones */
     651         [ #  # ]:          0 :                         for (j = 0; j < i; j++)
     652                 :          0 :                                 edac_device_delete_block(edac_dev,
     653                 :          0 :                                                         &instance->blocks[j]);
     654                 :          0 :                         goto err_release_instance_kobj;
     655                 :            :                 }
     656                 :            :         }
     657                 :          0 :         kobject_uevent(&instance->kobj, KOBJ_ADD);
     658                 :            : 
     659                 :          0 :         edac_dbg(4, "Registered instance %d '%s' kobject\n",
     660                 :            :                  idx, instance->name);
     661                 :            : 
     662                 :          0 :         return 0;
     663                 :            : 
     664                 :            :         /* error unwind stack */
     665                 :            : err_release_instance_kobj:
     666                 :          0 :         kobject_put(&instance->kobj);
     667                 :            : 
     668                 :            : err_out:
     669                 :            :         return err;
     670                 :            : }
     671                 :            : 
     672                 :            : /*
     673                 :            :  * edac_device_remove_instance
     674                 :            :  *      remove an edac_device instance
     675                 :            :  */
     676                 :            : static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
     677                 :            :                                         int idx)
     678                 :            : {
     679                 :            :         struct edac_device_instance *instance;
     680                 :            :         int i;
     681                 :            : 
     682                 :            :         instance = &edac_dev->instances[idx];
     683                 :            : 
     684                 :            :         /* unregister all blocks in this instance */
     685                 :            :         for (i = 0; i < instance->nr_blocks; i++)
     686                 :            :                 edac_device_delete_block(edac_dev, &instance->blocks[i]);
     687                 :            : 
     688                 :            :         /* unregister this instance's kobject, SEE:
     689                 :            :          *      edac_device_ctrl_instance_release() for callback operation
     690                 :            :          */
     691                 :            :         kobject_put(&instance->kobj);
     692                 :            : }
     693                 :            : 
     694                 :            : /*
     695                 :            :  * edac_device_create_instances
     696                 :            :  *      create the first level of 'instances' for this device
     697                 :            :  *      (ie  'cache' might have 'cache0', 'cache1', 'cache2', etc
     698                 :            :  */
     699                 :          0 : static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
     700                 :            : {
     701                 :          0 :         int i, j;
     702                 :          0 :         int err;
     703                 :            : 
     704                 :          0 :         edac_dbg(0, "\n");
     705                 :            : 
     706                 :            :         /* iterate over creation of the instances */
     707         [ #  # ]:          0 :         for (i = 0; i < edac_dev->nr_instances; i++) {
     708                 :          0 :                 err = edac_device_create_instance(edac_dev, i);
     709         [ #  # ]:          0 :                 if (err) {
     710                 :            :                         /* unwind previous instances on error */
     711         [ #  # ]:          0 :                         for (j = 0; j < i; j++)
     712                 :          0 :                                 edac_device_delete_instance(edac_dev, j);
     713                 :            :                         return err;
     714                 :            :                 }
     715                 :            :         }
     716                 :            : 
     717                 :            :         return 0;
     718                 :            : }
     719                 :            : 
     720                 :            : /*
     721                 :            :  * edac_device_delete_instances(edac_dev);
     722                 :            :  *      unregister all the kobjects of the instances
     723                 :            :  */
     724                 :          0 : static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
     725                 :            : {
     726                 :          0 :         int i;
     727                 :            : 
     728                 :            :         /* iterate over creation of the instances */
     729         [ #  # ]:          0 :         for (i = 0; i < edac_dev->nr_instances; i++)
     730                 :          0 :                 edac_device_delete_instance(edac_dev, i);
     731                 :            : }
     732                 :            : 
     733                 :            : /* edac_dev sysfs ctor/dtor  code */
     734                 :            : 
     735                 :            : /*
     736                 :            :  * edac_device_add_main_sysfs_attributes
     737                 :            :  *      add some attributes to this instance's main kobject
     738                 :            :  */
     739                 :          0 : static int edac_device_add_main_sysfs_attributes(
     740                 :            :                         struct edac_device_ctl_info *edac_dev)
     741                 :            : {
     742                 :          0 :         struct edac_dev_sysfs_attribute *sysfs_attrib;
     743                 :          0 :         int err = 0;
     744                 :            : 
     745                 :          0 :         sysfs_attrib = edac_dev->sysfs_attributes;
     746         [ #  # ]:          0 :         if (sysfs_attrib) {
     747                 :            :                 /* iterate over the array and create an attribute for each
     748                 :            :                  * entry in the list
     749                 :            :                  */
     750         [ #  # ]:          0 :                 while (sysfs_attrib->attr.name != NULL) {
     751                 :          0 :                         err = sysfs_create_file(&edac_dev->kobj,
     752                 :            :                                 (struct attribute*) sysfs_attrib);
     753         [ #  # ]:          0 :                         if (err)
     754                 :          0 :                                 goto err_out;
     755                 :            : 
     756                 :          0 :                         sysfs_attrib++;
     757                 :            :                 }
     758                 :            :         }
     759                 :            : 
     760                 :          0 : err_out:
     761                 :          0 :         return err;
     762                 :            : }
     763                 :            : 
     764                 :            : /*
     765                 :            :  * edac_device_remove_main_sysfs_attributes
     766                 :            :  *      remove any attributes to this instance's main kobject
     767                 :            :  */
     768                 :          0 : static void edac_device_remove_main_sysfs_attributes(
     769                 :            :                         struct edac_device_ctl_info *edac_dev)
     770                 :            : {
     771                 :          0 :         struct edac_dev_sysfs_attribute *sysfs_attrib;
     772                 :            : 
     773                 :            :         /* if there are main attributes, defined, remove them. First,
     774                 :            :          * point to the start of the array and iterate over it
     775                 :            :          * removing each attribute listed from this device's instance's kobject
     776                 :            :          */
     777                 :          0 :         sysfs_attrib = edac_dev->sysfs_attributes;
     778         [ #  # ]:          0 :         if (sysfs_attrib) {
     779         [ #  # ]:          0 :                 while (sysfs_attrib->attr.name != NULL) {
     780                 :          0 :                         sysfs_remove_file(&edac_dev->kobj,
     781                 :            :                                         (struct attribute *) sysfs_attrib);
     782                 :          0 :                         sysfs_attrib++;
     783                 :            :                 }
     784                 :            :         }
     785                 :          0 : }
     786                 :            : 
     787                 :            : /*
     788                 :            :  * edac_device_create_sysfs() Constructor
     789                 :            :  *
     790                 :            :  * accept a created edac_device control structure
     791                 :            :  * and 'export' it to sysfs. The 'main' kobj should already have been
     792                 :            :  * created. 'instance' and 'block' kobjects should be registered
     793                 :            :  * along with any 'block' attributes from the low driver. In addition,
     794                 :            :  * the main attributes (if any) are connected to the main kobject of
     795                 :            :  * the control structure.
     796                 :            :  *
     797                 :            :  * Return:
     798                 :            :  *      0       Success
     799                 :            :  *      !0      Failure
     800                 :            :  */
     801                 :          0 : int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
     802                 :            : {
     803                 :          0 :         int err;
     804                 :          0 :         struct kobject *edac_kobj = &edac_dev->kobj;
     805                 :            : 
     806                 :          0 :         edac_dbg(0, "idx=%d\n", edac_dev->dev_idx);
     807                 :            : 
     808                 :            :         /*  go create any main attributes callers wants */
     809                 :          0 :         err = edac_device_add_main_sysfs_attributes(edac_dev);
     810         [ #  # ]:          0 :         if (err) {
     811                 :          0 :                 edac_dbg(0, "failed to add sysfs attribs\n");
     812                 :          0 :                 goto err_out;
     813                 :            :         }
     814                 :            : 
     815                 :            :         /* create a symlink from the edac device
     816                 :            :          * to the platform 'device' being used for this
     817                 :            :          */
     818                 :          0 :         err = sysfs_create_link(edac_kobj,
     819                 :          0 :                                 &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
     820         [ #  # ]:          0 :         if (err) {
     821                 :          0 :                 edac_dbg(0, "sysfs_create_link() returned err= %d\n", err);
     822                 :          0 :                 goto err_remove_main_attribs;
     823                 :            :         }
     824                 :            : 
     825                 :            :         /* Create the first level instance directories
     826                 :            :          * In turn, the nested blocks beneath the instances will
     827                 :            :          * be registered as well
     828                 :            :          */
     829                 :          0 :         err = edac_device_create_instances(edac_dev);
     830         [ #  # ]:          0 :         if (err) {
     831                 :          0 :                 edac_dbg(0, "edac_device_create_instances() returned err= %d\n",
     832                 :            :                          err);
     833                 :          0 :                 goto err_remove_link;
     834                 :            :         }
     835                 :            : 
     836                 :            : 
     837                 :            :         edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx);
     838                 :            : 
     839                 :            :         return 0;
     840                 :            : 
     841                 :            :         /* Error unwind stack */
     842                 :            : err_remove_link:
     843                 :            :         /* remove the sym link */
     844                 :          0 :         sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
     845                 :            : 
     846                 :          0 : err_remove_main_attribs:
     847                 :          0 :         edac_device_remove_main_sysfs_attributes(edac_dev);
     848                 :            : 
     849                 :            : err_out:
     850                 :            :         return err;
     851                 :            : }
     852                 :            : 
     853                 :            : /*
     854                 :            :  * edac_device_remove_sysfs() destructor
     855                 :            :  *
     856                 :            :  * given an edac_device struct, tear down the kobject resources
     857                 :            :  */
     858                 :          0 : void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
     859                 :            : {
     860                 :          0 :         edac_dbg(0, "\n");
     861                 :            : 
     862                 :            :         /* remove any main attributes for this device */
     863                 :          0 :         edac_device_remove_main_sysfs_attributes(edac_dev);
     864                 :            : 
     865                 :            :         /* remove the device sym link */
     866                 :          0 :         sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
     867                 :            : 
     868                 :            :         /* walk the instance/block kobject tree, deconstructing it */
     869                 :          0 :         edac_device_delete_instances(edac_dev);
     870                 :          0 : }

Generated by: LCOV version 1.14