diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 16:55:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 16:55:42 -0700 |
commit | f5e7e844a571124ffc117d4696787d6afc4fc5ae (patch) | |
tree | 26bb17dc94e9536da540c187b00cedb0c1b24664 /drivers/mtd/mtdcore.c | |
parent | 48445159e9ecb44a96a4de06c6ae7c54eb43ba5b (diff) | |
parent | 4a43faf54e9173b6acce37cf7f053fc9515a2cdf (diff) | |
download | linux-stable-f5e7e844a571124ffc117d4696787d6afc4fc5ae.tar.gz linux-stable-f5e7e844a571124ffc117d4696787d6afc4fc5ae.tar.bz2 linux-stable-f5e7e844a571124ffc117d4696787d6afc4fc5ae.zip |
Merge tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd
Pull mtd update from David Woodhouse:
- More robust parsing especially of xattr data in JFFS2
- Updates to mxc_nand and gpmi drivers to support new boards and device tree
- Improve consistency of information about ECC strength in NAND devices
- Clean up partition handling of plat_nand
- Support NAND drivers without dedicated access to OOB area
- BCH hardware ECC support for OMAP
- Other fixes and cleanups, and a few new device IDs
Fixed trivial conflict in drivers/mtd/nand/gpmi-nand/gpmi-nand.c due to
added include files next to each other.
* tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd: (75 commits)
mtd: mxc_nand: move ecc strengh setup before nand_scan_tail
mtd: block2mtd: fix recursive call of mtd_writev
mtd: gpmi-nand: define ecc.strength
mtd: of_parts: fix breakage in Kconfig
mtd: nand: fix scan_read_raw_oob
mtd: docg3 fix in-middle of blocks reads
mtd: cfi_cmdset_0002: Slight cleanup of fixup messages
mtd: add fixup for S29NS512P NOR flash.
jffs2: allow to complete xattr integrity check on first GC scan
jffs2: allow to discriminate between recoverable and non-recoverable errors
mtd: nand: omap: add support for hardware BCH ecc
ARM: OMAP3: gpmc: add BCH ecc api and modes
mtd: nand: check the return code of 'read_oob/read_oob_raw'
mtd: nand: remove 'sndcmd' parameter of 'read_oob/read_oob_raw'
mtd: m25p80: Add support for Winbond W25Q80BW
jffs2: get rid of jffs2_sync_super
jffs2: remove unnecessary GC pass on sync
jffs2: remove unnecessary GC pass on umount
jffs2: remove lock_super
mtd: gpmi: add gpmi support for mx6q
...
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c837507dfb1c..575730744fdb 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -250,6 +250,43 @@ static ssize_t mtd_name_show(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); +static ssize_t mtd_ecc_strength_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mtd_info *mtd = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); +} +static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); + +static ssize_t mtd_bitflip_threshold_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mtd_info *mtd = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); +} + +static ssize_t mtd_bitflip_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mtd_info *mtd = dev_get_drvdata(dev); + unsigned int bitflip_threshold; + int retval; + + retval = kstrtouint(buf, 0, &bitflip_threshold); + if (retval) + return retval; + + mtd->bitflip_threshold = bitflip_threshold; + return count; +} +static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, + mtd_bitflip_threshold_show, + mtd_bitflip_threshold_store); + static struct attribute *mtd_attrs[] = { &dev_attr_type.attr, &dev_attr_flags.attr, @@ -260,6 +297,8 @@ static struct attribute *mtd_attrs[] = { &dev_attr_oobsize.attr, &dev_attr_numeraseregions.attr, &dev_attr_name.attr, + &dev_attr_ecc_strength.attr, + &dev_attr_bitflip_threshold.attr, NULL, }; @@ -322,6 +361,10 @@ int add_mtd_device(struct mtd_info *mtd) mtd->index = i; mtd->usecount = 0; + /* default value if not set by driver */ + if (mtd->bitflip_threshold == 0) + mtd->bitflip_threshold = mtd->ecc_strength; + if (is_power_of_2(mtd->erasesize)) mtd->erasesize_shift = ffs(mtd->erasesize) - 1; else @@ -757,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); |