Skip to content

Commit 6e94119

Browse files
Boris BREZILLONcomputersforpeace
authored andcommitted
mtd: nand: return consistent error codes in ecc.correct() implementations
The error code returned by the ecc.correct() are not consistent over the all implementations. Document the expected behavior in include/linux/mtd/nand.h and fix offending implementations. [Brian: this looks like a bugfix for the ECC reporting in the bf5xx_nand driver, but we haven't seen any testing results for it] Signed-off-by: Boris Brezillon <[email protected]> Tested-by: Franklin S Cooper Jr. <[email protected]> Signed-off-by: Brian Norris <[email protected]>
1 parent 6f357de commit 6e94119

File tree

11 files changed

+37
-23
lines changed

11 files changed

+37
-23
lines changed

drivers/mtd/nand/atmel_nand.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
14451445
* We can't correct so many errors */
14461446
dev_dbg(host->dev, "atmel_nand : multiple errors detected."
14471447
" Unable to correct.\n");
1448-
return -EIO;
1448+
return -EBADMSG;
14491449
}
14501450

14511451
/* if there's a single bit error : we can correct it */

drivers/mtd/nand/bf5xx_nand.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
252252
*/
253253
if (hweight32(syndrome[0]) == 1) {
254254
dev_err(info->device, "ECC data was incorrect!\n");
255-
return 1;
255+
return -EBADMSG;
256256
}
257257

258258
syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
@@ -285,7 +285,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
285285
data = data ^ (0x1 << failing_bit);
286286
*(dat + failing_byte) = data;
287287

288-
return 0;
288+
return 1;
289289
}
290290

291291
/*
@@ -298,26 +298,34 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
298298
dev_err(info->device,
299299
"Please discard data, mark bad block\n");
300300

301-
return 1;
301+
return -EBADMSG;
302302
}
303303

304304
static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
305305
u_char *read_ecc, u_char *calc_ecc)
306306
{
307307
struct nand_chip *chip = mtd_to_nand(mtd);
308-
int ret;
308+
int ret, bitflips = 0;
309309

310310
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
311+
if (ret < 0)
312+
return ret;
313+
314+
bitflips = ret;
311315

312316
/* If ecc size is 512, correct second 256 bytes */
313317
if (chip->ecc.size == 512) {
314318
dat += 256;
315319
read_ecc += 3;
316320
calc_ecc += 3;
317-
ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
321+
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
322+
if (ret < 0)
323+
return ret;
324+
325+
bitflips += ret;
318326
}
319327

320-
return ret;
328+
return bitflips;
321329
}
322330

323331
static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)

drivers/mtd/nand/davinci_nand.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,15 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
207207
dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7);
208208
return 1;
209209
} else {
210-
return -1;
210+
return -EBADMSG;
211211
}
212212
} else if (!(diff & (diff - 1))) {
213213
/* Single bit ECC error in the ECC itself,
214214
* nothing to fix */
215215
return 1;
216216
} else {
217217
/* Uncorrectable error */
218-
return -1;
218+
return -EBADMSG;
219219
}
220220

221221
}
@@ -391,7 +391,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
391391
return 0;
392392
case 1: /* five or more errors detected */
393393
davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
394-
return -EIO;
394+
return -EBADMSG;
395395
case 2: /* error addresses computed */
396396
case 3:
397397
num_errors = 1 + ((fsr >> 16) & 0x03);

drivers/mtd/nand/jz4740_nand.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,15 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
254254
} while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout);
255255

256256
if (timeout == 0)
257-
return -1;
257+
return -ETIMEDOUT;
258258

259259
reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
260260
reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
261261
writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
262262

263263
if (status & JZ_NAND_STATUS_ERROR) {
264264
if (status & JZ_NAND_STATUS_UNCOR_ERROR)
265-
return -1;
265+
return -EBADMSG;
266266

267267
error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
268268

drivers/mtd/nand/mxc_nand.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
674674

675675
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
676676
pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
677-
return -1;
677+
return -EBADMSG;
678678
}
679679

680680
return 0;
@@ -701,7 +701,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
701701
err = ecc_stat & ecc_bit_mask;
702702
if (err > err_limit) {
703703
printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
704-
return -1;
704+
return -EBADMSG;
705705
} else {
706706
ret += err;
707707
}

drivers/mtd/nand/nand_bch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
9898
}
9999
} else if (count < 0) {
100100
printk(KERN_ERR "ecc unrecoverable error\n");
101-
count = -1;
101+
count = -EBADMSG;
102102
}
103103
return count;
104104
}

drivers/mtd/nand/nand_ecc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *buf,
507507
return 1; /* error in ECC data; no action needed */
508508

509509
pr_err("%s: uncorrectable ECC error\n", __func__);
510-
return -1;
510+
return -EBADMSG;
511511
}
512512
EXPORT_SYMBOL(__nand_correct_data);
513513

drivers/mtd/nand/omap2.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -826,12 +826,12 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
826826
case 1:
827827
/* Uncorrectable error */
828828
pr_debug("ECC UNCORRECTED_ERROR 1\n");
829-
return -1;
829+
return -EBADMSG;
830830

831831
case 11:
832832
/* UN-Correctable error */
833833
pr_debug("ECC UNCORRECTED_ERROR B\n");
834-
return -1;
834+
return -EBADMSG;
835835

836836
case 12:
837837
/* Correctable error */
@@ -861,7 +861,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
861861
return 0;
862862
}
863863
pr_debug("UNCORRECTED_ERROR default\n");
864-
return -1;
864+
return -EBADMSG;
865865
}
866866
}
867867

drivers/mtd/nand/r852.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
477477

478478
if (dev->dma_error) {
479479
dev->dma_error = 0;
480-
return -1;
480+
return -EIO;
481481
}
482482

483483
r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
@@ -491,7 +491,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
491491
/* ecc uncorrectable error */
492492
if (ecc_status & R852_ECC_FAIL) {
493493
dbg("ecc: unrecoverable error, in half %d", i);
494-
error = -1;
494+
error = -EBADMSG;
495495
goto exit;
496496
}
497497

include/linux/mtd/nand.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,13 @@ struct nand_hw_control {
456456
* @hwctl: function to control hardware ECC generator. Must only
457457
* be provided if an hardware ECC is available
458458
* @calculate: function for ECC calculation or readback from ECC hardware
459-
* @correct: function for ECC correction, matching to ECC generator (sw/hw)
459+
* @correct: function for ECC correction, matching to ECC generator (sw/hw).
460+
* Should return a positive number representing the number of
461+
* corrected bitflips, -EBADMSG if the number of bitflips exceed
462+
* ECC strength, or any other error code if the error is not
463+
* directly related to correction.
464+
* If -EBADMSG is returned the input buffers should be left
465+
* untouched.
460466
* @read_page_raw: function to read a raw page without ECC. This function
461467
* should hide the specific layout used by the ECC
462468
* controller and always return contiguous in-band and

include/linux/mtd/nand_bch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static inline int
5555
nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
5656
unsigned char *read_ecc, unsigned char *calc_ecc)
5757
{
58-
return -1;
58+
return -ENOTSUPP;
5959
}
6060

6161
static inline struct nand_bch_control *

0 commit comments

Comments
 (0)