diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-27 09:22:36 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-30 13:56:54 -0400 |
commit | 57021918aa9c310524d7e9754506e4e8272b4c0e (patch) | |
tree | afa0b4aac5a27ea1c7f9f5b26050ed34d18df487 /drivers/edac/i7300_edac.c | |
parent | 15154c57c62494292f43df9133a7b370cbbf1ecb (diff) |
i7300_edac: Add support for reporting FBD errors
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac/i7300_edac.c')
-rw-r--r-- | drivers/edac/i7300_edac.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index b5152256967f..728f9b0ab62c 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c | |||
@@ -161,6 +161,63 @@ static const char *numcol_toString[] = { | |||
161 | /************************************************ | 161 | /************************************************ |
162 | * i7300 Register definitions for error detection | 162 | * i7300 Register definitions for error detection |
163 | ************************************************/ | 163 | ************************************************/ |
164 | |||
165 | /* | ||
166 | * Device 16.1: FBD Error Registers | ||
167 | */ | ||
168 | #define FERR_FAT_FBD 0x98 | ||
169 | static const char *ferr_fat_fbd_name[] = { | ||
170 | [22] = "Non-Redundant Fast Reset Timeout", | ||
171 | [2] = ">Tmid Thermal event with intelligent throttling disabled", | ||
172 | [1] = "Memory or FBD configuration CRC read error", | ||
173 | [0] = "Memory Write error on non-redundant retry or " | ||
174 | "FBD configuration Write error on retry", | ||
175 | }; | ||
176 | #define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28)) | ||
177 | #define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) | ||
178 | |||
179 | #define FERR_NF_FBD 0xa0 | ||
180 | static const char *ferr_nf_fbd_name[] = { | ||
181 | [24] = "DIMM-Spare Copy Completed", | ||
182 | [23] = "DIMM-Spare Copy Initiated", | ||
183 | [22] = "Redundant Fast Reset Timeout", | ||
184 | [21] = "Memory Write error on redundant retry", | ||
185 | [18] = "SPD protocol Error", | ||
186 | [17] = "FBD Northbound parity error on FBD Sync Status", | ||
187 | [16] = "Correctable Patrol Data ECC", | ||
188 | [15] = "Correctable Resilver- or Spare-Copy Data ECC", | ||
189 | [14] = "Correctable Mirrored Demand Data ECC", | ||
190 | [13] = "Correctable Non-Mirrored Demand Data ECC", | ||
191 | [11] = "Memory or FBD configuration CRC read error", | ||
192 | [10] = "FBD Configuration Write error on first attempt", | ||
193 | [9] = "Memory Write error on first attempt", | ||
194 | [8] = "Non-Aliased Uncorrectable Patrol Data ECC", | ||
195 | [7] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", | ||
196 | [6] = "Non-Aliased Uncorrectable Mirrored Demand Data ECC", | ||
197 | [5] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC", | ||
198 | [4] = "Aliased Uncorrectable Patrol Data ECC", | ||
199 | [3] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC", | ||
200 | [2] = "Aliased Uncorrectable Mirrored Demand Data ECC", | ||
201 | [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", | ||
202 | [0] = "Uncorrectable Data ECC on Replay", | ||
203 | }; | ||
204 | #define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28)) | ||
205 | #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ | ||
206 | (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ | ||
207 | (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ | ||
208 | (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ | ||
209 | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ | ||
210 | (1 << 1) | (1 << 0)) | ||
211 | |||
212 | #define EMASK_FBD 0xa8 | ||
213 | #define EMASK_FBD_ERR_MASK ((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24) |\ | ||
214 | (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) |\ | ||
215 | (1 << 18) | (1 << 17) | (1 << 16) | (1 << 14) |\ | ||
216 | (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) |\ | ||
217 | (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\ | ||
218 | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\ | ||
219 | (1 << 1) | (1 << 0)) | ||
220 | |||
164 | /* | 221 | /* |
165 | * Device 16.2: Global Error Registers | 222 | * Device 16.2: Global Error Registers |
166 | */ | 223 | */ |
@@ -339,6 +396,61 @@ error_global: | |||
339 | } | 396 | } |
340 | 397 | ||
341 | /* | 398 | /* |
399 | * i7300_process_fbd_error Retrieve the hardware error information from | ||
400 | * the hardware and cache it in the 'info' | ||
401 | * structure | ||
402 | */ | ||
403 | static void i7300_process_fbd_error(struct mem_ctl_info *mci, | ||
404 | struct i7300_error_info *info) | ||
405 | { | ||
406 | struct i7300_pvt *pvt; | ||
407 | u32 errnum, value; | ||
408 | int branch; | ||
409 | unsigned long errors; | ||
410 | const char *specific; | ||
411 | bool is_fatal; | ||
412 | |||
413 | pvt = mci->pvt_info; | ||
414 | |||
415 | /* read in the 1st FATAL error register */ | ||
416 | pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, | ||
417 | FERR_FAT_FBD, &value); | ||
418 | if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) { | ||
419 | errors = value & FERR_FAT_FBD_ERR_MASK ; | ||
420 | errnum = find_first_bit(&errors, | ||
421 | ARRAY_SIZE(ferr_fat_fbd_name)); | ||
422 | specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); | ||
423 | is_fatal = 1; | ||
424 | |||
425 | branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; | ||
426 | |||
427 | goto error_fbd; | ||
428 | } | ||
429 | |||
430 | /* read in the 1st NON-FATAL error register */ | ||
431 | pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, | ||
432 | FERR_NF_FBD, &value); | ||
433 | if (unlikely(value & FERR_NF_FBD_ERR_MASK)) { | ||
434 | errors = value & FERR_NF_FBD_ERR_MASK; | ||
435 | errnum = find_first_bit(&errors, | ||
436 | ARRAY_SIZE(ferr_nf_fbd_name)); | ||
437 | specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); | ||
438 | is_fatal = 0; | ||
439 | |||
440 | /* Clear the error bit */ | ||
441 | pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, | ||
442 | FERR_GLOBAL_LO, value); | ||
443 | |||
444 | goto error_fbd; | ||
445 | } | ||
446 | return; | ||
447 | |||
448 | error_fbd: | ||
449 | i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n", | ||
450 | is_fatal ? "Fatal" : "NOT fatal", branch, specific); | ||
451 | } | ||
452 | |||
453 | /* | ||
342 | * i7300_process_error_info Retrieve the hardware error information from | 454 | * i7300_process_error_info Retrieve the hardware error information from |
343 | * the hardware and cache it in the 'info' | 455 | * the hardware and cache it in the 'info' |
344 | * structure | 456 | * structure |
@@ -347,6 +459,7 @@ static void i7300_process_error_info(struct mem_ctl_info *mci, | |||
347 | struct i7300_error_info *info) | 459 | struct i7300_error_info *info) |
348 | { | 460 | { |
349 | i7300_process_error_global(mci, info); | 461 | i7300_process_error_global(mci, info); |
462 | i7300_process_fbd_error(mci, info); | ||
350 | }; | 463 | }; |
351 | 464 | ||
352 | /* | 465 | /* |
@@ -381,6 +494,18 @@ static void i7300_check_error(struct mem_ctl_info *mci) | |||
381 | */ | 494 | */ |
382 | static void i7300_enable_error_reporting(struct mem_ctl_info *mci) | 495 | static void i7300_enable_error_reporting(struct mem_ctl_info *mci) |
383 | { | 496 | { |
497 | struct i7300_pvt *pvt = mci->pvt_info; | ||
498 | u32 fbd_error_mask; | ||
499 | |||
500 | /* Read the FBD Error Mask Register */ | ||
501 | pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, | ||
502 | EMASK_FBD, &fbd_error_mask); | ||
503 | |||
504 | /* Enable with a '0' */ | ||
505 | fbd_error_mask &= ~(EMASK_FBD_ERR_MASK); | ||
506 | |||
507 | pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map, | ||
508 | EMASK_FBD, fbd_error_mask); | ||
384 | } | 509 | } |
385 | 510 | ||
386 | /************************************************ | 511 | /************************************************ |