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>
This commit is contained in:
Родитель
a9b672e82b
Коммит
d062d4ede8
|
@ -135,3 +135,39 @@ Description:
|
|||
have multiple ecc steps within each writesize region.
|
||||
|
||||
In the case of devices lacking any ECC capability, it is 0.
|
||||
|
||||
What: /sys/class/mtd/mtdX/bitflip_threshold
|
||||
Date: April 2012
|
||||
KernelVersion: 3.4
|
||||
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(). If the maximum number of
|
||||
bit errors that were corrected on any single region comprising
|
||||
an ecc step (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 specified by the flash device driver.
|
||||
If not, then the default value is ecc_strength.
|
||||
|
||||
The introduction of this feature brings a subtle change to the
|
||||
meaning of the -EUCLEAN return code. Previously, it was
|
||||
interpreted to mean simply "one or more bit errors were
|
||||
corrected". Its new interpretation can be phrased as "a
|
||||
dangerously high number of bit errors were corrected on one or
|
||||
more regions comprising an ecc step". The precise definition of
|
||||
"dangerously high" can be adjusted by the user with
|
||||
bitflip_threshold. Users are discouraged from doing this,
|
||||
however, unless they know what they are doing and have intimate
|
||||
knowledge of the properties of their device. Broadly speaking,
|
||||
bitflip_threshold should be low enough to detect genuine erase
|
||||
block degradation, but high enough to avoid the consequences of
|
||||
a persistent return value of -EUCLEAN on devices where sticky
|
||||
bitflips occur. Note that if bitflip_threshold exceeds
|
||||
ecc_strength, -EUCLEAN is never returned by the read functions.
|
||||
|
||||
This is generally applicable only to NAND flash devices with ECC
|
||||
capability. It is ignored on devices lacking ECC capability.
|
||||
|
|
|
@ -259,6 +259,34 @@ static ssize_t mtd_ecc_strength_show(struct device *dev,
|
|||
}
|
||||
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,
|
||||
|
@ -270,6 +298,7 @@ static struct attribute *mtd_attrs[] = {
|
|||
&dev_attr_numeraseregions.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_ecc_strength.attr,
|
||||
&dev_attr_bitflip_threshold.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -332,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
|
||||
|
|
|
@ -517,6 +517,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
|
|||
|
||||
slave->mtd.ecclayout = master->ecclayout;
|
||||
slave->mtd.ecc_strength = master->ecc_strength;
|
||||
slave->mtd.bitflip_threshold = master->bitflip_threshold;
|
||||
|
||||
if (master->_block_isbad) {
|
||||
uint64_t offs = 0;
|
||||
|
||||
|
|
|
@ -157,6 +157,15 @@ struct mtd_info {
|
|||
unsigned int erasesize_mask;
|
||||
unsigned int writesize_mask;
|
||||
|
||||
/*
|
||||
* read ops return -EUCLEAN if max number of bitflips corrected on any
|
||||
* one region comprising an ecc step equals or exceeds this value.
|
||||
* Settable by driver, else defaults to ecc_strength. User can override
|
||||
* in sysfs. N.B. The meaning of the -EUCLEAN return code has changed;
|
||||
* see Documentation/ABI/testing/sysfs-class-mtd for more detail.
|
||||
*/
|
||||
unsigned int bitflip_threshold;
|
||||
|
||||
// Kernel-only stuff starts here.
|
||||
const char *name;
|
||||
int index;
|
||||
|
|
Загрузка…
Ссылка в новой задаче