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 <boris.brezillon@free-electrons.com> Tested-by: Franklin S Cooper Jr. <fcooper@ti.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
This commit is contained in:
parent
6f357de854
commit
6e9411923b
11 changed files with 37 additions and 23 deletions
|
@ -1445,7 +1445,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
|
|||
* We can't correct so many errors */
|
||||
dev_dbg(host->dev, "atmel_nand : multiple errors detected."
|
||||
" Unable to correct.\n");
|
||||
return -EIO;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
/* if there's a single bit error : we can correct it */
|
||||
|
|
|
@ -252,7 +252,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
*/
|
||||
if (hweight32(syndrome[0]) == 1) {
|
||||
dev_err(info->device, "ECC data was incorrect!\n");
|
||||
return 1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
|
||||
|
@ -285,7 +285,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
data = data ^ (0x1 << failing_bit);
|
||||
*(dat + failing_byte) = data;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -298,26 +298,34 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
|
|||
dev_err(info->device,
|
||||
"Please discard data, mark bad block\n");
|
||||
|
||||
return 1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
int ret;
|
||||
int ret, bitflips = 0;
|
||||
|
||||
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bitflips = ret;
|
||||
|
||||
/* If ecc size is 512, correct second 256 bytes */
|
||||
if (chip->ecc.size == 512) {
|
||||
dat += 256;
|
||||
read_ecc += 3;
|
||||
calc_ecc += 3;
|
||||
ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bitflips += ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return bitflips;
|
||||
}
|
||||
|
||||
static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
|
|
|
@ -207,7 +207,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
|
|||
dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7);
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
} else if (!(diff & (diff - 1))) {
|
||||
/* Single bit ECC error in the ECC itself,
|
||||
|
@ -215,7 +215,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
|
|||
return 1;
|
||||
} else {
|
||||
/* Uncorrectable error */
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
|
|||
return 0;
|
||||
case 1: /* five or more errors detected */
|
||||
davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET);
|
||||
return -EIO;
|
||||
return -EBADMSG;
|
||||
case 2: /* error addresses computed */
|
||||
case 3:
|
||||
num_errors = 1 + ((fsr >> 16) & 0x03);
|
||||
|
|
|
@ -254,7 +254,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
} while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout);
|
||||
|
||||
if (timeout == 0)
|
||||
return -1;
|
||||
return -ETIMEDOUT;
|
||||
|
||||
reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
|
||||
reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
|
||||
|
@ -262,7 +262,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
|
||||
if (status & JZ_NAND_STATUS_ERROR) {
|
||||
if (status & JZ_NAND_STATUS_UNCOR_ERROR)
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
|
||||
|
||||
|
|
|
@ -674,7 +674,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
|
|||
|
||||
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
|
||||
pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -701,7 +701,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
|
|||
err = ecc_stat & ecc_bit_mask;
|
||||
if (err > err_limit) {
|
||||
printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
} else {
|
||||
ret += err;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
|
|||
}
|
||||
} else if (count < 0) {
|
||||
printk(KERN_ERR "ecc unrecoverable error\n");
|
||||
count = -1;
|
||||
count = -EBADMSG;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *buf,
|
|||
return 1; /* error in ECC data; no action needed */
|
||||
|
||||
pr_err("%s: uncorrectable ECC error\n", __func__);
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
EXPORT_SYMBOL(__nand_correct_data);
|
||||
|
||||
|
|
|
@ -826,12 +826,12 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
|
|||
case 1:
|
||||
/* Uncorrectable error */
|
||||
pr_debug("ECC UNCORRECTED_ERROR 1\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
case 11:
|
||||
/* UN-Correctable error */
|
||||
pr_debug("ECC UNCORRECTED_ERROR B\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
|
||||
case 12:
|
||||
/* Correctable error */
|
||||
|
@ -861,7 +861,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
|
|||
return 0;
|
||||
}
|
||||
pr_debug("UNCORRECTED_ERROR default\n");
|
||||
return -1;
|
||||
return -EBADMSG;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -477,7 +477,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
|
|||
|
||||
if (dev->dma_error) {
|
||||
dev->dma_error = 0;
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
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,
|
|||
/* ecc uncorrectable error */
|
||||
if (ecc_status & R852_ECC_FAIL) {
|
||||
dbg("ecc: unrecoverable error, in half %d", i);
|
||||
error = -1;
|
||||
error = -EBADMSG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -456,7 +456,13 @@ struct nand_hw_control {
|
|||
* @hwctl: function to control hardware ECC generator. Must only
|
||||
* be provided if an hardware ECC is available
|
||||
* @calculate: function for ECC calculation or readback from ECC hardware
|
||||
* @correct: function for ECC correction, matching to ECC generator (sw/hw)
|
||||
* @correct: function for ECC correction, matching to ECC generator (sw/hw).
|
||||
* Should return a positive number representing the number of
|
||||
* corrected bitflips, -EBADMSG if the number of bitflips exceed
|
||||
* ECC strength, or any other error code if the error is not
|
||||
* directly related to correction.
|
||||
* If -EBADMSG is returned the input buffers should be left
|
||||
* untouched.
|
||||
* @read_page_raw: function to read a raw page without ECC. This function
|
||||
* should hide the specific layout used by the ECC
|
||||
* controller and always return contiguous in-band and
|
||||
|
|
|
@ -55,7 +55,7 @@ static inline int
|
|||
nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
|
||||
unsigned char *read_ecc, unsigned char *calc_ecc)
|
||||
{
|
||||
return -1;
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct nand_bch_control *
|
||||
|
|
Loading…
Reference in a new issue