.. | .. |
---|
31 | 31 | extern int edac_op_state; |
---|
32 | 32 | |
---|
33 | 33 | struct bus_type *edac_get_sysfs_subsys(void); |
---|
34 | | -int edac_get_report_status(void); |
---|
35 | | -void edac_set_report_status(int new); |
---|
36 | | - |
---|
37 | | -enum { |
---|
38 | | - EDAC_REPORTING_ENABLED, |
---|
39 | | - EDAC_REPORTING_DISABLED, |
---|
40 | | - EDAC_REPORTING_FORCE |
---|
41 | | -}; |
---|
42 | 34 | |
---|
43 | 35 | static inline void opstate_init(void) |
---|
44 | 36 | { |
---|
.. | .. |
---|
362 | 354 | */ |
---|
363 | 355 | #define EDAC_MAX_LAYERS 3 |
---|
364 | 356 | |
---|
365 | | -/** |
---|
366 | | - * EDAC_DIMM_OFF - Macro responsible to get a pointer offset inside a pointer |
---|
367 | | - * array for the element given by [layer0,layer1,layer2] |
---|
368 | | - * position |
---|
369 | | - * |
---|
370 | | - * @layers: a struct edac_mc_layer array, describing how many elements |
---|
371 | | - * were allocated for each layer |
---|
372 | | - * @nlayers: Number of layers at the @layers array |
---|
373 | | - * @layer0: layer0 position |
---|
374 | | - * @layer1: layer1 position. Unused if n_layers < 2 |
---|
375 | | - * @layer2: layer2 position. Unused if n_layers < 3 |
---|
376 | | - * |
---|
377 | | - * For 1 layer, this macro returns "var[layer0] - var"; |
---|
378 | | - * |
---|
379 | | - * For 2 layers, this macro is similar to allocate a bi-dimensional array |
---|
380 | | - * and to return "var[layer0][layer1] - var"; |
---|
381 | | - * |
---|
382 | | - * For 3 layers, this macro is similar to allocate a tri-dimensional array |
---|
383 | | - * and to return "var[layer0][layer1][layer2] - var". |
---|
384 | | - * |
---|
385 | | - * A loop could be used here to make it more generic, but, as we only have |
---|
386 | | - * 3 layers, this is a little faster. |
---|
387 | | - * |
---|
388 | | - * By design, layers can never be 0 or more than 3. If that ever happens, |
---|
389 | | - * a NULL is returned, causing an OOPS during the memory allocation routine, |
---|
390 | | - * with would point to the developer that he's doing something wrong. |
---|
391 | | - */ |
---|
392 | | -#define EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2) ({ \ |
---|
393 | | - int __i; \ |
---|
394 | | - if ((nlayers) == 1) \ |
---|
395 | | - __i = layer0; \ |
---|
396 | | - else if ((nlayers) == 2) \ |
---|
397 | | - __i = (layer1) + ((layers[1]).size * (layer0)); \ |
---|
398 | | - else if ((nlayers) == 3) \ |
---|
399 | | - __i = (layer2) + ((layers[2]).size * ((layer1) + \ |
---|
400 | | - ((layers[1]).size * (layer0)))); \ |
---|
401 | | - else \ |
---|
402 | | - __i = -EINVAL; \ |
---|
403 | | - __i; \ |
---|
404 | | -}) |
---|
405 | | - |
---|
406 | | -/** |
---|
407 | | - * EDAC_DIMM_PTR - Macro responsible to get a pointer inside a pointer array |
---|
408 | | - * for the element given by [layer0,layer1,layer2] position |
---|
409 | | - * |
---|
410 | | - * @layers: a struct edac_mc_layer array, describing how many elements |
---|
411 | | - * were allocated for each layer |
---|
412 | | - * @var: name of the var where we want to get the pointer |
---|
413 | | - * (like mci->dimms) |
---|
414 | | - * @nlayers: Number of layers at the @layers array |
---|
415 | | - * @layer0: layer0 position |
---|
416 | | - * @layer1: layer1 position. Unused if n_layers < 2 |
---|
417 | | - * @layer2: layer2 position. Unused if n_layers < 3 |
---|
418 | | - * |
---|
419 | | - * For 1 layer, this macro returns "var[layer0]"; |
---|
420 | | - * |
---|
421 | | - * For 2 layers, this macro is similar to allocate a bi-dimensional array |
---|
422 | | - * and to return "var[layer0][layer1]"; |
---|
423 | | - * |
---|
424 | | - * For 3 layers, this macro is similar to allocate a tri-dimensional array |
---|
425 | | - * and to return "var[layer0][layer1][layer2]"; |
---|
426 | | - */ |
---|
427 | | -#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ |
---|
428 | | - typeof(*var) __p; \ |
---|
429 | | - int ___i = EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2); \ |
---|
430 | | - if (___i < 0) \ |
---|
431 | | - __p = NULL; \ |
---|
432 | | - else \ |
---|
433 | | - __p = (var)[___i]; \ |
---|
434 | | - __p; \ |
---|
435 | | -}) |
---|
436 | | - |
---|
437 | 357 | struct dimm_info { |
---|
438 | 358 | struct device dev; |
---|
439 | 359 | |
---|
440 | 360 | char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ |
---|
441 | 361 | |
---|
442 | 362 | /* Memory location data */ |
---|
443 | | - unsigned location[EDAC_MAX_LAYERS]; |
---|
| 363 | + unsigned int location[EDAC_MAX_LAYERS]; |
---|
444 | 364 | |
---|
445 | 365 | struct mem_ctl_info *mci; /* the parent */ |
---|
| 366 | + unsigned int idx; /* index within the parent dimm array */ |
---|
446 | 367 | |
---|
447 | 368 | u32 grain; /* granularity of reported error in bytes */ |
---|
448 | 369 | enum dev_type dtype; /* memory device type */ |
---|
.. | .. |
---|
451 | 372 | |
---|
452 | 373 | u32 nr_pages; /* number of pages on this dimm */ |
---|
453 | 374 | |
---|
454 | | - unsigned csrow, cschannel; /* Points to the old API data */ |
---|
| 375 | + unsigned int csrow, cschannel; /* Points to the old API data */ |
---|
| 376 | + |
---|
| 377 | + u16 smbios_handle; /* Handle for SMBIOS type 17 */ |
---|
| 378 | + |
---|
| 379 | + u32 ce_count; |
---|
| 380 | + u32 ue_count; |
---|
455 | 381 | }; |
---|
456 | 382 | |
---|
457 | 383 | /** |
---|
.. | .. |
---|
511 | 437 | * struct edac_raw_error_desc - Raw error report structure |
---|
512 | 438 | * @grain: minimum granularity for an error report, in bytes |
---|
513 | 439 | * @error_count: number of errors of the same type |
---|
| 440 | + * @type: severity of the error (CE/UE/Fatal) |
---|
514 | 441 | * @top_layer: top layer of the error (layer[0]) |
---|
515 | 442 | * @mid_layer: middle layer of the error (layer[1]) |
---|
516 | 443 | * @low_layer: low layer of the error (layer[2]) |
---|
.. | .. |
---|
522 | 449 | * @location: location of the error |
---|
523 | 450 | * @label: label of the affected DIMM(s) |
---|
524 | 451 | * @other_detail: other driver-specific detail about the error |
---|
525 | | - * @enable_per_layer_report: if false, the error affects all layers |
---|
526 | | - * (typically, a memory controller error) |
---|
527 | 452 | */ |
---|
528 | 453 | struct edac_raw_error_desc { |
---|
529 | | - /* |
---|
530 | | - * NOTE: everything before grain won't be cleaned by |
---|
531 | | - * edac_raw_error_desc_clean() |
---|
532 | | - */ |
---|
533 | 454 | char location[LOCATION_SIZE]; |
---|
534 | 455 | char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * EDAC_MAX_LABELS]; |
---|
535 | 456 | long grain; |
---|
536 | 457 | |
---|
537 | | - /* the vars below and grain will be cleaned on every new error report */ |
---|
538 | 458 | u16 error_count; |
---|
| 459 | + enum hw_event_mc_err_type type; |
---|
539 | 460 | int top_layer; |
---|
540 | 461 | int mid_layer; |
---|
541 | 462 | int low_layer; |
---|
.. | .. |
---|
544 | 465 | unsigned long syndrome; |
---|
545 | 466 | const char *msg; |
---|
546 | 467 | const char *other_detail; |
---|
547 | | - bool enable_per_layer_report; |
---|
548 | 468 | }; |
---|
549 | 469 | |
---|
550 | 470 | /* MEMORY controller information structure |
---|
.. | .. |
---|
595 | 515 | unsigned long page); |
---|
596 | 516 | int mc_idx; |
---|
597 | 517 | struct csrow_info **csrows; |
---|
598 | | - unsigned nr_csrows, num_cschannel; |
---|
| 518 | + unsigned int nr_csrows, num_cschannel; |
---|
599 | 519 | |
---|
600 | 520 | /* |
---|
601 | 521 | * Memory Controller hierarchy |
---|
.. | .. |
---|
606 | 526 | * of the recent drivers enumerate memories per DIMM, instead. |
---|
607 | 527 | * When the memory controller is per rank, csbased is true. |
---|
608 | 528 | */ |
---|
609 | | - unsigned n_layers; |
---|
| 529 | + unsigned int n_layers; |
---|
610 | 530 | struct edac_mc_layer *layers; |
---|
611 | 531 | bool csbased; |
---|
612 | 532 | |
---|
613 | 533 | /* |
---|
614 | 534 | * DIMM info. Will eventually remove the entire csrows_info some day |
---|
615 | 535 | */ |
---|
616 | | - unsigned tot_dimms; |
---|
| 536 | + unsigned int tot_dimms; |
---|
617 | 537 | struct dimm_info **dimms; |
---|
618 | 538 | |
---|
619 | 539 | /* |
---|
.. | .. |
---|
634 | 554 | */ |
---|
635 | 555 | u32 ce_noinfo_count, ue_noinfo_count; |
---|
636 | 556 | u32 ue_mc, ce_mc; |
---|
637 | | - u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS]; |
---|
638 | 557 | |
---|
639 | 558 | struct completion complete; |
---|
640 | 559 | |
---|
.. | .. |
---|
668 | 587 | u16 fake_inject_count; |
---|
669 | 588 | }; |
---|
670 | 589 | |
---|
671 | | -/* |
---|
672 | | - * Maximum number of memory controllers in the coherent fabric. |
---|
673 | | - */ |
---|
674 | | -#define EDAC_MAX_MCS 2 * MAX_NUMNODES |
---|
| 590 | +#define mci_for_each_dimm(mci, dimm) \ |
---|
| 591 | + for ((dimm) = (mci)->dimms[0]; \ |
---|
| 592 | + (dimm); \ |
---|
| 593 | + (dimm) = (dimm)->idx + 1 < (mci)->tot_dimms \ |
---|
| 594 | + ? (mci)->dimms[(dimm)->idx + 1] \ |
---|
| 595 | + : NULL) |
---|
675 | 596 | |
---|
676 | | -#endif |
---|
| 597 | +/** |
---|
| 598 | + * edac_get_dimm - Get DIMM info from a memory controller given by |
---|
| 599 | + * [layer0,layer1,layer2] position |
---|
| 600 | + * |
---|
| 601 | + * @mci: MC descriptor struct mem_ctl_info |
---|
| 602 | + * @layer0: layer0 position |
---|
| 603 | + * @layer1: layer1 position. Unused if n_layers < 2 |
---|
| 604 | + * @layer2: layer2 position. Unused if n_layers < 3 |
---|
| 605 | + * |
---|
| 606 | + * For 1 layer, this function returns "dimms[layer0]"; |
---|
| 607 | + * |
---|
| 608 | + * For 2 layers, this function is similar to allocating a two-dimensional |
---|
| 609 | + * array and returning "dimms[layer0][layer1]"; |
---|
| 610 | + * |
---|
| 611 | + * For 3 layers, this function is similar to allocating a tri-dimensional |
---|
| 612 | + * array and returning "dimms[layer0][layer1][layer2]"; |
---|
| 613 | + */ |
---|
| 614 | +static inline struct dimm_info *edac_get_dimm(struct mem_ctl_info *mci, |
---|
| 615 | + int layer0, int layer1, int layer2) |
---|
| 616 | +{ |
---|
| 617 | + int index; |
---|
| 618 | + |
---|
| 619 | + if (layer0 < 0 |
---|
| 620 | + || (mci->n_layers > 1 && layer1 < 0) |
---|
| 621 | + || (mci->n_layers > 2 && layer2 < 0)) |
---|
| 622 | + return NULL; |
---|
| 623 | + |
---|
| 624 | + index = layer0; |
---|
| 625 | + |
---|
| 626 | + if (mci->n_layers > 1) |
---|
| 627 | + index = index * mci->layers[1].size + layer1; |
---|
| 628 | + |
---|
| 629 | + if (mci->n_layers > 2) |
---|
| 630 | + index = index * mci->layers[2].size + layer2; |
---|
| 631 | + |
---|
| 632 | + if (index < 0 || index >= mci->tot_dimms) |
---|
| 633 | + return NULL; |
---|
| 634 | + |
---|
| 635 | + if (WARN_ON_ONCE(mci->dimms[index]->idx != index)) |
---|
| 636 | + return NULL; |
---|
| 637 | + |
---|
| 638 | + return mci->dimms[index]; |
---|
| 639 | +} |
---|
| 640 | +#endif /* _LINUX_EDAC_H_ */ |
---|