Re: [PATCH v1 4/5] mtd: rawnand: meson: clear OOB buffer before read

From: Liang Yang
Date: Tue Apr 18 2023 - 23:05:16 EST


Hi Arseniy,

On 2023/4/18 22:57, Arseniy Krasnov wrote:
[ EXTERNAL EMAIL ]



On 18.04.2023 16:25, Miquel Raynal wrote:
Hi Arseniy,

Hello again @Liang @Miquel!

One more question about OOB access, as I can see current driver uses the following
callbacks:

    nand->ecc.write_oob_raw = nand_write_oob_std;
    nand->ecc.write_oob = nand_write_oob_std;


Function 'nand_write_oob_std()' writes data to the end of the page. But as I
can see by dumping 'data_buf' during read, physical layout of each page is the
following (1KB ECC):

0x000: [         1 KB of data        ]
0x400: [ 2B user data] [ 14B ECC code]
0x410: [         1 KB of data        ]    (A)
0x810: [ 2B user data] [ 14B ECC code]
0x820: [        32B unused           ]



So, after 'nand_write_oob_std()' (let data be sequence from [0x0 ... 0x3f]),
page will look like this:

0x000: [             0xFF            ]
0x400: [           ........          ]
0x7f0: [             0xFF            ]
0x800: [ 00 .......................  ]
0x830: [ ........................ 3f ]

Here we have two problems:
1) Attempt to display raw data by 'nanddump' utility produces a little bit
    invalid output, as driver relies on layout (A) from above. E.g. OOB data
    is at 0x400 and 0x810. Here is an example (attempt to write 0x11 0x22 0x33 0x44):

0x000007f0: 11 22 ff ff ff ff ff ff ff ff ff ff ff ff ff ff  |."..............|
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  |................|
   OOB Data: 33 44 ff ff ff ff ff ff ff ff ff ff ff ff ff ff  |3D..............|
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  |................|
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  |................|
Hi Arseniy,

I realized the write_oob_raw() and write_oob() are wrong in meson_nand.c. I suggest both of them should be reworked and follow the format of meson nand controller. i.e. firstly format the data in Layout (A) and then write. reading is firstly reading the data of layout (A) and then compost the layout (B).

IIUC after such writing only OOB (e.g. user bytes) according layout (A), hw will also write ECC codes, so
it will be impossible to write data to this page later, because we cannot update ECC codes properly for the newly
written data (we can't update bits from 0 to 1).



2) Attempt to read data in ECC mode will fail, because IIUC page is in dirty
    state (I mean was written at least once) and NAND controller tries to use
    ECC codes at 0x400 and 0x810, which are obviously broken in this case. Thus

As i said above, write_oob_raw() and write_oob() should be reworked.
i don't know what do you mean page was written at least once. anyway the page should be written once, even just write_oob_raw().

Sorry, You mean that after OOB write, we cannot write to the data area (e.g. 0x0 .. 0x810) until page will be erased? For example
JFFS2 writes to OOB own markers, then it tries to write to the data area of such page.

@Liang, I'll describe current test case in details:
1) I have erased page, I can read it in both raw and ecc modes - no problem (it is full of 0xFF).
2) I (JFFS2 for example) want to write only OOB - let it be clean markers.
3) I use raw write to the needed page (please correct me if i'm wrong). Four bytes
at 0x400 and 0x810 are updated. All other bytes still 0xff.
4) Now, when i'm trying to read this page in ECC mode, I get ECC errors: IIUC this
happens because from controller point of view ECC codes are invalid for current
data (all ECCs are 0xff). Is this behaviour is ok?

Yes, it is exactly reported ECC errors.

5) Ok, don't care on these ECC errors, let's go further.
6) I'm going to write same page in ECC mode - how to do it correctly? There is already
4 OOB bytes, considered to be covered by ECC (but in fact now - ECC area is FFed).

If step 4 has excuted "program" command at the page (nand_write_oob_std() does), it can't be written again before erasing the page(block). so we have to read the whole page in the ddr and change the content, erase block, write it again.

I don't think Jffs2 has the same steps (1-6) as you said above. are you sure that happes on Jffs2 or just an example?


That's why I asked Your opinion about moving OOB data to nonprotected by ECC area (and
leave user's bytes untouched). In this case OOB access is free and not linked with ECC
codes which also covers data.

Thanks, Arseniy


A page is written after two steps:
- loading the data into the NAND chip cache (that's when you use the
bus)
- programming the NAND array with the data loaded in cache (that's when
you wait)

In theory it does not matter where you write in the cache, it's regular
DRAM, you can make random writes there with the appropriate NAND
commands. Of course when using embedded hardware ECC engines, the
controllers usually expect to be fed in a certain way in order to
produce the ECC bytes and put them at the right location in cache.

And then, when you actually send the "program" command, the NAND cells
actually get programmed based on what has been loaded in cache.

Thanks for this details! Very interesting!



Thanks,
Miquèl