diff options
| -rw-r--r-- | drivers/edac/i7300_edac.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index e33c9900e269..a06db65e1fef 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c | |||
| @@ -277,6 +277,17 @@ static const char *ferr_global_lo_name[] = { | |||
| 277 | #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff) | 277 | #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff) |
| 278 | #define NRECMEMB_RAS(v) ((v) & 0xffff) | 278 | #define NRECMEMB_RAS(v) ((v) & 0xffff) |
| 279 | 279 | ||
| 280 | #define REDMEMA 0xdc | ||
| 281 | |||
| 282 | #define RECMEMA 0xe0 | ||
| 283 | #define RECMEMA_BANK(v) (((v) >> 12) & 7) | ||
| 284 | #define RECMEMA_RANK(v) (((v) >> 8) & 15) | ||
| 285 | |||
| 286 | #define RECMEMB 0xe4 | ||
| 287 | #define RECMEMB_IS_WR(v) ((v) & (1 << 31)) | ||
| 288 | #define RECMEMB_CAS(v) (((v) >> 16) & 0x1fff) | ||
| 289 | #define RECMEMB_RAS(v) ((v) & 0xffff) | ||
| 290 | |||
| 280 | 291 | ||
| 281 | /* Device name and register DID (Device ID) */ | 292 | /* Device name and register DID (Device ID) */ |
| 282 | struct i7300_dev_info { | 293 | struct i7300_dev_info { |
| @@ -403,10 +414,12 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) | |||
| 403 | struct i7300_pvt *pvt; | 414 | struct i7300_pvt *pvt; |
| 404 | u32 errnum, value; | 415 | u32 errnum, value; |
| 405 | u16 val16; | 416 | u16 val16; |
| 406 | int branch, bank, rank, cas, ras; | 417 | unsigned branch, bank, rank, cas, ras; |
| 418 | u32 syndrome; | ||
| 419 | |||
| 407 | unsigned long errors; | 420 | unsigned long errors; |
| 408 | const char *specific; | 421 | const char *specific; |
| 409 | bool is_fatal, is_wr; | 422 | bool is_wr; |
| 410 | 423 | ||
| 411 | pvt = mci->pvt_info; | 424 | pvt = mci->pvt_info; |
| 412 | 425 | ||
| @@ -418,7 +431,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) | |||
| 418 | errnum = find_first_bit(&errors, | 431 | errnum = find_first_bit(&errors, |
| 419 | ARRAY_SIZE(ferr_fat_fbd_name)); | 432 | ARRAY_SIZE(ferr_fat_fbd_name)); |
| 420 | specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); | 433 | specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); |
| 421 | is_fatal = 1; | ||
| 422 | 434 | ||
| 423 | branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; | 435 | branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; |
| 424 | pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, | 436 | pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, |
| @@ -436,7 +448,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) | |||
| 436 | snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, | 448 | snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, |
| 437 | "FATAL (Branch=%d DRAM-Bank=%d %s " | 449 | "FATAL (Branch=%d DRAM-Bank=%d %s " |
| 438 | "RAS=%d CAS=%d Err=0x%lx (%s))", | 450 | "RAS=%d CAS=%d Err=0x%lx (%s))", |
| 439 | branch >> 1, bank, | 451 | branch, bank, |
| 440 | is_wr ? "RDWR" : "RD", | 452 | is_wr ? "RDWR" : "RD", |
| 441 | ras, cas, | 453 | ras, cas, |
| 442 | errors, specific); | 454 | errors, specific); |
| @@ -445,7 +457,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) | |||
| 445 | edac_mc_handle_fbd_ue(mci, rank, branch << 1, | 457 | edac_mc_handle_fbd_ue(mci, rank, branch << 1, |
| 446 | (branch << 1) + 1, | 458 | (branch << 1) + 1, |
| 447 | pvt->tmp_prt_buffer); | 459 | pvt->tmp_prt_buffer); |
| 448 | return; | ||
| 449 | } | 460 | } |
| 450 | 461 | ||
| 451 | /* read in the 1st NON-FATAL error register */ | 462 | /* read in the 1st NON-FATAL error register */ |
| @@ -456,20 +467,48 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) | |||
| 456 | errnum = find_first_bit(&errors, | 467 | errnum = find_first_bit(&errors, |
| 457 | ARRAY_SIZE(ferr_nf_fbd_name)); | 468 | ARRAY_SIZE(ferr_nf_fbd_name)); |
| 458 | specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); | 469 | specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); |
| 459 | is_fatal = 0; | ||
| 460 | 470 | ||
| 461 | /* Clear the error bit */ | 471 | /* Clear the error bit */ |
| 462 | pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, | 472 | pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, |
| 463 | FERR_GLOBAL_LO, value); | 473 | FERR_GLOBAL_LO, value); |
| 464 | 474 | ||
| 465 | goto error_fbd; | 475 | pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, |
| 466 | } | 476 | REDMEMA, &syndrome); |
| 467 | return; | ||
| 468 | 477 | ||
| 469 | error_fbd: | 478 | branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0; |
| 479 | pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, | ||
| 480 | RECMEMA, &val16); | ||
| 481 | bank = RECMEMA_BANK(val16); | ||
| 482 | rank = RECMEMA_RANK(val16); | ||
| 470 | 483 | ||
| 471 | i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n", | 484 | pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, |
| 472 | is_fatal ? "Fatal" : "NOT fatal", branch, specific); | 485 | RECMEMB, &value); |
| 486 | |||
| 487 | is_wr = RECMEMB_IS_WR(value); | ||
| 488 | cas = RECMEMB_CAS(value); | ||
| 489 | ras = RECMEMB_RAS(value); | ||
| 490 | |||
| 491 | /* Form out message */ | ||
| 492 | snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, | ||
| 493 | "Corrected error (Branch=%d (channel %d or %d), " | ||
| 494 | " DRAM-Bank=%d %s " | ||
| 495 | "RAS=%d CAS=%d, CE Err=0x%lx, Syndrome=0x%08x(%s))", | ||
| 496 | branch, branch << 1, (branch << 1) + 1, | ||
| 497 | bank, | ||
| 498 | is_wr ? "RDWR" : "RD", | ||
| 499 | ras, cas, | ||
| 500 | errors, syndrome, specific); | ||
| 501 | |||
| 502 | /* | ||
| 503 | * Call the helper to output message | ||
| 504 | * NOTE: Errors are reported per-branch, and not per-channel | ||
| 505 | * Currently, we don't know how to identify the right | ||
| 506 | * channel. | ||
| 507 | */ | ||
| 508 | edac_mc_handle_fbd_ce(mci, rank, branch << 1, | ||
| 509 | pvt->tmp_prt_buffer); | ||
| 510 | } | ||
| 511 | return; | ||
| 473 | } | 512 | } |
| 474 | 513 | ||
| 475 | /* | 514 | /* |
