mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 21:21:49 -04:00
mtd: nand: omap: ecc.correct: omap_elm_correct_data: fix programmed-page bit-flip correction logic
This patch updates following checks when bit-flips are detected by ELM:
- Do not evaluate bit-flips when un-correctable bit-flips is reported by ELM,
because as per [1] when ELM reports an un-correctable bit-flips,
'number of error' field in its ELM_LOCATION_STATUS register is also invalid.
- Return with error-code '-EBADMSG' on detection of un-correctable bit-flip.
- Return with error-code '-EBADMSG' when bit-flips position is outside current
Sector and OOB area.
[1] ELM IP spec Table-25 ELM_LOCATION_STATUS Register.
ELM_LOCATION_STATUS[8] = ECC_CORRECTABLE: Error location process exit status
0x0: ECC error location process failed.
Number of errors and error locations are invalid.
0x1: all errors were successfully located.
Number of errors and error locations are valid.
Tested-by: Stefan Roese <sr@denx.de>
Signed-off-by: Pekon Gupta <pekon@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
This commit is contained in:
committed by
Brian Norris
parent
b08e1f632c
commit
13fbe0641e
@@ -1353,6 +1353,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
|
||||
int bitflip_count;
|
||||
bool is_error_reported = false;
|
||||
u32 bit_pos, byte_pos, error_max, pos;
|
||||
int err;
|
||||
|
||||
switch (info->ecc_opt) {
|
||||
case OMAP_ECC_BCH4_CODE_HW:
|
||||
@@ -1434,8 +1435,12 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
|
||||
/* Decode BCH error using ELM module */
|
||||
elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec);
|
||||
|
||||
err = 0;
|
||||
for (i = 0; i < eccsteps; i++) {
|
||||
if (err_vec[i].error_reported) {
|
||||
if (err_vec[i].error_uncorrectable) {
|
||||
pr_err("nand: uncorrectable bit-flips found\n");
|
||||
err = -EBADMSG;
|
||||
} else if (err_vec[i].error_reported) {
|
||||
for (j = 0; j < err_vec[i].error_count; j++) {
|
||||
switch (info->ecc_opt) {
|
||||
case OMAP_ECC_BCH4_CODE_HW:
|
||||
@@ -1457,13 +1462,22 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
|
||||
byte_pos = (error_max - pos - 1) / 8;
|
||||
|
||||
if (pos < error_max) {
|
||||
if (byte_pos < 512)
|
||||
if (byte_pos < 512) {
|
||||
pr_debug("bitflip@dat[%d]=%x\n",
|
||||
byte_pos, data[byte_pos]);
|
||||
data[byte_pos] ^= 1 << bit_pos;
|
||||
else
|
||||
} else {
|
||||
pr_debug("bitflip@oob[%d]=%x\n",
|
||||
(byte_pos - 512),
|
||||
spare_ecc[byte_pos - 512]);
|
||||
spare_ecc[byte_pos - 512] ^=
|
||||
1 << bit_pos;
|
||||
}
|
||||
} else {
|
||||
pr_err("invalid bit-flip @ %d:%d\n",
|
||||
byte_pos, bit_pos);
|
||||
err = -EBADMSG;
|
||||
}
|
||||
/* else, not interested to correct ecc */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1475,12 +1489,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
|
||||
spare_ecc += ecc->bytes;
|
||||
}
|
||||
|
||||
for (i = 0; i < eccsteps; i++)
|
||||
/* Return error if uncorrectable error present */
|
||||
if (err_vec[i].error_uncorrectable)
|
||||
return -EINVAL;
|
||||
|
||||
return stat;
|
||||
return (err) ? err : stat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user