[v2] mtd: rawnand: sunxi: fit maximized ECC step to page size

Message ID 20260904-submit-sunxi-nand-ecc-step-validation-v2-1-6e3ba6200948@gmail.com (mailing list archive)
State New
Headers
Series [v2] mtd: rawnand: sunxi: fit maximized ECC step to page size |

Commit Message

James Hilliard Sept. 4, 2026, 10:39 p.m. UTC
When nand-ecc-maximize is set, the driver unconditionally selects a
1024-byte ECC step. A NAND with a 512-byte page consequently produces
zero ECC steps before the available OOB bytes are divided by the step
count.

The older sunxi NAND controllers support 512-byte ECC blocks. Select the
smaller of the page size and the preferred 1024-byte step, using a
512-byte step for a 512-byte page while retaining 1024-byte steps for
larger pages. Unsupported smaller steps and controllers without
512-byte support continue to be rejected by the existing checks.

Fixes: 4796d8655915 ("mtd: nand: sunxi: Support ECC maximization")
Cc: stable@vger.kernel.org
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Changes in v2:
- fix ECC maximization at its source by selecting a 512-byte step for
  512-byte pages instead of validating the derived step count
- retain 1024-byte steps for larger pages and the existing capability checks
- rebase on the current MTD nand/next branch
- Link to v1: https://patch.msgid.link/20260811060651.227431-1-james.hilliard1@gmail.com
---
 drivers/mtd/nand/raw/sunxi_nand.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


---
base-commit: def559a215699aa2f2d8ef98f30156b9d562a154
change-id: 20260904-submit-sunxi-nand-ecc-step-validation-0e571088b5e7

Best regards,
--  
James Hilliard <james.hilliard1@gmail.com>
  

Comments

sashiko-bot@kernel.org Sept. 4, 2026, 10:47 p.m. UTC | #1
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] ECC strength maximization overestimates available capacity for 512-byte pages due to a bit-length calculation mismatch, causing initialization failures.
--

commit de85ead656c2f999d69dec7e2c0a592634ba071e
Author: James Hilliard <james.hilliard1@gmail.com>

mtd: rawnand: sunxi: fit maximized ECC step to page size

This commit addresses an issue where maximizing ECC strength for a NAND
with a 512-byte page yields zero ECC steps. It modifies the driver to
dynamically select a 512-byte step for 512-byte pages, while retaining
1024-byte steps for larger pages.

> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 83666dd6cb2a8..de1e6b49f79aa 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -2084,7 +2084,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>  	if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) {
>  		int bytes = mtd->oobsize;
>  
> -		ecc->size = 1024;
> +		ecc->size = min_t(unsigned int, mtd->writesize, 1024);

[Severity: High]
Does setting ecc->size to 512 for 512-byte pages cause a bit-length
calculation mismatch downstream?

When ecc->size is 512, the maximum ECC strength is estimated using 13 bits
per symbol (fls(4096)):

sunxi_nand_hw_ecc_ctrl_init() {
    ...
		ecc->strength = bytes * 8 / fls(8 * ecc->size);
    ...
}

However, the driver later unconditionally calculates the required ECC bytes
assuming 14 bits per symbol:

sunxi_nand_hw_ecc_ctrl_init() {
    ...
	/* HW ECC always request ECC bytes for 1024 bytes blocks */
	ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
    ...
}

This mismatch overestimates the maximum strength. For example, with 26
available OOB bytes, the 13-bit estimation incorrectly selects a strength of
16, but the 14-bit calculation requires 28 bytes. 

The subsequent bounds check:

sunxi_nand_hw_ecc_ctrl_init() {
    ...
	if (mtd->oobsize < (ecc->bytes * nsectors + total_user_data_sz))
		return -EINVAL;
    ...
}

then fails, causing the driver probe to abort for 512-byte page devices when
nand-ecc-maximize is enabled.

>  		nsectors = mtd->writesize / ecc->size;
>  
>  		if (!nfc->caps->reg_user_data_len) {
  

Patch

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 83666dd6cb2a..de1e6b49f79a 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -2084,7 +2084,7 @@  static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 	if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) {
 		int bytes = mtd->oobsize;
 
-		ecc->size = 1024;
+		ecc->size = min_t(unsigned int, mtd->writesize, 1024);
 		nsectors = mtd->writesize / ecc->size;
 
 		if (!nfc->caps->reg_user_data_len) {