Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf2ef288 authored by Nikhilesh Reddy's avatar Nikhilesh Reddy
Browse files

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.

NOTE: This patch was missed during the kernel upgrade. Not sure why but
before this can be merged, it needs to validated on the 3.18 kernel first.

Change-Id: I43d7a769a1d4ef769823d0b5bbe132adb474f892
Signed-off-by: default avatarMurali Palnati <palnatim@codeaurora.org>
Signed-off-by: default avatarKrishna Konda <kkonda@codeaurora.org>
Signed-off-by: default avatarNikhilesh Reddy <reddyn@codeaurora.org>
parent 6cb8923f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -309,6 +309,17 @@ config MTD_SWAP
	  The driver provides wear leveling by storing erase counter into the
	  OOB.

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"
+4 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>

#include <asm/uaccess.h>

@@ -964,6 +965,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;
+27 −11
Original line number Diff line number Diff line
@@ -322,6 +322,29 @@ 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 *master;
	struct mtd_part *part;

	part = PART(mtd);
	master = part->master;

	if (master->_block_isbad) {
		mtd->ecc_stats.badblocks = 0;
		mtd->ecc_stats.bbtblocks = 0;

		while (offs < mtd->size) {
			if (mtd_block_isreserved(master, offs + part->offset))
				mtd->ecc_stats.bbtblocks++;
			else if (mtd_block_isbad(master, offs + part->offset))
				mtd->ecc_stats.badblocks++;
			offs += mtd->erasesize;
		}
	}
}

/*
 * This function unregisters and destroy all slave MTD objects which are
 * attached to the given master MTD object.
@@ -531,17 +554,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
	slave->mtd.ecc_strength = master->ecc_strength;
	slave->mtd.bitflip_threshold = master->bitflip_threshold;

	if (master->_block_isbad) {
		uint64_t offs = 0;

		while (offs < slave->mtd.size) {
			if (mtd_block_isreserved(master, offs + slave->offset))
				slave->mtd.ecc_stats.bbtblocks++;
			else if (mtd_block_isbad(master, 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;
+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ struct mtd_part_parser_data {
};


void part_fill_badblockstats(struct mtd_info *mtd);

/*
 * Functions dealing with the various ways of partitioning the space
 */