diff options
| author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-21 10:08:06 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-11 12:23:41 -0400 |
| commit | 5c4cdb5ae72988ef93f72ad6f46be0e4eea5be8d (patch) | |
| tree | 209b4462654701012593482c7b10bdccdf6ef08b | |
| parent | c56087595fb6531f359925b581529f1b2aef10f1 (diff) | |
i7core_edac: convert it to use struct device
Instead of relying on a complex logic inside the edac core to create
a "device tree-like" sysfs struct, just use device_add.
Reviewed-by: Aristeu Rozanski <arozansk@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/edac/i7core_edac.c | 338 |
1 files changed, 209 insertions, 129 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 598d215f7bd5..ab3b84b906b9 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
| @@ -248,6 +248,8 @@ struct i7core_dev { | |||
| 248 | }; | 248 | }; |
| 249 | 249 | ||
| 250 | struct i7core_pvt { | 250 | struct i7core_pvt { |
| 251 | struct device addrmatch_dev, chancounts_dev; | ||
| 252 | |||
| 251 | struct pci_dev *pci_noncore; | 253 | struct pci_dev *pci_noncore; |
| 252 | struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; | 254 | struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; |
| 253 | struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; | 255 | struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; |
| @@ -662,6 +664,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 662 | Error insertion routines | 664 | Error insertion routines |
| 663 | ****************************************************************************/ | 665 | ****************************************************************************/ |
| 664 | 666 | ||
| 667 | #define to_mci(k) container_of(k, struct mem_ctl_info, dev) | ||
| 668 | |||
| 665 | /* The i7core has independent error injection features per channel. | 669 | /* The i7core has independent error injection features per channel. |
| 666 | However, to have a simpler code, we don't allow enabling error injection | 670 | However, to have a simpler code, we don't allow enabling error injection |
| 667 | on more than one channel. | 671 | on more than one channel. |
| @@ -691,9 +695,11 @@ static int disable_inject(const struct mem_ctl_info *mci) | |||
| 691 | * bit 0 - refers to the lower 32-byte half cacheline | 695 | * bit 0 - refers to the lower 32-byte half cacheline |
| 692 | * bit 1 - refers to the upper 32-byte half cacheline | 696 | * bit 1 - refers to the upper 32-byte half cacheline |
| 693 | */ | 697 | */ |
| 694 | static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, | 698 | static ssize_t i7core_inject_section_store(struct device *dev, |
| 699 | struct device_attribute *mattr, | ||
| 695 | const char *data, size_t count) | 700 | const char *data, size_t count) |
| 696 | { | 701 | { |
| 702 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 697 | struct i7core_pvt *pvt = mci->pvt_info; | 703 | struct i7core_pvt *pvt = mci->pvt_info; |
| 698 | unsigned long value; | 704 | unsigned long value; |
| 699 | int rc; | 705 | int rc; |
| @@ -709,9 +715,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, | |||
| 709 | return count; | 715 | return count; |
| 710 | } | 716 | } |
| 711 | 717 | ||
| 712 | static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, | 718 | static ssize_t i7core_inject_section_show(struct device *dev, |
| 713 | char *data) | 719 | struct device_attribute *mattr, |
| 720 | char *data) | ||
| 714 | { | 721 | { |
| 722 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 715 | struct i7core_pvt *pvt = mci->pvt_info; | 723 | struct i7core_pvt *pvt = mci->pvt_info; |
| 716 | return sprintf(data, "0x%08x\n", pvt->inject.section); | 724 | return sprintf(data, "0x%08x\n", pvt->inject.section); |
| 717 | } | 725 | } |
| @@ -724,10 +732,12 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, | |||
| 724 | * bit 1 - inject ECC error | 732 | * bit 1 - inject ECC error |
| 725 | * bit 2 - inject parity error | 733 | * bit 2 - inject parity error |
| 726 | */ | 734 | */ |
| 727 | static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, | 735 | static ssize_t i7core_inject_type_store(struct device *dev, |
| 736 | struct device_attribute *mattr, | ||
| 728 | const char *data, size_t count) | 737 | const char *data, size_t count) |
| 729 | { | 738 | { |
| 730 | struct i7core_pvt *pvt = mci->pvt_info; | 739 | struct mem_ctl_info *mci = to_mci(dev); |
| 740 | struct i7core_pvt *pvt = mci->pvt_info; | ||
| 731 | unsigned long value; | 741 | unsigned long value; |
| 732 | int rc; | 742 | int rc; |
| 733 | 743 | ||
| @@ -742,10 +752,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, | |||
| 742 | return count; | 752 | return count; |
| 743 | } | 753 | } |
| 744 | 754 | ||
| 745 | static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, | 755 | static ssize_t i7core_inject_type_show(struct device *dev, |
| 746 | char *data) | 756 | struct device_attribute *mattr, |
| 757 | char *data) | ||
| 747 | { | 758 | { |
| 759 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 748 | struct i7core_pvt *pvt = mci->pvt_info; | 760 | struct i7core_pvt *pvt = mci->pvt_info; |
| 761 | |||
| 749 | return sprintf(data, "0x%08x\n", pvt->inject.type); | 762 | return sprintf(data, "0x%08x\n", pvt->inject.type); |
| 750 | } | 763 | } |
| 751 | 764 | ||
| @@ -759,9 +772,11 @@ static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, | |||
| 759 | * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an | 772 | * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an |
| 760 | * uncorrectable error to be injected. | 773 | * uncorrectable error to be injected. |
| 761 | */ | 774 | */ |
| 762 | static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, | 775 | static ssize_t i7core_inject_eccmask_store(struct device *dev, |
| 763 | const char *data, size_t count) | 776 | struct device_attribute *mattr, |
| 777 | const char *data, size_t count) | ||
| 764 | { | 778 | { |
| 779 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 765 | struct i7core_pvt *pvt = mci->pvt_info; | 780 | struct i7core_pvt *pvt = mci->pvt_info; |
| 766 | unsigned long value; | 781 | unsigned long value; |
| 767 | int rc; | 782 | int rc; |
| @@ -777,10 +792,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, | |||
| 777 | return count; | 792 | return count; |
| 778 | } | 793 | } |
| 779 | 794 | ||
| 780 | static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, | 795 | static ssize_t i7core_inject_eccmask_show(struct device *dev, |
| 781 | char *data) | 796 | struct device_attribute *mattr, |
| 797 | char *data) | ||
| 782 | { | 798 | { |
| 799 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 783 | struct i7core_pvt *pvt = mci->pvt_info; | 800 | struct i7core_pvt *pvt = mci->pvt_info; |
| 801 | |||
| 784 | return sprintf(data, "0x%08x\n", pvt->inject.eccmask); | 802 | return sprintf(data, "0x%08x\n", pvt->inject.eccmask); |
| 785 | } | 803 | } |
| 786 | 804 | ||
| @@ -797,9 +815,11 @@ static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, | |||
| 797 | 815 | ||
| 798 | #define DECLARE_ADDR_MATCH(param, limit) \ | 816 | #define DECLARE_ADDR_MATCH(param, limit) \ |
| 799 | static ssize_t i7core_inject_store_##param( \ | 817 | static ssize_t i7core_inject_store_##param( \ |
| 800 | struct mem_ctl_info *mci, \ | 818 | struct device *dev, \ |
| 801 | const char *data, size_t count) \ | 819 | struct device_attribute *mattr, \ |
| 820 | const char *data, size_t count) \ | ||
| 802 | { \ | 821 | { \ |
| 822 | struct mem_ctl_info *mci = to_mci(dev); \ | ||
| 803 | struct i7core_pvt *pvt; \ | 823 | struct i7core_pvt *pvt; \ |
| 804 | long value; \ | 824 | long value; \ |
| 805 | int rc; \ | 825 | int rc; \ |
| @@ -824,9 +844,11 @@ static ssize_t i7core_inject_store_##param( \ | |||
| 824 | } \ | 844 | } \ |
| 825 | \ | 845 | \ |
| 826 | static ssize_t i7core_inject_show_##param( \ | 846 | static ssize_t i7core_inject_show_##param( \ |
| 827 | struct mem_ctl_info *mci, \ | 847 | struct device *dev, \ |
| 828 | char *data) \ | 848 | struct device_attribute *mattr, \ |
| 849 | char *data) \ | ||
| 829 | { \ | 850 | { \ |
| 851 | struct mem_ctl_info *mci = to_mci(dev); \ | ||
| 830 | struct i7core_pvt *pvt; \ | 852 | struct i7core_pvt *pvt; \ |
| 831 | \ | 853 | \ |
| 832 | pvt = mci->pvt_info; \ | 854 | pvt = mci->pvt_info; \ |
| @@ -838,14 +860,9 @@ static ssize_t i7core_inject_show_##param( \ | |||
| 838 | } | 860 | } |
| 839 | 861 | ||
| 840 | #define ATTR_ADDR_MATCH(param) \ | 862 | #define ATTR_ADDR_MATCH(param) \ |
| 841 | { \ | 863 | static DEVICE_ATTR(param, S_IRUGO | S_IWUSR, \ |
| 842 | .attr = { \ | 864 | i7core_inject_show_##param, \ |
| 843 | .name = #param, \ | 865 | i7core_inject_store_##param) |
| 844 | .mode = (S_IRUGO | S_IWUSR) \ | ||
| 845 | }, \ | ||
| 846 | .show = i7core_inject_show_##param, \ | ||
| 847 | .store = i7core_inject_store_##param, \ | ||
| 848 | } | ||
| 849 | 866 | ||
| 850 | DECLARE_ADDR_MATCH(channel, 3); | 867 | DECLARE_ADDR_MATCH(channel, 3); |
| 851 | DECLARE_ADDR_MATCH(dimm, 3); | 868 | DECLARE_ADDR_MATCH(dimm, 3); |
| @@ -854,6 +871,13 @@ DECLARE_ADDR_MATCH(bank, 32); | |||
| 854 | DECLARE_ADDR_MATCH(page, 0x10000); | 871 | DECLARE_ADDR_MATCH(page, 0x10000); |
| 855 | DECLARE_ADDR_MATCH(col, 0x4000); | 872 | DECLARE_ADDR_MATCH(col, 0x4000); |
| 856 | 873 | ||
| 874 | ATTR_ADDR_MATCH(channel); | ||
| 875 | ATTR_ADDR_MATCH(dimm); | ||
| 876 | ATTR_ADDR_MATCH(rank); | ||
| 877 | ATTR_ADDR_MATCH(bank); | ||
| 878 | ATTR_ADDR_MATCH(page); | ||
| 879 | ATTR_ADDR_MATCH(col); | ||
| 880 | |||
| 857 | static int write_and_test(struct pci_dev *dev, const int where, const u32 val) | 881 | static int write_and_test(struct pci_dev *dev, const int where, const u32 val) |
| 858 | { | 882 | { |
| 859 | u32 read; | 883 | u32 read; |
| @@ -899,9 +923,11 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val) | |||
| 899 | * is reliable enough to check if the MC is using the | 923 | * is reliable enough to check if the MC is using the |
| 900 | * three channels. However, this is not clear at the datasheet. | 924 | * three channels. However, this is not clear at the datasheet. |
| 901 | */ | 925 | */ |
| 902 | static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, | 926 | static ssize_t i7core_inject_enable_store(struct device *dev, |
| 903 | const char *data, size_t count) | 927 | struct device_attribute *mattr, |
| 928 | const char *data, size_t count) | ||
| 904 | { | 929 | { |
| 930 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 905 | struct i7core_pvt *pvt = mci->pvt_info; | 931 | struct i7core_pvt *pvt = mci->pvt_info; |
| 906 | u32 injectmask; | 932 | u32 injectmask; |
| 907 | u64 mask = 0; | 933 | u64 mask = 0; |
| @@ -1002,9 +1028,11 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, | |||
| 1002 | return count; | 1028 | return count; |
| 1003 | } | 1029 | } |
| 1004 | 1030 | ||
| 1005 | static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, | 1031 | static ssize_t i7core_inject_enable_show(struct device *dev, |
| 1006 | char *data) | 1032 | struct device_attribute *mattr, |
| 1033 | char *data) | ||
| 1007 | { | 1034 | { |
| 1035 | struct mem_ctl_info *mci = to_mci(dev); | ||
| 1008 | struct i7core_pvt *pvt = mci->pvt_info; | 1036 | struct i7core_pvt *pvt = mci->pvt_info; |
| 1009 | u32 injectmask; | 1037 | u32 injectmask; |
| 1010 | 1038 | ||
| @@ -1024,12 +1052,14 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, | |||
| 1024 | 1052 | ||
| 1025 | #define DECLARE_COUNTER(param) \ | 1053 | #define DECLARE_COUNTER(param) \ |
| 1026 | static ssize_t i7core_show_counter_##param( \ | 1054 | static ssize_t i7core_show_counter_##param( \ |
| 1027 | struct mem_ctl_info *mci, \ | 1055 | struct device *dev, \ |
| 1028 | char *data) \ | 1056 | struct device_attribute *mattr, \ |
| 1057 | char *data) \ | ||
| 1029 | { \ | 1058 | { \ |
| 1059 | struct mem_ctl_info *mci = to_mci(dev); \ | ||
| 1030 | struct i7core_pvt *pvt = mci->pvt_info; \ | 1060 | struct i7core_pvt *pvt = mci->pvt_info; \ |
| 1031 | \ | 1061 | \ |
| 1032 | debugf1("%s() \n", __func__); \ | 1062 | debugf1("%s()\n", __func__); \ |
| 1033 | if (!pvt->ce_count_available || (pvt->is_registered)) \ | 1063 | if (!pvt->ce_count_available || (pvt->is_registered)) \ |
| 1034 | return sprintf(data, "data unavailable\n"); \ | 1064 | return sprintf(data, "data unavailable\n"); \ |
| 1035 | return sprintf(data, "%lu\n", \ | 1065 | return sprintf(data, "%lu\n", \ |
| @@ -1037,121 +1067,167 @@ static ssize_t i7core_show_counter_##param( \ | |||
| 1037 | } | 1067 | } |
| 1038 | 1068 | ||
| 1039 | #define ATTR_COUNTER(param) \ | 1069 | #define ATTR_COUNTER(param) \ |
| 1040 | { \ | 1070 | static DEVICE_ATTR(udimm##param, S_IRUGO | S_IWUSR, \ |
| 1041 | .attr = { \ | 1071 | i7core_show_counter_##param, \ |
| 1042 | .name = __stringify(udimm##param), \ | 1072 | NULL) |
| 1043 | .mode = (S_IRUGO | S_IWUSR) \ | ||
| 1044 | }, \ | ||
| 1045 | .show = i7core_show_counter_##param \ | ||
| 1046 | } | ||
| 1047 | 1073 | ||
| 1048 | DECLARE_COUNTER(0); | 1074 | DECLARE_COUNTER(0); |
| 1049 | DECLARE_COUNTER(1); | 1075 | DECLARE_COUNTER(1); |
| 1050 | DECLARE_COUNTER(2); | 1076 | DECLARE_COUNTER(2); |
| 1051 | 1077 | ||
| 1078 | ATTR_COUNTER(0); | ||
| 1079 | ATTR_COUNTER(1); | ||
| 1080 | ATTR_COUNTER(2); | ||
| 1081 | |||
| 1052 | /* | 1082 | /* |
| 1053 | * Sysfs struct | 1083 | * inject_addrmatch device sysfs struct |
| 1054 | */ | 1084 | */ |
| 1055 | 1085 | ||
| 1056 | static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = { | 1086 | static struct attribute *i7core_addrmatch_attrs[] = { |
| 1057 | ATTR_ADDR_MATCH(channel), | 1087 | &dev_attr_channel.attr, |
| 1058 | ATTR_ADDR_MATCH(dimm), | 1088 | &dev_attr_dimm.attr, |
| 1059 | ATTR_ADDR_MATCH(rank), | 1089 | &dev_attr_rank.attr, |
| 1060 | ATTR_ADDR_MATCH(bank), | 1090 | &dev_attr_bank.attr, |
| 1061 | ATTR_ADDR_MATCH(page), | 1091 | &dev_attr_page.attr, |
| 1062 | ATTR_ADDR_MATCH(col), | 1092 | &dev_attr_col.attr, |
| 1063 | { } /* End of list */ | 1093 | NULL |
| 1064 | }; | 1094 | }; |
| 1065 | 1095 | ||
| 1066 | static const struct mcidev_sysfs_group i7core_inject_addrmatch = { | 1096 | static struct attribute_group addrmatch_grp = { |
| 1067 | .name = "inject_addrmatch", | 1097 | .attrs = i7core_addrmatch_attrs, |
| 1068 | .mcidev_attr = i7core_addrmatch_attrs, | ||
| 1069 | }; | 1098 | }; |
| 1070 | 1099 | ||
| 1071 | static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { | 1100 | static const struct attribute_group *addrmatch_groups[] = { |
| 1072 | ATTR_COUNTER(0), | 1101 | &addrmatch_grp, |
| 1073 | ATTR_COUNTER(1), | 1102 | NULL |
| 1074 | ATTR_COUNTER(2), | ||
| 1075 | { .attr = { .name = NULL } } | ||
| 1076 | }; | 1103 | }; |
| 1077 | 1104 | ||
| 1078 | static const struct mcidev_sysfs_group i7core_udimm_counters = { | 1105 | static void addrmatch_release(struct device *device) |
| 1079 | .name = "all_channel_counts", | 1106 | { |
| 1080 | .mcidev_attr = i7core_udimm_counters_attrs, | 1107 | debugf1("Releasing device %s\n", dev_name(device)); |
| 1108 | } | ||
| 1109 | |||
| 1110 | static struct device_type addrmatch_type = { | ||
| 1111 | .groups = addrmatch_groups, | ||
| 1112 | .release = addrmatch_release, | ||
| 1081 | }; | 1113 | }; |
| 1082 | 1114 | ||
| 1083 | static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = { | 1115 | /* |
| 1084 | { | 1116 | * all_channel_counts sysfs struct |
| 1085 | .attr = { | 1117 | */ |
| 1086 | .name = "inject_section", | 1118 | |
| 1087 | .mode = (S_IRUGO | S_IWUSR) | 1119 | static struct attribute *i7core_udimm_counters_attrs[] = { |
| 1088 | }, | 1120 | &dev_attr_udimm0.attr, |
| 1089 | .show = i7core_inject_section_show, | 1121 | &dev_attr_udimm1.attr, |
| 1090 | .store = i7core_inject_section_store, | 1122 | &dev_attr_udimm2.attr, |
| 1091 | }, { | 1123 | NULL |
| 1092 | .attr = { | 1124 | }; |
| 1093 | .name = "inject_type", | 1125 | |
| 1094 | .mode = (S_IRUGO | S_IWUSR) | 1126 | static struct attribute_group all_channel_counts_grp = { |
| 1095 | }, | 1127 | .attrs = i7core_udimm_counters_attrs, |
| 1096 | .show = i7core_inject_type_show, | ||
| 1097 | .store = i7core_inject_type_store, | ||
| 1098 | }, { | ||
| 1099 | .attr = { | ||
| 1100 | .name = "inject_eccmask", | ||
| 1101 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1102 | }, | ||
| 1103 | .show = i7core_inject_eccmask_show, | ||
| 1104 | .store = i7core_inject_eccmask_store, | ||
| 1105 | }, { | ||
| 1106 | .grp = &i7core_inject_addrmatch, | ||
| 1107 | }, { | ||
| 1108 | .attr = { | ||
| 1109 | .name = "inject_enable", | ||
| 1110 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1111 | }, | ||
| 1112 | .show = i7core_inject_enable_show, | ||
| 1113 | .store = i7core_inject_enable_store, | ||
| 1114 | }, | ||
| 1115 | { } /* End of list */ | ||
| 1116 | }; | 1128 | }; |
| 1117 | 1129 | ||
| 1118 | static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = { | 1130 | static const struct attribute_group *all_channel_counts_groups[] = { |
| 1119 | { | 1131 | &all_channel_counts_grp, |
| 1120 | .attr = { | 1132 | NULL |
| 1121 | .name = "inject_section", | ||
| 1122 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1123 | }, | ||
| 1124 | .show = i7core_inject_section_show, | ||
| 1125 | .store = i7core_inject_section_store, | ||
| 1126 | }, { | ||
| 1127 | .attr = { | ||
| 1128 | .name = "inject_type", | ||
| 1129 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1130 | }, | ||
| 1131 | .show = i7core_inject_type_show, | ||
| 1132 | .store = i7core_inject_type_store, | ||
| 1133 | }, { | ||
| 1134 | .attr = { | ||
| 1135 | .name = "inject_eccmask", | ||
| 1136 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1137 | }, | ||
| 1138 | .show = i7core_inject_eccmask_show, | ||
| 1139 | .store = i7core_inject_eccmask_store, | ||
| 1140 | }, { | ||
| 1141 | .grp = &i7core_inject_addrmatch, | ||
| 1142 | }, { | ||
| 1143 | .attr = { | ||
| 1144 | .name = "inject_enable", | ||
| 1145 | .mode = (S_IRUGO | S_IWUSR) | ||
| 1146 | }, | ||
| 1147 | .show = i7core_inject_enable_show, | ||
| 1148 | .store = i7core_inject_enable_store, | ||
| 1149 | }, { | ||
| 1150 | .grp = &i7core_udimm_counters, | ||
| 1151 | }, | ||
| 1152 | { } /* End of list */ | ||
| 1153 | }; | 1133 | }; |
| 1154 | 1134 | ||
| 1135 | static void all_channel_counts_release(struct device *device) | ||
| 1136 | { | ||
| 1137 | debugf1("Releasing device %s\n", dev_name(device)); | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | static struct device_type all_channel_counts_type = { | ||
| 1141 | .groups = all_channel_counts_groups, | ||
| 1142 | .release = all_channel_counts_release, | ||
| 1143 | }; | ||
| 1144 | |||
| 1145 | /* | ||
| 1146 | * inject sysfs attributes | ||
| 1147 | */ | ||
| 1148 | |||
| 1149 | static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, | ||
| 1150 | i7core_inject_section_show, i7core_inject_section_store); | ||
| 1151 | |||
| 1152 | static DEVICE_ATTR(inject_type, S_IRUGO | S_IWUSR, | ||
| 1153 | i7core_inject_type_show, i7core_inject_type_store); | ||
| 1154 | |||
| 1155 | |||
| 1156 | static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR, | ||
| 1157 | i7core_inject_eccmask_show, i7core_inject_eccmask_store); | ||
| 1158 | |||
| 1159 | static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR, | ||
| 1160 | i7core_inject_enable_show, i7core_inject_enable_store); | ||
| 1161 | |||
| 1162 | static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) | ||
| 1163 | { | ||
| 1164 | struct i7core_pvt *pvt = mci->pvt_info; | ||
| 1165 | int rc; | ||
| 1166 | |||
| 1167 | rc = device_create_file(&mci->dev, &dev_attr_inject_section); | ||
| 1168 | if (rc < 0) | ||
| 1169 | return rc; | ||
| 1170 | rc = device_create_file(&mci->dev, &dev_attr_inject_type); | ||
| 1171 | if (rc < 0) | ||
| 1172 | return rc; | ||
| 1173 | rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask); | ||
| 1174 | if (rc < 0) | ||
| 1175 | return rc; | ||
| 1176 | rc = device_create_file(&mci->dev, &dev_attr_inject_enable); | ||
| 1177 | if (rc < 0) | ||
| 1178 | return rc; | ||
| 1179 | |||
| 1180 | pvt->addrmatch_dev.type = &addrmatch_type; | ||
| 1181 | pvt->addrmatch_dev.bus = mci->dev.bus; | ||
| 1182 | device_initialize(&pvt->addrmatch_dev); | ||
| 1183 | pvt->addrmatch_dev.parent = &mci->dev; | ||
| 1184 | dev_set_name(&pvt->addrmatch_dev, "inject_addrmatch"); | ||
| 1185 | dev_set_drvdata(&pvt->addrmatch_dev, mci); | ||
| 1186 | |||
| 1187 | debugf1("%s(): creating %s\n", __func__, | ||
| 1188 | dev_name(&pvt->addrmatch_dev)); | ||
| 1189 | |||
| 1190 | rc = device_add(&pvt->addrmatch_dev); | ||
| 1191 | if (rc < 0) | ||
| 1192 | return rc; | ||
| 1193 | |||
| 1194 | if (!pvt->is_registered) { | ||
| 1195 | pvt->chancounts_dev.type = &all_channel_counts_type; | ||
| 1196 | pvt->chancounts_dev.bus = mci->dev.bus; | ||
| 1197 | device_initialize(&pvt->chancounts_dev); | ||
| 1198 | pvt->chancounts_dev.parent = &mci->dev; | ||
| 1199 | dev_set_name(&pvt->chancounts_dev, "all_channel_counts"); | ||
| 1200 | dev_set_drvdata(&pvt->chancounts_dev, mci); | ||
| 1201 | |||
| 1202 | debugf1("%s(): creating %s\n", __func__, | ||
| 1203 | dev_name(&pvt->chancounts_dev)); | ||
| 1204 | |||
| 1205 | rc = device_add(&pvt->chancounts_dev); | ||
| 1206 | if (rc < 0) | ||
| 1207 | return rc; | ||
| 1208 | } | ||
| 1209 | return 0; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) | ||
| 1213 | { | ||
| 1214 | struct i7core_pvt *pvt = mci->pvt_info; | ||
| 1215 | |||
| 1216 | debugf1("\n"); | ||
| 1217 | |||
| 1218 | device_remove_file(&mci->dev, &dev_attr_inject_section); | ||
| 1219 | device_remove_file(&mci->dev, &dev_attr_inject_type); | ||
| 1220 | device_remove_file(&mci->dev, &dev_attr_inject_eccmask); | ||
| 1221 | device_remove_file(&mci->dev, &dev_attr_inject_enable); | ||
| 1222 | |||
| 1223 | if (!pvt->is_registered) { | ||
| 1224 | put_device(&pvt->chancounts_dev); | ||
| 1225 | device_del(&pvt->chancounts_dev); | ||
| 1226 | } | ||
| 1227 | put_device(&pvt->addrmatch_dev); | ||
| 1228 | device_del(&pvt->addrmatch_dev); | ||
| 1229 | } | ||
| 1230 | |||
| 1155 | /**************************************************************************** | 1231 | /**************************************************************************** |
| 1156 | Device initialization routines: put/get, init/exit | 1232 | Device initialization routines: put/get, init/exit |
| 1157 | ****************************************************************************/ | 1233 | ****************************************************************************/ |
| @@ -2122,6 +2198,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) | |||
| 2122 | i7core_pci_ctl_release(pvt); | 2198 | i7core_pci_ctl_release(pvt); |
| 2123 | 2199 | ||
| 2124 | /* Remove MC sysfs nodes */ | 2200 | /* Remove MC sysfs nodes */ |
| 2201 | i7core_delete_sysfs_devices(mci); | ||
| 2125 | edac_mc_del_mc(mci->pdev); | 2202 | edac_mc_del_mc(mci->pdev); |
| 2126 | 2203 | ||
| 2127 | debugf1("%s: free mci struct\n", mci->ctl_name); | 2204 | debugf1("%s: free mci struct\n", mci->ctl_name); |
| @@ -2180,10 +2257,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) | |||
| 2180 | if (unlikely(rc < 0)) | 2257 | if (unlikely(rc < 0)) |
| 2181 | goto fail0; | 2258 | goto fail0; |
| 2182 | 2259 | ||
| 2183 | if (pvt->is_registered) | ||
| 2184 | mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs; | ||
| 2185 | else | ||
| 2186 | mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs; | ||
| 2187 | 2260 | ||
| 2188 | /* Get dimm basic config */ | 2261 | /* Get dimm basic config */ |
| 2189 | get_dimm_config(mci); | 2262 | get_dimm_config(mci); |
| @@ -2207,6 +2280,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) | |||
| 2207 | rc = -EINVAL; | 2280 | rc = -EINVAL; |
| 2208 | goto fail0; | 2281 | goto fail0; |
| 2209 | } | 2282 | } |
| 2283 | if (i7core_create_sysfs_devices(mci)) { | ||
| 2284 | debugf0("MC: " __FILE__ | ||
| 2285 | ": %s(): failed to create sysfs nodes\n", __func__); | ||
| 2286 | edac_mc_del_mc(mci->pdev); | ||
| 2287 | rc = -EINVAL; | ||
| 2288 | goto fail0; | ||
| 2289 | } | ||
| 2210 | 2290 | ||
| 2211 | /* Default error mask is any memory */ | 2291 | /* Default error mask is any memory */ |
| 2212 | pvt->inject.channel = 0; | 2292 | pvt->inject.channel = 0; |
