summaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-09-23 21:26:09 +0200
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 16:45:01 +0200
commit9fa2fc2e2d641df7d69dc4e06cf2552c44b58e95 (patch)
tree2fdcdf1b688d006f0c4b99076ff242b1f8b5063b /drivers/edac
parenti7core_edac: Avoid printing a warning when debug is disabled (diff)
downloadlinux-9fa2fc2e2d641df7d69dc4e06cf2552c44b58e95.tar.xz
linux-9fa2fc2e2d641df7d69dc4e06cf2552c44b58e95.zip
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 <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/edac_core.h12
-rw-r--r--drivers/edac/edac_mc_sysfs.c83
2 files changed, 67 insertions, 28 deletions
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 001b2e797fb3..97071ff1d22d 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 418b65f1a1da..655aa1a1f4f9 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 */