[U-Boot] [PATCH v5 2/5] mtd: add an mtd method for get_len_incl_bad()

Scott Wood
2010-08-30T20:57:24Z

On Mon, 30 Aug 2010 13:38:57 -0400
Ben Gardiner <bengardiner@nanometrics.ca> wrote:

> The logic to 'spread' mtd partitions needs to calculate the length in
> the mtd device, including bad blocks.
>
> This patch introduces a new function, mtd_get_len_incl_bad that can
> return both the length including bad blocks and whether that length
> was truncated on the device. This new function will be used by the
> mtdparts spread command later in this series. The definition of the
> function is #ifdef'd out in configurations that do not use the new
> 'mtdparts spread' command.
>
> Signed-off-by: Ben Gardiner<bengardiner@nanometrics.ca>
> CC: Scott Wood <scottwood@freescale.com>
>
> ---
>
> Note: the mtd_get_len_incl_bad() function could also be used by the
> get_len_incl_bad() function in nand_util.c except for the fact that
> boards can enable NAND support without enabling MTD support. A note
> has been added to get_len_incl_bad() to remind us to refactor when/if
> MTD support is available whenever NAND support is enabled.
>
> V5:
> * introduced in v5 of this patchset
> ---
> drivers/mtd/mtdcore.c | 44 ++++++++++++++++++++++++++++++++++++++++++
> drivers/mtd/nand/nand_util.c | 6 +++++
> include/linux/mtd/mtd.h | 4 ++-
> 3 files changed, 53 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 6eb52ed..cb86657 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -142,3 +142,47 @@ void put_mtd_device(struct mtd_info *mtd)
> c = --mtd->usecount;
> BUG_ON(c < 0);
> }
> +
> +#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
> +/**
> + * mtd_get_len_incl_bad
> + *
> + * Check if length including bad blocks fits into device.
> + *
> + * @param mtd an MTD device
> + * @param offset offset in flash
> + * @param length image length
> + * @return image length including bad blocks in *len_incl_bad and whether or not
> + * the length returned was truncated in *truncated
> + */
> +void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
> + const uint64_t length, uint64_t *len_incl_bad,
> + int *truncated)
> +{
> + *truncated = 0;
> + *len_incl_bad = 0;
> +
> + if (!mtd->block_isbad) {
> + *len_incl_bad = length;
> + return;
> + }
> +
> + uint64_t len_excl_bad = 0;
> + uint64_t block_len;
> +
> + while (len_excl_bad < length) {
> + block_len = mtd->erasesize - (offset & (mtd->erasesize - 1));
> +
> + if (!mtd->block_isbad(mtd, offset & ~(mtd->erasesize - 1)))
> + len_excl_bad += block_len;
> +
> + *len_incl_bad += block_len;
> + offset += block_len;
> +
> + if (offset >= mtd->size) {
> + *truncated = 1;
> + break;
> + }
> + }

If this function is called with offset == mtd->size, you should return
length zero and truncated, without calling block_isbad().

-Scott