diff options
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, | |||
| 250 | } | 250 | } |
| 251 | static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); | 251 | static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); |
| 252 | 252 | ||
| 253 | static ssize_t mtd_ecc_strength_show(struct device *dev, | ||
| 254 | struct device_attribute *attr, char *buf) | ||
| 255 | { | ||
| 256 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
| 257 | |||
| 258 | return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); | ||
| 259 | } | ||
| 260 | static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); | ||
| 261 | |||
| 262 | static ssize_t mtd_bitflip_threshold_show(struct device *dev, | ||
| 263 | struct device_attribute *attr, | ||
| 264 | char *buf) | ||
| 265 | { | ||
| 266 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
| 267 | |||
| 268 | return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); | ||
| 269 | } | ||
| 270 | |||
| 271 | static ssize_t mtd_bitflip_threshold_store(struct device *dev, | ||
| 272 | struct device_attribute *attr, | ||
| 273 | const char *buf, size_t count) | ||
| 274 | { | ||
| 275 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
| 276 | unsigned int bitflip_threshold; | ||
| 277 | int retval; | ||
| 278 | |||
| 279 | retval = kstrtouint(buf, 0, &bitflip_threshold); | ||
| 280 | if (retval) | ||
| 281 | return retval; | ||
| 282 | |||
| 283 | mtd->bitflip_threshold = bitflip_threshold; | ||
| 284 | return count; | ||
| 285 | } | ||
| 286 | static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, | ||
| 287 | mtd_bitflip_threshold_show, | ||
| 288 | mtd_bitflip_threshold_store); | ||
| 289 | |||
| 253 | static struct attribute *mtd_attrs[] = { | 290 | static struct attribute *mtd_attrs[] = { |
| 254 | &dev_attr_type.attr, | 291 | &dev_attr_type.attr, |
| 255 | &dev_attr_flags.attr, | 292 | &dev_attr_flags.attr, |
| @@ -260,6 +297,8 @@ static struct attribute *mtd_attrs[] = { | |||
| 260 | &dev_attr_oobsize.attr, | 297 | &dev_attr_oobsize.attr, |
| 261 | &dev_attr_numeraseregions.attr, | 298 | &dev_attr_numeraseregions.attr, |
| 262 | &dev_attr_name.attr, | 299 | &dev_attr_name.attr, |
| 300 | &dev_attr_ecc_strength.attr, | ||
| 301 | &dev_attr_bitflip_threshold.attr, | ||
| 263 | NULL, | 302 | NULL, |
| 264 | }; | 303 | }; |
| 265 | 304 | ||
| @@ -322,6 +361,10 @@ int add_mtd_device(struct mtd_info *mtd) | |||
| 322 | mtd->index = i; | 361 | mtd->index = i; |
| 323 | mtd->usecount = 0; | 362 | mtd->usecount = 0; |
| 324 | 363 | ||
| 364 | /* default value if not set by driver */ | ||
| 365 | if (mtd->bitflip_threshold == 0) | ||
| 366 | mtd->bitflip_threshold = mtd->ecc_strength; | ||
| 367 | |||
| 325 | if (is_power_of_2(mtd->erasesize)) | 368 | if (is_power_of_2(mtd->erasesize)) |
| 326 | mtd->erasesize_shift = ffs(mtd->erasesize) - 1; | 369 | mtd->erasesize_shift = ffs(mtd->erasesize) - 1; |
| 327 | else | 370 | else |
| @@ -757,12 +800,24 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); | |||
| 757 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | 800 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
| 758 | u_char *buf) | 801 | u_char *buf) |
| 759 | { | 802 | { |
| 803 | int ret_code; | ||
| 760 | *retlen = 0; | 804 | *retlen = 0; |
| 761 | if (from < 0 || from > mtd->size || len > mtd->size - from) | 805 | if (from < 0 || from > mtd->size || len > mtd->size - from) |
| 762 | return -EINVAL; | 806 | return -EINVAL; |
| 763 | if (!len) | 807 | if (!len) |
| 764 | return 0; | 808 | return 0; |
| 765 | return mtd->_read(mtd, from, len, retlen, buf); | 809 | |
| 810 | /* | ||
| 811 | * In the absence of an error, drivers return a non-negative integer | ||
| 812 | * representing the maximum number of bitflips that were corrected on | ||
| 813 | * any one ecc region (if applicable; zero otherwise). | ||
| 814 | */ | ||
| 815 | ret_code = mtd->_read(mtd, from, len, retlen, buf); | ||
| 816 | if (unlikely(ret_code < 0)) | ||
| 817 | return ret_code; | ||
| 818 | if (mtd->ecc_strength == 0) | ||
| 819 | return 0; /* device lacks ecc */ | ||
| 820 | return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; | ||
| 766 | } | 821 | } |
| 767 | EXPORT_SYMBOL_GPL(mtd_read); | 822 | EXPORT_SYMBOL_GPL(mtd_read); |
| 768 | 823 | ||
