@@ -360,6 +360,7 @@ enum brcmnand_reg {
360360 BRCMNAND_CORR_THRESHOLD_EXT ,
361361 BRCMNAND_UNCORR_COUNT ,
362362 BRCMNAND_CORR_COUNT ,
363+ BRCMNAND_READ_ERROR_COUNT ,
363364 BRCMNAND_CORR_EXT_ADDR ,
364365 BRCMNAND_CORR_ADDR ,
365366 BRCMNAND_UNCORR_EXT_ADDR ,
@@ -390,6 +391,7 @@ static const u16 brcmnand_regs_v21[] = {
390391 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
391392 [BRCMNAND_UNCORR_COUNT ] = 0 ,
392393 [BRCMNAND_CORR_COUNT ] = 0 ,
394+ [BRCMNAND_READ_ERROR_COUNT ] = 0 ,
393395 [BRCMNAND_CORR_EXT_ADDR ] = 0x60 ,
394396 [BRCMNAND_CORR_ADDR ] = 0x64 ,
395397 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x68 ,
@@ -420,6 +422,7 @@ static const u16 brcmnand_regs_v33[] = {
420422 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
421423 [BRCMNAND_UNCORR_COUNT ] = 0 ,
422424 [BRCMNAND_CORR_COUNT ] = 0 ,
425+ [BRCMNAND_READ_ERROR_COUNT ] = 0x80 ,
423426 [BRCMNAND_CORR_EXT_ADDR ] = 0x70 ,
424427 [BRCMNAND_CORR_ADDR ] = 0x74 ,
425428 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x78 ,
@@ -450,6 +453,7 @@ static const u16 brcmnand_regs_v50[] = {
450453 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
451454 [BRCMNAND_UNCORR_COUNT ] = 0 ,
452455 [BRCMNAND_CORR_COUNT ] = 0 ,
456+ [BRCMNAND_READ_ERROR_COUNT ] = 0x80 ,
453457 [BRCMNAND_CORR_EXT_ADDR ] = 0x70 ,
454458 [BRCMNAND_CORR_ADDR ] = 0x74 ,
455459 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x78 ,
@@ -480,6 +484,7 @@ static const u16 brcmnand_regs_v60[] = {
480484 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0xc4 ,
481485 [BRCMNAND_UNCORR_COUNT ] = 0xfc ,
482486 [BRCMNAND_CORR_COUNT ] = 0x100 ,
487+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
483488 [BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
484489 [BRCMNAND_CORR_ADDR ] = 0x110 ,
485490 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -510,6 +515,7 @@ static const u16 brcmnand_regs_v71[] = {
510515 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0xe0 ,
511516 [BRCMNAND_UNCORR_COUNT ] = 0xfc ,
512517 [BRCMNAND_CORR_COUNT ] = 0x100 ,
518+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
513519 [BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
514520 [BRCMNAND_CORR_ADDR ] = 0x110 ,
515521 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -540,6 +546,7 @@ static const u16 brcmnand_regs_v72[] = {
540546 [BRCMNAND_CORR_THRESHOLD_EXT ] = 0xe0 ,
541547 [BRCMNAND_UNCORR_COUNT ] = 0xfc ,
542548 [BRCMNAND_CORR_COUNT ] = 0x100 ,
549+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
543550 [BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
544551 [BRCMNAND_CORR_ADDR ] = 0x110 ,
545552 [BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -960,11 +967,11 @@ static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs,
960967 return offs_cs0 + cs * ctrl -> reg_spacing + cs_offs ;
961968}
962969
963- static inline u32 brcmnand_count_corrected (struct brcmnand_controller * ctrl )
970+ static inline u32 brcmnand_corr_total (struct brcmnand_controller * ctrl )
964971{
965- if (ctrl -> nand_version < 0x0600 )
966- return 1 ;
967- return brcmnand_read_reg (ctrl , BRCMNAND_CORR_COUNT );
972+ if (ctrl -> nand_version < 0x400 )
973+ return 0 ;
974+ return brcmnand_read_reg (ctrl , BRCMNAND_READ_ERROR_COUNT );
968975}
969976
970977static void brcmnand_wr_corr_thresh (struct brcmnand_host * host , u8 val )
@@ -2067,15 +2074,20 @@ static int brcmnand_dma_trans(struct brcmnand_host *host, u64 addr, u32 *buf,
20672074 */
20682075static int brcmnand_read_by_pio (struct mtd_info * mtd , struct nand_chip * chip ,
20692076 u64 addr , unsigned int trans , u32 * buf ,
2070- u8 * oob , u64 * err_addr )
2077+ u8 * oob , u64 * err_addr , unsigned int * corr )
20712078{
20722079 struct brcmnand_host * host = nand_get_controller_data (chip );
20732080 struct brcmnand_controller * ctrl = host -> ctrl ;
20742081 int i , ret = 0 ;
2082+ unsigned int prev_corr ;
2083+
2084+ if (corr )
2085+ * corr = 0 ;
20752086
20762087 brcmnand_clear_ecc_addr (ctrl );
20772088
20782089 for (i = 0 ; i < trans ; i ++ , addr += FC_BYTES ) {
2090+ prev_corr = brcmnand_corr_total (ctrl );
20792091 brcmnand_set_cmd_addr (mtd , addr );
20802092 /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
20812093 brcmnand_send_cmd (host , CMD_PAGE_READ );
@@ -2100,13 +2112,16 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
21002112
21012113 if (* err_addr )
21022114 ret = - EBADMSG ;
2103- }
2115+ else {
2116+ * err_addr = brcmnand_get_correcc_addr (ctrl );
21042117
2105- if (! ret ) {
2106- * err_addr = brcmnand_get_correcc_addr ( ctrl ) ;
2118+ if (* err_addr ) {
2119+ ret = - EUCLEAN ;
21072120
2108- if (* err_addr )
2109- ret = - EUCLEAN ;
2121+ if (corr && (brcmnand_corr_total (ctrl ) - prev_corr ) > * corr )
2122+ * corr = brcmnand_corr_total (ctrl ) - prev_corr ;
2123+ }
2124+ }
21102125 }
21112126 }
21122127
@@ -2174,6 +2189,8 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
21742189 int err ;
21752190 bool retry = true;
21762191 bool edu_err = false;
2192+ unsigned int corrected = 0 ; /* max corrected bits per subpage */
2193+ unsigned int prev_tot = brcmnand_corr_total (ctrl );
21772194
21782195 dev_dbg (ctrl -> dev , "read %llx -> %p\n" , (unsigned long long )addr , buf );
21792196
@@ -2201,9 +2218,11 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
22012218 memset (oob , 0x99 , mtd -> oobsize );
22022219
22032220 err = brcmnand_read_by_pio (mtd , chip , addr , trans , buf ,
2204- oob , & err_addr );
2221+ oob , & err_addr , & corrected );
22052222 }
22062223
2224+ mtd -> ecc_stats .corrected += brcmnand_corr_total (ctrl ) - prev_tot ;
2225+
22072226 if (mtd_is_eccerr (err )) {
22082227 /*
22092228 * On controller version and 7.0, 7.1 , DMA read after a
@@ -2241,16 +2260,20 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
22412260 }
22422261
22432262 if (mtd_is_bitflip (err )) {
2244- unsigned int corrected = brcmnand_count_corrected (ctrl );
2245-
22462263 /* in case of EDU correctable error we read again using PIO */
22472264 if (edu_err )
22482265 err = brcmnand_read_by_pio (mtd , chip , addr , trans , buf ,
2249- oob , & err_addr );
2266+ oob , & err_addr , & corrected );
22502267
22512268 dev_dbg (ctrl -> dev , "corrected error at 0x%llx\n" ,
22522269 (unsigned long long )err_addr );
2253- mtd -> ecc_stats .corrected += corrected ;
2270+ /*
2271+ * if flipped bits accumulator is not supported but we detected
2272+ * a correction, increase stat by 1 to match previous behavior.
2273+ */
2274+ if (brcmnand_corr_total (ctrl ) == prev_tot )
2275+ mtd -> ecc_stats .corrected ++ ;
2276+
22542277 /* Always exceed the software-imposed threshold */
22552278 return max (mtd -> bitflip_threshold , corrected );
22562279 }
0 commit comments