mtd: Collect bad block count for ecc stats lazily

Normally bad block counts for ECC stats are collected
during boot time. This can be done lazily when the
ECCGETSTATS ioctl is invoked on the partition.

This can significantly decrease boot time, depending
on the size of the partition. Also rescanning on every
ioctl invocation helps in having the latest bad block count
rather than depending on the count that is collected during boot.

Change-Id: I43d7a769a1d4ef769823d0b5bbe132adb474f892
Signed-off-by: Murali Palnati <palnatim@codeaurora.org>
Signed-off-by: Krishna Konda <kkonda@codeaurora.org>
Signed-off-by: Nikhilesh Reddy <reddyn@codeaurora.org>
Signed-off-by: Pradeep P V K <ppvk@codeaurora.org>
Signed-off-by: Sarthak Garg <sartgarg@codeaurora.org>
Signed-off-by: Sai Kannan <quic_csaikann@quicinc.com>
This commit is contained in:
Krishna Konda 2020-12-10 12:42:30 +05:30 committed by Sai Kannan Chintakayala
parent 840e64a463
commit 0f5ad37363
4 changed files with 38 additions and 11 deletions

View file

@ -206,6 +206,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"

View file

@ -1174,6 +1174,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;

View file

@ -32,6 +32,26 @@ static inline void free_partition(struct mtd_info *mtd)
kfree(mtd);
}
void part_fill_badblockstats(struct mtd_info *mtd)
{
uint64_t offs = 0;
struct mtd_info *parent = mtd->parent;
struct mtd_info *master = mtd_get_master(parent);
if (master->_block_isbad) {
mtd->ecc_stats.badblocks = 0;
mtd->ecc_stats.bbtblocks = 0;
while (offs < mtd->part.size) {
if (mtd_block_isreserved(mtd, offs))
mtd->ecc_stats.bbtblocks++;
else if (mtd_block_isbad(mtd, offs))
mtd->ecc_stats.badblocks++;
offs += mtd->erasesize;
}
}
}
static struct mtd_info *allocate_partition(struct mtd_info *parent,
const struct mtd_partition *part,
int partno, uint64_t cur_offset)
@ -197,17 +217,9 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
child->ecc_strength = parent->ecc_strength;
child->bitflip_threshold = parent->bitflip_threshold;
if (master->_block_isbad) {
uint64_t offs = 0;
while (offs < child->part.size) {
if (mtd_block_isreserved(child, offs))
child->ecc_stats.bbtblocks++;
else if (mtd_block_isbad(child, offs))
child->ecc_stats.badblocks++;
offs += child->erasesize;
}
}
#ifndef CONFIG_MTD_LAZYECCSTATS
part_fill_badblockstats(child);
#endif
out_register:
return child;

View file

@ -70,6 +70,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