diff options
| -rw-r--r-- | drivers/edac/mce_amd.c | 176 | ||||
| -rw-r--r-- | drivers/edac/mce_amd.h | 1 |
2 files changed, 48 insertions, 129 deletions
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index bf6dd9978aa7..f6ebe5e9a57f 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
| @@ -64,17 +64,6 @@ EXPORT_SYMBOL_GPL(to_msgs); | |||
| 64 | const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; | 64 | const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; |
| 65 | EXPORT_SYMBOL_GPL(ii_msgs); | 65 | EXPORT_SYMBOL_GPL(ii_msgs); |
| 66 | 66 | ||
| 67 | static const char *f10h_nb_mce_desc[] = { | ||
| 68 | "HT link data error", | ||
| 69 | "Protocol error (link, L3, probe filter, etc.)", | ||
| 70 | "Parity error in NB-internal arrays", | ||
| 71 | "Link Retry due to IO link transmission error", | ||
| 72 | "L3 ECC data cache error", | ||
| 73 | "ECC error in L3 cache tag", | ||
| 74 | "L3 LRU parity bits error", | ||
| 75 | "ECC Error in the Probe Filter directory" | ||
| 76 | }; | ||
| 77 | |||
| 78 | static const char * const f15h_ic_mce_desc[] = { | 67 | static const char * const f15h_ic_mce_desc[] = { |
| 79 | "UC during a demand linefill from L2", | 68 | "UC during a demand linefill from L2", |
| 80 | "Parity error during data load from IC", | 69 | "Parity error during data load from IC", |
| @@ -112,6 +101,28 @@ static const char * const f15h_cu_mce_desc[] = { | |||
| 112 | "PRB address parity error" | 101 | "PRB address parity error" |
| 113 | }; | 102 | }; |
| 114 | 103 | ||
| 104 | static const char *nb_mce_desc[] = { | ||
| 105 | "DRAM ECC error detected on the NB", | ||
| 106 | "CRC error detected on HT link", | ||
| 107 | "Link-defined sync error packets detected on HT link", | ||
| 108 | "HT Master abort", | ||
| 109 | "HT Target abort", | ||
| 110 | "Invalid GART PTE entry during GART table walk", | ||
| 111 | "Unsupported atomic RMW received from an IO link", | ||
| 112 | "Watchdog timeout due to lack of progress", | ||
| 113 | "DRAM ECC error detected on the NB", | ||
| 114 | "SVM DMA Exclusion Vector error", | ||
| 115 | "HT data error detected on link", | ||
| 116 | "Protocol error (link, L3, probe filter)", | ||
| 117 | "NB internal arrays parity error", | ||
| 118 | "DRAM addr/ctl signals parity error", | ||
| 119 | "IO link transmission error", | ||
| 120 | "L3 data cache ECC error", /* xec = 0x1c */ | ||
| 121 | "L3 cache tag error", | ||
| 122 | "L3 LRU parity bits error", | ||
| 123 | "ECC Error in the Probe Filter directory" | ||
| 124 | }; | ||
| 125 | |||
| 115 | static const char * const fr_ex_mce_desc[] = { | 126 | static const char * const fr_ex_mce_desc[] = { |
| 116 | "CPU Watchdog timer expire", | 127 | "CPU Watchdog timer expire", |
| 117 | "Wakeup array dest tag", | 128 | "Wakeup array dest tag", |
| @@ -499,58 +510,31 @@ wrong_ls_mce: | |||
| 499 | pr_emerg(HW_ERR "Corrupted LS MCE info?\n"); | 510 | pr_emerg(HW_ERR "Corrupted LS MCE info?\n"); |
| 500 | } | 511 | } |
| 501 | 512 | ||
| 502 | static bool k8_nb_mce(u16 ec, u8 xec) | 513 | void amd_decode_nb_mce(struct mce *m) |
| 503 | { | 514 | { |
| 504 | bool ret = true; | 515 | struct cpuinfo_x86 *c = &boot_cpu_data; |
| 505 | 516 | int node_id = amd_get_nb_id(m->extcpu); | |
| 506 | switch (xec) { | 517 | u16 ec = EC(m->status); |
| 507 | case 0x1: | 518 | u8 xec = XEC(m->status, 0x1f); |
| 508 | pr_cont("CRC error detected on HT link.\n"); | 519 | u8 offset = 0; |
| 509 | break; | ||
| 510 | |||
| 511 | case 0x5: | ||
| 512 | pr_cont("Invalid GART PTE entry during GART table walk.\n"); | ||
| 513 | break; | ||
| 514 | |||
| 515 | case 0x6: | ||
| 516 | pr_cont("Unsupported atomic RMW received from an IO link.\n"); | ||
| 517 | break; | ||
| 518 | |||
| 519 | case 0x0: | ||
| 520 | case 0x8: | ||
| 521 | if (boot_cpu_data.x86 == 0x11) | ||
| 522 | return false; | ||
| 523 | |||
| 524 | pr_cont("DRAM ECC error detected on the NB.\n"); | ||
| 525 | break; | ||
| 526 | |||
| 527 | case 0xd: | ||
| 528 | pr_cont("Parity error on the DRAM addr/ctl signals.\n"); | ||
| 529 | break; | ||
| 530 | |||
| 531 | default: | ||
| 532 | ret = false; | ||
| 533 | break; | ||
| 534 | } | ||
| 535 | 520 | ||
| 536 | return ret; | 521 | pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id); |
| 537 | } | ||
| 538 | 522 | ||
| 539 | static bool f10h_nb_mce(u16 ec, u8 xec) | 523 | switch (xec) { |
| 540 | { | 524 | case 0x0 ... 0xe: |
| 541 | bool ret = true; | ||
| 542 | u8 offset = 0; | ||
| 543 | 525 | ||
| 544 | if (k8_nb_mce(ec, xec)) | 526 | /* special handling for DRAM ECCs */ |
| 545 | return true; | 527 | if (xec == 0x0 || xec == 0x8) { |
| 528 | /* no ECCs on F11h */ | ||
| 529 | if (c->x86 == 0x11) | ||
| 530 | goto wrong_nb_mce; | ||
| 546 | 531 | ||
| 547 | switch(xec) { | 532 | pr_cont("%s.\n", nb_mce_desc[xec]); |
| 548 | case 0xa ... 0xc: | ||
| 549 | offset = 10; | ||
| 550 | break; | ||
| 551 | 533 | ||
| 552 | case 0xe: | 534 | if (nb_bus_decoder) |
| 553 | offset = 11; | 535 | nb_bus_decoder(node_id, m); |
| 536 | return; | ||
| 537 | } | ||
| 554 | break; | 538 | break; |
| 555 | 539 | ||
| 556 | case 0xf: | 540 | case 0xf: |
| @@ -559,83 +543,25 @@ static bool f10h_nb_mce(u16 ec, u8 xec) | |||
| 559 | else if (BUS_ERROR(ec)) | 543 | else if (BUS_ERROR(ec)) |
| 560 | pr_cont("DMA Exclusion Vector Table Walk error.\n"); | 544 | pr_cont("DMA Exclusion Vector Table Walk error.\n"); |
| 561 | else | 545 | else |
| 562 | ret = false; | 546 | goto wrong_nb_mce; |
| 563 | 547 | return; | |
| 564 | goto out; | ||
| 565 | break; | ||
| 566 | 548 | ||
| 567 | case 0x19: | 549 | case 0x19: |
| 568 | if (boot_cpu_data.x86 == 0x15) | 550 | if (boot_cpu_data.x86 == 0x15) |
| 569 | pr_cont("Compute Unit Data Error.\n"); | 551 | pr_cont("Compute Unit Data Error.\n"); |
| 570 | else | 552 | else |
| 571 | ret = false; | 553 | goto wrong_nb_mce; |
| 572 | 554 | return; | |
| 573 | goto out; | ||
| 574 | break; | ||
| 575 | 555 | ||
| 576 | case 0x1c ... 0x1f: | 556 | case 0x1c ... 0x1f: |
| 577 | offset = 24; | 557 | offset = 13; |
| 578 | break; | 558 | break; |
| 579 | 559 | ||
| 580 | default: | 560 | default: |
| 581 | ret = false; | ||
| 582 | |||
| 583 | goto out; | ||
| 584 | break; | ||
| 585 | } | ||
| 586 | |||
| 587 | pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]); | ||
| 588 | |||
| 589 | out: | ||
| 590 | return ret; | ||
| 591 | } | ||
| 592 | |||
| 593 | static bool nb_noop_mce(u16 ec, u8 xec) | ||
| 594 | { | ||
| 595 | return false; | ||
| 596 | } | ||
| 597 | |||
| 598 | void amd_decode_nb_mce(struct mce *m) | ||
| 599 | { | ||
| 600 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 601 | int node_id = amd_get_nb_id(m->extcpu); | ||
| 602 | u16 ec = EC(m->status); | ||
| 603 | u8 xec = XEC(m->status, 0x1f); | ||
| 604 | |||
| 605 | pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id); | ||
| 606 | |||
| 607 | switch (xec) { | ||
| 608 | case 0x2: | ||
| 609 | pr_cont("Sync error (sync packets on HT link detected).\n"); | ||
| 610 | return; | ||
| 611 | |||
| 612 | case 0x3: | ||
| 613 | pr_cont("HT Master abort.\n"); | ||
| 614 | return; | ||
| 615 | |||
| 616 | case 0x4: | ||
| 617 | pr_cont("HT Target abort.\n"); | ||
| 618 | return; | ||
| 619 | |||
| 620 | case 0x7: | ||
| 621 | pr_cont("NB Watchdog timeout.\n"); | ||
| 622 | return; | ||
| 623 | |||
| 624 | case 0x9: | ||
| 625 | pr_cont("SVM DMA Exclusion Vector error.\n"); | ||
| 626 | return; | ||
| 627 | |||
| 628 | default: | ||
| 629 | break; | ||
| 630 | } | ||
| 631 | |||
| 632 | if (!fam_ops->nb_mce(ec, xec)) | ||
| 633 | goto wrong_nb_mce; | 561 | goto wrong_nb_mce; |
| 562 | } | ||
| 634 | 563 | ||
| 635 | if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15) | 564 | pr_cont("%s.\n", nb_mce_desc[xec - offset]); |
| 636 | if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) | ||
| 637 | nb_bus_decoder(node_id, m); | ||
| 638 | |||
| 639 | return; | 565 | return; |
| 640 | 566 | ||
| 641 | wrong_nb_mce: | 567 | wrong_nb_mce: |
| @@ -844,39 +770,33 @@ static int __init mce_amd_init(void) | |||
| 844 | case 0xf: | 770 | case 0xf: |
| 845 | fam_ops->dc_mce = k8_dc_mce; | 771 | fam_ops->dc_mce = k8_dc_mce; |
| 846 | fam_ops->ic_mce = k8_ic_mce; | 772 | fam_ops->ic_mce = k8_ic_mce; |
| 847 | fam_ops->nb_mce = k8_nb_mce; | ||
| 848 | break; | 773 | break; |
| 849 | 774 | ||
| 850 | case 0x10: | 775 | case 0x10: |
| 851 | fam_ops->dc_mce = f10h_dc_mce; | 776 | fam_ops->dc_mce = f10h_dc_mce; |
| 852 | fam_ops->ic_mce = k8_ic_mce; | 777 | fam_ops->ic_mce = k8_ic_mce; |
| 853 | fam_ops->nb_mce = f10h_nb_mce; | ||
| 854 | break; | 778 | break; |
| 855 | 779 | ||
| 856 | case 0x11: | 780 | case 0x11: |
| 857 | fam_ops->dc_mce = k8_dc_mce; | 781 | fam_ops->dc_mce = k8_dc_mce; |
| 858 | fam_ops->ic_mce = k8_ic_mce; | 782 | fam_ops->ic_mce = k8_ic_mce; |
| 859 | fam_ops->nb_mce = f10h_nb_mce; | ||
| 860 | break; | 783 | break; |
| 861 | 784 | ||
| 862 | case 0x12: | 785 | case 0x12: |
| 863 | fam_ops->dc_mce = f12h_dc_mce; | 786 | fam_ops->dc_mce = f12h_dc_mce; |
| 864 | fam_ops->ic_mce = k8_ic_mce; | 787 | fam_ops->ic_mce = k8_ic_mce; |
| 865 | fam_ops->nb_mce = nb_noop_mce; | ||
| 866 | break; | 788 | break; |
| 867 | 789 | ||
| 868 | case 0x14: | 790 | case 0x14: |
| 869 | nb_err_cpumask = 0x3; | 791 | nb_err_cpumask = 0x3; |
| 870 | fam_ops->dc_mce = f14h_dc_mce; | 792 | fam_ops->dc_mce = f14h_dc_mce; |
| 871 | fam_ops->ic_mce = f14h_ic_mce; | 793 | fam_ops->ic_mce = f14h_ic_mce; |
| 872 | fam_ops->nb_mce = nb_noop_mce; | ||
| 873 | break; | 794 | break; |
| 874 | 795 | ||
| 875 | case 0x15: | 796 | case 0x15: |
| 876 | xec_mask = 0x1f; | 797 | xec_mask = 0x1f; |
| 877 | fam_ops->dc_mce = f15h_dc_mce; | 798 | fam_ops->dc_mce = f15h_dc_mce; |
| 878 | fam_ops->ic_mce = f15h_ic_mce; | 799 | fam_ops->ic_mce = f15h_ic_mce; |
| 879 | fam_ops->nb_mce = f10h_nb_mce; | ||
| 880 | break; | 800 | break; |
| 881 | 801 | ||
| 882 | default: | 802 | default: |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 0106747e240c..6fcf599e691f 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
| @@ -82,7 +82,6 @@ extern const char *ii_msgs[]; | |||
| 82 | struct amd_decoder_ops { | 82 | struct amd_decoder_ops { |
| 83 | bool (*dc_mce)(u16, u8); | 83 | bool (*dc_mce)(u16, u8); |
| 84 | bool (*ic_mce)(u16, u8); | 84 | bool (*ic_mce)(u16, u8); |
| 85 | bool (*nb_mce)(u16, u8); | ||
| 86 | }; | 85 | }; |
| 87 | 86 | ||
| 88 | void amd_report_gart_errors(bool); | 87 | void amd_report_gart_errors(bool); |
