Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310210
b: refs/heads/master
c: edbc454
h: refs/heads/master
v: v3
  • Loading branch information
Mike Dunn authored and David Woodhouse committed May 14, 2012
1 parent af11201 commit 270b2d3
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e2788c98b98269a3131bffd2b57599280d7abd73
refs/heads/master: edbc4540e02c201bdd4f4d498ebb6ed517fd36e2
7 changes: 5 additions & 2 deletions trunk/Documentation/ABI/testing/sysfs-class-mtd
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ Description:
block degradation, but high enough to avoid the consequences of
a persistent return value of -EUCLEAN on devices where sticky
bitflips occur. Note that if bitflip_threshold exceeds
ecc_strength, -EUCLEAN is never returned by the read functions.
ecc_strength, -EUCLEAN is never returned by mtd_read().
Conversely, if bitflip_threshold is zero, -EUCLEAN is always
returned, absent a hard error.

This is generally applicable only to NAND flash devices with ECC
capability. It is ignored on devices lacking ECC capability.
capability. It is ignored on devices lacking ECC capability;
i.e., devices for which ecc_strength is zero.
6 changes: 4 additions & 2 deletions trunk/drivers/mtd/devices/docg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from,
u8 *buf = ops->datbuf;
size_t len, ooblen, nbdata, nboob;
u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1;
int max_bitflips = 0;

if (buf)
len = ops->len;
Expand All @@ -876,7 +877,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from,
ret = 0;
skip = from % DOC_LAYOUT_PAGE_SIZE;
mutex_lock(&docg3->cascade->lock);
while (!ret && (len > 0 || ooblen > 0)) {
while (ret >= 0 && (len > 0 || ooblen > 0)) {
calc_block_sector(from - skip, &block0, &block1, &page, &ofs,
docg3->reliable);
nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip);
Expand Down Expand Up @@ -936,7 +937,8 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from,
}
if (ret > 0) {
mtd->ecc_stats.corrected += ret;
ret = -EUCLEAN;
max_bitflips = max(max_bitflips, ret);
ret = max_bitflips;
}
}

Expand Down
14 changes: 13 additions & 1 deletion trunk/drivers/mtd/mtdcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,12 +800,24 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf)
{
int ret_code;
*retlen = 0;
if (from < 0 || from > mtd->size || len > mtd->size - from)
return -EINVAL;
if (!len)
return 0;
return mtd->_read(mtd, from, len, retlen, buf);

/*
* In the absence of an error, drivers return a non-negative integer
* representing the maximum number of bitflips that were corrected on
* any one ecc region (if applicable; zero otherwise).
*/
ret_code = mtd->_read(mtd, from, len, retlen, buf);
if (unlikely(ret_code < 0))
return ret_code;
if (mtd->ecc_strength == 0)
return 0; /* device lacks ecc */
return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
}
EXPORT_SYMBOL_GPL(mtd_read);

Expand Down
12 changes: 6 additions & 6 deletions trunk/drivers/mtd/mtdpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
stats = part->master->ecc_stats;
res = part->master->_read(part->master, from + part->offset, len,
retlen, buf);
if (unlikely(res)) {
if (mtd_is_bitflip(res))
mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
if (mtd_is_eccerr(res))
mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
}
if (unlikely(mtd_is_eccerr(res)))
mtd->ecc_stats.failed +=
part->master->ecc_stats.failed - stats.failed;
else
mtd->ecc_stats.corrected +=
part->master->ecc_stats.corrected - stats.corrected;
return res;
}

Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/mtd/nand/alauda.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len,
}
err = 0;
if (corrected)
err = -EUCLEAN;
err = 1; /* return max_bitflips per ecc step */
if (uncorrected)
err = -EBADMSG;
out:
Expand Down Expand Up @@ -446,7 +446,7 @@ static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len,
}
err = 0;
if (corrected)
err = -EUCLEAN;
err = 1; /* return max_bitflips per ecc step */
if (uncorrected)
err = -EBADMSG;
return err;
Expand Down
18 changes: 14 additions & 4 deletions trunk/drivers/mtd/nand/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
mtd->oobavail : mtd->oobsize;

uint8_t *bufpoi, *oob, *buf;
unsigned int max_bitflips = 0;

stats = mtd->ecc_stats;

Expand Down Expand Up @@ -1513,7 +1514,10 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
sndcmd = 0;
}

/* Now read the page into the buffer */
/*
* Now read the page into the buffer. Absent an error,
* the read methods return max bitflips per ecc step.
*/
if (unlikely(ops->mode == MTD_OPS_RAW))
ret = chip->ecc.read_page_raw(mtd, chip,
bufpoi, page);
Expand All @@ -1530,15 +1534,19 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
break;
}

max_bitflips = max_t(unsigned int, max_bitflips, ret);

/* Transfer not aligned data */
if (!aligned) {
if (!NAND_SUBPAGE_READ(chip) && !oob &&
!(mtd->ecc_stats.failed - stats.failed) &&
(ops->mode != MTD_OPS_RAW))
(ops->mode != MTD_OPS_RAW)) {
chip->pagebuf = realpage;
else
chip->pagebuf_bitflips = ret;
} else {
/* Invalidate page cache */
chip->pagebuf = -1;
}
memcpy(buf, chip->buffers->databuf + col, bytes);
}

Expand Down Expand Up @@ -1571,6 +1579,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
} else {
memcpy(buf, chip->buffers->databuf + col, bytes);
buf += bytes;
max_bitflips = max_t(unsigned int, max_bitflips,
chip->pagebuf_bitflips);
}

readlen -= bytes;
Expand Down Expand Up @@ -1609,7 +1619,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (mtd->ecc_stats.failed - stats.failed)
return -EBADMSG;

return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
return max_bitflips;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/mtd/onenand/onenand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,8 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
if (mtd->ecc_stats.failed - stats.failed)
return -EBADMSG;

return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
/* return max bitflips per ecc step; ONENANDs correct 1 bit only */
return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0;
}

/**
Expand Down Expand Up @@ -1333,7 +1334,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
if (mtd->ecc_stats.failed - stats.failed)
return -EBADMSG;

return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
/* return max bitflips per ecc step; ONENANDs correct 1 bit only */
return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/mtd/nand.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ struct nand_buffers {
* @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
* @pagebuf: [INTERN] holds the pagenumber which is currently in
* data_buf.
* @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is
* currently in data_buf.
* @subpagesize: [INTERN] holds the subpagesize
* @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded),
* non 0 if ONFI supported.
Expand Down Expand Up @@ -519,6 +521,7 @@ struct nand_chip {
uint64_t chipsize;
int pagemask;
int pagebuf;
unsigned int pagebuf_bitflips;
int subpagesize;
uint8_t cellinfo;
int badblockpos;
Expand Down

0 comments on commit 270b2d3

Please sign in to comment.