| .. | .. |
|---|
| 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_ */ |
|---|