edac_core: Allow the creation of sysfs groups
authorMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 23 Sep 2009 19:26:09 +0000 (16:26 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 10 May 2010 14:45:01 +0000 (11:45 -0300)
Currently, all sysfs nodes are stored at /sys/.*/mc. (regex)
However, sometimes it is needed to create attribute groups.

This patch extends edac_core to allow groups creation.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/edac/edac_core.h
drivers/edac/edac_mc_sysfs.c

index 001b2e7..97071ff 100644 (file)
@@ -341,12 +341,22 @@ struct csrow_info {
        struct channel_info *channels;
 };
 
+struct mcidev_sysfs_group {
+       const char *name;
+       struct mcidev_sysfs_attribute *mcidev_attr;
+       struct kobject kobj;
+};
+
+
 /* mcidev_sysfs_attribute structure
  *     used for driver sysfs attributes and in mem_ctl_info
  *     sysfs top level entries
  */
 struct mcidev_sysfs_attribute {
-        struct attribute attr;
+       struct attribute attr;
+
+       struct mcidev_sysfs_group *grp;
+
         ssize_t (*show)(struct mem_ctl_info *,char *);
         ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
 };
index 418b65f..655aa1a 100644 (file)
@@ -728,26 +728,43 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 
 /*
  * edac_create_mci_instance_attributes
- *     create MC driver specific attributes at the topmost level
- *     directory of this mci instance.
+ *     create MC driver specific attributes bellow an specified kobj
+ * This routine calls itself recursively, in order to create an entire
+ * object tree.
  */
-static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
+static int edac_create_mci_instance_attributes(
+                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               struct kobject *kobj)
 {
        int err;
-       struct mcidev_sysfs_attribute *sysfs_attrib;
 
-       /* point to the start of the array and iterate over it
-        * adding each attribute listed to this mci instance's kobject
-        */
-       sysfs_attrib = mci->mc_driver_sysfs_attributes;
+       while (sysfs_attrib) {
+               if (sysfs_attrib->grp) {
+                       struct kobject *newkobj = &sysfs_attrib->grp->kobj;
+                       debugf0("%s() grp %s\n", __func__,
+                               sysfs_attrib->grp->name);
+
+                       err = kobject_init_and_add(newkobj, NULL,
+                                               kobj,
+                                               sysfs_attrib->grp->name);
+                       if (err)
+                               return err;
+
+                       err = edac_create_mci_instance_attributes(
+                                       sysfs_attrib->grp->mcidev_attr, newkobj);
+                       if (err)
+                               return err;
+               } else if (sysfs_attrib->attr.name) {
+                       debugf0("%s() file %s\n", __func__,
+                               sysfs_attrib->attr.name);
+
+                       err = sysfs_create_file(kobj, &sysfs_attrib->attr);
+               } else
+                       break;
 
-       while (sysfs_attrib && sysfs_attrib->attr.name) {
-               err = sysfs_create_file(&mci->edac_mci_kobj,
-                                       (struct attribute*) sysfs_attrib);
                if (err) {
                        return err;
                }
-
                sysfs_attrib++;
        }
 
@@ -759,19 +776,28 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
  *     remove MC driver specific attributes at the topmost level
  *     directory of this mci instance.
  */
-static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci)
+static void edac_remove_mci_instance_attributes(
+                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               struct kobject *kobj)
 {
-       struct mcidev_sysfs_attribute *sysfs_attrib;
-
-       /* point to the start of the array and iterate over it
-        * adding each attribute listed to this mci instance's kobject
-        */
-       sysfs_attrib = mci->mc_driver_sysfs_attributes;
-
        /* loop if there are attributes and until we hit a NULL entry */
-       while (sysfs_attrib && sysfs_attrib->attr.name) {
-               sysfs_remove_file(&mci->edac_mci_kobj,
-                                       (struct attribute *) sysfs_attrib);
+       while (sysfs_attrib) {
+               if (sysfs_attrib->grp) {
+                       struct kobject *newkobj = &sysfs_attrib->grp->kobj;
+
+                       debugf0("%s() grp %s\n", __func__,
+                               sysfs_attrib->grp->name);
+
+                       edac_remove_mci_instance_attributes(
+                               sysfs_attrib->grp->mcidev_attr, newkobj);
+
+                       kobject_put(newkobj);
+               } else  if (sysfs_attrib->attr.name) {
+                       debugf0("%s() file %s\n", __func__,
+                               sysfs_attrib->attr.name);
+                       sysfs_remove_file(kobj, &sysfs_attrib->attr);
+               } else
+                       break;
                sysfs_attrib++;
        }
 }
@@ -806,7 +832,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
         * then create them now for the driver.
         */
        if (mci->mc_driver_sysfs_attributes) {
-               err = edac_create_mci_instance_attributes(mci);
+               err = edac_create_mci_instance_attributes(
+                                       mci->mc_driver_sysfs_attributes,
+                                       &mci->edac_mci_kobj);
                if (err) {
                        debugf1("%s() failure to create mci attributes\n",
                                __func__);
@@ -841,7 +869,8 @@ fail1:
        }
 
        /* remove the mci instance's attributes, if any */
-       edac_remove_mci_instance_attributes(mci);
+       edac_remove_mci_instance_attributes(
+               mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj);
 
        /* remove the symlink */
        sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
@@ -875,8 +904,8 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
        debugf0("%s()  remove_mci_instance\n", __func__);
 
        /* remove this mci instance's attribtes */
-       edac_remove_mci_instance_attributes(mci);
-
+       edac_remove_mci_instance_attributes(mci->mc_driver_sysfs_attributes,
+                                           &mci->edac_mci_kobj);
        debugf0("%s()  unregister this mci kobj\n", __func__);
 
        /* unregister this instance's kobject */