Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: bitflip_threshold added to mtd_info and sysfs

An element 'bitflip_threshold' is added to struct mtd_info, and also exposed as
a read/write variable in sysfs. This will be used to determine whether or not
mtd_read() returns -EUCLEAN or 0 (absent a hard error). If the driver leaves it
as zero, mtd will set it to a default value of ecc_strength.

This v2 adds the line that propagates bitflip_threshold from the master to the
partitions - thanks Ivan¹.

¹ http://lists.infradead.org/pipermail/linux-mtd/2012-April/040900.html

Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

authored by

Mike Dunn and committed by
David Woodhouse
d062d4ed a9b672e8

+80
+36
Documentation/ABI/testing/sysfs-class-mtd
··· 135 135 have multiple ecc steps within each writesize region. 136 136 137 137 In the case of devices lacking any ECC capability, it is 0. 138 + 139 + What: /sys/class/mtd/mtdX/bitflip_threshold 140 + Date: April 2012 141 + KernelVersion: 3.4 142 + Contact: linux-mtd@lists.infradead.org 143 + Description: 144 + This allows the user to examine and adjust the criteria by which 145 + mtd returns -EUCLEAN from mtd_read(). If the maximum number of 146 + bit errors that were corrected on any single region comprising 147 + an ecc step (as reported by the driver) equals or exceeds this 148 + value, -EUCLEAN is returned. Otherwise, absent an error, 0 is 149 + returned. Higher layers (e.g., UBI) use this return code as an 150 + indication that an erase block may be degrading and should be 151 + scrutinized as a candidate for being marked as bad. 152 + 153 + The initial value may be specified by the flash device driver. 154 + If not, then the default value is ecc_strength. 155 + 156 + The introduction of this feature brings a subtle change to the 157 + meaning of the -EUCLEAN return code. Previously, it was 158 + interpreted to mean simply "one or more bit errors were 159 + corrected". Its new interpretation can be phrased as "a 160 + dangerously high number of bit errors were corrected on one or 161 + more regions comprising an ecc step". The precise definition of 162 + "dangerously high" can be adjusted by the user with 163 + bitflip_threshold. Users are discouraged from doing this, 164 + however, unless they know what they are doing and have intimate 165 + knowledge of the properties of their device. Broadly speaking, 166 + bitflip_threshold should be low enough to detect genuine erase 167 + block degradation, but high enough to avoid the consequences of 168 + a persistent return value of -EUCLEAN on devices where sticky 169 + bitflips occur. Note that if bitflip_threshold exceeds 170 + ecc_strength, -EUCLEAN is never returned by the read functions. 171 + 172 + This is generally applicable only to NAND flash devices with ECC 173 + capability. It is ignored on devices lacking ECC capability.
+33
drivers/mtd/mtdcore.c
··· 259 259 } 260 260 static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); 261 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 + 262 290 static struct attribute *mtd_attrs[] = { 263 291 &dev_attr_type.attr, 264 292 &dev_attr_flags.attr, ··· 298 270 &dev_attr_numeraseregions.attr, 299 271 &dev_attr_name.attr, 300 272 &dev_attr_ecc_strength.attr, 273 + &dev_attr_bitflip_threshold.attr, 301 274 NULL, 302 275 }; 303 276 ··· 360 331 361 332 mtd->index = i; 362 333 mtd->usecount = 0; 334 + 335 + /* default value if not set by driver */ 336 + if (mtd->bitflip_threshold == 0) 337 + mtd->bitflip_threshold = mtd->ecc_strength; 363 338 364 339 if (is_power_of_2(mtd->erasesize)) 365 340 mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+2
drivers/mtd/mtdpart.c
··· 517 517 518 518 slave->mtd.ecclayout = master->ecclayout; 519 519 slave->mtd.ecc_strength = master->ecc_strength; 520 + slave->mtd.bitflip_threshold = master->bitflip_threshold; 521 + 520 522 if (master->_block_isbad) { 521 523 uint64_t offs = 0; 522 524
+9
include/linux/mtd/mtd.h
··· 157 157 unsigned int erasesize_mask; 158 158 unsigned int writesize_mask; 159 159 160 + /* 161 + * read ops return -EUCLEAN if max number of bitflips corrected on any 162 + * one region comprising an ecc step equals or exceeds this value. 163 + * Settable by driver, else defaults to ecc_strength. User can override 164 + * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; 165 + * see Documentation/ABI/testing/sysfs-class-mtd for more detail. 166 + */ 167 + unsigned int bitflip_threshold; 168 + 160 169 // Kernel-only stuff starts here. 161 170 const char *name; 162 171 int index;