Blame view

drivers/edac/amd64_edac_inj.c 5 KB
eb919690b   Doug Thompson   amd64_edac: add D...
1
  #include "amd64_edac.h"
94baaee49   Borislav Petkov   amd64_edac: beef ...
2
3
4
5
6
7
  static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	return sprintf(buf, "0x%x
  ", pvt->injection.section);
  }
eb919690b   Doug Thompson   amd64_edac: add D...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /*
   * store error injection section value which refers to one of 4 16-byte sections
   * within a 64-byte cacheline
   *
   * range: 0..3
   */
  static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
  					  const char *data, size_t count)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	unsigned long value;
  	int ret = 0;
  
  	ret = strict_strtoul(data, 10, &value);
  	if (ret != -EINVAL) {
94baaee49   Borislav Petkov   amd64_edac: beef ...
23
24
  
  		if (value > 3) {
24f9a7fe3   Borislav Petkov   amd64_edac: Rewor...
25
26
  			amd64_warn("%s: invalid section 0x%lx
  ", __func__, value);
94baaee49   Borislav Petkov   amd64_edac: beef ...
27
28
  			return -EINVAL;
  		}
eb919690b   Doug Thompson   amd64_edac: add D...
29
30
31
32
33
  		pvt->injection.section = (u32) value;
  		return count;
  	}
  	return ret;
  }
94baaee49   Borislav Petkov   amd64_edac: beef ...
34
35
36
37
38
39
  static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	return sprintf(buf, "0x%x
  ", pvt->injection.word);
  }
eb919690b   Doug Thompson   amd64_edac: add D...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  /*
   * store error injection word value which refers to one of 9 16-bit word of the
   * 16-byte (128-bit + ECC bits) section
   *
   * range: 0..8
   */
  static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
  					const char *data, size_t count)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	unsigned long value;
  	int ret = 0;
  
  	ret = strict_strtoul(data, 10, &value);
  	if (ret != -EINVAL) {
94baaee49   Borislav Petkov   amd64_edac: beef ...
55
  		if (value > 8) {
24f9a7fe3   Borislav Petkov   amd64_edac: Rewor...
56
57
  			amd64_warn("%s: invalid word 0x%lx
  ", __func__, value);
94baaee49   Borislav Petkov   amd64_edac: beef ...
58
59
  			return -EINVAL;
  		}
eb919690b   Doug Thompson   amd64_edac: add D...
60

94baaee49   Borislav Petkov   amd64_edac: beef ...
61
  		pvt->injection.word = (u32) value;
eb919690b   Doug Thompson   amd64_edac: add D...
62
63
64
65
  		return count;
  	}
  	return ret;
  }
94baaee49   Borislav Petkov   amd64_edac: beef ...
66
67
68
69
70
71
  static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	return sprintf(buf, "0x%x
  ", pvt->injection.bit_map);
  }
eb919690b   Doug Thompson   amd64_edac: add D...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  /*
   * store 16 bit error injection vector which enables injecting errors to the
   * corresponding bit within the error injection word above. When used during a
   * DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
   */
  static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
  					     const char *data, size_t count)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	unsigned long value;
  	int ret = 0;
  
  	ret = strict_strtoul(data, 16, &value);
  	if (ret != -EINVAL) {
94baaee49   Borislav Petkov   amd64_edac: beef ...
86
  		if (value & 0xFFFF0000) {
24f9a7fe3   Borislav Petkov   amd64_edac: Rewor...
87
88
89
  			amd64_warn("%s: invalid EccVector: 0x%lx
  ",
  				   __func__, value);
94baaee49   Borislav Petkov   amd64_edac: beef ...
90
91
  			return -EINVAL;
  		}
eb919690b   Doug Thompson   amd64_edac: add D...
92

94baaee49   Borislav Petkov   amd64_edac: beef ...
93
  		pvt->injection.bit_map = (u32) value;
eb919690b   Doug Thompson   amd64_edac: add D...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  		return count;
  	}
  	return ret;
  }
  
  /*
   * Do a DRAM ECC read. Assemble staged values in the pvt area, format into
   * fields needed by the injection registers and read the NB Array Data Port.
   */
  static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
  					const char *data, size_t count)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	unsigned long value;
  	u32 section, word_bits;
  	int ret = 0;
  
  	ret = strict_strtoul(data, 10, &value);
  	if (ret != -EINVAL) {
  
  		/* Form value to choose 16-byte section of cacheline */
  		section = F10_NB_ARRAY_DRAM_ECC |
  				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
b2b0c6054   Borislav Petkov   amd64_edac: Add s...
117
  		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
eb919690b   Doug Thompson   amd64_edac: add D...
118
119
120
121
122
  
  		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
  						pvt->injection.bit_map);
  
  		/* Issue 'word' and 'bit' along with the READ request */
b2b0c6054   Borislav Petkov   amd64_edac: Add s...
123
  		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
eb919690b   Doug Thompson   amd64_edac: add D...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  
  		debugf0("section=0x%x word_bits=0x%x
  ", section, word_bits);
  
  		return count;
  	}
  	return ret;
  }
  
  /*
   * Do a DRAM ECC write. Assemble staged values in the pvt area and format into
   * fields needed by the injection registers.
   */
  static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
  					const char *data, size_t count)
  {
  	struct amd64_pvt *pvt = mci->pvt_info;
  	unsigned long value;
  	u32 section, word_bits;
  	int ret = 0;
  
  	ret = strict_strtoul(data, 10, &value);
  	if (ret != -EINVAL) {
  
  		/* Form value to choose 16-byte section of cacheline */
  		section = F10_NB_ARRAY_DRAM_ECC |
  				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
b2b0c6054   Borislav Petkov   amd64_edac: Add s...
151
  		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
eb919690b   Doug Thompson   amd64_edac: add D...
152
153
154
155
156
  
  		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
  						pvt->injection.bit_map);
  
  		/* Issue 'word' and 'bit' along with the READ request */
b2b0c6054   Borislav Petkov   amd64_edac: Add s...
157
  		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
eb919690b   Doug Thompson   amd64_edac: add D...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  
  		debugf0("section=0x%x word_bits=0x%x
  ", section, word_bits);
  
  		return count;
  	}
  	return ret;
  }
  
  /*
   * update NUM_INJ_ATTRS in case you add new members
   */
  struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
  
  	{
  		.attr = {
  			.name = "inject_section",
  			.mode = (S_IRUGO | S_IWUSR)
  		},
94baaee49   Borislav Petkov   amd64_edac: beef ...
177
  		.show = amd64_inject_section_show,
eb919690b   Doug Thompson   amd64_edac: add D...
178
179
180
181
182
183
184
  		.store = amd64_inject_section_store,
  	},
  	{
  		.attr = {
  			.name = "inject_word",
  			.mode = (S_IRUGO | S_IWUSR)
  		},
94baaee49   Borislav Petkov   amd64_edac: beef ...
185
  		.show = amd64_inject_word_show,
eb919690b   Doug Thompson   amd64_edac: add D...
186
187
188
189
190
191
192
  		.store = amd64_inject_word_store,
  	},
  	{
  		.attr = {
  			.name = "inject_ecc_vector",
  			.mode = (S_IRUGO | S_IWUSR)
  		},
94baaee49   Borislav Petkov   amd64_edac: beef ...
193
  		.show = amd64_inject_ecc_vector_show,
eb919690b   Doug Thompson   amd64_edac: add D...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  		.store = amd64_inject_ecc_vector_store,
  	},
  	{
  		.attr = {
  			.name = "inject_write",
  			.mode = (S_IRUGO | S_IWUSR)
  		},
  		.show = NULL,
  		.store = amd64_inject_write_store,
  	},
  	{
  		.attr = {
  			.name = "inject_read",
  			.mode = (S_IRUGO | S_IWUSR)
  		},
  		.show = NULL,
  		.store = amd64_inject_read_store,
  	},
  };