Branch data Line data Source code
1 : : /*
2 : : * edac_mc kernel module
3 : : * (C) 2005, 2006 Linux Networx (http://lnxi.com)
4 : : * This file may be distributed under the terms of the
5 : : * GNU General Public License.
6 : : *
7 : : * Written by Thayne Harbaugh
8 : : * Based on work by Dan Hollis <goemon at anime dot net> and others.
9 : : * http://www.anime.net/~goemon/linux-ecc/
10 : : *
11 : : * Modified by Dave Peterson and Doug Thompson
12 : : *
13 : : */
14 : :
15 : : #include <linux/module.h>
16 : : #include <linux/proc_fs.h>
17 : : #include <linux/kernel.h>
18 : : #include <linux/types.h>
19 : : #include <linux/smp.h>
20 : : #include <linux/init.h>
21 : : #include <linux/sysctl.h>
22 : : #include <linux/highmem.h>
23 : : #include <linux/timer.h>
24 : : #include <linux/slab.h>
25 : : #include <linux/jiffies.h>
26 : : #include <linux/spinlock.h>
27 : : #include <linux/list.h>
28 : : #include <linux/ctype.h>
29 : : #include <linux/edac.h>
30 : : #include <linux/bitops.h>
31 : : #include <linux/uaccess.h>
32 : : #include <asm/page.h>
33 : : #include "edac_mc.h"
34 : : #include "edac_module.h"
35 : : #include <ras/ras_event.h>
36 : :
37 : : #ifdef CONFIG_EDAC_ATOMIC_SCRUB
38 : : #include <asm/edac.h>
39 : : #else
40 : : #define edac_atomic_scrub(va, size) do { } while (0)
41 : : #endif
42 : :
43 : : int edac_op_state = EDAC_OPSTATE_INVAL;
44 : : EXPORT_SYMBOL_GPL(edac_op_state);
45 : :
46 : : static int edac_report = EDAC_REPORTING_ENABLED;
47 : :
48 : : /* lock to memory controller's control array */
49 : : static DEFINE_MUTEX(mem_ctls_mutex);
50 : : static LIST_HEAD(mc_devices);
51 : :
52 : : /*
53 : : * Used to lock EDAC MC to just one module, avoiding two drivers e. g.
54 : : * apei/ghes and i7core_edac to be used at the same time.
55 : : */
56 : : static const char *edac_mc_owner;
57 : :
58 : 0 : int edac_get_report_status(void)
59 : : {
60 : 0 : return edac_report;
61 : : }
62 : : EXPORT_SYMBOL_GPL(edac_get_report_status);
63 : :
64 : 0 : void edac_set_report_status(int new)
65 : : {
66 : 0 : if (new == EDAC_REPORTING_ENABLED ||
67 [ # # ]: 0 : new == EDAC_REPORTING_DISABLED ||
68 : : new == EDAC_REPORTING_FORCE)
69 : 0 : edac_report = new;
70 : 0 : }
71 : : EXPORT_SYMBOL_GPL(edac_set_report_status);
72 : :
73 : 0 : static int edac_report_set(const char *str, const struct kernel_param *kp)
74 : : {
75 [ # # ]: 0 : if (!str)
76 : : return -EINVAL;
77 : :
78 [ # # ]: 0 : if (!strncmp(str, "on", 2))
79 : 0 : edac_report = EDAC_REPORTING_ENABLED;
80 [ # # ]: 0 : else if (!strncmp(str, "off", 3))
81 : 0 : edac_report = EDAC_REPORTING_DISABLED;
82 [ # # ]: 0 : else if (!strncmp(str, "force", 5))
83 : 0 : edac_report = EDAC_REPORTING_FORCE;
84 : :
85 : : return 0;
86 : : }
87 : :
88 : 0 : static int edac_report_get(char *buffer, const struct kernel_param *kp)
89 : : {
90 : 0 : int ret = 0;
91 : :
92 [ # # # # ]: 0 : switch (edac_report) {
93 : 0 : case EDAC_REPORTING_ENABLED:
94 : 0 : ret = sprintf(buffer, "on");
95 : 0 : break;
96 : 0 : case EDAC_REPORTING_DISABLED:
97 : 0 : ret = sprintf(buffer, "off");
98 : 0 : break;
99 : 0 : case EDAC_REPORTING_FORCE:
100 : 0 : ret = sprintf(buffer, "force");
101 : 0 : break;
102 : : default:
103 : : ret = -EINVAL;
104 : : break;
105 : : }
106 : :
107 : 0 : return ret;
108 : : }
109 : :
110 : : static const struct kernel_param_ops edac_report_ops = {
111 : : .set = edac_report_set,
112 : : .get = edac_report_get,
113 : : };
114 : :
115 : : module_param_cb(edac_report, &edac_report_ops, &edac_report, 0644);
116 : :
117 : 0 : unsigned int edac_dimm_info_location(struct dimm_info *dimm, char *buf,
118 : : unsigned int len)
119 : : {
120 : 0 : struct mem_ctl_info *mci = dimm->mci;
121 : 0 : int i, n, count = 0;
122 : 0 : char *p = buf;
123 : :
124 [ # # ]: 0 : for (i = 0; i < mci->n_layers; i++) {
125 : 0 : n = snprintf(p, len, "%s %d ",
126 : 0 : edac_layer_name[mci->layers[i].type],
127 : : dimm->location[i]);
128 : 0 : p += n;
129 : 0 : len -= n;
130 : 0 : count += n;
131 [ # # ]: 0 : if (!len)
132 : : break;
133 : : }
134 : :
135 : 0 : return count;
136 : : }
137 : :
138 : : #ifdef CONFIG_EDAC_DEBUG
139 : :
140 : : static void edac_mc_dump_channel(struct rank_info *chan)
141 : : {
142 : : edac_dbg(4, " channel->chan_idx = %d\n", chan->chan_idx);
143 : : edac_dbg(4, " channel = %p\n", chan);
144 : : edac_dbg(4, " channel->csrow = %p\n", chan->csrow);
145 : : edac_dbg(4, " channel->dimm = %p\n", chan->dimm);
146 : : }
147 : :
148 : : static void edac_mc_dump_dimm(struct dimm_info *dimm)
149 : : {
150 : : char location[80];
151 : :
152 : : if (!dimm->nr_pages)
153 : : return;
154 : :
155 : : edac_dimm_info_location(dimm, location, sizeof(location));
156 : :
157 : : edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n",
158 : : dimm->mci->csbased ? "rank" : "dimm",
159 : : dimm->idx, location, dimm->csrow, dimm->cschannel);
160 : : edac_dbg(4, " dimm = %p\n", dimm);
161 : : edac_dbg(4, " dimm->label = '%s'\n", dimm->label);
162 : : edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages);
163 : : edac_dbg(4, " dimm->grain = %d\n", dimm->grain);
164 : : edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages);
165 : : }
166 : :
167 : : static void edac_mc_dump_csrow(struct csrow_info *csrow)
168 : : {
169 : : edac_dbg(4, "csrow->csrow_idx = %d\n", csrow->csrow_idx);
170 : : edac_dbg(4, " csrow = %p\n", csrow);
171 : : edac_dbg(4, " csrow->first_page = 0x%lx\n", csrow->first_page);
172 : : edac_dbg(4, " csrow->last_page = 0x%lx\n", csrow->last_page);
173 : : edac_dbg(4, " csrow->page_mask = 0x%lx\n", csrow->page_mask);
174 : : edac_dbg(4, " csrow->nr_channels = %d\n", csrow->nr_channels);
175 : : edac_dbg(4, " csrow->channels = %p\n", csrow->channels);
176 : : edac_dbg(4, " csrow->mci = %p\n", csrow->mci);
177 : : }
178 : :
179 : : static void edac_mc_dump_mci(struct mem_ctl_info *mci)
180 : : {
181 : : edac_dbg(3, "\tmci = %p\n", mci);
182 : : edac_dbg(3, "\tmci->mtype_cap = %lx\n", mci->mtype_cap);
183 : : edac_dbg(3, "\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
184 : : edac_dbg(3, "\tmci->edac_cap = %lx\n", mci->edac_cap);
185 : : edac_dbg(4, "\tmci->edac_check = %p\n", mci->edac_check);
186 : : edac_dbg(3, "\tmci->nr_csrows = %d, csrows = %p\n",
187 : : mci->nr_csrows, mci->csrows);
188 : : edac_dbg(3, "\tmci->nr_dimms = %d, dimms = %p\n",
189 : : mci->tot_dimms, mci->dimms);
190 : : edac_dbg(3, "\tdev = %p\n", mci->pdev);
191 : : edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n",
192 : : mci->mod_name, mci->ctl_name);
193 : : edac_dbg(3, "\tpvt_info = %p\n\n", mci->pvt_info);
194 : : }
195 : :
196 : : #endif /* CONFIG_EDAC_DEBUG */
197 : :
198 : : const char * const edac_mem_types[] = {
199 : : [MEM_EMPTY] = "Empty",
200 : : [MEM_RESERVED] = "Reserved",
201 : : [MEM_UNKNOWN] = "Unknown",
202 : : [MEM_FPM] = "FPM",
203 : : [MEM_EDO] = "EDO",
204 : : [MEM_BEDO] = "BEDO",
205 : : [MEM_SDR] = "Unbuffered-SDR",
206 : : [MEM_RDR] = "Registered-SDR",
207 : : [MEM_DDR] = "Unbuffered-DDR",
208 : : [MEM_RDDR] = "Registered-DDR",
209 : : [MEM_RMBS] = "RMBS",
210 : : [MEM_DDR2] = "Unbuffered-DDR2",
211 : : [MEM_FB_DDR2] = "FullyBuffered-DDR2",
212 : : [MEM_RDDR2] = "Registered-DDR2",
213 : : [MEM_XDR] = "XDR",
214 : : [MEM_DDR3] = "Unbuffered-DDR3",
215 : : [MEM_RDDR3] = "Registered-DDR3",
216 : : [MEM_LRDDR3] = "Load-Reduced-DDR3-RAM",
217 : : [MEM_DDR4] = "Unbuffered-DDR4",
218 : : [MEM_RDDR4] = "Registered-DDR4",
219 : : [MEM_LRDDR4] = "Load-Reduced-DDR4-RAM",
220 : : [MEM_NVDIMM] = "Non-volatile-RAM",
221 : : };
222 : : EXPORT_SYMBOL_GPL(edac_mem_types);
223 : :
224 : : /**
225 : : * edac_align_ptr - Prepares the pointer offsets for a single-shot allocation
226 : : * @p: pointer to a pointer with the memory offset to be used. At
227 : : * return, this will be incremented to point to the next offset
228 : : * @size: Size of the data structure to be reserved
229 : : * @n_elems: Number of elements that should be reserved
230 : : *
231 : : * If 'size' is a constant, the compiler will optimize this whole function
232 : : * down to either a no-op or the addition of a constant to the value of '*p'.
233 : : *
234 : : * The 'p' pointer is absolutely needed to keep the proper advancing
235 : : * further in memory to the proper offsets when allocating the struct along
236 : : * with its embedded structs, as edac_device_alloc_ctl_info() does it
237 : : * above, for example.
238 : : *
239 : : * At return, the pointer 'p' will be incremented to be used on a next call
240 : : * to this function.
241 : : */
242 : 0 : void *edac_align_ptr(void **p, unsigned int size, int n_elems)
243 : : {
244 : 0 : unsigned int align, r;
245 : 0 : void *ptr = *p;
246 : :
247 : 0 : *p += size * n_elems;
248 : :
249 : : /*
250 : : * 'p' can possibly be an unaligned item X such that sizeof(X) is
251 : : * 'size'. Adjust 'p' so that its alignment is at least as
252 : : * stringent as what the compiler would provide for X and return
253 : : * the aligned result.
254 : : * Here we assume that the alignment of a "long long" is the most
255 : : * stringent alignment that the compiler will ever provide by default.
256 : : * As far as I know, this is a reasonable assumption.
257 : : */
258 [ # # ]: 0 : if (size > sizeof(long))
259 : : align = sizeof(long long);
260 [ # # # # ]: 0 : else if (size > sizeof(int))
261 : : align = sizeof(long);
262 [ # # # # ]: 0 : else if (size > sizeof(short))
263 : : align = sizeof(int);
264 [ # # # # ]: 0 : else if (size > sizeof(char))
265 : : align = sizeof(short);
266 : : else
267 : : return (char *)ptr;
268 : :
269 : 0 : r = (unsigned long)p % align;
270 : :
271 [ # # # # ]: 0 : if (r == 0)
272 : : return (char *)ptr;
273 : :
274 : 0 : *p += align - r;
275 : :
276 : 0 : return (void *)(((unsigned long)ptr) + align - r);
277 : : }
278 : :
279 : 0 : static void _edac_mc_free(struct mem_ctl_info *mci)
280 : : {
281 : 0 : struct csrow_info *csr;
282 : 0 : int i, chn, row;
283 : :
284 [ # # ]: 0 : if (mci->dimms) {
285 [ # # ]: 0 : for (i = 0; i < mci->tot_dimms; i++)
286 : 0 : kfree(mci->dimms[i]);
287 : 0 : kfree(mci->dimms);
288 : : }
289 : :
290 [ # # ]: 0 : if (mci->csrows) {
291 [ # # ]: 0 : for (row = 0; row < mci->nr_csrows; row++) {
292 : 0 : csr = mci->csrows[row];
293 [ # # ]: 0 : if (!csr)
294 : 0 : continue;
295 : :
296 [ # # ]: 0 : if (csr->channels) {
297 [ # # ]: 0 : for (chn = 0; chn < mci->num_cschannel; chn++)
298 : 0 : kfree(csr->channels[chn]);
299 : 0 : kfree(csr->channels);
300 : : }
301 : 0 : kfree(csr);
302 : : }
303 : 0 : kfree(mci->csrows);
304 : : }
305 : 0 : kfree(mci);
306 : 0 : }
307 : :
308 : 0 : struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
309 : : unsigned int n_layers,
310 : : struct edac_mc_layer *layers,
311 : : unsigned int sz_pvt)
312 : : {
313 : 0 : struct mem_ctl_info *mci;
314 : 0 : struct edac_mc_layer *layer;
315 : 0 : struct csrow_info *csr;
316 : 0 : struct rank_info *chan;
317 : 0 : struct dimm_info *dimm;
318 : 0 : u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS];
319 : 0 : unsigned int pos[EDAC_MAX_LAYERS];
320 : 0 : unsigned int idx, size, tot_dimms = 1, count = 1;
321 : 0 : unsigned int tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
322 : 0 : void *pvt, *p, *ptr = NULL;
323 : 0 : int i, j, row, chn, n, len;
324 : 0 : bool per_rank = false;
325 : :
326 [ # # # # ]: 0 : if (WARN_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0))
327 : : return NULL;
328 : :
329 : : /*
330 : : * Calculate the total amount of dimms and csrows/cschannels while
331 : : * in the old API emulation mode
332 : : */
333 [ # # ]: 0 : for (idx = 0; idx < n_layers; idx++) {
334 : 0 : tot_dimms *= layers[idx].size;
335 : :
336 [ # # ]: 0 : if (layers[idx].is_virt_csrow)
337 : 0 : tot_csrows *= layers[idx].size;
338 : : else
339 : 0 : tot_channels *= layers[idx].size;
340 : :
341 [ # # ]: 0 : if (layers[idx].type == EDAC_MC_LAYER_CHIP_SELECT)
342 : 0 : per_rank = true;
343 : : }
344 : :
345 : : /* Figure out the offsets of the various items from the start of an mc
346 : : * structure. We want the alignment of each item to be at least as
347 : : * stringent as what the compiler would provide if we could simply
348 : : * hardcode everything into a single struct.
349 : : */
350 : 0 : mci = edac_align_ptr(&ptr, sizeof(*mci), 1);
351 : 0 : layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers);
352 [ # # ]: 0 : for (i = 0; i < n_layers; i++) {
353 : 0 : count *= layers[i].size;
354 : 0 : edac_dbg(4, "errcount layer %d size %d\n", i, count);
355 : 0 : ce_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count);
356 : 0 : ue_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count);
357 : 0 : tot_errcount += 2 * count;
358 : : }
359 : :
360 : 0 : edac_dbg(4, "allocating %d error counters\n", tot_errcount);
361 [ # # ]: 0 : pvt = edac_align_ptr(&ptr, sz_pvt, 1);
362 : 0 : size = ((unsigned long)pvt) + sz_pvt;
363 : :
364 : 0 : edac_dbg(1, "allocating %u bytes for mci data (%d %s, %d csrows/channels)\n",
365 : : size,
366 : : tot_dimms,
367 : : per_rank ? "ranks" : "dimms",
368 : : tot_csrows * tot_channels);
369 : :
370 : 0 : mci = kzalloc(size, GFP_KERNEL);
371 [ # # ]: 0 : if (mci == NULL)
372 : : return NULL;
373 : :
374 : : /* Adjust pointers so they point within the memory we just allocated
375 : : * rather than an imaginary chunk of memory located at address 0.
376 : : */
377 : 0 : layer = (struct edac_mc_layer *)(((char *)mci) + ((unsigned long)layer));
378 [ # # ]: 0 : for (i = 0; i < n_layers; i++) {
379 : 0 : mci->ce_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ce_per_layer[i]));
380 : 0 : mci->ue_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ue_per_layer[i]));
381 : : }
382 [ # # ]: 0 : pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL;
383 : :
384 : : /* setup index and various internal pointers */
385 : 0 : mci->mc_idx = mc_num;
386 : 0 : mci->tot_dimms = tot_dimms;
387 : 0 : mci->pvt_info = pvt;
388 : 0 : mci->n_layers = n_layers;
389 : 0 : mci->layers = layer;
390 : 0 : memcpy(mci->layers, layers, sizeof(*layer) * n_layers);
391 : 0 : mci->nr_csrows = tot_csrows;
392 : 0 : mci->num_cschannel = tot_channels;
393 : 0 : mci->csbased = per_rank;
394 : :
395 : : /*
396 : : * Alocate and fill the csrow/channels structs
397 : : */
398 : 0 : mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL);
399 [ # # ]: 0 : if (!mci->csrows)
400 : 0 : goto error;
401 [ # # ]: 0 : for (row = 0; row < tot_csrows; row++) {
402 : 0 : csr = kzalloc(sizeof(**mci->csrows), GFP_KERNEL);
403 [ # # ]: 0 : if (!csr)
404 : 0 : goto error;
405 : 0 : mci->csrows[row] = csr;
406 : 0 : csr->csrow_idx = row;
407 : 0 : csr->mci = mci;
408 : 0 : csr->nr_channels = tot_channels;
409 : 0 : csr->channels = kcalloc(tot_channels, sizeof(*csr->channels),
410 : : GFP_KERNEL);
411 [ # # ]: 0 : if (!csr->channels)
412 : 0 : goto error;
413 : :
414 [ # # ]: 0 : for (chn = 0; chn < tot_channels; chn++) {
415 : 0 : chan = kzalloc(sizeof(**csr->channels), GFP_KERNEL);
416 [ # # ]: 0 : if (!chan)
417 : 0 : goto error;
418 : 0 : csr->channels[chn] = chan;
419 : 0 : chan->chan_idx = chn;
420 : 0 : chan->csrow = csr;
421 : : }
422 : : }
423 : :
424 : : /*
425 : : * Allocate and fill the dimm structs
426 : : */
427 : 0 : mci->dimms = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL);
428 [ # # ]: 0 : if (!mci->dimms)
429 : 0 : goto error;
430 : :
431 : 0 : memset(&pos, 0, sizeof(pos));
432 : 0 : row = 0;
433 : 0 : chn = 0;
434 [ # # ]: 0 : for (idx = 0; idx < tot_dimms; idx++) {
435 : 0 : chan = mci->csrows[row]->channels[chn];
436 : :
437 : 0 : dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL);
438 [ # # ]: 0 : if (!dimm)
439 : 0 : goto error;
440 : 0 : mci->dimms[idx] = dimm;
441 : 0 : dimm->mci = mci;
442 : 0 : dimm->idx = idx;
443 : :
444 : : /*
445 : : * Copy DIMM location and initialize it.
446 : : */
447 : 0 : len = sizeof(dimm->label);
448 : 0 : p = dimm->label;
449 : 0 : n = snprintf(p, len, "mc#%u", mc_num);
450 : 0 : p += n;
451 : 0 : len -= n;
452 [ # # ]: 0 : for (j = 0; j < n_layers; j++) {
453 : 0 : n = snprintf(p, len, "%s#%u",
454 : 0 : edac_layer_name[layers[j].type],
455 : : pos[j]);
456 : 0 : p += n;
457 : 0 : len -= n;
458 : 0 : dimm->location[j] = pos[j];
459 : :
460 [ # # ]: 0 : if (len <= 0)
461 : : break;
462 : : }
463 : :
464 : : /* Link it to the csrows old API data */
465 : 0 : chan->dimm = dimm;
466 : 0 : dimm->csrow = row;
467 : 0 : dimm->cschannel = chn;
468 : :
469 : : /* Increment csrow location */
470 [ # # ]: 0 : if (layers[0].is_virt_csrow) {
471 : 0 : chn++;
472 [ # # ]: 0 : if (chn == tot_channels) {
473 : 0 : chn = 0;
474 : 0 : row++;
475 : : }
476 : : } else {
477 : 0 : row++;
478 [ # # ]: 0 : if (row == tot_csrows) {
479 : 0 : row = 0;
480 : 0 : chn++;
481 : : }
482 : : }
483 : :
484 : : /* Increment dimm location */
485 [ # # ]: 0 : for (j = n_layers - 1; j >= 0; j--) {
486 : 0 : pos[j]++;
487 [ # # ]: 0 : if (pos[j] < layers[j].size)
488 : : break;
489 : 0 : pos[j] = 0;
490 : : }
491 : : }
492 : :
493 : 0 : mci->op_state = OP_ALLOC;
494 : :
495 : 0 : return mci;
496 : :
497 : 0 : error:
498 : 0 : _edac_mc_free(mci);
499 : :
500 : 0 : return NULL;
501 : : }
502 : : EXPORT_SYMBOL_GPL(edac_mc_alloc);
503 : :
504 : 0 : void edac_mc_free(struct mem_ctl_info *mci)
505 : : {
506 : 0 : edac_dbg(1, "\n");
507 : :
508 [ # # ]: 0 : if (device_is_registered(&mci->dev))
509 : 0 : edac_unregister_sysfs(mci);
510 : :
511 : 0 : _edac_mc_free(mci);
512 : 0 : }
513 : : EXPORT_SYMBOL_GPL(edac_mc_free);
514 : :
515 : 0 : bool edac_has_mcs(void)
516 : : {
517 : 0 : bool ret;
518 : :
519 : 0 : mutex_lock(&mem_ctls_mutex);
520 : :
521 : 0 : ret = list_empty(&mc_devices);
522 : :
523 : 0 : mutex_unlock(&mem_ctls_mutex);
524 : :
525 : 0 : return !ret;
526 : : }
527 : : EXPORT_SYMBOL_GPL(edac_has_mcs);
528 : :
529 : : /* Caller must hold mem_ctls_mutex */
530 : 0 : static struct mem_ctl_info *__find_mci_by_dev(struct device *dev)
531 : : {
532 : 0 : struct mem_ctl_info *mci;
533 : 0 : struct list_head *item;
534 : :
535 : 0 : edac_dbg(3, "\n");
536 : :
537 [ # # # # : 0 : list_for_each(item, &mc_devices) {
# # ]
538 : 0 : mci = list_entry(item, struct mem_ctl_info, link);
539 : :
540 [ # # # # : 0 : if (mci->pdev == dev)
# # ]
541 : : return mci;
542 : : }
543 : :
544 : : return NULL;
545 : : }
546 : :
547 : : /**
548 : : * find_mci_by_dev
549 : : *
550 : : * scan list of controllers looking for the one that manages
551 : : * the 'dev' device
552 : : * @dev: pointer to a struct device related with the MCI
553 : : */
554 : 0 : struct mem_ctl_info *find_mci_by_dev(struct device *dev)
555 : : {
556 : 0 : struct mem_ctl_info *ret;
557 : :
558 : 0 : mutex_lock(&mem_ctls_mutex);
559 : 0 : ret = __find_mci_by_dev(dev);
560 : 0 : mutex_unlock(&mem_ctls_mutex);
561 : :
562 : 0 : return ret;
563 : : }
564 : : EXPORT_SYMBOL_GPL(find_mci_by_dev);
565 : :
566 : : /*
567 : : * edac_mc_workq_function
568 : : * performs the operation scheduled by a workq request
569 : : */
570 : 0 : static void edac_mc_workq_function(struct work_struct *work_req)
571 : : {
572 : 0 : struct delayed_work *d_work = to_delayed_work(work_req);
573 : 0 : struct mem_ctl_info *mci = to_edac_mem_ctl_work(d_work);
574 : :
575 : 0 : mutex_lock(&mem_ctls_mutex);
576 : :
577 [ # # ]: 0 : if (mci->op_state != OP_RUNNING_POLL) {
578 : 0 : mutex_unlock(&mem_ctls_mutex);
579 : 0 : return;
580 : : }
581 : :
582 [ # # ]: 0 : if (edac_op_state == EDAC_OPSTATE_POLL)
583 : 0 : mci->edac_check(mci);
584 : :
585 : 0 : mutex_unlock(&mem_ctls_mutex);
586 : :
587 : : /* Queue ourselves again. */
588 : 0 : edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
589 : : }
590 : :
591 : : /*
592 : : * edac_mc_reset_delay_period(unsigned long value)
593 : : *
594 : : * user space has updated our poll period value, need to
595 : : * reset our workq delays
596 : : */
597 : 0 : void edac_mc_reset_delay_period(unsigned long value)
598 : : {
599 : 0 : struct mem_ctl_info *mci;
600 : 0 : struct list_head *item;
601 : :
602 : 0 : mutex_lock(&mem_ctls_mutex);
603 : :
604 [ # # ]: 0 : list_for_each(item, &mc_devices) {
605 : 0 : mci = list_entry(item, struct mem_ctl_info, link);
606 : :
607 [ # # ]: 0 : if (mci->op_state == OP_RUNNING_POLL)
608 : 0 : edac_mod_work(&mci->work, value);
609 : : }
610 : 0 : mutex_unlock(&mem_ctls_mutex);
611 : 0 : }
612 : :
613 : :
614 : :
615 : : /* Return 0 on success, 1 on failure.
616 : : * Before calling this function, caller must
617 : : * assign a unique value to mci->mc_idx.
618 : : *
619 : : * locking model:
620 : : *
621 : : * called with the mem_ctls_mutex lock held
622 : : */
623 : 0 : static int add_mc_to_global_list(struct mem_ctl_info *mci)
624 : : {
625 : 0 : struct list_head *item, *insert_before;
626 : 0 : struct mem_ctl_info *p;
627 : :
628 : 0 : insert_before = &mc_devices;
629 : :
630 : 0 : p = __find_mci_by_dev(mci->pdev);
631 [ # # ]: 0 : if (unlikely(p != NULL))
632 : 0 : goto fail0;
633 : :
634 [ # # ]: 0 : list_for_each(item, &mc_devices) {
635 : 0 : p = list_entry(item, struct mem_ctl_info, link);
636 : :
637 [ # # ]: 0 : if (p->mc_idx >= mci->mc_idx) {
638 [ # # ]: 0 : if (unlikely(p->mc_idx == mci->mc_idx))
639 : 0 : goto fail1;
640 : :
641 : : insert_before = item;
642 : : break;
643 : : }
644 : : }
645 : :
646 : 0 : list_add_tail_rcu(&mci->link, insert_before);
647 : 0 : return 0;
648 : :
649 : : fail0:
650 [ # # ]: 0 : edac_printk(KERN_WARNING, EDAC_MC,
651 : : "%s (%s) %s %s already assigned %d\n", dev_name(p->pdev),
652 : : edac_dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx);
653 : 0 : return 1;
654 : :
655 : : fail1:
656 : 0 : edac_printk(KERN_WARNING, EDAC_MC,
657 : : "bug in low-level driver: attempt to assign\n"
658 : : " duplicate mc_idx %d in %s()\n", p->mc_idx, __func__);
659 : 0 : return 1;
660 : : }
661 : :
662 : 0 : static int del_mc_from_global_list(struct mem_ctl_info *mci)
663 : : {
664 : 0 : list_del_rcu(&mci->link);
665 : :
666 : : /* these are for safe removal of devices from global list while
667 : : * NMI handlers may be traversing list
668 : : */
669 : 0 : synchronize_rcu();
670 [ # # ]: 0 : INIT_LIST_HEAD(&mci->link);
671 : :
672 [ # # ]: 0 : return list_empty(&mc_devices);
673 : : }
674 : :
675 : 0 : struct mem_ctl_info *edac_mc_find(int idx)
676 : : {
677 : 0 : struct mem_ctl_info *mci;
678 : 0 : struct list_head *item;
679 : :
680 : 0 : mutex_lock(&mem_ctls_mutex);
681 : :
682 [ # # ]: 0 : list_for_each(item, &mc_devices) {
683 : 0 : mci = list_entry(item, struct mem_ctl_info, link);
684 [ # # ]: 0 : if (mci->mc_idx == idx)
685 : 0 : goto unlock;
686 : : }
687 : :
688 : : mci = NULL;
689 : 0 : unlock:
690 : 0 : mutex_unlock(&mem_ctls_mutex);
691 : 0 : return mci;
692 : : }
693 : : EXPORT_SYMBOL(edac_mc_find);
694 : :
695 : 0 : const char *edac_get_owner(void)
696 : : {
697 : 0 : return edac_mc_owner;
698 : : }
699 : : EXPORT_SYMBOL_GPL(edac_get_owner);
700 : :
701 : : /* FIXME - should a warning be printed if no error detection? correction? */
702 : 0 : int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
703 : : const struct attribute_group **groups)
704 : : {
705 : 0 : int ret = -EINVAL;
706 : 0 : edac_dbg(0, "\n");
707 : :
708 : : #ifdef CONFIG_EDAC_DEBUG
709 : : if (edac_debug_level >= 3)
710 : : edac_mc_dump_mci(mci);
711 : :
712 : : if (edac_debug_level >= 4) {
713 : : struct dimm_info *dimm;
714 : : int i;
715 : :
716 : : for (i = 0; i < mci->nr_csrows; i++) {
717 : : struct csrow_info *csrow = mci->csrows[i];
718 : : u32 nr_pages = 0;
719 : : int j;
720 : :
721 : : for (j = 0; j < csrow->nr_channels; j++)
722 : : nr_pages += csrow->channels[j]->dimm->nr_pages;
723 : : if (!nr_pages)
724 : : continue;
725 : : edac_mc_dump_csrow(csrow);
726 : : for (j = 0; j < csrow->nr_channels; j++)
727 : : if (csrow->channels[j]->dimm->nr_pages)
728 : : edac_mc_dump_channel(csrow->channels[j]);
729 : : }
730 : :
731 : : mci_for_each_dimm(mci, dimm)
732 : : edac_mc_dump_dimm(dimm);
733 : : }
734 : : #endif
735 : 0 : mutex_lock(&mem_ctls_mutex);
736 : :
737 [ # # # # ]: 0 : if (edac_mc_owner && edac_mc_owner != mci->mod_name) {
738 : 0 : ret = -EPERM;
739 : 0 : goto fail0;
740 : : }
741 : :
742 [ # # ]: 0 : if (add_mc_to_global_list(mci))
743 : 0 : goto fail0;
744 : :
745 : : /* set load time so that error rate can be tracked */
746 : 0 : mci->start_time = jiffies;
747 : :
748 : 0 : mci->bus = edac_get_sysfs_subsys();
749 : :
750 [ # # ]: 0 : if (edac_create_sysfs_mci_device(mci, groups)) {
751 : 0 : edac_mc_printk(mci, KERN_WARNING,
752 : : "failed to create sysfs device\n");
753 : 0 : goto fail1;
754 : : }
755 : :
756 [ # # ]: 0 : if (mci->edac_check) {
757 : 0 : mci->op_state = OP_RUNNING_POLL;
758 : :
759 : 0 : INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
760 : 0 : edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
761 : :
762 : : } else {
763 : 0 : mci->op_state = OP_RUNNING_INTERRUPT;
764 : : }
765 : :
766 : : /* Report action taken */
767 : 0 : edac_mc_printk(mci, KERN_INFO,
768 : : "Giving out device to module %s controller %s: DEV %s (%s)\n",
769 : : mci->mod_name, mci->ctl_name, mci->dev_name,
770 : : edac_op_state_to_string(mci->op_state));
771 : :
772 : 0 : edac_mc_owner = mci->mod_name;
773 : :
774 : 0 : mutex_unlock(&mem_ctls_mutex);
775 : 0 : return 0;
776 : :
777 : : fail1:
778 : 0 : del_mc_from_global_list(mci);
779 : :
780 : 0 : fail0:
781 : 0 : mutex_unlock(&mem_ctls_mutex);
782 : 0 : return ret;
783 : : }
784 : : EXPORT_SYMBOL_GPL(edac_mc_add_mc_with_groups);
785 : :
786 : 0 : struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
787 : : {
788 : 0 : struct mem_ctl_info *mci;
789 : :
790 : 0 : edac_dbg(0, "\n");
791 : :
792 : 0 : mutex_lock(&mem_ctls_mutex);
793 : :
794 : : /* find the requested mci struct in the global list */
795 : 0 : mci = __find_mci_by_dev(dev);
796 [ # # ]: 0 : if (mci == NULL) {
797 : 0 : mutex_unlock(&mem_ctls_mutex);
798 : 0 : return NULL;
799 : : }
800 : :
801 : : /* mark MCI offline: */
802 : 0 : mci->op_state = OP_OFFLINE;
803 : :
804 [ # # ]: 0 : if (del_mc_from_global_list(mci))
805 : 0 : edac_mc_owner = NULL;
806 : :
807 : 0 : mutex_unlock(&mem_ctls_mutex);
808 : :
809 [ # # ]: 0 : if (mci->edac_check)
810 : 0 : edac_stop_work(&mci->work);
811 : :
812 : : /* remove from sysfs */
813 : 0 : edac_remove_sysfs_mci_device(mci);
814 : :
815 : 0 : edac_printk(KERN_INFO, EDAC_MC,
816 : : "Removed device %d for %s %s: DEV %s\n", mci->mc_idx,
817 : : mci->mod_name, mci->ctl_name, edac_dev_name(mci));
818 : :
819 : 0 : return mci;
820 : : }
821 : : EXPORT_SYMBOL_GPL(edac_mc_del_mc);
822 : :
823 : 0 : static void edac_mc_scrub_block(unsigned long page, unsigned long offset,
824 : : u32 size)
825 : : {
826 : 0 : struct page *pg;
827 : 0 : void *virt_addr;
828 : 0 : unsigned long flags = 0;
829 : :
830 : 0 : edac_dbg(3, "\n");
831 : :
832 : : /* ECC error page was not in our memory. Ignore it. */
833 [ # # ]: 0 : if (!pfn_valid(page))
834 : : return;
835 : :
836 : : /* Find the actual page structure then map it and fix */
837 : 0 : pg = pfn_to_page(page);
838 : :
839 : 0 : if (PageHighMem(pg))
840 : 0 : local_irq_save(flags);
841 : :
842 : 0 : virt_addr = kmap_atomic(pg);
843 : :
844 : : /* Perform architecture specific atomic scrub operation */
845 : 0 : edac_atomic_scrub(virt_addr + offset, size);
846 : :
847 : : /* Unmap and complete */
848 : 0 : kunmap_atomic(virt_addr);
849 : :
850 : 0 : if (PageHighMem(pg))
851 : 0 : local_irq_restore(flags);
852 : : }
853 : :
854 : : /* FIXME - should return -1 */
855 : 0 : int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
856 : : {
857 : 0 : struct csrow_info **csrows = mci->csrows;
858 : 0 : int row, i, j, n;
859 : :
860 : 0 : edac_dbg(1, "MC%d: 0x%lx\n", mci->mc_idx, page);
861 : 0 : row = -1;
862 : :
863 [ # # ]: 0 : for (i = 0; i < mci->nr_csrows; i++) {
864 : 0 : struct csrow_info *csrow = csrows[i];
865 : 0 : n = 0;
866 [ # # ]: 0 : for (j = 0; j < csrow->nr_channels; j++) {
867 : 0 : struct dimm_info *dimm = csrow->channels[j]->dimm;
868 : 0 : n += dimm->nr_pages;
869 : : }
870 [ # # ]: 0 : if (n == 0)
871 : 0 : continue;
872 : :
873 : 0 : edac_dbg(3, "MC%d: first(0x%lx) page(0x%lx) last(0x%lx) mask(0x%lx)\n",
874 : : mci->mc_idx,
875 : : csrow->first_page, page, csrow->last_page,
876 : : csrow->page_mask);
877 : :
878 [ # # ]: 0 : if ((page >= csrow->first_page) &&
879 [ # # ]: 0 : (page <= csrow->last_page) &&
880 [ # # ]: 0 : ((page & csrow->page_mask) ==
881 : : (csrow->first_page & csrow->page_mask))) {
882 : : row = i;
883 : : break;
884 : : }
885 : : }
886 : :
887 [ # # ]: 0 : if (row == -1)
888 : 0 : edac_mc_printk(mci, KERN_ERR,
889 : : "could not look up page error address %lx\n",
890 : : (unsigned long)page);
891 : :
892 : 0 : return row;
893 : : }
894 : : EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page);
895 : :
896 : : const char *edac_layer_name[] = {
897 : : [EDAC_MC_LAYER_BRANCH] = "branch",
898 : : [EDAC_MC_LAYER_CHANNEL] = "channel",
899 : : [EDAC_MC_LAYER_SLOT] = "slot",
900 : : [EDAC_MC_LAYER_CHIP_SELECT] = "csrow",
901 : : [EDAC_MC_LAYER_ALL_MEM] = "memory",
902 : : };
903 : : EXPORT_SYMBOL_GPL(edac_layer_name);
904 : :
905 : 0 : static void edac_inc_ce_error(struct mem_ctl_info *mci,
906 : : bool enable_per_layer_report,
907 : : const int pos[EDAC_MAX_LAYERS],
908 : : const u16 count)
909 : : {
910 : 0 : int i, index = 0;
911 : :
912 : 0 : mci->ce_mc += count;
913 : :
914 [ # # ]: 0 : if (!enable_per_layer_report) {
915 : 0 : mci->ce_noinfo_count += count;
916 : 0 : return;
917 : : }
918 : :
919 [ # # ]: 0 : for (i = 0; i < mci->n_layers; i++) {
920 [ # # ]: 0 : if (pos[i] < 0)
921 : : break;
922 : 0 : index += pos[i];
923 : 0 : mci->ce_per_layer[i][index] += count;
924 : :
925 [ # # ]: 0 : if (i < mci->n_layers - 1)
926 : 0 : index *= mci->layers[i + 1].size;
927 : : }
928 : : }
929 : :
930 : 0 : static void edac_inc_ue_error(struct mem_ctl_info *mci,
931 : : bool enable_per_layer_report,
932 : : const int pos[EDAC_MAX_LAYERS],
933 : : const u16 count)
934 : : {
935 : 0 : int i, index = 0;
936 : :
937 : 0 : mci->ue_mc += count;
938 : :
939 [ # # ]: 0 : if (!enable_per_layer_report) {
940 : 0 : mci->ue_noinfo_count += count;
941 : 0 : return;
942 : : }
943 : :
944 [ # # ]: 0 : for (i = 0; i < mci->n_layers; i++) {
945 [ # # ]: 0 : if (pos[i] < 0)
946 : : break;
947 : 0 : index += pos[i];
948 : 0 : mci->ue_per_layer[i][index] += count;
949 : :
950 [ # # ]: 0 : if (i < mci->n_layers - 1)
951 : 0 : index *= mci->layers[i + 1].size;
952 : : }
953 : : }
954 : :
955 : 0 : static void edac_ce_error(struct mem_ctl_info *mci,
956 : : const u16 error_count,
957 : : const int pos[EDAC_MAX_LAYERS],
958 : : const char *msg,
959 : : const char *location,
960 : : const char *label,
961 : : const char *detail,
962 : : const char *other_detail,
963 : : const bool enable_per_layer_report,
964 : : const unsigned long page_frame_number,
965 : : const unsigned long offset_in_page,
966 : : long grain)
967 : : {
968 : 0 : unsigned long remapped_page;
969 : 0 : char *msg_aux = "";
970 : :
971 [ # # ]: 0 : if (*msg)
972 : 0 : msg_aux = " ";
973 : :
974 [ # # ]: 0 : if (edac_mc_get_log_ce()) {
975 [ # # # # ]: 0 : if (other_detail && *other_detail)
976 : 0 : edac_mc_printk(mci, KERN_WARNING,
977 : : "%d CE %s%son %s (%s %s - %s)\n",
978 : : error_count, msg, msg_aux, label,
979 : : location, detail, other_detail);
980 : : else
981 : 0 : edac_mc_printk(mci, KERN_WARNING,
982 : : "%d CE %s%son %s (%s %s)\n",
983 : : error_count, msg, msg_aux, label,
984 : : location, detail);
985 : : }
986 : 0 : edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count);
987 : :
988 [ # # ]: 0 : if (mci->scrub_mode == SCRUB_SW_SRC) {
989 : : /*
990 : : * Some memory controllers (called MCs below) can remap
991 : : * memory so that it is still available at a different
992 : : * address when PCI devices map into memory.
993 : : * MC's that can't do this, lose the memory where PCI
994 : : * devices are mapped. This mapping is MC-dependent
995 : : * and so we call back into the MC driver for it to
996 : : * map the MC page to a physical (CPU) page which can
997 : : * then be mapped to a virtual page - which can then
998 : : * be scrubbed.
999 : : */
1000 : 0 : remapped_page = mci->ctl_page_to_phys ?
1001 [ # # ]: 0 : mci->ctl_page_to_phys(mci, page_frame_number) :
1002 : : page_frame_number;
1003 : :
1004 : 0 : edac_mc_scrub_block(remapped_page,
1005 : : offset_in_page, grain);
1006 : : }
1007 : 0 : }
1008 : :
1009 : 0 : static void edac_ue_error(struct mem_ctl_info *mci,
1010 : : const u16 error_count,
1011 : : const int pos[EDAC_MAX_LAYERS],
1012 : : const char *msg,
1013 : : const char *location,
1014 : : const char *label,
1015 : : const char *detail,
1016 : : const char *other_detail,
1017 : : const bool enable_per_layer_report)
1018 : : {
1019 : 0 : char *msg_aux = "";
1020 : :
1021 [ # # ]: 0 : if (*msg)
1022 : 0 : msg_aux = " ";
1023 : :
1024 [ # # ]: 0 : if (edac_mc_get_log_ue()) {
1025 [ # # # # ]: 0 : if (other_detail && *other_detail)
1026 : 0 : edac_mc_printk(mci, KERN_WARNING,
1027 : : "%d UE %s%son %s (%s %s - %s)\n",
1028 : : error_count, msg, msg_aux, label,
1029 : : location, detail, other_detail);
1030 : : else
1031 : 0 : edac_mc_printk(mci, KERN_WARNING,
1032 : : "%d UE %s%son %s (%s %s)\n",
1033 : : error_count, msg, msg_aux, label,
1034 : : location, detail);
1035 : : }
1036 : :
1037 [ # # ]: 0 : if (edac_mc_get_panic_on_ue()) {
1038 [ # # # # ]: 0 : if (other_detail && *other_detail)
1039 : 0 : panic("UE %s%son %s (%s%s - %s)\n",
1040 : : msg, msg_aux, label, location, detail, other_detail);
1041 : : else
1042 : 0 : panic("UE %s%son %s (%s%s)\n",
1043 : : msg, msg_aux, label, location, detail);
1044 : : }
1045 : :
1046 : 0 : edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count);
1047 : 0 : }
1048 : :
1049 : 0 : void edac_raw_mc_handle_error(const enum hw_event_mc_err_type type,
1050 : : struct mem_ctl_info *mci,
1051 : : struct edac_raw_error_desc *e)
1052 : : {
1053 : 0 : char detail[80];
1054 : 0 : int pos[EDAC_MAX_LAYERS] = { e->top_layer, e->mid_layer, e->low_layer };
1055 : 0 : u8 grain_bits;
1056 : :
1057 : : /* Sanity-check driver-supplied grain value. */
1058 [ # # # # ]: 0 : if (WARN_ON_ONCE(!e->grain))
1059 : 0 : e->grain = 1;
1060 : :
1061 : 0 : grain_bits = fls_long(e->grain - 1);
1062 : :
1063 : : /* Report the error via the trace interface */
1064 : 0 : if (IS_ENABLED(CONFIG_RAS))
1065 : 0 : trace_mc_event(type, e->msg, e->label, e->error_count,
1066 : 0 : mci->mc_idx, e->top_layer, e->mid_layer,
1067 : : e->low_layer,
1068 : 0 : (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page,
1069 : : grain_bits, e->syndrome, e->other_detail);
1070 : :
1071 : : /* Memory type dependent details about the error */
1072 [ # # ]: 0 : if (type == HW_EVENT_ERR_CORRECTED) {
1073 : 0 : snprintf(detail, sizeof(detail),
1074 : : "page:0x%lx offset:0x%lx grain:%ld syndrome:0x%lx",
1075 : : e->page_frame_number, e->offset_in_page,
1076 : : e->grain, e->syndrome);
1077 : 0 : edac_ce_error(mci, e->error_count, pos, e->msg, e->location, e->label,
1078 : 0 : detail, e->other_detail, e->enable_per_layer_report,
1079 : : e->page_frame_number, e->offset_in_page, e->grain);
1080 : : } else {
1081 : 0 : snprintf(detail, sizeof(detail),
1082 : : "page:0x%lx offset:0x%lx grain:%ld",
1083 : : e->page_frame_number, e->offset_in_page, e->grain);
1084 : :
1085 : 0 : edac_ue_error(mci, e->error_count, pos, e->msg, e->location, e->label,
1086 : 0 : detail, e->other_detail, e->enable_per_layer_report);
1087 : : }
1088 : :
1089 : :
1090 : 0 : }
1091 : : EXPORT_SYMBOL_GPL(edac_raw_mc_handle_error);
1092 : :
1093 : 0 : void edac_mc_handle_error(const enum hw_event_mc_err_type type,
1094 : : struct mem_ctl_info *mci,
1095 : : const u16 error_count,
1096 : : const unsigned long page_frame_number,
1097 : : const unsigned long offset_in_page,
1098 : : const unsigned long syndrome,
1099 : : const int top_layer,
1100 : : const int mid_layer,
1101 : : const int low_layer,
1102 : : const char *msg,
1103 : : const char *other_detail)
1104 : : {
1105 : 0 : struct dimm_info *dimm;
1106 : 0 : char *p;
1107 : 0 : int row = -1, chan = -1;
1108 : 0 : int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer };
1109 : 0 : int i, n_labels = 0;
1110 : 0 : struct edac_raw_error_desc *e = &mci->error_desc;
1111 : :
1112 : 0 : edac_dbg(3, "MC%d\n", mci->mc_idx);
1113 : :
1114 : : /* Fills the error report buffer */
1115 : 0 : memset(e, 0, sizeof (*e));
1116 : 0 : e->error_count = error_count;
1117 : 0 : e->top_layer = top_layer;
1118 : 0 : e->mid_layer = mid_layer;
1119 : 0 : e->low_layer = low_layer;
1120 : 0 : e->page_frame_number = page_frame_number;
1121 : 0 : e->offset_in_page = offset_in_page;
1122 : 0 : e->syndrome = syndrome;
1123 : 0 : e->msg = msg;
1124 : 0 : e->other_detail = other_detail;
1125 : :
1126 : : /*
1127 : : * Check if the event report is consistent and if the memory
1128 : : * location is known. If it is known, enable_per_layer_report will be
1129 : : * true, the DIMM(s) label info will be filled and the per-layer
1130 : : * error counters will be incremented.
1131 : : */
1132 [ # # ]: 0 : for (i = 0; i < mci->n_layers; i++) {
1133 [ # # ]: 0 : if (pos[i] >= (int)mci->layers[i].size) {
1134 : :
1135 : 0 : edac_mc_printk(mci, KERN_ERR,
1136 : : "INTERNAL ERROR: %s value is out of range (%d >= %d)\n",
1137 : : edac_layer_name[mci->layers[i].type],
1138 : : pos[i], mci->layers[i].size);
1139 : : /*
1140 : : * Instead of just returning it, let's use what's
1141 : : * known about the error. The increment routines and
1142 : : * the DIMM filter logic will do the right thing by
1143 : : * pointing the likely damaged DIMMs.
1144 : : */
1145 : 0 : pos[i] = -1;
1146 : : }
1147 [ # # ]: 0 : if (pos[i] >= 0)
1148 : 0 : e->enable_per_layer_report = true;
1149 : : }
1150 : :
1151 : : /*
1152 : : * Get the dimm label/grain that applies to the match criteria.
1153 : : * As the error algorithm may not be able to point to just one memory
1154 : : * stick, the logic here will get all possible labels that could
1155 : : * pottentially be affected by the error.
1156 : : * On FB-DIMM memory controllers, for uncorrected errors, it is common
1157 : : * to have only the MC channel and the MC dimm (also called "branch")
1158 : : * but the channel is not known, as the memory is arranged in pairs,
1159 : : * where each memory belongs to a separate channel within the same
1160 : : * branch.
1161 : : */
1162 : 0 : p = e->label;
1163 : 0 : *p = '\0';
1164 : :
1165 [ # # # # ]: 0 : mci_for_each_dimm(mci, dimm) {
1166 [ # # # # ]: 0 : if (top_layer >= 0 && top_layer != dimm->location[0])
1167 : 0 : continue;
1168 [ # # # # ]: 0 : if (mid_layer >= 0 && mid_layer != dimm->location[1])
1169 : 0 : continue;
1170 [ # # # # ]: 0 : if (low_layer >= 0 && low_layer != dimm->location[2])
1171 : 0 : continue;
1172 : :
1173 : : /* get the max grain, over the error match range */
1174 [ # # ]: 0 : if (dimm->grain > e->grain)
1175 : 0 : e->grain = dimm->grain;
1176 : :
1177 : : /*
1178 : : * If the error is memory-controller wide, there's no need to
1179 : : * seek for the affected DIMMs because the whole
1180 : : * channel/memory controller/... may be affected.
1181 : : * Also, don't show errors for empty DIMM slots.
1182 : : */
1183 [ # # # # ]: 0 : if (!e->enable_per_layer_report || !dimm->nr_pages)
1184 : 0 : continue;
1185 : :
1186 [ # # ]: 0 : if (n_labels >= EDAC_MAX_LABELS) {
1187 : 0 : e->enable_per_layer_report = false;
1188 : 0 : break;
1189 : : }
1190 : 0 : n_labels++;
1191 [ # # ]: 0 : if (p != e->label) {
1192 : 0 : strcpy(p, OTHER_LABEL);
1193 : 0 : p += strlen(OTHER_LABEL);
1194 : : }
1195 : 0 : strcpy(p, dimm->label);
1196 : 0 : p += strlen(p);
1197 : :
1198 : : /*
1199 : : * get csrow/channel of the DIMM, in order to allow
1200 : : * incrementing the compat API counters
1201 : : */
1202 : 0 : edac_dbg(4, "%s csrows map: (%d,%d)\n",
1203 : : mci->csbased ? "rank" : "dimm",
1204 : : dimm->csrow, dimm->cschannel);
1205 [ # # ]: 0 : if (row == -1)
1206 : 0 : row = dimm->csrow;
1207 [ # # # # ]: 0 : else if (row >= 0 && row != dimm->csrow)
1208 : 0 : row = -2;
1209 : :
1210 [ # # ]: 0 : if (chan == -1)
1211 : 0 : chan = dimm->cschannel;
1212 [ # # # # ]: 0 : else if (chan >= 0 && chan != dimm->cschannel)
1213 : 0 : chan = -2;
1214 : : }
1215 : :
1216 [ # # ]: 0 : if (!e->enable_per_layer_report) {
1217 : 0 : strcpy(e->label, "any memory");
1218 : : } else {
1219 : 0 : edac_dbg(4, "csrow/channel to increment: (%d,%d)\n", row, chan);
1220 [ # # ]: 0 : if (p == e->label)
1221 : 0 : strcpy(e->label, "unknown memory");
1222 [ # # ]: 0 : if (type == HW_EVENT_ERR_CORRECTED) {
1223 [ # # ]: 0 : if (row >= 0) {
1224 : 0 : mci->csrows[row]->ce_count += error_count;
1225 [ # # ]: 0 : if (chan >= 0)
1226 : 0 : mci->csrows[row]->channels[chan]->ce_count += error_count;
1227 : : }
1228 : : } else
1229 [ # # ]: 0 : if (row >= 0)
1230 : 0 : mci->csrows[row]->ue_count += error_count;
1231 : : }
1232 : :
1233 : : /* Fill the RAM location data */
1234 : 0 : p = e->location;
1235 : :
1236 [ # # ]: 0 : for (i = 0; i < mci->n_layers; i++) {
1237 [ # # ]: 0 : if (pos[i] < 0)
1238 : 0 : continue;
1239 : :
1240 : 0 : p += sprintf(p, "%s:%d ",
1241 : 0 : edac_layer_name[mci->layers[i].type],
1242 : : pos[i]);
1243 : : }
1244 [ # # ]: 0 : if (p > e->location)
1245 : 0 : *(p - 1) = '\0';
1246 : :
1247 : 0 : edac_raw_mc_handle_error(type, mci, e);
1248 : 0 : }
1249 : : EXPORT_SYMBOL_GPL(edac_mc_handle_error);
|