Skip to content

Commit 40cbe6e

Browse files
Boris BREZILLONcomputersforpeace
authored andcommitted
mtd: nand: use nand_check_erased_ecc_chunk in default ECC read functions
The default NAND read functions are relying on the underlying controller driver to correct bitflips, but some of those controllers cannot properly fix bitflips in erased pages. Check for bitflips in erased pages in default core functions if the driver delegated the this check by setting the NAND_ECC_GENERIC_ERASED_CHECK flag. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Tested-by: Franklin S Cooper Jr. <fcooper@ti.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
1 parent 6e94119 commit 40cbe6e

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

drivers/mtd/nand/nand_base.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
14261426

14271427
stat = chip->ecc.correct(mtd, p,
14281428
&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
1429+
if (stat == -EBADMSG &&
1430+
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
1431+
/* check for empty pages with bitflips */
1432+
stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
1433+
&chip->buffers->ecccode[i],
1434+
chip->ecc.bytes,
1435+
NULL, 0,
1436+
chip->ecc.strength);
1437+
}
1438+
14291439
if (stat < 0) {
14301440
mtd->ecc_stats.failed++;
14311441
} else {
@@ -1475,6 +1485,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
14751485
int stat;
14761486

14771487
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
1488+
if (stat == -EBADMSG &&
1489+
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
1490+
/* check for empty pages with bitflips */
1491+
stat = nand_check_erased_ecc_chunk(p, eccsize,
1492+
&ecc_code[i], eccbytes,
1493+
NULL, 0,
1494+
chip->ecc.strength);
1495+
}
1496+
14781497
if (stat < 0) {
14791498
mtd->ecc_stats.failed++;
14801499
} else {
@@ -1527,6 +1546,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
15271546
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
15281547

15291548
stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
1549+
if (stat == -EBADMSG &&
1550+
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
1551+
/* check for empty pages with bitflips */
1552+
stat = nand_check_erased_ecc_chunk(p, eccsize,
1553+
&ecc_code[i], eccbytes,
1554+
NULL, 0,
1555+
chip->ecc.strength);
1556+
}
1557+
15301558
if (stat < 0) {
15311559
mtd->ecc_stats.failed++;
15321560
} else {
@@ -1554,6 +1582,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
15541582
int i, eccsize = chip->ecc.size;
15551583
int eccbytes = chip->ecc.bytes;
15561584
int eccsteps = chip->ecc.steps;
1585+
int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
15571586
uint8_t *p = buf;
15581587
uint8_t *oob = chip->oob_poi;
15591588
unsigned int max_bitflips = 0;
@@ -1573,19 +1602,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
15731602
chip->read_buf(mtd, oob, eccbytes);
15741603
stat = chip->ecc.correct(mtd, p, oob, NULL);
15751604

1576-
if (stat < 0) {
1577-
mtd->ecc_stats.failed++;
1578-
} else {
1579-
mtd->ecc_stats.corrected += stat;
1580-
max_bitflips = max_t(unsigned int, max_bitflips, stat);
1581-
}
1582-
15831605
oob += eccbytes;
15841606

15851607
if (chip->ecc.postpad) {
15861608
chip->read_buf(mtd, oob, chip->ecc.postpad);
15871609
oob += chip->ecc.postpad;
15881610
}
1611+
1612+
if (stat == -EBADMSG &&
1613+
(chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
1614+
/* check for empty pages with bitflips */
1615+
stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
1616+
oob - eccpadbytes,
1617+
eccpadbytes,
1618+
NULL, 0,
1619+
chip->ecc.strength);
1620+
}
1621+
1622+
if (stat < 0) {
1623+
mtd->ecc_stats.failed++;
1624+
} else {
1625+
mtd->ecc_stats.corrected += stat;
1626+
max_bitflips = max_t(unsigned int, max_bitflips, stat);
1627+
}
15891628
}
15901629

15911630
/* Calculate remaining oob bytes */

include/linux/mtd/nand.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ typedef enum {
129129
/* Enable Hardware ECC before syndrome is read back from flash */
130130
#define NAND_ECC_READSYN 2
131131

132+
/*
133+
* Enable generic NAND 'page erased' check. This check is only done when
134+
* ecc.correct() returns -EBADMSG.
135+
* Set this flag if your implementation does not fix bitflips in erased
136+
* pages and you want to rely on the default implementation.
137+
*/
138+
#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0)
139+
132140
/* Bit mask for flags passed to do_nand_read_ecc */
133141
#define NAND_GET_DEVICE 0x80
134142

@@ -451,6 +459,7 @@ struct nand_hw_control {
451459
* @total: total number of ECC bytes per page
452460
* @prepad: padding information for syndrome based ECC generators
453461
* @postpad: padding information for syndrome based ECC generators
462+
* @options: ECC specific options (see NAND_ECC_XXX flags defined above)
454463
* @layout: ECC layout control struct pointer
455464
* @priv: pointer to private ECC control data
456465
* @hwctl: function to control hardware ECC generator. Must only
@@ -500,6 +509,7 @@ struct nand_ecc_ctrl {
500509
int strength;
501510
int prepad;
502511
int postpad;
512+
unsigned int options;
503513
struct nand_ecclayout *layout;
504514
void *priv;
505515
void (*hwctl)(struct mtd_info *mtd, int mode);

0 commit comments

Comments
 (0)