i7300_edac: enrich FBD error info for corrected errors
[deliverable/linux.git] / drivers / edac / i7300_edac.c
index e33c9900e269d61e61d37364e0cb3f95d7edd2a9..a06db65e1fefae2130ba8289121e6697ec994103 100644 (file)
@@ -277,6 +277,17 @@ static const char *ferr_global_lo_name[] = {
   #define NRECMEMB_CAS(v)      (((v) >> 16) & 0x1fff)
   #define NRECMEMB_RAS(v)      ((v) & 0xffff)
 
+#define REDMEMA                0xdc
+
+#define RECMEMA                0xe0
+  #define RECMEMA_BANK(v)      (((v) >> 12) & 7)
+  #define RECMEMA_RANK(v)      (((v) >> 8) & 15)
+
+#define RECMEMB                0xe4
+  #define RECMEMB_IS_WR(v)     ((v) & (1 << 31))
+  #define RECMEMB_CAS(v)       (((v) >> 16) & 0x1fff)
+  #define RECMEMB_RAS(v)       ((v) & 0xffff)
+
 
 /* Device name and register DID (Device ID) */
 struct i7300_dev_info {
@@ -403,10 +414,12 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
        struct i7300_pvt *pvt;
        u32 errnum, value;
        u16 val16;
-       int branch, bank, rank, cas, ras;
+       unsigned branch, bank, rank, cas, ras;
+       u32 syndrome;
+
        unsigned long errors;
        const char *specific;
-       bool is_fatal, is_wr;
+       bool is_wr;
 
        pvt = mci->pvt_info;
 
@@ -418,7 +431,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
                errnum = find_first_bit(&errors,
                                        ARRAY_SIZE(ferr_fat_fbd_name));
                specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
-               is_fatal = 1;
 
                branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
                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)
                snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
                        "FATAL (Branch=%d DRAM-Bank=%d %s "
                        "RAS=%d CAS=%d Err=0x%lx (%s))",
-                       branch >> 1, bank,
+                       branch, bank,
                        is_wr ? "RDWR" : "RD",
                        ras, cas,
                        errors, specific);
@@ -445,7 +457,6 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
                edac_mc_handle_fbd_ue(mci, rank, branch << 1,
                                      (branch << 1) + 1,
                                      pvt->tmp_prt_buffer);
-               return;
        }
 
        /* read in the 1st NON-FATAL error register */
@@ -456,20 +467,48 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
                errnum = find_first_bit(&errors,
                                        ARRAY_SIZE(ferr_nf_fbd_name));
                specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-               is_fatal = 0;
 
                /* Clear the error bit */
                pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
                                       FERR_GLOBAL_LO, value);
 
-               goto error_fbd;
-       }
-       return;
+               pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+                       REDMEMA, &syndrome);
 
-error_fbd:
+               branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
+               pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
+                                    RECMEMA, &val16);
+               bank = RECMEMA_BANK(val16);
+               rank = RECMEMA_RANK(val16);
 
-       i7300_mc_printk(mci, KERN_EMERG, "%s FBD error on branch %d: %s\n",
-                       is_fatal ? "Fatal" : "NOT fatal", branch, specific);
+               pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+                               RECMEMB, &value);
+
+               is_wr = RECMEMB_IS_WR(value);
+               cas = RECMEMB_CAS(value);
+               ras = RECMEMB_RAS(value);
+
+               /* Form out message */
+               snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
+                       "Corrected error (Branch=%d (channel %d or %d), "
+                       " DRAM-Bank=%d %s "
+                       "RAS=%d CAS=%d, CE Err=0x%lx, Syndrome=0x%08x(%s))",
+                       branch, branch << 1, (branch << 1) + 1,
+                       bank,
+                       is_wr ? "RDWR" : "RD",
+                       ras, cas,
+                       errors, syndrome, specific);
+
+               /*
+                * Call the helper to output message
+                * NOTE: Errors are reported per-branch, and not per-channel
+                *       Currently, we don't know how to identify the right
+                *       channel.
+                */
+               edac_mc_handle_fbd_ce(mci, rank, branch << 1,
+                                     pvt->tmp_prt_buffer);
+       }
+       return;
 }
 
 /*
This page took 0.033122 seconds and 5 git commands to generate.