diff options
-rw-r--r-- | drivers/edac/edac_core.h | 12 | ||||
-rw-r--r-- | 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 001b2e797fb3..97071ff1d22d 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -341,12 +341,22 @@ struct csrow_info { | |||
341 | struct channel_info *channels; | 341 | struct channel_info *channels; |
342 | }; | 342 | }; |
343 | 343 | ||
344 | struct mcidev_sysfs_group { | ||
345 | const char *name; | ||
346 | struct mcidev_sysfs_attribute *mcidev_attr; | ||
347 | struct kobject kobj; | ||
348 | }; | ||
349 | |||
350 | |||
344 | /* mcidev_sysfs_attribute structure | 351 | /* mcidev_sysfs_attribute structure |
345 | * used for driver sysfs attributes and in mem_ctl_info | 352 | * used for driver sysfs attributes and in mem_ctl_info |
346 | * sysfs top level entries | 353 | * sysfs top level entries |
347 | */ | 354 | */ |
348 | struct mcidev_sysfs_attribute { | 355 | struct mcidev_sysfs_attribute { |
349 | struct attribute attr; | 356 | struct attribute attr; |
357 | |||
358 | struct mcidev_sysfs_group *grp; | ||
359 | |||
350 | ssize_t (*show)(struct mem_ctl_info *,char *); | 360 | ssize_t (*show)(struct mem_ctl_info *,char *); |
351 | ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); | 361 | ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); |
352 | }; | 362 | }; |
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) | |||
728 | 728 | ||
729 | /* | 729 | /* |
730 | * edac_create_mci_instance_attributes | 730 | * edac_create_mci_instance_attributes |
731 | * create MC driver specific attributes at the topmost level | 731 | * create MC driver specific attributes bellow an specified kobj |
732 | * directory of this mci instance. | 732 | * This routine calls itself recursively, in order to create an entire |
733 | * object tree. | ||
733 | */ | 734 | */ |
734 | static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci) | 735 | static int edac_create_mci_instance_attributes( |
736 | struct mcidev_sysfs_attribute *sysfs_attrib, | ||
737 | struct kobject *kobj) | ||
735 | { | 738 | { |
736 | int err; | 739 | int err; |
737 | struct mcidev_sysfs_attribute *sysfs_attrib; | ||
738 | 740 | ||
739 | /* point to the start of the array and iterate over it | 741 | while (sysfs_attrib) { |
740 | * adding each attribute listed to this mci instance's kobject | 742 | if (sysfs_attrib->grp) { |
741 | */ | 743 | struct kobject *newkobj = &sysfs_attrib->grp->kobj; |
742 | sysfs_attrib = mci->mc_driver_sysfs_attributes; | 744 | debugf0("%s() grp %s\n", __func__, |
745 | sysfs_attrib->grp->name); | ||
746 | |||
747 | err = kobject_init_and_add(newkobj, NULL, | ||
748 | kobj, | ||
749 | sysfs_attrib->grp->name); | ||
750 | if (err) | ||
751 | return err; | ||
752 | |||
753 | err = edac_create_mci_instance_attributes( | ||
754 | sysfs_attrib->grp->mcidev_attr, newkobj); | ||
755 | if (err) | ||
756 | return err; | ||
757 | } else if (sysfs_attrib->attr.name) { | ||
758 | debugf0("%s() file %s\n", __func__, | ||
759 | sysfs_attrib->attr.name); | ||
760 | |||
761 | err = sysfs_create_file(kobj, &sysfs_attrib->attr); | ||
762 | } else | ||
763 | break; | ||
743 | 764 | ||
744 | while (sysfs_attrib && sysfs_attrib->attr.name) { | ||
745 | err = sysfs_create_file(&mci->edac_mci_kobj, | ||
746 | (struct attribute*) sysfs_attrib); | ||
747 | if (err) { | 765 | if (err) { |
748 | return err; | 766 | return err; |
749 | } | 767 | } |
750 | |||
751 | sysfs_attrib++; | 768 | sysfs_attrib++; |
752 | } | 769 | } |
753 | 770 | ||
@@ -759,19 +776,28 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci) | |||
759 | * remove MC driver specific attributes at the topmost level | 776 | * remove MC driver specific attributes at the topmost level |
760 | * directory of this mci instance. | 777 | * directory of this mci instance. |
761 | */ | 778 | */ |
762 | static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci) | 779 | static void edac_remove_mci_instance_attributes( |
780 | struct mcidev_sysfs_attribute *sysfs_attrib, | ||
781 | struct kobject *kobj) | ||
763 | { | 782 | { |
764 | struct mcidev_sysfs_attribute *sysfs_attrib; | ||
765 | |||
766 | /* point to the start of the array and iterate over it | ||
767 | * adding each attribute listed to this mci instance's kobject | ||
768 | */ | ||
769 | sysfs_attrib = mci->mc_driver_sysfs_attributes; | ||
770 | |||
771 | /* loop if there are attributes and until we hit a NULL entry */ | 783 | /* loop if there are attributes and until we hit a NULL entry */ |
772 | while (sysfs_attrib && sysfs_attrib->attr.name) { | 784 | while (sysfs_attrib) { |
773 | sysfs_remove_file(&mci->edac_mci_kobj, | 785 | if (sysfs_attrib->grp) { |
774 | (struct attribute *) sysfs_attrib); | 786 | struct kobject *newkobj = &sysfs_attrib->grp->kobj; |
787 | |||
788 | debugf0("%s() grp %s\n", __func__, | ||
789 | sysfs_attrib->grp->name); | ||
790 | |||
791 | edac_remove_mci_instance_attributes( | ||
792 | sysfs_attrib->grp->mcidev_attr, newkobj); | ||
793 | |||
794 | kobject_put(newkobj); | ||
795 | } else if (sysfs_attrib->attr.name) { | ||
796 | debugf0("%s() file %s\n", __func__, | ||
797 | sysfs_attrib->attr.name); | ||
798 | sysfs_remove_file(kobj, &sysfs_attrib->attr); | ||
799 | } else | ||
800 | break; | ||
775 | sysfs_attrib++; | 801 | sysfs_attrib++; |
776 | } | 802 | } |
777 | } | 803 | } |
@@ -806,7 +832,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) | |||
806 | * then create them now for the driver. | 832 | * then create them now for the driver. |
807 | */ | 833 | */ |
808 | if (mci->mc_driver_sysfs_attributes) { | 834 | if (mci->mc_driver_sysfs_attributes) { |
809 | err = edac_create_mci_instance_attributes(mci); | 835 | err = edac_create_mci_instance_attributes( |
836 | mci->mc_driver_sysfs_attributes, | ||
837 | &mci->edac_mci_kobj); | ||
810 | if (err) { | 838 | if (err) { |
811 | debugf1("%s() failure to create mci attributes\n", | 839 | debugf1("%s() failure to create mci attributes\n", |
812 | __func__); | 840 | __func__); |
@@ -841,7 +869,8 @@ fail1: | |||
841 | } | 869 | } |
842 | 870 | ||
843 | /* remove the mci instance's attributes, if any */ | 871 | /* remove the mci instance's attributes, if any */ |
844 | edac_remove_mci_instance_attributes(mci); | 872 | edac_remove_mci_instance_attributes( |
873 | mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); | ||
845 | 874 | ||
846 | /* remove the symlink */ | 875 | /* remove the symlink */ |
847 | sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); | 876 | sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); |
@@ -875,8 +904,8 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) | |||
875 | debugf0("%s() remove_mci_instance\n", __func__); | 904 | debugf0("%s() remove_mci_instance\n", __func__); |
876 | 905 | ||
877 | /* remove this mci instance's attribtes */ | 906 | /* remove this mci instance's attribtes */ |
878 | edac_remove_mci_instance_attributes(mci); | 907 | edac_remove_mci_instance_attributes(mci->mc_driver_sysfs_attributes, |
879 | 908 | &mci->edac_mci_kobj); | |
880 | debugf0("%s() unregister this mci kobj\n", __func__); | 909 | debugf0("%s() unregister this mci kobj\n", __func__); |
881 | 910 | ||
882 | /* unregister this instance's kobject */ | 911 | /* unregister this instance's kobject */ |