clarify calculation in nand_read_subpage and fix possible bug
Alexey Korolev
akorolev at infradead.org
Thu Nov 6 13:23:24 EST 2008
Hi Werner,
Sorry for delay.
I studied your patch. I liked it. It improves readability.
But I did not understand the note about a bug.
What is the case when bug appears? (What is the distribution of ecc
positions)
Thanks,
Alexey
> Alexey,
>
> while debugging a NAND ECC problem, I tried to figure out how the
> optimized ECC position calculation in nand_read_subpage worked. A
> few pulled hairs later :-) ... I think it could be simplified a
> bit, which also helps GCC to generate more compact code for it.
>
> If I understand things correctly, it also seems that the original
> algorithm had a small bug that would show with busw = 2 and
> non-contiguous ECC blocks. My analysis is below.
>
> Could you please have a look at it and ack it if you think it's
> okay ?
>
> Thanks !
>
> - Werner
>
> ---------------------------------- cut here -----------------------------------
>
> clarify-nand-ecc-access.patch
>
> The ECC access calculation in nand_read_subpage is quite hard to
> understand. This patch makes it more readable.
>
> There is a small change in what the algorithm does: while
> if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
> looks at the position of the ECC byte following the bytes we're
> currently reading,
> aligned_len = ALIGN(eccfrag_len+(pos-aligned_pos), busw);
> only looks at their length plus the additional data we have to read
> due to aligning the start position.
>
> I believe the latter to be more correct than the former, since the
> next ECC byte could be located anywhere and its location therefore
> may not give the alignment information we seek. I'm not even sure
> its position is always defined (what if we're reading the last ECC
> of the page ?).
>
> The last byte considered in the "gaps" test that checks that all ECC
> bytes are contiguous is
> eccfrag_len-2+start_step*ecc.bytes+1 =
> num_steps*ecc.bytes-2+start_step*ecc.bytes+1 =
> (start_step+num+steps)*ecc.bytes-1
> so it doesn't include (start_step + num_steps) * chip->ecc.bytes.
>
> The change also saves 44 bytes on ARM.
>
> ---
>
> Index: ktrack/drivers/mtd/nand/nand_base.c
> ===================================================================
> --- ktrack.orig/drivers/mtd/nand/nand_base.c 2008-11-02 02:28:19.000000000 -0200
> +++ ktrack/drivers/mtd/nand/nand_base.c 2008-11-02 02:38:22.000000000 -0200
> @@ -851,12 +851,12 @@
> } else {
> /* send the command to read the particular ecc bytes */
> /* take care about buswidth alignment in read_buf */
> - aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1);
> - aligned_len = eccfrag_len;
> - if (eccpos[start_step * chip->ecc.bytes] & (busw - 1))
> - aligned_len++;
> - if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
> - aligned_len++;
> +
> + int pos;
> +
> + pos = eccpos[start_step * chip->ecc.bytes];
> + aligned_pos = pos & ~(busw - 1);
> + aligned_len = ALIGN(eccfrag_len+(pos-aligned_pos), busw);
>
> chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1);
> chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
More information about the linux-mtd
mailing list