diff options
| author | Ben Gardiner <bengardiner@nanometrics.ca> | 2011-06-14 16:35:06 -0400 | 
|---|---|---|
| committer | Scott Wood <scottwood@freescale.com> | 2011-07-01 15:56:51 -0500 | 
| commit | 169d54d8b33b4d06d6f215e2b312a0b18f7909dc (patch) | |
| tree | 0911e2f0acb0279b3bf8239c8d32546499a9ee18 | |
| parent | c135456ff59aed0302f99a2e1327939bdced77f5 (diff) | |
| download | olio-uboot-2014.01-169d54d8b33b4d06d6f215e2b312a0b18f7909dc.tar.xz olio-uboot-2014.01-169d54d8b33b4d06d6f215e2b312a0b18f7909dc.zip | |
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>
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 40 | ||||
| -rw-r--r-- | include/nand.h | 1 | 
2 files changed, 38 insertions, 3 deletions
| diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index e4ef8588a..81bf36615 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;  		} diff --git a/include/nand.h b/include/nand.h index c5818f179..8d94b5cbd 100644 --- a/include/nand.h +++ b/include/nand.h @@ -118,6 +118,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,  #define WITH_YAFFS_OOB	(1 << 0) /* whether write with yaffs format. This flag  				  * is a 'mode' meaning it cannot be mixed with  				  * other flags */ +#define WITH_DROP_FFS	(1 << 1) /* drop trailing all-0xff pages */  int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,  			u_char *buffer, int flags); |