diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-22 20:45:50 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-10 10:44:54 -0400 |
commit | 276b824c3095b09e8cb76f5709f56e9c6818ae85 (patch) | |
tree | 8902c16854157bcecbcfc230e1d21ee935697d98 /drivers/edac | |
parent | 17cb7b0cf78c14913c5410eff2ce03e1d9c8d958 (diff) |
i7core_edac: some fixes at error injection code
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i7core_edac.c | 104 |
1 files changed, 51 insertions, 53 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 86af14840b88..72859e87aeb2 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | #include "edac_core.h" | 33 | #include "edac_core.h" |
34 | 34 | ||
35 | /* To use the new pci_[read/write]_config_qword instead of two dword */ | ||
36 | #define USE_QWORD 0 | ||
37 | |||
38 | /* | 35 | /* |
39 | * Alter this version for the module when modifications are made | 36 | * Alter this version for the module when modifications are made |
40 | */ | 37 | */ |
@@ -473,7 +470,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket) | |||
473 | "x%x x 0x%x\n", | 470 | "x%x x 0x%x\n", |
474 | numdimms(pvt->info.max_dod), | 471 | numdimms(pvt->info.max_dod), |
475 | numrank(pvt->info.max_dod >> 2), | 472 | numrank(pvt->info.max_dod >> 2), |
476 | numbank(pvt->info.max_dod >> 4)); | 473 | numbank(pvt->info.max_dod >> 4), |
477 | numrow(pvt->info.max_dod >> 6), | 474 | numrow(pvt->info.max_dod >> 6), |
478 | numcol(pvt->info.max_dod >> 9)); | 475 | numcol(pvt->info.max_dod >> 9)); |
479 | 476 | ||
@@ -646,7 +643,7 @@ static ssize_t i7core_inject_socket_store(struct mem_ctl_info *mci, | |||
646 | int rc; | 643 | int rc; |
647 | 644 | ||
648 | rc = strict_strtoul(data, 10, &value); | 645 | rc = strict_strtoul(data, 10, &value); |
649 | if ((rc < 0) || (value > pvt->sockets)) | 646 | if ((rc < 0) || (value >= pvt->sockets)) |
650 | return 0; | 647 | return 0; |
651 | 648 | ||
652 | pvt->inject.section = (u32) value; | 649 | pvt->inject.section = (u32) value; |
@@ -803,7 +800,7 @@ static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci, | |||
803 | else | 800 | else |
804 | return cmd - data; | 801 | return cmd - data; |
805 | } else if (!strcasecmp(cmd, "dimm")) { | 802 | } else if (!strcasecmp(cmd, "dimm")) { |
806 | if (value < 4) | 803 | if (value < 3) |
807 | pvt->inject.dimm = value; | 804 | pvt->inject.dimm = value; |
808 | else | 805 | else |
809 | return cmd - data; | 806 | return cmd - data; |
@@ -813,7 +810,7 @@ static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci, | |||
813 | else | 810 | else |
814 | return cmd - data; | 811 | return cmd - data; |
815 | } else if (!strcasecmp(cmd, "bank")) { | 812 | } else if (!strcasecmp(cmd, "bank")) { |
816 | if (value < 4) | 813 | if (value < 32) |
817 | pvt->inject.bank = value; | 814 | pvt->inject.bank = value; |
818 | else | 815 | else |
819 | return cmd - data; | 816 | return cmd - data; |
@@ -870,6 +867,28 @@ static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci, | |||
870 | channel, dimm, bank, rank, page, col); | 867 | channel, dimm, bank, rank, page, col); |
871 | } | 868 | } |
872 | 869 | ||
870 | static int write_and_test(struct pci_dev *dev, int where, u32 val) | ||
871 | { | ||
872 | u32 read; | ||
873 | int count; | ||
874 | |||
875 | for (count = 0; count < 10; count++) { | ||
876 | if (count) | ||
877 | msleep (100); | ||
878 | pci_write_config_dword(dev, where, val); | ||
879 | pci_read_config_dword(dev, where, &read); | ||
880 | |||
881 | if (read == val) | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | debugf0("Error Injection Register 0x%02x: Tried to write 0x%08x, " | ||
886 | "but read: 0x%08x\n", where, val, read); | ||
887 | |||
888 | return -EINVAL; | ||
889 | } | ||
890 | |||
891 | |||
873 | /* | 892 | /* |
874 | * This routine prepares the Memory Controller for error injection. | 893 | * This routine prepares the Memory Controller for error injection. |
875 | * The error will be injected when some process tries to write to the | 894 | * The error will be injected when some process tries to write to the |
@@ -949,70 +968,49 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, | |||
949 | else | 968 | else |
950 | mask |= (pvt->inject.col & 0x3fffL); | 969 | mask |= (pvt->inject.col & 0x3fffL); |
951 | 970 | ||
952 | /* Unlock writes to registers */ | 971 | /* |
972 | * bit 0: REPEAT_EN | ||
973 | * bits 1-2: MASK_HALF_CACHELINE | ||
974 | * bit 3: INJECT_ECC | ||
975 | * bit 4: INJECT_ADDR_PARITY | ||
976 | */ | ||
977 | |||
978 | injectmask = (pvt->inject.type & 1) | | ||
979 | (pvt->inject.section & 0x3) << 1 | | ||
980 | (pvt->inject.type & 0x6) << (3 - 1); | ||
981 | |||
982 | /* Unlock writes to registers - this register is write only */ | ||
953 | pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket], | 983 | pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket], |
954 | MC_CFG_CONTROL, 0x2); | 984 | MC_CFG_CONTROL, 0x2); |
955 | msleep(100); | ||
956 | 985 | ||
986 | #if 0 | ||
957 | /* Zeroes error count registers */ | 987 | /* Zeroes error count registers */ |
958 | pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4], | 988 | pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4], |
959 | MC_TEST_ERR_RCV1, 0); | 989 | MC_TEST_ERR_RCV1, 0); |
960 | pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4], | 990 | pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4], |
961 | MC_TEST_ERR_RCV0, 0); | 991 | MC_TEST_ERR_RCV0, 0); |
962 | pvt->ce_count_available[pvt->inject.socket] = 0; | 992 | pvt->ce_count_available[pvt->inject.socket] = 0; |
993 | #endif | ||
963 | 994 | ||
964 | 995 | write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | |
965 | #if USE_QWORD | ||
966 | pci_write_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
967 | MC_CHANNEL_ADDR_MATCH, mask); | 996 | MC_CHANNEL_ADDR_MATCH, mask); |
968 | #else | 997 | write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], |
969 | pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
970 | MC_CHANNEL_ADDR_MATCH, mask); | ||
971 | pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
972 | MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L); | 998 | MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L); |
973 | #endif | ||
974 | 999 | ||
975 | #if 1 | 1000 | write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], |
976 | #if USE_QWORD | ||
977 | u64 rdmask; | ||
978 | pci_read_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
979 | MC_CHANNEL_ADDR_MATCH, &rdmask); | ||
980 | debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n", | ||
981 | mask, rdmask); | ||
982 | #else | ||
983 | u32 rdmask1, rdmask2; | ||
984 | |||
985 | pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
986 | MC_CHANNEL_ADDR_MATCH, &rdmask1); | ||
987 | pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
988 | MC_CHANNEL_ADDR_MATCH + 4, &rdmask2); | ||
989 | |||
990 | debugf0("Inject addr match write 0x%016llx, read: 0x%08x 0x%08x\n", | ||
991 | mask, rdmask1, rdmask2); | ||
992 | #endif | ||
993 | #endif | ||
994 | |||
995 | pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
996 | MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask); | 1001 | MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask); |
997 | 1002 | ||
1003 | write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
1004 | MC_CHANNEL_ERROR_MASK, injectmask); | ||
1005 | |||
998 | /* | 1006 | /* |
999 | * bit 0: REPEAT_EN | 1007 | * This is something undocumented, based on my tests |
1000 | * bits 1-2: MASK_HALF_CACHELINE | 1008 | * Without writing 8 to this register, errors aren't injected. Not sure |
1001 | * bit 3: INJECT_ECC | 1009 | * why. |
1002 | * bit 4: INJECT_ADDR_PARITY | ||
1003 | */ | 1010 | */ |
1011 | pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket], | ||
1012 | MC_CFG_CONTROL, 8); | ||
1004 | 1013 | ||
1005 | injectmask = (pvt->inject.type & 1) | | ||
1006 | (pvt->inject.section & 0x3) << 1 | | ||
1007 | (pvt->inject.type & 0x6) << (3 - 1); | ||
1008 | |||
1009 | pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], | ||
1010 | MC_CHANNEL_ERROR_MASK, injectmask); | ||
1011 | |||
1012 | #if 0 | ||
1013 | /* lock writes to registers */ | ||
1014 | pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0); | ||
1015 | #endif | ||
1016 | debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," | 1014 | debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," |
1017 | " inject 0x%08x\n", | 1015 | " inject 0x%08x\n", |
1018 | mask, pvt->inject.eccmask, injectmask); | 1016 | mask, pvt->inject.eccmask, injectmask); |