Skip to content

Commit 23584da

Browse files
David Reganmiquelraynal
authored andcommitted
mtd: nand: brcmnand: fix mtd corrected bits stat
Currently we attempt to get the amount of flipped bits from a hardware location which is reset on every subpage. Instead obtain total flipped bits stat from hardware accumulator. In addition identify the correct maximum subpage corrected bits. Signed-off-by: David Regan <[email protected]> Reviewed-by: William Zhang <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent 79e441e commit 23584da

File tree

1 file changed

+38
-15
lines changed

1 file changed

+38
-15
lines changed

drivers/mtd/nand/raw/brcmnand/brcmnand.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

970977
static 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
*/
20682075
static 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

Comments
 (0)