diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 33f900e73..6db1c6db3 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -75,12 +75,11 @@ static ssize_t mtd_op_read(struct cdev *cdev, void* buf, size_t count, offset, count); ret = mtd_read(mtd, offset, count, &retlen, buf); - - if(ret) { - printf("err %d\n", ret); + if (ret < 0) return ret; - } - return retlen; + if (mtd->ecc_strength == 0) + return retlen; /* device lacks ecc */ + return ret >= mtd->bitflip_threshold ? -EUCLEAN : retlen; } #define NOTALIGNED(x) (x & (mtd->writesize - 1)) != 0 @@ -237,6 +236,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) user->erasesize = mtd->erasesize; user->writesize = mtd->writesize; user->oobsize = mtd->oobsize; + user->subpagesize = mtd->writesize >> mtd->subpage_sft; user->mtd = mtd; /* The below fields are obsolete */ user->ecctype = -1; @@ -314,7 +314,20 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - return mtd->read(mtd, from, len, retlen, buf); + int ret_code; + *retlen = 0; + + /* + * 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; } int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, diff --git a/fs/devfs-core.c b/fs/devfs-core.c index a92d4347f..44f0169e6 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -171,6 +171,7 @@ static int partition_ioctl(struct cdev *cdev, int request, void *buf) user->erasesize = cdev->mtd->erasesize; user->writesize = cdev->mtd->writesize; user->oobsize = cdev->mtd->oobsize; + user->subpagesize = cdev->mtd->writesize >> cdev->mtd->subpage_sft; user->mtd = cdev->mtd; /* The below fields are obsolete */ user->ecctype = -1; diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index fa8e36f13..11d51e274 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/linux/mtd/mtd-abi.h @@ -82,6 +82,7 @@ struct mtd_info_user { uint32_t ecctype; uint32_t eccsize; struct mtd_info *mtd; + uint32_t subpagesize; }; struct region_info_user { diff --git a/lib/libmtd.c b/lib/libmtd.c index eecc76054..1606b872f 100644 --- a/lib/libmtd.c +++ b/lib/libmtd.c @@ -308,6 +308,7 @@ int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd) mtd->eb_size = ui.erasesize; mtd->min_io_size = ui.writesize; mtd->oob_size = ui.oobsize; + mtd->subpage_size = ui.subpagesize; if (mtd->min_io_size <= 0) { errmsg("%s has insane min. I/O unit size %d", @@ -356,7 +357,6 @@ int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd) if (ui.flags & MTD_WRITEABLE) mtd->writable = 1; - mtd->subpage_size = mtd->min_io_size; close(fd);