[PATCH v3 12/15] mtd: rawnand: sunxi: combine contiguous unprotected OOB reads
James Hilliard
james.hilliard1 at gmail.com
Wed Sep 9 01:30:45 PDT 2026
The randomized-format OOB reader fetches each parity region and the
unprotected tail separately. H6/H616 pack protected user data before the
first ECC step, leaving a contiguous range of parity bytes and tail data.
Combine adjacent parity regions without crossing protected user data,
and include the tail in the final transfer. Keep software de-randomization
separate so each ECC step and the tail retain their existing seed phases
and PIO/DMA representations. The NAND operation parser splits transfers
which exceed the controller SRAM size.
This reduces column commands for OOB reads without changing erased-page
classification, data-only reads or the plain-marker paths.
Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 6e54d3a92219..bbfed22640c8 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1412,15 +1412,28 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(struct nand_chip *nand,
int ret, i;
for (i = 0; i < ecc->steps; i++) {
- len = sunxi_nfc_user_data_sz(sunxi_nand, i);
off = sunxi_get_ecc_offset(sunxi_nand, ecc, i);
+ len = ecc->bytes;
+ /* Keep decoded user data, but combine adjacent parity regions. */
+ while (i + 1 < ecc->steps &&
+ !sunxi_nfc_user_data_sz(sunxi_nand, i + 1)) {
+ len += ecc->bytes;
+ i++;
+ }
+ if (i + 1 == ecc->steps)
+ len = mtd->oobsize - off;
+
ret = nand_change_read_column_op(nand, mtd->writesize + off,
- nand->oob_poi + off,
- ecc->bytes, false);
+ nand->oob_poi + off, len, false);
if (ret)
return ret;
- /* Preserve each path's normal representation of ECC bytes. */
- if (!dma) {
+ }
+
+ /* Preserve each path's normal representation of ECC bytes. */
+ if (!dma) {
+ for (i = 0; i < ecc->steps; i++) {
+ len = sunxi_nfc_user_data_sz(sunxi_nand, i);
+ off = sunxi_get_ecc_offset(sunxi_nand, ecc, i);
state = sunxi_nfc_randomizer_state(nand, page, true);
state = sunxi_nfc_randomizer_step(state, len * 8 + 15);
sunxi_nfc_randomize_buf(state, nand->oob_poi + off,
@@ -1431,10 +1444,6 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(struct nand_chip *nand,
off = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps);
len = mtd->oobsize - off;
if (len) {
- ret = nand_change_read_column_op(nand, mtd->writesize + off,
- nand->oob_poi + off, len, false);
- if (ret)
- return ret;
/* The unprotected tail uses the page seed and its 15-bit advance. */
state = sunxi_nfc_randomizer_state(nand, page, false);
state = sunxi_nfc_randomizer_step(state, 15);
--
2.53.0
More information about the linux-mtd
mailing list