diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-25 12:42:25 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-10 10:49:30 -0400 |
commit | b968759ee7102f86fec5f3349f7a8ab4556884a3 (patch) | |
tree | dcea622a061de20fee0e64b8224e323a1fa5b4b1 /drivers/edac | |
parent | 35be95446734cbb10b088a6b38269ac4a8ac3a86 (diff) |
edac: Create an unique instance for each kobj
Current code only works when there's just one memory
controller, since we need one kobj for each instance.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/edac_core.h | 21 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 75 |
2 files changed, 64 insertions, 32 deletions
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 02bbbc9696d9..efca9343d26a 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -342,23 +342,29 @@ struct csrow_info { | |||
342 | }; | 342 | }; |
343 | 343 | ||
344 | struct mcidev_sysfs_group { | 344 | struct mcidev_sysfs_group { |
345 | const char *name; | 345 | const char *name; /* group name */ |
346 | struct mcidev_sysfs_attribute *mcidev_attr; | 346 | struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ |
347 | struct kobject kobj; | 347 | }; |
348 | |||
349 | struct mcidev_sysfs_group_kobj { | ||
350 | struct list_head list; /* list for all instances within a mc */ | ||
351 | |||
352 | struct kobject kobj; /* kobj for the group */ | ||
348 | 353 | ||
354 | struct mcidev_sysfs_group *grp; /* group description table */ | ||
349 | struct mem_ctl_info *mci; /* the parent */ | 355 | struct mem_ctl_info *mci; /* the parent */ |
350 | }; | 356 | }; |
351 | 357 | ||
352 | |||
353 | /* mcidev_sysfs_attribute structure | 358 | /* mcidev_sysfs_attribute structure |
354 | * used for driver sysfs attributes and in mem_ctl_info | 359 | * used for driver sysfs attributes and in mem_ctl_info |
355 | * sysfs top level entries | 360 | * sysfs top level entries |
356 | */ | 361 | */ |
357 | struct mcidev_sysfs_attribute { | 362 | struct mcidev_sysfs_attribute { |
363 | /* It should use either attr or grp */ | ||
358 | struct attribute attr; | 364 | struct attribute attr; |
365 | struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ | ||
359 | 366 | ||
360 | struct mcidev_sysfs_group *grp; | 367 | /* Ops for show/store values at the attribute - not used on group */ |
361 | |||
362 | ssize_t (*show)(struct mem_ctl_info *,char *); | 368 | ssize_t (*show)(struct mem_ctl_info *,char *); |
363 | ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); | 369 | ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); |
364 | }; | 370 | }; |
@@ -436,6 +442,9 @@ struct mem_ctl_info { | |||
436 | /* edac sysfs device control */ | 442 | /* edac sysfs device control */ |
437 | struct kobject edac_mci_kobj; | 443 | struct kobject edac_mci_kobj; |
438 | 444 | ||
445 | /* list for all grp instances within a mc */ | ||
446 | struct list_head grp_kobj_list; | ||
447 | |||
439 | /* Additional top controller level attributes, but specified | 448 | /* Additional top controller level attributes, but specified |
440 | * by the low level driver. | 449 | * by the low level driver. |
441 | * | 450 | * |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index f689d7d6ab46..c200c2fd43ea 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -730,7 +730,7 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci) | |||
730 | 730 | ||
731 | #define EDAC_DEVICE_SYMLINK "device" | 731 | #define EDAC_DEVICE_SYMLINK "device" |
732 | 732 | ||
733 | #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group, kobj)->mci) | 733 | #define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci) |
734 | 734 | ||
735 | /* MCI show/store functions for top most object */ | 735 | /* MCI show/store functions for top most object */ |
736 | static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, | 736 | static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, |
@@ -764,12 +764,12 @@ static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr, | |||
764 | /* No memory to release for this kobj */ | 764 | /* No memory to release for this kobj */ |
765 | static void edac_inst_grp_release(struct kobject *kobj) | 765 | static void edac_inst_grp_release(struct kobject *kobj) |
766 | { | 766 | { |
767 | struct mcidev_sysfs_group *grp; | 767 | struct mcidev_sysfs_group_kobj *grp; |
768 | struct mem_ctl_info *mci; | 768 | struct mem_ctl_info *mci; |
769 | 769 | ||
770 | debugf1("%s()\n", __func__); | 770 | debugf1("%s()\n", __func__); |
771 | 771 | ||
772 | grp = container_of(kobj, struct mcidev_sysfs_group, kobj); | 772 | grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj); |
773 | mci = grp->mci; | 773 | mci = grp->mci; |
774 | 774 | ||
775 | kobject_put(&mci->edac_mci_kobj); | 775 | kobject_put(&mci->edac_mci_kobj); |
@@ -804,22 +804,30 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, | |||
804 | 804 | ||
805 | while (sysfs_attrib) { | 805 | while (sysfs_attrib) { |
806 | if (sysfs_attrib->grp) { | 806 | if (sysfs_attrib->grp) { |
807 | struct kobject *newkobj = &sysfs_attrib->grp->kobj; | 807 | struct mcidev_sysfs_group_kobj *grp_kobj; |
808 | |||
809 | grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL); | ||
810 | if (!grp_kobj) | ||
811 | return -ENOMEM; | ||
812 | |||
813 | list_add_tail(&grp_kobj->list, &mci->grp_kobj_list); | ||
814 | |||
815 | grp_kobj->grp = sysfs_attrib->grp; | ||
816 | grp_kobj->mci = mci; | ||
808 | 817 | ||
809 | debugf0("%s() grp %s, mci %p\n", __func__, | 818 | debugf0("%s() grp %s, mci %p\n", __func__, |
810 | sysfs_attrib->grp->name, mci); | 819 | sysfs_attrib->grp->name, mci); |
811 | 820 | ||
812 | sysfs_attrib->grp->mci = mci; | 821 | err = kobject_init_and_add(&grp_kobj->kobj, |
813 | 822 | &ktype_inst_grp, | |
814 | err = kobject_init_and_add(newkobj, &ktype_inst_grp, | ||
815 | &mci->edac_mci_kobj, | 823 | &mci->edac_mci_kobj, |
816 | sysfs_attrib->grp->name); | 824 | sysfs_attrib->grp->name); |
817 | if (err) | 825 | if (err) |
818 | return err; | 826 | return err; |
819 | 827 | ||
820 | err = edac_create_mci_instance_attributes(mci, | 828 | err = edac_create_mci_instance_attributes(mci, |
821 | sysfs_attrib->grp->mcidev_attr, | 829 | grp_kobj->grp->mcidev_attr, |
822 | newkobj); | 830 | &grp_kobj->kobj); |
823 | 831 | ||
824 | if (err) | 832 | if (err) |
825 | return err; | 833 | return err; |
@@ -845,25 +853,27 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, | |||
845 | * remove MC driver specific attributes at the topmost level | 853 | * remove MC driver specific attributes at the topmost level |
846 | * directory of this mci instance. | 854 | * directory of this mci instance. |
847 | */ | 855 | */ |
848 | static void edac_remove_mci_instance_attributes( | 856 | static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, |
849 | struct mcidev_sysfs_attribute *sysfs_attrib, | 857 | struct mcidev_sysfs_attribute *sysfs_attrib, |
850 | struct kobject *kobj) | 858 | struct kobject *kobj, int count) |
851 | { | 859 | { |
860 | struct mcidev_sysfs_group_kobj *grp_kobj, *tmp; | ||
861 | |||
852 | debugf1("%s()\n", __func__); | 862 | debugf1("%s()\n", __func__); |
853 | 863 | ||
854 | /* loop if there are attributes and until we hit a NULL entry */ | 864 | /* |
865 | * loop if there are attributes and until we hit a NULL entry | ||
866 | * Remove first all the atributes | ||
867 | */ | ||
855 | while (sysfs_attrib) { | 868 | while (sysfs_attrib) { |
856 | if (sysfs_attrib->grp) { | 869 | if (sysfs_attrib->grp) { |
857 | struct kobject *newkobj = &sysfs_attrib->grp->kobj; | 870 | list_for_each_entry(grp_kobj, &mci->grp_kobj_list, |
858 | 871 | list) | |
859 | debugf0("%s() grp %s\n", __func__, | 872 | if (grp_kobj->grp == sysfs_attrib->grp) |
860 | sysfs_attrib->grp->name); | 873 | edac_remove_mci_instance_attributes(mci, |
861 | 874 | grp_kobj->grp->mcidev_attr, | |
862 | edac_remove_mci_instance_attributes( | 875 | &grp_kobj->kobj, count + 1); |
863 | sysfs_attrib->grp->mcidev_attr, newkobj); | 876 | } else if (sysfs_attrib->attr.name) { |
864 | |||
865 | kobject_put(newkobj); | ||
866 | } else if (sysfs_attrib->attr.name) { | ||
867 | debugf0("%s() file %s\n", __func__, | 877 | debugf0("%s() file %s\n", __func__, |
868 | sysfs_attrib->attr.name); | 878 | sysfs_attrib->attr.name); |
869 | sysfs_remove_file(kobj, &sysfs_attrib->attr); | 879 | sysfs_remove_file(kobj, &sysfs_attrib->attr); |
@@ -871,6 +881,16 @@ static void edac_remove_mci_instance_attributes( | |||
871 | break; | 881 | break; |
872 | sysfs_attrib++; | 882 | sysfs_attrib++; |
873 | } | 883 | } |
884 | |||
885 | /* | ||
886 | * Now that all attributes got removed, it is save to remove all groups | ||
887 | */ | ||
888 | if (!count) | ||
889 | list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list, | ||
890 | list) { | ||
891 | debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name); | ||
892 | kobject_put(&grp_kobj->kobj); | ||
893 | } | ||
874 | } | 894 | } |
875 | 895 | ||
876 | 896 | ||
@@ -891,6 +911,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) | |||
891 | 911 | ||
892 | debugf0("%s() idx=%d\n", __func__, mci->mc_idx); | 912 | debugf0("%s() idx=%d\n", __func__, mci->mc_idx); |
893 | 913 | ||
914 | INIT_LIST_HEAD(&mci->grp_kobj_list); | ||
915 | |||
894 | /* create a symlink for the device */ | 916 | /* create a symlink for the device */ |
895 | err = sysfs_create_link(kobj_mci, &mci->dev->kobj, | 917 | err = sysfs_create_link(kobj_mci, &mci->dev->kobj, |
896 | EDAC_DEVICE_SYMLINK); | 918 | EDAC_DEVICE_SYMLINK); |
@@ -940,8 +962,8 @@ fail1: | |||
940 | } | 962 | } |
941 | 963 | ||
942 | /* remove the mci instance's attributes, if any */ | 964 | /* remove the mci instance's attributes, if any */ |
943 | edac_remove_mci_instance_attributes( | 965 | edac_remove_mci_instance_attributes(mci, |
944 | mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj); | 966 | mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); |
945 | 967 | ||
946 | /* remove the symlink */ | 968 | /* remove the symlink */ |
947 | sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); | 969 | sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); |
@@ -975,8 +997,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) | |||
975 | debugf0("%s() remove_mci_instance\n", __func__); | 997 | debugf0("%s() remove_mci_instance\n", __func__); |
976 | 998 | ||
977 | /* remove this mci instance's attribtes */ | 999 | /* remove this mci instance's attribtes */ |
978 | edac_remove_mci_instance_attributes(mci->mc_driver_sysfs_attributes, | 1000 | edac_remove_mci_instance_attributes(mci, |
979 | &mci->edac_mci_kobj); | 1001 | mci->mc_driver_sysfs_attributes, |
1002 | &mci->edac_mci_kobj, 0); | ||
980 | debugf0("%s() unregister this mci kobj\n", __func__); | 1003 | debugf0("%s() unregister this mci kobj\n", __func__); |
981 | 1004 | ||
982 | /* unregister this instance's kobject */ | 1005 | /* unregister this instance's kobject */ |