aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r--drivers/mtd/mtdcore.c57
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}
251static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); 251static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
252 252
253static 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}
260static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL);
261
262static 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
271static 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}
286static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR,
287 mtd_bitflip_threshold_show,
288 mtd_bitflip_threshold_store);
289
253static struct attribute *mtd_attrs[] = { 290static 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);
757int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 800int 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}
767EXPORT_SYMBOL_GPL(mtd_read); 822EXPORT_SYMBOL_GPL(mtd_read);
768 823