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

Ben Gardiner
2010-08-31T21:48:01Z

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

V6:
* return zero length and truncated if mtd_get_len_incl_bad is
called with offset>=size -- as per Scott Wood's review
comments

---
drivers/mtd/mtdcore.c | 49 ++++++++++++++++++++++++++++++++++++++++++
drivers/mtd/nand/nand_util.c | 6 +++++
include/linux/mtd/mtd.h | 4 ++-
3 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6eb52ed..78f2a08 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -142,3 +142,52 @@ 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 (offset >= mtd->size) {
+ *truncated = 1;
+ return;
+ }
+
+ 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;
+ }
+ }
+}
+#endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 29c42f7..622237f 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -435,6 +435,12 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)
static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,
const size_t length)
{
+ /*
+ * TODO: replace this implementation with a call to
+ * mtd_get_len_incl_bad((struct mtd_info *) nand, ...)
+ * when CONFIG_MTD_DEVICE is required for NAND support
+ */
+
size_t len_incl_bad = 0;
size_t len_excl_bad = 0;
size_t block_len;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 16556c4..8e8ec7c 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -259,7 +259,9 @@ extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
extern struct mtd_info *get_mtd_device_nm(const char *name);

extern void put_mtd_device(struct mtd_info *mtd);
-
+extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+ const uint64_t length, uint64_t *len_incl_bad,
+ int *truncated);
/* XXX U-BOOT XXX */
#if 0
struct mtd_notifier {
--
1.7.0.4