summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gardiner <bengardiner@nanometrics.ca>2010-08-31 17:48:01 -0400
committerScott Wood <scottwood@freescale.com>2010-10-11 15:11:00 -0500
commit4ba692fb1e413db974037238370b8402c8a60750 (patch)
tree055ea79276b8429c8653a85589052ffdd6e80d36
parent0a026d3e86f3981f6fc4f6d634708442f65873e5 (diff)
downloadu-boot-imx-4ba692fb1e413db974037238370b8402c8a60750.zip
u-boot-imx-4ba692fb1e413db974037238370b8402c8a60750.tar.gz
u-boot-imx-4ba692fb1e413db974037238370b8402c8a60750.tar.bz2
mtd: add an mtd method for get_len_incl_bad()
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>
-rw-r--r--drivers/mtd/mtdcore.c49
-rw-r--r--include/linux/mtd/mtd.h4
2 files changed, 52 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/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index f1cdf23..3b18d7d 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -255,7 +255,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 {