Loading drivers/edac/edac_core.h +15 −6 Original line number Diff line number Diff line Loading @@ -342,23 +342,29 @@ struct csrow_info { }; struct mcidev_sysfs_group { const char *name; struct mcidev_sysfs_attribute *mcidev_attr; struct kobject kobj; const char *name; /* group name */ struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ }; struct mcidev_sysfs_group_kobj { struct list_head list; /* list for all instances within a mc */ struct kobject kobj; /* kobj for the group */ struct mcidev_sysfs_group *grp; /* group description table */ struct mem_ctl_info *mci; /* the parent */ }; /* mcidev_sysfs_attribute structure * used for driver sysfs attributes and in mem_ctl_info * sysfs top level entries */ struct mcidev_sysfs_attribute { /* It should use either attr or grp */ struct attribute attr; struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ struct mcidev_sysfs_group *grp; /* Ops for show/store values at the attribute - not used on group */ ssize_t (*show)(struct mem_ctl_info *,char *); ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); }; Loading Loading @@ -436,6 +442,9 @@ struct mem_ctl_info { /* edac sysfs device control */ struct kobject edac_mci_kobj; /* list for all grp instances within a mc */ struct list_head grp_kobj_list; /* Additional top controller level attributes, but specified * by the low level driver. * Loading drivers/edac/edac_mc_sysfs.c +49 −26 Original line number Diff line number Diff line Loading @@ -730,7 +730,7 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci) #define EDAC_DEVICE_SYMLINK "device" #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group, kobj)->mci) #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci) /* MCI show/store functions for top most object */ static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, Loading Loading @@ -764,12 +764,12 @@ static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr, /* No memory to release for this kobj */ static void edac_inst_grp_release(struct kobject *kobj) { struct mcidev_sysfs_group *grp; struct mcidev_sysfs_group_kobj *grp; struct mem_ctl_info *mci; debugf1("%s()\n", __func__); grp = container_of(kobj, struct mcidev_sysfs_group, kobj); grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj); mci = grp->mci; kobject_put(&mci->edac_mci_kobj); Loading Loading @@ -804,22 +804,30 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, while (sysfs_attrib) { if (sysfs_attrib->grp) { struct kobject *newkobj = &sysfs_attrib->grp->kobj; struct mcidev_sysfs_group_kobj *grp_kobj; grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL); if (!grp_kobj) return -ENOMEM; list_add_tail(&grp_kobj->list, &mci->grp_kobj_list); grp_kobj->grp = sysfs_attrib->grp; grp_kobj->mci = mci; debugf0("%s() grp %s, mci %p\n", __func__, sysfs_attrib->grp->name, mci); sysfs_attrib->grp->mci = mci; err = kobject_init_and_add(newkobj, &ktype_inst_grp, err = kobject_init_and_add(&grp_kobj->kobj, &ktype_inst_grp, &mci->edac_mci_kobj, sysfs_attrib->grp->name); if (err) return err; err = edac_create_mci_instance_attributes(mci, sysfs_attrib->grp->mcidev_attr, newkobj); grp_kobj->grp->mcidev_attr, &grp_kobj->kobj); if (err) return err; Loading @@ -845,24 +853,26 @@ 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( static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, struct mcidev_sysfs_attribute *sysfs_attrib, struct kobject *kobj) struct kobject *kobj, int count) { struct mcidev_sysfs_group_kobj *grp_kobj, *tmp; debugf1("%s()\n", __func__); /* loop if there are attributes and until we hit a NULL entry */ /* * loop if there are attributes and until we hit a NULL entry * Remove first all the atributes */ 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); list_for_each_entry(grp_kobj, &mci->grp_kobj_list, list) if (grp_kobj->grp == sysfs_attrib->grp) edac_remove_mci_instance_attributes(mci, grp_kobj->grp->mcidev_attr, &grp_kobj->kobj, count + 1); } else if (sysfs_attrib->attr.name) { debugf0("%s() file %s\n", __func__, sysfs_attrib->attr.name); Loading @@ -871,6 +881,16 @@ static void edac_remove_mci_instance_attributes( break; sysfs_attrib++; } /* * Now that all attributes got removed, it is save to remove all groups */ if (!count) list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list, list) { debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name); kobject_put(&grp_kobj->kobj); } } Loading @@ -891,6 +911,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) debugf0("%s() idx=%d\n", __func__, mci->mc_idx); INIT_LIST_HEAD(&mci->grp_kobj_list); /* create a symlink for the device */ err = sysfs_create_link(kobj_mci, &mci->dev->kobj, EDAC_DEVICE_SYMLINK); Loading Loading @@ -940,8 +962,8 @@ fail1: } /* remove the mci instance's attributes, if any */ edac_remove_mci_instance_attributes( mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); edac_remove_mci_instance_attributes(mci, mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); /* remove the symlink */ sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); Loading Loading @@ -975,8 +997,9 @@ 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->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); edac_remove_mci_instance_attributes(mci, mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); debugf0("%s() unregister this mci kobj\n", __func__); /* unregister this instance's kobject */ Loading Loading
drivers/edac/edac_core.h +15 −6 Original line number Diff line number Diff line Loading @@ -342,23 +342,29 @@ struct csrow_info { }; struct mcidev_sysfs_group { const char *name; struct mcidev_sysfs_attribute *mcidev_attr; struct kobject kobj; const char *name; /* group name */ struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ }; struct mcidev_sysfs_group_kobj { struct list_head list; /* list for all instances within a mc */ struct kobject kobj; /* kobj for the group */ struct mcidev_sysfs_group *grp; /* group description table */ struct mem_ctl_info *mci; /* the parent */ }; /* mcidev_sysfs_attribute structure * used for driver sysfs attributes and in mem_ctl_info * sysfs top level entries */ struct mcidev_sysfs_attribute { /* It should use either attr or grp */ struct attribute attr; struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ struct mcidev_sysfs_group *grp; /* Ops for show/store values at the attribute - not used on group */ ssize_t (*show)(struct mem_ctl_info *,char *); ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); }; Loading Loading @@ -436,6 +442,9 @@ struct mem_ctl_info { /* edac sysfs device control */ struct kobject edac_mci_kobj; /* list for all grp instances within a mc */ struct list_head grp_kobj_list; /* Additional top controller level attributes, but specified * by the low level driver. * Loading
drivers/edac/edac_mc_sysfs.c +49 −26 Original line number Diff line number Diff line Loading @@ -730,7 +730,7 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci) #define EDAC_DEVICE_SYMLINK "device" #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group, kobj)->mci) #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci) /* MCI show/store functions for top most object */ static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, Loading Loading @@ -764,12 +764,12 @@ static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr, /* No memory to release for this kobj */ static void edac_inst_grp_release(struct kobject *kobj) { struct mcidev_sysfs_group *grp; struct mcidev_sysfs_group_kobj *grp; struct mem_ctl_info *mci; debugf1("%s()\n", __func__); grp = container_of(kobj, struct mcidev_sysfs_group, kobj); grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj); mci = grp->mci; kobject_put(&mci->edac_mci_kobj); Loading Loading @@ -804,22 +804,30 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, while (sysfs_attrib) { if (sysfs_attrib->grp) { struct kobject *newkobj = &sysfs_attrib->grp->kobj; struct mcidev_sysfs_group_kobj *grp_kobj; grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL); if (!grp_kobj) return -ENOMEM; list_add_tail(&grp_kobj->list, &mci->grp_kobj_list); grp_kobj->grp = sysfs_attrib->grp; grp_kobj->mci = mci; debugf0("%s() grp %s, mci %p\n", __func__, sysfs_attrib->grp->name, mci); sysfs_attrib->grp->mci = mci; err = kobject_init_and_add(newkobj, &ktype_inst_grp, err = kobject_init_and_add(&grp_kobj->kobj, &ktype_inst_grp, &mci->edac_mci_kobj, sysfs_attrib->grp->name); if (err) return err; err = edac_create_mci_instance_attributes(mci, sysfs_attrib->grp->mcidev_attr, newkobj); grp_kobj->grp->mcidev_attr, &grp_kobj->kobj); if (err) return err; Loading @@ -845,24 +853,26 @@ 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( static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, struct mcidev_sysfs_attribute *sysfs_attrib, struct kobject *kobj) struct kobject *kobj, int count) { struct mcidev_sysfs_group_kobj *grp_kobj, *tmp; debugf1("%s()\n", __func__); /* loop if there are attributes and until we hit a NULL entry */ /* * loop if there are attributes and until we hit a NULL entry * Remove first all the atributes */ 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); list_for_each_entry(grp_kobj, &mci->grp_kobj_list, list) if (grp_kobj->grp == sysfs_attrib->grp) edac_remove_mci_instance_attributes(mci, grp_kobj->grp->mcidev_attr, &grp_kobj->kobj, count + 1); } else if (sysfs_attrib->attr.name) { debugf0("%s() file %s\n", __func__, sysfs_attrib->attr.name); Loading @@ -871,6 +881,16 @@ static void edac_remove_mci_instance_attributes( break; sysfs_attrib++; } /* * Now that all attributes got removed, it is save to remove all groups */ if (!count) list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list, list) { debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name); kobject_put(&grp_kobj->kobj); } } Loading @@ -891,6 +911,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) debugf0("%s() idx=%d\n", __func__, mci->mc_idx); INIT_LIST_HEAD(&mci->grp_kobj_list); /* create a symlink for the device */ err = sysfs_create_link(kobj_mci, &mci->dev->kobj, EDAC_DEVICE_SYMLINK); Loading Loading @@ -940,8 +962,8 @@ fail1: } /* remove the mci instance's attributes, if any */ edac_remove_mci_instance_attributes( mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); edac_remove_mci_instance_attributes(mci, mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); /* remove the symlink */ sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); Loading Loading @@ -975,8 +997,9 @@ 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->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); edac_remove_mci_instance_attributes(mci, mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); debugf0("%s() unregister this mci kobj\n", __func__); /* unregister this instance's kobject */ Loading