Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[firefly-linux-kernel-4.4.55.git] / drivers / edac / amd64_edac_inj.c
1 #include "amd64_edac.h"
2
3 static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
4 {
5         struct amd64_pvt *pvt = mci->pvt_info;
6         return sprintf(buf, "0x%x\n", pvt->injection.section);
7 }
8
9 /*
10  * store error injection section value which refers to one of 4 16-byte sections
11  * within a 64-byte cacheline
12  *
13  * range: 0..3
14  */
15 static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
16                                           const char *data, size_t count)
17 {
18         struct amd64_pvt *pvt = mci->pvt_info;
19         unsigned long value;
20         int ret = 0;
21
22         ret = strict_strtoul(data, 10, &value);
23         if (ret != -EINVAL) {
24
25                 if (value > 3) {
26                         amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
27                         return -EINVAL;
28                 }
29
30                 pvt->injection.section = (u32) value;
31                 return count;
32         }
33         return ret;
34 }
35
36 static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
37 {
38         struct amd64_pvt *pvt = mci->pvt_info;
39         return sprintf(buf, "0x%x\n", pvt->injection.word);
40 }
41
42 /*
43  * store error injection word value which refers to one of 9 16-bit word of the
44  * 16-byte (128-bit + ECC bits) section
45  *
46  * range: 0..8
47  */
48 static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
49                                         const char *data, size_t count)
50 {
51         struct amd64_pvt *pvt = mci->pvt_info;
52         unsigned long value;
53         int ret = 0;
54
55         ret = strict_strtoul(data, 10, &value);
56         if (ret != -EINVAL) {
57
58                 if (value > 8) {
59                         amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
60                         return -EINVAL;
61                 }
62
63                 pvt->injection.word = (u32) value;
64                 return count;
65         }
66         return ret;
67 }
68
69 static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
70 {
71         struct amd64_pvt *pvt = mci->pvt_info;
72         return sprintf(buf, "0x%x\n", pvt->injection.bit_map);
73 }
74
75 /*
76  * store 16 bit error injection vector which enables injecting errors to the
77  * corresponding bit within the error injection word above. When used during a
78  * DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
79  */
80 static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
81                                              const char *data, size_t count)
82 {
83         struct amd64_pvt *pvt = mci->pvt_info;
84         unsigned long value;
85         int ret = 0;
86
87         ret = strict_strtoul(data, 16, &value);
88         if (ret != -EINVAL) {
89
90                 if (value & 0xFFFF0000) {
91                         amd64_warn("%s: invalid EccVector: 0x%lx\n",
92                                    __func__, value);
93                         return -EINVAL;
94                 }
95
96                 pvt->injection.bit_map = (u32) value;
97                 return count;
98         }
99         return ret;
100 }
101
102 /*
103  * Do a DRAM ECC read. Assemble staged values in the pvt area, format into
104  * fields needed by the injection registers and read the NB Array Data Port.
105  */
106 static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
107                                         const char *data, size_t count)
108 {
109         struct amd64_pvt *pvt = mci->pvt_info;
110         unsigned long value;
111         u32 section, word_bits;
112         int ret = 0;
113
114         ret = strict_strtoul(data, 10, &value);
115         if (ret != -EINVAL) {
116
117                 /* Form value to choose 16-byte section of cacheline */
118                 section = F10_NB_ARRAY_DRAM_ECC |
119                                 SET_NB_ARRAY_ADDRESS(pvt->injection.section);
120                 pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
121
122                 word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
123                                                 pvt->injection.bit_map);
124
125                 /* Issue 'word' and 'bit' along with the READ request */
126                 pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
127
128                 debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
129
130                 return count;
131         }
132         return ret;
133 }
134
135 /*
136  * Do a DRAM ECC write. Assemble staged values in the pvt area and format into
137  * fields needed by the injection registers.
138  */
139 static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
140                                         const char *data, size_t count)
141 {
142         struct amd64_pvt *pvt = mci->pvt_info;
143         unsigned long value;
144         u32 section, word_bits;
145         int ret = 0;
146
147         ret = strict_strtoul(data, 10, &value);
148         if (ret != -EINVAL) {
149
150                 /* Form value to choose 16-byte section of cacheline */
151                 section = F10_NB_ARRAY_DRAM_ECC |
152                                 SET_NB_ARRAY_ADDRESS(pvt->injection.section);
153                 pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
154
155                 word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
156                                                 pvt->injection.bit_map);
157
158                 /* Issue 'word' and 'bit' along with the READ request */
159                 pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
160
161                 debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
162
163                 return count;
164         }
165         return ret;
166 }
167
168 /*
169  * update NUM_INJ_ATTRS in case you add new members
170  */
171 struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
172
173         {
174                 .attr = {
175                         .name = "inject_section",
176                         .mode = (S_IRUGO | S_IWUSR)
177                 },
178                 .show = amd64_inject_section_show,
179                 .store = amd64_inject_section_store,
180         },
181         {
182                 .attr = {
183                         .name = "inject_word",
184                         .mode = (S_IRUGO | S_IWUSR)
185                 },
186                 .show = amd64_inject_word_show,
187                 .store = amd64_inject_word_store,
188         },
189         {
190                 .attr = {
191                         .name = "inject_ecc_vector",
192                         .mode = (S_IRUGO | S_IWUSR)
193                 },
194                 .show = amd64_inject_ecc_vector_show,
195                 .store = amd64_inject_ecc_vector_store,
196         },
197         {
198                 .attr = {
199                         .name = "inject_write",
200                         .mode = (S_IRUGO | S_IWUSR)
201                 },
202                 .show = NULL,
203                 .store = amd64_inject_write_store,
204         },
205         {
206                 .attr = {
207                         .name = "inject_read",
208                         .mode = (S_IRUGO | S_IWUSR)
209                 },
210                 .show = NULL,
211                 .store = amd64_inject_read_store,
212         },
213 };