diff mbox

UBI FS on 2MiB eraseblock Hynix MLC NAND

Message ID CAKa7sPSB+p6Zxk8uM9famKsg_Bhdv7=LirUimaV+Jti2aRRPZA@mail.gmail.com
State New, archived
Headers show

Commit Message

Viktar Palstsiuk Aug. 16, 2011, 7:48 a.m. UTC
The problem was caused by behavior of H27UBG8T2ATR Hynix MLC NAND
while UBI FS was trying to do page write operation. UBI FS was trying
to write data to the first empty page assuming that 0xFF page is
erased and writable. But this type of NAND returns error on page write
operation even if it was entirely written with 0xFF before. As far as
I'm using U-boot's 'nand write' to flash UBI image I've added skip if
U-boot trying to write 0xFF-page.

 	if (args.min_io_size < 0)

Best regards,
Viktar Palstsiuk

On Mon, Aug 15, 2011 at 7:01 PM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Thu, 2011-08-04 at 16:59 +0300, Viktar Palstsiuk wrote:
>> Hello,
>>
>> While trying to use UBI FS on Hynix MLC NAND (2MiB eraseblock, 8k
>> pagesize) I faced with the problem that root mounts well only during
>> first boot after it was flashed.
>> On the second boot it reports that it failed to recover master node.
>> If some one has tested UBI FS on devices with large eraseblock?
>
> Well, in theory it should work, but I've never heard about such huge
> eraseblock so probably you are the first trying it, and probably there
> is a bug.
>
>> NET: Registered protocol family 17
>> lib80211: common routines for IEEE802.11 drivers
>> rtc-mv rtc-mv: setting system clock to 2000-02-26 02:34:28 UTC (951532468)
>> UBIFS error (pid 1): ubifs_recover_master_node: failed to recover master node
>
> Could you please enable UBIFS debugging, reproduce the issue and send me
> all the kernel output - e.g., by typing dmesg or booting with the
> ignore_loglevel kernel option?
>
> --
> Best Regards,
> Artem Bityutskiy
>
>

Comments

Artem Bityutskiy Aug. 16, 2011, 8:08 a.m. UTC | #1
Hi,

On Tue, 2011-08-16 at 10:48 +0300, Viktar Palstsiuk wrote:
> The problem was caused by behavior of H27UBG8T2ATR Hynix MLC NAND
> while UBI FS was trying to do page write operation. UBI FS was trying
> to write data to the first empty page assuming that 0xFF page is
> erased and writable. But this type of NAND returns error on page write
> operation even if it was entirely written with 0xFF before. As far as
> I'm using U-boot's 'nand write' to flash UBI image I've added skip if
> U-boot trying to write 0xFF-page.
> 
> --- drivers/mtd/nand/nand_base.c
> +++ drivers/mtd/nand/nand_base.c	(working copy)
> @@ -1761,7 +1761,18 @@
>  			   const uint8_t *buf, int page, int cached, int raw)
>  {
>  	int status;
> +	int i;
> 
> +	/* Skip empty page */
> +	for (i = 0; i < mtd->writesize; i++)
> +                if (buf[i] != 0xFF)
> +                        break;
> +	
> +	if (i == mtd->writesize) {
> +		printf ("nand_write_page: Skip 0xFF page\n");
> +		return 0;
> +	}
> +	

This solution is not acceptable as we are currently discussing in the
"GPMI-NAND Status" thread in this mailing list.

Instead, you should just change u-boot, and I believe someone has done
this recently - ask the u-boot mailing list. I think that was Ben -
CCed.

The alternative is to use the new UBIFS "fixup" feature, see
http://www.linux-mtd.infradead.org/faq/ubifs.html#L_free_space_fixup

Additionally, here is my old writing about how the UBI flasher should
work, just FYI:
http://www.linux-mtd.infradead.org/doc/ubi.html#L_flasher_algo

> So it works fine now.

No, with this change if my data happens to be all 0xFFs - it will be unprotected
against bit flips.

BTW, I asumme you read this:

http://www.linux-mtd.infradead.org/faq/ubifs.html#L_ubifs_mlc

> diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
> index dcdb722..307edff 100644
> --- a/mkfs.ubifs/mkfs.ubifs.c
> +++ b/mkfs.ubifs/mkfs.ubifs.c
> @@ -390,7 +390,7 @@ static int validate_options(void)
>  		return err_msg("LEB should be multiple of min. I/O units");
>  	if (c->leb_size % 8)
>  		return err_msg("LEB size has to be multiple of 8");
> -	if (c->leb_size > 1024*1024)
> +	if (c->leb_size > 2*1024*1024)
>  		return err_msg("too large LEB size %d", c->leb_size);
>  	if (c->max_leb_cnt < UBIFS_MIN_LEB_CNT)
>  		return err_msg("too low max. count of LEBs, minimum is %d",
> diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
> index 453494d..a71d067 100644
> --- a/ubi-utils/ubinize.c
> +++ b/ubi-utils/ubinize.c
> @@ -253,7 +253,7 @@ static int parse_opt(int argc, char * const argv[])
>  	if (args.peb_size < 0)
>  		return errmsg("physical eraseblock size was not specified (use -h
> for help)");
> 
> -	if (args.peb_size > 1024*1024)
> +	if (args.peb_size > 2*1024*1024)
>  		return errmsg("too high physical eraseblock size %d", args.peb_size);
> 
>  	if (args.min_io_size < 0)

Please, introduce a nice macro like MAX_PEB_SIZE and use it instead
Yauhen Kharuzhy Aug. 16, 2011, 8:30 a.m. UTC | #2
On Tue, Aug 16, 2011 at 11:08:20AM +0300, Artem Bityutskiy wrote:
> Hi,
> 
> On Tue, 2011-08-16 at 10:48 +0300, Viktar Palstsiuk wrote:
> > The problem was caused by behavior of H27UBG8T2ATR Hynix MLC NAND
> > while UBI FS was trying to do page write operation. UBI FS was trying
> > to write data to the first empty page assuming that 0xFF page is
> > erased and writable. But this type of NAND returns error on page write
> > operation even if it was entirely written with 0xFF before. As far as
> > I'm using U-boot's 'nand write' to flash UBI image I've added skip if
> > U-boot trying to write 0xFF-page.
> > 
> > --- drivers/mtd/nand/nand_base.c
> > +++ drivers/mtd/nand/nand_base.c	(working copy)
> > @@ -1761,7 +1761,18 @@
> >  			   const uint8_t *buf, int page, int cached, int raw)
> >  {
> >  	int status;
> > +	int i;
> > 
> > +	/* Skip empty page */
> > +	for (i = 0; i < mtd->writesize; i++)
> > +                if (buf[i] != 0xFF)
> > +                        break;
> > +	
> > +	if (i == mtd->writesize) {
> > +		printf ("nand_write_page: Skip 0xFF page\n");
> > +		return 0;
> > +	}
> > +	
> 
> This solution is not acceptable as we are currently discussing in the
> "GPMI-NAND Status" thread in this mailing list.
> 
> Instead, you should just change u-boot, and I believe someone has done
> this recently - ask the u-boot mailing list. I think that was Ben -
> CCed.

As I understood, above Victor's patch is for U-Boot, not for kernel.
Viktar Palstsiuk Aug. 16, 2011, 8:49 a.m. UTC | #3
On Tue, Aug 16, 2011 at 11:08 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> The alternative is to use the new UBIFS "fixup" feature, see
> http://www.linux-mtd.infradead.org/faq/ubifs.html#L_free_space_fixup

Does UBIFS fixup works on 2.6.39.2 or should I switch to kernel version 3.0?

Best regards,
Viktar Palstsiuk
Ben Gardiner Aug. 22, 2011, 1:10 p.m. UTC | #4
Hi Viktar, Artem,

On Tue, Aug 16, 2011 at 4:08 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Tue, 2011-08-16 at 10:48 +0300, Viktar Palstsiuk wrote:
>> [...]
> This solution is not acceptable as we are currently discussing in the
> "GPMI-NAND Status" thread in this mailing list.
>
> Instead, you should just change u-boot, and I believe someone has done
> this recently - ask the u-boot mailing list. I think that was Ben -
> CCed.

Yep. That was me (with some critical help from others of course).

The problem to which you (Viktar) are refferring is certainly not
limited to hynix, 2mib or mlc. I agree with Artem's assessment: use
the new 'nand write.trimffs'  command in u-boot or use the fixup flag
in your ubi images.

Best Regards,
Ben Gardiner

---
Nanometrics Inc.
http://www.nanometrics.ca
diff mbox

Patch

--- drivers/mtd/nand/nand_base.c
+++ drivers/mtd/nand/nand_base.c	(working copy)
@@ -1761,7 +1761,18 @@ 
 			   const uint8_t *buf, int page, int cached, int raw)
 {
 	int status;
+	int i;

+	/* Skip empty page */
+	for (i = 0; i < mtd->writesize; i++)
+                if (buf[i] != 0xFF)
+                        break;
+	
+	if (i == mtd->writesize) {
+		printf ("nand_write_page: Skip 0xFF page\n");
+		return 0;
+	}
+	
 	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);

 	if (unlikely(raw))

So it works fine now.

I also had to increase PEB size limit in mtd-utils to create UBI image.

diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index dcdb722..307edff 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -390,7 +390,7 @@  static int validate_options(void)
 		return err_msg("LEB should be multiple of min. I/O units");
 	if (c->leb_size % 8)
 		return err_msg("LEB size has to be multiple of 8");
-	if (c->leb_size > 1024*1024)
+	if (c->leb_size > 2*1024*1024)
 		return err_msg("too large LEB size %d", c->leb_size);
 	if (c->max_leb_cnt < UBIFS_MIN_LEB_CNT)
 		return err_msg("too low max. count of LEBs, minimum is %d",
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 453494d..a71d067 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -253,7 +253,7 @@  static int parse_opt(int argc, char * const argv[])
 	if (args.peb_size < 0)
 		return errmsg("physical eraseblock size was not specified (use -h
for help)");

-	if (args.peb_size > 1024*1024)
+	if (args.peb_size > 2*1024*1024)
 		return errmsg("too high physical eraseblock size %d", args.peb_size);