@@ -123,3 +123,26 @@ Description:
half page, or a quarter page).
In the case of ECC NOR, it is the ECC block size.
+
+What: /sys/class/mtd/mtdX/euclean_threshold
+Date: March 2012
+KernelVersion: 3.3.1
+Contact: linux-mtd@lists.infradead.org
+Description:
+ This allows the user to examine and adjust the criteria by which
+ mtd returns -EUCLEAN from mtd_read() and mtd_read_oob(). If the
+ maximum number of bit errors corrected on any single writesize
+ during the read operation (as reported by the driver) equals or
+ exceeds this value, -EUCLEAN is returned. Otherwise, absent an
+ error, 0 is returned. Higher layers (e.g., UBI) use this return
+ code as an indication that an erase block may be degrading and
+ should be scrutinized as a candidate for being marked as bad.
+
+ The initial value may be set by the flash device driver. If
+ not, then it is equal to the maximum number of bit errors that
+ the device's ECC facility is capable of correcting per
+ writesize. Users who wish to be more paranoid about data
+ integrity can lower the value.
+
+ This is generally applicable only to NAND flash devices with
+ ECC capability.
@@ -250,6 +250,34 @@ static ssize_t mtd_name_show(struct device *dev,
}
static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
+static ssize_t mtd_euclean_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->euclean_threshold);
+}
+
+static ssize_t mtd_euclean_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 euclean_threshold;
+ int retval;
+
+ retval = kstrtouint(buf, 0, &euclean_threshold);
+ if (retval)
+ return retval;
+
+ mtd->euclean_threshold = euclean_threshold;
+ return count;
+}
+static DEVICE_ATTR(euclean_threshold, S_IRUGO | S_IWUSR,
+ mtd_euclean_threshold_show,
+ mtd_euclean_threshold_store);
+
static struct attribute *mtd_attrs[] = {
&dev_attr_type.attr,
&dev_attr_flags.attr,
@@ -260,6 +288,7 @@ static struct attribute *mtd_attrs[] = {
&dev_attr_oobsize.attr,
&dev_attr_numeraseregions.attr,
&dev_attr_name.attr,
+ &dev_attr_euclean_threshold.attr,
NULL,
};
@@ -322,6 +351,10 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->index = i;
mtd->usecount = 0;
+ /* default value if not set by driver */
+ if (mtd->euclean_threshold == 0)
+ mtd->euclean_threshold = mtd->ecc_strength;
+
if (is_power_of_2(mtd->erasesize))
mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
else
@@ -157,6 +157,13 @@ struct mtd_info {
unsigned int erasesize_mask;
unsigned int writesize_mask;
+ /*
+ * read ops return -EUCLEAN if max number of bitflips corrected on any
+ * one writesize region equals or exceeds this value. Settable by
+ * driver, else defaults to ecc_strength. User can override in sysfs.
+ */
+ unsigned int euclean_threshold;
+
// Kernel-only stuff starts here.
const char *name;
int index;
The element 'euclean_threshold' is added to struct mtd_info. If the driver leaves this uninitialized, mtd sets it to ecc_strength when the device or partition is registered. This element is also exposed for reading and writing from userspace through sysfs. Signed-off-by: Mike Dunn <mikedunn@newsguy.com> --- An afterthought... ecc_strength should probably also be exposed through syfs as a r/o value. Ioctls for querying both these values could also be added to mtdchar. Documentation/ABI/testing/sysfs-class-mtd | 23 ++++++++++++++++++++ drivers/mtd/mtdcore.c | 33 +++++++++++++++++++++++++++++ include/linux/mtd/mtd.h | 7 ++++++ 3 files changed, 63 insertions(+), 0 deletions(-)