aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBen Gardiner2011-06-14 16:35:06 -0400
committerScott Wood2011-07-01 15:56:51 -0500
commit169d54d8b33b4d06d6f215e2b312a0b18f7909dc (patch)
tree0911e2f0acb0279b3bf8239c8d32546499a9ee18 /drivers/mtd
parentc135456ff59aed0302f99a2e1327939bdced77f5 (diff)
nand_util: drop trailing all-0xff pages if requested
Add a flag to nand_read_skip_bad() such that if true, any trailing pages in an eraseblock whose contents are entirely 0xff will be dropped. The implementation is via a new drop_ffs() function which is based on the function of the same name from the ubiformat utility by Artem Bityutskiy. This is as-per the reccomendations of the UBI FAQ [1] [1] http://www.linux-mtd.infradead.org/doc/ubi.html#L_flasher_algo Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca> CC: Artem Bityutskiy <dedekind1@gmail.com> Acked-by: Detlev Zundel <dzu@denx.de> CC: Scott Wood <scottwood@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/nand_util.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index e4ef8588a74..81bf366159e 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -11,6 +11,9 @@
* nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
* and Thomas Gleixner (tglx@linutronix.de)
*
+ * Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
+ * Artem Bityutskiy <dedekind1@gmail.com> from mtd-utils
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -436,6 +439,29 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
return ret;
}
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
+ const size_t *len)
+{
+ size_t i, l = *len;
+
+ for (i = l - 1; i >= 0; i--)
+ if (buf[i] != 0xFF)
+ break;
+
+ /* The resulting length must be aligned to the minimum flash I/O size */
+ l = i + 1;
+ l = (l + nand->writesize - 1) / nand->writesize;
+ l *= nand->writesize;
+
+ /*
+ * since the input length may be unaligned, prevent access past the end
+ * of the buffer
+ */
+ return min(l, *len);
+}
+#endif
+
/**
* nand_write_skip_bad:
*
@@ -502,7 +528,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
return -EINVAL;
}
- if (!need_skip) {
+ if (!need_skip && !(flags & WITH_DROP_FFS)) {
rval = nand_write (nand, offset, length, buffer);
if (rval == 0)
return 0;
@@ -515,7 +541,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
while (left_to_write > 0) {
size_t block_offset = offset & (nand->erasesize - 1);
- size_t write_size;
+ size_t write_size, truncated_write_size;
WATCHDOG_RESET ();
@@ -561,7 +587,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
else
#endif
{
- rval = nand_write (nand, offset, &write_size, p_buffer);
+ truncated_write_size = write_size;
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+ if (flags & WITH_DROP_FFS)
+ truncated_write_size = drop_ffs(nand, p_buffer,
+ &write_size);
+#endif
+
+ rval = nand_write(nand, offset, &truncated_write_size,
+ p_buffer);
offset += write_size;
p_buffer += write_size;
}