Patchwork [U-Boot,3/4,v2] nand_util: drop trailing all-0xff pages if requested

login
register
mail settings
Submitter Ben Gardiner
Date May 19, 2011, 4:49 p.m.
Message ID <5f4c5335ba60c7a41055d7069d92bbc46a5f8366.1305823168.git.bengardiner@nanometrics.ca>
Download mbox | patch
Permalink /patch/96427/
State Superseded
Headers show

Comments

Ben Gardiner - May 19, 2011, 4:49 p.m.
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]

Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
CC: Artem Bityutskiy <dedekind1@gmail.com>

[1] http://www.linux-mtd.infradead.org/doc/ubi.html#L_flasher_algo

---

This behaviour was found to fix both UBI and JFFS2 images written to
cleanly erased NAND partitions on da850evm.

Changes since v1:
 * rebased to HEAD of git://git.denx.de/u-boot-nand-flash.git : ff7b4a0
   ("env_nand: zero-initialize variable nand_erase_options")
 * wrap the new functionality in a CONFIG_CMD_NAND_TRIMFFS ifdef to
   reduce size impact of new feature

---
 drivers/mtd/nand/nand_util.c |   32 +++++++++++++++++++++++++++++---
 include/nand.h               |    1 +
 2 files changed, 30 insertions(+), 3 deletions(-)
Detlev Zundel - May 24, 2011, 1:23 p.m.
Hi Ben,

> 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]
>
> Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
> CC: Artem Bityutskiy <dedekind1@gmail.com>

Acked-by: Detlev Zundel <dzu@denx.de>

Cheers
  Detlev

Patch

diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 03ccd02..2bfe743 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -436,6 +436,24 @@  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 (((const uint8_t *)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;
+	return l;
+}
+#endif
+
 /**
  * nand_write_skip_bad:
  *
@@ -499,7 +517,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;
@@ -512,7 +530,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 ();
 
@@ -558,7 +576,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;
 		}
diff --git a/include/nand.h b/include/nand.h
index 95b83a0..a5368e2 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -116,6 +116,7 @@  int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		       u_char *buffer);
 
 #define WITH_YAFFS_OOB	(1 << 0) /* whether write with yaffs format */
+#define WITH_DROP_FFS	(1 << 1) /* drop trailing all-0xff pages */
 #define WITH_DEFAULTS	0
 
 int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,