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