From 9fa2fc2e2d641df7d69dc4e06cf2552c44b58e95 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Sep 2009 16:26:09 -0300 Subject: edac_core: Allow the creation of sysfs groups 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 --- drivers/edac/edac_core.h | 12 ++++++- drivers/edac/edac_mc_sysfs.c | 83 ++++++++++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 001b2e79..97071ff 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -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); }; diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 418b65f..655aa1a 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -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 */ -- cgit v1.1