diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 42d401ea60ee..151571f760c8 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -193,6 +193,17 @@ config MTD_PARTITIONED_MASTER the parent of the partition device be the master device, rather than what lies behind the master. +config MTD_LAZYECCSTATS + bool "MTD Lazy ECC Stats collection support" + default y + help + Normally bad block counts for ECC stats are collected at boot time. + This option delays the badblock stats collection until ECCGETSTATS + ioctl is invoked on the partition. + + This can significantly decrease boot times depending on the size of + the partition. If unsure, say 'N'. + source "drivers/mtd/chips/Kconfig" source "drivers/mtd/maps/Kconfig" diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 48832f9b215c..dcec39905adc 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -971,6 +971,9 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) case ECCGETSTATS: { +#ifdef CONFIG_MTD_LAZYECCSTATS + part_fill_badblockstats(mtd); +#endif if (copy_to_user(argp, &mtd->ecc_stats, sizeof(struct mtd_ecc_stats))) return -EFAULT; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 7328c066c5ba..ee3a17fe87c3 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -317,6 +317,28 @@ static inline void free_partition(struct mtd_part *p) kfree(p); } +void part_fill_badblockstats(struct mtd_info *mtd) +{ + uint64_t offs = 0; + struct mtd_info *parent; + struct mtd_part *part = mtd_to_part(mtd); + + parent = part->parent; + + if (parent->_block_isbad) { + mtd->ecc_stats.badblocks = 0; + mtd->ecc_stats.bbtblocks = 0; + + while (offs < mtd->size) { + if (mtd_block_isreserved(parent, offs + part->offset)) + mtd->ecc_stats.bbtblocks++; + else if (mtd_block_isbad(parent, offs + part->offset)) + mtd->ecc_stats.badblocks++; + offs += mtd->erasesize; + } + } +} + static struct mtd_part *allocate_partition(struct mtd_info *parent, const struct mtd_partition *part, int partno, uint64_t cur_offset) @@ -537,17 +559,9 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent, slave->mtd.ecc_strength = parent->ecc_strength; slave->mtd.bitflip_threshold = parent->bitflip_threshold; - if (parent->_block_isbad) { - uint64_t offs = 0; - - while (offs < slave->mtd.size) { - if (mtd_block_isreserved(parent, offs + slave->offset)) - slave->mtd.ecc_stats.bbtblocks++; - else if (mtd_block_isbad(parent, offs + slave->offset)) - slave->mtd.ecc_stats.badblocks++; - offs += slave->mtd.erasesize; - } - } +#ifndef CONFIG_MTD_LAZYECCSTATS + part_fill_badblockstats(&(slave->mtd)); +#endif out_register: return slave; diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 11cb0c50cd84..aa2b92bc6c53 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -68,6 +68,7 @@ struct mtd_part_parser_data { unsigned long origin; }; +void part_fill_badblockstats(struct mtd_info *mtd); /* * Functions dealing with the various ways of partitioning the space