[PATCH v3 12/15] mtd: rawnand: sunxi: combine contiguous unprotected OOB reads
From: James Hilliard <hidden>
Date: 2026-09-09 08:31:12
Also in:
linux-devicetree, linux-sunxi, lkml
Subsystem:
memory technology devices (mtd), nand flash subsystem, the rest · Maintainers:
Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Linus Torvalds
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 <redacted> --- 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