1 #include "amd64_edac.h"
3 static ssize_t
amd64_inject_section_show(struct device
*dev
,
4 struct device_attribute
*mattr
,
7 struct mem_ctl_info
*mci
= to_mci(dev
);
8 struct amd64_pvt
*pvt
= mci
->pvt_info
;
9 return sprintf(buf
, "0x%x\n", pvt
->injection
.section
);
13 * store error injection section value which refers to one of 4 16-byte sections
14 * within a 64-byte cacheline
18 static ssize_t
amd64_inject_section_store(struct device
*dev
,
19 struct device_attribute
*mattr
,
20 const char *data
, size_t count
)
22 struct mem_ctl_info
*mci
= to_mci(dev
);
23 struct amd64_pvt
*pvt
= mci
->pvt_info
;
27 ret
= kstrtoul(data
, 10, &value
);
32 amd64_warn("%s: invalid section 0x%lx\n", __func__
, value
);
36 pvt
->injection
.section
= (u32
) value
;
40 static ssize_t
amd64_inject_word_show(struct device
*dev
,
41 struct device_attribute
*mattr
,
44 struct mem_ctl_info
*mci
= to_mci(dev
);
45 struct amd64_pvt
*pvt
= mci
->pvt_info
;
46 return sprintf(buf
, "0x%x\n", pvt
->injection
.word
);
50 * store error injection word value which refers to one of 9 16-bit word of the
51 * 16-byte (128-bit + ECC bits) section
55 static ssize_t
amd64_inject_word_store(struct device
*dev
,
56 struct device_attribute
*mattr
,
57 const char *data
, size_t count
)
59 struct mem_ctl_info
*mci
= to_mci(dev
);
60 struct amd64_pvt
*pvt
= mci
->pvt_info
;
64 ret
= kstrtoul(data
, 10, &value
);
69 amd64_warn("%s: invalid word 0x%lx\n", __func__
, value
);
73 pvt
->injection
.word
= (u32
) value
;
77 static ssize_t
amd64_inject_ecc_vector_show(struct device
*dev
,
78 struct device_attribute
*mattr
,
81 struct mem_ctl_info
*mci
= to_mci(dev
);
82 struct amd64_pvt
*pvt
= mci
->pvt_info
;
83 return sprintf(buf
, "0x%x\n", pvt
->injection
.bit_map
);
87 * store 16 bit error injection vector which enables injecting errors to the
88 * corresponding bit within the error injection word above. When used during a
89 * DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
91 static ssize_t
amd64_inject_ecc_vector_store(struct device
*dev
,
92 struct device_attribute
*mattr
,
93 const char *data
, size_t count
)
95 struct mem_ctl_info
*mci
= to_mci(dev
);
96 struct amd64_pvt
*pvt
= mci
->pvt_info
;
100 ret
= kstrtoul(data
, 16, &value
);
104 if (value
& 0xFFFF0000) {
105 amd64_warn("%s: invalid EccVector: 0x%lx\n", __func__
, value
);
109 pvt
->injection
.bit_map
= (u32
) value
;
114 * Do a DRAM ECC read. Assemble staged values in the pvt area, format into
115 * fields needed by the injection registers and read the NB Array Data Port.
117 static ssize_t
amd64_inject_read_store(struct device
*dev
,
118 struct device_attribute
*mattr
,
119 const char *data
, size_t count
)
121 struct mem_ctl_info
*mci
= to_mci(dev
);
122 struct amd64_pvt
*pvt
= mci
->pvt_info
;
124 u32 section
, word_bits
;
127 ret
= kstrtoul(data
, 10, &value
);
131 /* Form value to choose 16-byte section of cacheline */
132 section
= F10_NB_ARRAY_DRAM
| SET_NB_ARRAY_ADDR(pvt
->injection
.section
);
134 amd64_write_pci_cfg(pvt
->F3
, F10_NB_ARRAY_ADDR
, section
);
136 word_bits
= SET_NB_DRAM_INJECTION_READ(pvt
->injection
);
138 /* Issue 'word' and 'bit' along with the READ request */
139 amd64_write_pci_cfg(pvt
->F3
, F10_NB_ARRAY_DATA
, word_bits
);
141 edac_dbg(0, "section=0x%x word_bits=0x%x\n", section
, word_bits
);
147 * Do a DRAM ECC write. Assemble staged values in the pvt area and format into
148 * fields needed by the injection registers.
150 static ssize_t
amd64_inject_write_store(struct device
*dev
,
151 struct device_attribute
*mattr
,
152 const char *data
, size_t count
)
154 struct mem_ctl_info
*mci
= to_mci(dev
);
155 struct amd64_pvt
*pvt
= mci
->pvt_info
;
156 u32 section
, word_bits
, tmp
;
160 ret
= kstrtoul(data
, 10, &value
);
164 /* Form value to choose 16-byte section of cacheline */
165 section
= F10_NB_ARRAY_DRAM
| SET_NB_ARRAY_ADDR(pvt
->injection
.section
);
167 amd64_write_pci_cfg(pvt
->F3
, F10_NB_ARRAY_ADDR
, section
);
169 word_bits
= SET_NB_DRAM_INJECTION_WRITE(pvt
->injection
);
171 pr_notice_once("Don't forget to decrease MCE polling interval in\n"
172 "/sys/bus/machinecheck/devices/machinecheck<CPUNUM>/check_interval\n"
173 "so that you can get the error report faster.\n");
175 on_each_cpu(disable_caches
, NULL
, 1);
177 /* Issue 'word' and 'bit' along with the READ request */
178 amd64_write_pci_cfg(pvt
->F3
, F10_NB_ARRAY_DATA
, word_bits
);
181 /* wait until injection happens */
182 amd64_read_pci_cfg(pvt
->F3
, F10_NB_ARRAY_DATA
, &tmp
);
183 if (tmp
& F10_NB_ARR_ECC_WR_REQ
) {
188 on_each_cpu(enable_caches
, NULL
, 1);
190 edac_dbg(0, "section=0x%x word_bits=0x%x\n", section
, word_bits
);
196 * update NUM_INJ_ATTRS in case you add new members
199 static DEVICE_ATTR(inject_section
, S_IRUGO
| S_IWUSR
,
200 amd64_inject_section_show
, amd64_inject_section_store
);
201 static DEVICE_ATTR(inject_word
, S_IRUGO
| S_IWUSR
,
202 amd64_inject_word_show
, amd64_inject_word_store
);
203 static DEVICE_ATTR(inject_ecc_vector
, S_IRUGO
| S_IWUSR
,
204 amd64_inject_ecc_vector_show
, amd64_inject_ecc_vector_store
);
205 static DEVICE_ATTR(inject_write
, S_IWUSR
,
206 NULL
, amd64_inject_write_store
);
207 static DEVICE_ATTR(inject_read
, S_IWUSR
,
208 NULL
, amd64_inject_read_store
);
211 int amd64_create_sysfs_inject_files(struct mem_ctl_info
*mci
)
215 rc
= device_create_file(&mci
->dev
, &dev_attr_inject_section
);
218 rc
= device_create_file(&mci
->dev
, &dev_attr_inject_word
);
221 rc
= device_create_file(&mci
->dev
, &dev_attr_inject_ecc_vector
);
224 rc
= device_create_file(&mci
->dev
, &dev_attr_inject_write
);
227 rc
= device_create_file(&mci
->dev
, &dev_attr_inject_read
);
234 void amd64_remove_sysfs_inject_files(struct mem_ctl_info
*mci
)
236 device_remove_file(&mci
->dev
, &dev_attr_inject_section
);
237 device_remove_file(&mci
->dev
, &dev_attr_inject_word
);
238 device_remove_file(&mci
->dev
, &dev_attr_inject_ecc_vector
);
239 device_remove_file(&mci
->dev
, &dev_attr_inject_write
);
240 device_remove_file(&mci
->dev
, &dev_attr_inject_read
);