Skip to content

Commit 8eab721

Browse files
Abhishek Sahumiquelraynal
authored andcommitted
mtd: rawnand: qcom: erased page detection for uncorrectable errors only
Following is the flow in the HW if controller tries to read erased page: 1. First ECC uncorrectable error will be generated from ECC engine since ECC engine first calculates the ECC with all 0xff and match the calculated ECC with ECC code in OOB (which is again all 0xff). 2. After getting ECC error, erased CW detection logic will be applied which is different for BCH and RS ECC a. For BCH, HW checks if all the bytes in page are 0xff and then it updates the status in separate register NAND_ERASED_CW_DETECT_STATUS. b. For RS ECC, the HW reports the same error when reading an erased CW, but it notifies that it is an erased CW by placing special characters at certain offsets in the buffer. So the erased CW detect status should be checked only if ECC engine generated the uncorrectable error. Currently for all other operational errors also (like TIMEOUT, MPU errors, etc.), the erased CW detect logic is being applied so fix this and return EIO for other operational errors. Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
1 parent 6f20070 commit 8eab721

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

drivers/mtd/nand/raw/qcom_nandc.c

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
15761576
struct nand_ecc_ctrl *ecc = &chip->ecc;
15771577
unsigned int max_bitflips = 0;
15781578
struct read_stats *buf;
1579+
bool flash_op_err = false;
15791580
int i;
15801581

15811582
buf = (struct read_stats *)nandc->reg_read_buf;
@@ -1597,8 +1598,18 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
15971598
buffer = le32_to_cpu(buf->buffer);
15981599
erased_cw = le32_to_cpu(buf->erased_cw);
15991600

1600-
if (flash & (FS_OP_ERR | FS_MPU_ERR)) {
1601+
/*
1602+
* Check ECC failure for each codeword. ECC failure can
1603+
* happen in either of the following conditions
1604+
* 1. If number of bitflips are greater than ECC engine
1605+
* capability.
1606+
* 2. If this codeword contains all 0xff for which erased
1607+
* codeword detection check will be done.
1608+
*/
1609+
if ((flash & FS_OP_ERR) && (buffer & BS_UNCORRECTABLE_BIT)) {
16011610
bool erased;
1611+
int ret, ecclen, extraooblen;
1612+
void *eccbuf;
16021613

16031614
/* ignore erased codeword errors */
16041615
if (host->bch_enabled) {
@@ -1616,29 +1627,36 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
16161627
continue;
16171628
}
16181629

1619-
if (buffer & BS_UNCORRECTABLE_BIT) {
1620-
int ret, ecclen, extraooblen;
1621-
void *eccbuf;
1622-
1623-
eccbuf = oob_buf ? oob_buf + oob_len : NULL;
1624-
ecclen = oob_buf ? host->ecc_bytes_hw : 0;
1625-
extraooblen = oob_buf ? oob_len : 0;
1626-
1627-
/*
1628-
* make sure it isn't an erased page reported
1629-
* as not-erased by HW because of a few bitflips
1630-
*/
1631-
ret = nand_check_erased_ecc_chunk(data_buf,
1632-
data_len, eccbuf, ecclen, oob_buf,
1633-
extraooblen, ecc->strength);
1634-
if (ret < 0) {
1635-
mtd->ecc_stats.failed++;
1636-
} else {
1637-
mtd->ecc_stats.corrected += ret;
1638-
max_bitflips =
1639-
max_t(unsigned int, max_bitflips, ret);
1640-
}
1630+
eccbuf = oob_buf ? oob_buf + oob_len : NULL;
1631+
ecclen = oob_buf ? host->ecc_bytes_hw : 0;
1632+
extraooblen = oob_buf ? oob_len : 0;
1633+
1634+
/*
1635+
* make sure it isn't an erased page reported
1636+
* as not-erased by HW because of a few bitflips
1637+
*/
1638+
ret = nand_check_erased_ecc_chunk(data_buf,
1639+
data_len, eccbuf, ecclen, oob_buf,
1640+
extraooblen, ecc->strength);
1641+
if (ret < 0) {
1642+
mtd->ecc_stats.failed++;
1643+
} else {
1644+
mtd->ecc_stats.corrected += ret;
1645+
max_bitflips =
1646+
max_t(unsigned int, max_bitflips, ret);
16411647
}
1648+
/*
1649+
* Check if MPU or any other operational error (timeout,
1650+
* device failure, etc.) happened for this codeword and
1651+
* make flash_op_err true. If flash_op_err is set, then
1652+
* EIO will be returned for page read.
1653+
*/
1654+
} else if (flash & (FS_OP_ERR | FS_MPU_ERR)) {
1655+
flash_op_err = true;
1656+
/*
1657+
* No ECC or operational errors happened. Check the number of
1658+
* bits corrected and update the ecc_stats.corrected.
1659+
*/
16421660
} else {
16431661
unsigned int stat;
16441662

@@ -1652,6 +1670,9 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
16521670
oob_buf += oob_len + ecc->bytes;
16531671
}
16541672

1673+
if (flash_op_err)
1674+
return -EIO;
1675+
16551676
return max_bitflips;
16561677
}
16571678

0 commit comments

Comments
 (0)