From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f39.google.com (mail-oo2-f39.google.com [74.125.231.167]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7322640B373 for ; Mon, 14 Sep 2026 21:09:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.167 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420201; cv=none; b=GAVY2G0BGPaiOZUnaFdrjV0xbDxyjrGBywI+ICeY6M3XhanWmo7snqVgww6pSBLcl6OEFQX5bN19PpOOq2P1iAWqZ+gbdQqtQ1IyzQfTigPkb4gxXKMUzFINPO3bK38rg9ULjKPbY0lwO2S8jCpP5wunh+EV9kk8cYaQT6GEouw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420201; c=relaxed/simple; bh=Lpu8BYiYZNteYXFlDSxlBr4C2CnU/Gx0SiTFgcn6nP0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aI80agxcCk6aVj+9BfyvgXPYahEmVSegH/YktD4P1GGu0kDRIJRiu5pD+GxXNzGqDO20MqqUM4AKlpLVMuvI2DO2z4YZY0YF7EtgZCG64PGbUsBw5hSziUFdDdGWSpmawbcMg4oglG7JiWCvWN3w/xC1GRkDoiPkRLtfPm7VzW4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ESj1jxDE; arc=none smtp.client-ip=74.125.231.167 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ESj1jxDE" Received: by mail-oo2-f39.google.com with SMTP id 006d021491bc7-6b4bff33ceaso1582196eaf.0 for ; Mon, 14 Sep 2026 14:09:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420196; x=1790024996; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=EsI+dpw6vMR742jYDR1gddCVyVHs7LTF48bPd8UEx9g=; b=ESj1jxDEdiHSeFw3lDieeXpPuAefVmMpIAIIciJkypCfYQgHlVRYZ9C3caqNiGHkg2 DsibmWK7k/EXsbddZvTopM2CLO1xA2cx7OsQW+iMhcHgM9xV0cDfD4g4V0ksxVbWyLD3 YYPZ2CiRlQkwU/l7eAo/BsGbfSWCAbXDHjwo06o4ZQymHwfMcdQn6AdUWzzoCLttvL7N Jb8MccZUNvHo76t7ZqTr/JbYp1X1gOkLrmhKA+fUta6zBgHBMhB5eGnynjCimKf2g0n5 ijvjnFGRMgqTKtReFk8MMj6sDYjRP/5Ty430yUqY+9xbmIMblcpE+Dhgo6R1mJJLdhHt bUxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420196; x=1790024996; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=EsI+dpw6vMR742jYDR1gddCVyVHs7LTF48bPd8UEx9g=; b=FC6m7OaE+4VsLLoBoAJrBTti8K5Zb2WiligWhYH/oLiUUxrbDL+z8DQXOmDSGFHjTN MiGDfpIQVXFSrtUJm4allCKYjoJW6tsKRA1dh1AeUiSMWNhdD0UgLjzeh5AfBTVH5x4c fz23KeMv3juRIg0JLDbv5LiJt+UX8VFtG/jMxhinn3ON1SjiKloe548HbsgZkHy6eMdh KR0yQF1u6/m0FAPYbBlxaSBuZ129w0FmGQMyM8ViSlY2hFPpIP/UChbX/UmGA5ro5ot1 yi/fpeI5/xe2jC0/kaFp3Nnn/H8Kr25Q12Gx0w+M4jBU8ljVRZe4iefdH3kafF3h9RYv cIGg== X-Forwarded-Encrypted: i=1; AKwUvBwV3SiMv2OLcHxfpynVSe50vycFko9DrdeYPQ2dOAi0hDmFUD8TsFp5sdcR2qpDzRDAmLPE8DVF7X/GeKU=@vger.kernel.org X-Gm-Message-State: AFuF++lI4M3G/ZJYWwKgG81SqoyIOKSUHo/FMt2lRqJqYYorQWuISCY7 BLC7xbQFsP0sBEhi8Vdo/GvghJhLKvi5fd4WcjnpWHPSXiAf3s4DC4ya X-Gm-Gg: AYBFou1iVhh3HfVA1XgNus2tQcyJegC5Bbxd9vTxl6W5XCD6HMQ6qkpFaoLk5qKpItv jC9hLNbf8AxizXFh1PT/4uYFWMlE9tydy+sV0UHq1Y3F1ZEx9S0k/bSSAGjE7GhueuWbkPM1G1U +IcU4fRKsbqA50/EqzsJ8M9zmDDYq8lH/G6JcbO8nKfHN3pnhY7PMYYNTYwHqnGbjNp7m6seaWN vOpfZgS72nRXEIA20VtZdnKbnLUSuZNyZG6I5EDHyTdx/OA+8rXMzS/PuzTkalJzTY3KBXhrSSl E1qjGvhXJEQ9cZLYlGrvRxJI4kxyNtIT6qeMmqoYQVqcky4XkPu15wKor1deqAXvzvTJQlpE4f4 y+GCsoAwdjQow0pudDQ97rdsJhbeaF4OBeNeKHHc1edZ1gpnOyeQFwTiyJlOWYZH+yx0Shdqs3a NnLv6vDvFQM1u7DMrBihZVV5hKsCkVay2VrTMEBosq1vZUMfaAfryCADGFQ7QjWzS07A0EHUWc9 c9d7t84Pjf6Dy7TPeB1Au3xaJjH3yGhl90oCFvK6omwIpv+Az4lTtt/jr1eIpOvBoTbLe8Or6Y5 DlxTph4U7KSznJcMIvpq1h6yIAflaCgpKlb2MclXXaHUivx0u0cLKVtnNsNC7Xz9pWDbLXGlUZi flw1etFC85VDvqNFrYMt1EdK8mHyw X-Received: by 2002:a05:6820:4d01:b0:6a1:4507:3544 with SMTP id 006d021491bc7-6c540d62bbfmr2624632eaf.28.1789420196428; Mon, 14 Sep 2026 14:09:56 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.09.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:09:55 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:47 -0600 Subject: [PATCH v6 01/18] mtd: rawnand: sunxi: drain interrupts before reusing the completion Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-1-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 A timed-out wait can return while the interrupt handler is still using the previous operation's interrupt status and enable mask. Starting the next wait calls init_completion() on the same object, which can reset its waitqueue lock while the old handler calls complete(). The old handler can also complete the new wait or restore an obsolete interrupt mask. Initialize the completion once in probe and use reinit_completion() for each interrupt-driven wait. On timeout, disable and synchronize the IRQ before masking controller interrupts and acknowledging the waited-for events. Draining the handler first also prevents a partial-event handler from rewriting the enable mask after it has been cleared. Flush these register writes before re-enabling the IRQ line, leaving the controller's interrupt sources masked. For successful waits, move complete() after the handler's register updates so that the next operation cannot race with those updates. Keep polling unchanged and leave controller and DMA abort handling to the existing callers. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index f41feebe4257..e50cf5b6a730 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -374,6 +374,7 @@ struct sunxi_nfc_caps { * @chips: a list containing all the NAND chips attached to this NAND * controller * @complete: a completion object used to wait for NAND controller events + * @irq: NAND controller interrupt * @dmac: the DMA channel attached to the NAND controller * @use_mdma: use an internal MBUS DMA backend * @mdma_desc: H6-style MBUS DMA descriptor @@ -393,6 +394,7 @@ struct sunxi_nfc { unsigned long clk_rate; struct list_head chips; struct completion complete; + int irq; struct dma_chan *dmac; bool use_mdma; struct sunxi_nfc_mdma_desc *mdma_desc; @@ -414,12 +416,13 @@ static irqreturn_t sunxi_nfc_interrupt(int irq, void = *dev_id) if (!(ien & st)) return IRQ_NONE; =20 - if ((ien & st) =3D=3D ien) - complete(&nfc->complete); - + /* Finish updating the interrupt state before waking the next operation. = */ writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST); writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT); =20 + if ((ien & st) =3D=3D ien) + complete(&nfc->complete); + return IRQ_HANDLED; } =20 @@ -435,16 +438,19 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nf= c, u32 events, timeout_ms =3D NFC_DEFAULT_TIMEOUT_MS; =20 if (!use_polling) { - init_completion(&nfc->complete); + reinit_completion(&nfc->complete); =20 writel(events, nfc->regs + NFC_REG_INT); =20 ret =3D wait_for_completion_timeout(&nfc->complete, msecs_to_jiffies(timeout_ms)); - if (!ret) + if (!ret) { + /* Drain the handler before it can restore an old IRQ mask. */ + disable_irq(nfc->irq); ret =3D -ETIMEDOUT; - else + } else { ret =3D 0; + } =20 writel(0, nfc->regs + NFC_REG_INT); } else { @@ -457,6 +463,12 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc= , u32 events, =20 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); =20 + if (!use_polling && ret) { + /* Flush the mask and acknowledgment before re-enabling the IRQ. */ + readl(nfc->regs + NFC_REG_INT); + enable_irq(nfc->irq); + } + if (ret) dev_err(nfc->dev, "wait interrupt timedout\n"); =20 @@ -2617,6 +2629,7 @@ static int sunxi_nfc_probe(struct platform_device *pd= ev) nfc->dev =3D dev; nand_controller_init(&nfc->controller); INIT_LIST_HEAD(&nfc->chips); + init_completion(&nfc->complete); =20 nfc->regs =3D devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(nfc->regs)) @@ -2625,6 +2638,7 @@ static int sunxi_nfc_probe(struct platform_device *pd= ev) irq =3D platform_get_irq(pdev, 0); if (irq < 0) return irq; + nfc->irq =3D irq; =20 nfc->caps =3D of_device_get_match_data(dev); if (!nfc->caps) --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f42.google.com (mail-oo2-f42.google.com [74.125.231.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1079476CDD for ; Mon, 14 Sep 2026 21:10:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420204; cv=none; b=qdechiRdt0Wfe40ohHrlXrQBG+EcYte138SR4zck0gGtaLYEblubc7GRW6qVtR05VPc+4oUL/1WR8u5qtbSYV6GfdP1IRbwiEwfmLXgkMcnffCeP33xC6PbUeeb0iDXHAyflKkrbWsP0r77i36ESqcbihufIaLUhY+yZPm0X4nQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420204; c=relaxed/simple; bh=QNBt+pFeHHzCr6qyz6aRzEV+o3fccMFb5SqOxfos0lA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lu26hQfM7+X904ViL4AzGnJWG1dDungmXn+TdNsy2e2YLLFxD3VEzjkfTnyNItryNJ2fICLKEAW+BimM7eBkRnvW8qo/Dim9oHCIlm3dq1nn+WOcXxya0s2CoqaFfEhIF030ATh7+FoSK5vCfgSluCG4NGzBdQ8Ojiv+eCQ61EA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ozvgo8/9; arc=none smtp.client-ip=74.125.231.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ozvgo8/9" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-7f4f0c89e34so1834157a34.1 for ; Mon, 14 Sep 2026 14:09:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420198; x=1790024998; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Z2QJ/YfTCDyKu7jznVj9GPPyAB75HsBI8sl5USMlUvk=; b=ozvgo8/97agg2f1pieCOMOFS3cyzv5+2CQ9bwTeqh7vDYNxYf5xo7fTZCoEH4eyZkc 26ZF3+Z4efP5Q8DLAvi1S5teGYgdtJkbXfF3zqmaNYXW+bE9iucmcZxpvBLCEIymtb5E gL2bfwtUF1Z7mUpvylcCe8/WEOGzN2JZLJChQmO78rTVwpZlQuskKEA7++yPeX4JwKcA 0ah/JaSZc6OGfkHhcnKpH6RspBJiY1rFKaGvHdqyR4Ru9Fe5QYhRds1uQYnbx9wIKRK3 RlPsMQ9ECiHfpLXwwNUXL92jOVLYGe6GDSKD9kQ714t9LkhVHC5BbyN+o3b9SmU0Bt1H 9ENw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420198; x=1790024998; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Z2QJ/YfTCDyKu7jznVj9GPPyAB75HsBI8sl5USMlUvk=; b=gHzgr9CLfV1pOudPerd8g6j+A413UYOpr6CncXxZ+aENl0vMQKjd9kc4R5XxHwjJPF lnP0ozmgINfPAKmp1tTx5vpPF0ssv173db4YzyaUt1HzG7wLvrLGJ/TnGT2WaqBDx4Mm ToAQAzCW8VKFkwCu2HoCex4iRtwQ2Hi5e9rU/5GDcOnOpDYllOn9yDTmzS7ki27sLRAC fz7ycvnKpAuSswXPb2ZfnDUdSrwjz5wC7VBAgA7fJ1pNRt6gQJ1+53jt15GvZm+zVroC /3TbWakSStjQVlG5VHYpqyy/hnvOQaE1VtSZ186nMyIyB8Hsty9hnr2DQN6j6UgPZ29U VThQ== X-Forwarded-Encrypted: i=1; AKwUvBwWwityESHCe9p4zz/CvSEUWasuE5Qiwg6e7kkd/FfjqJhSKu1OS8T0ojRMk885L2T4MPtFULI3yC3iR5g=@vger.kernel.org X-Gm-Message-State: AFuF++komZgQwtzowStmPPWxBe6gPOuAqHhKQBp3hHnFbO57MKJmXfZP oeyzlbfIseBRvAhZxjT3d8WkUbxUUr3mpua+dB8+fHbqjASeDkk55eUO X-Gm-Gg: AYBFou3qBUBW0gOUMUhpIGFGm/PhGka0M5Lsj+tb4CQn8OJMpTDDjr1hRogwW30CbER gH28SGmpw5lNQqwZL5MinCp/KmMczmFxGTGCJaoAA9V4U732osnqOobZwVr/IAxT/CSN7sbqmio TSPAiru8bxhVaphjPhIygl5ZBLF66ISBAdYF1z6eKLd7LLT4YwcKHh700vKKz0vqwhsZ6u5Dr2S YSoYbYzyVkRlN0JATleFDSDT19LjrvdlNqcXLL3cmdUKgVZo5i//djriVBfVQFoOQznMi4fQLPG PsxjGhoVmQgasPjG8GOZxDyLvZVV80Ze1uGnoKgh2C7WTN3u8nj+5fp41tjR1OntLcuyQtXb6TS eIymE/dJhSDHeN47SV25Fd3q15MPq1HneC8D2eJqKseL+LZNIyJF/f8bAypA7gDOFKA78SgR5nb Df/+EYPGVQwej/qsYFgVI0RI2VvbUIO74+WVv1zAQJVq5EcrsQU8gsSLTHk8YUS8mxytFUGarbK fayTVafrXZvyC9Fa32s6klImSqQdIUcyT+iRlzWCgqQ1QZvydcCnxW7axtBY1tH9wLyH7sbZyGZ PJZJlzHbx2Gf8SF0+MXTG0TSH2jExNCwU+qq0BZw9W7mtBvsrH4rRf4tgyADcbghfzfcdlMFia8 oofAcXGPVWBFMGnI3tBqXmNSFrlAb X-Received: by 2002:a05:6820:98e:b0:6c1:c628:b0bf with SMTP id 006d021491bc7-6c53f44bc19mr2434309eaf.13.1789420197732; Mon, 14 Sep 2026 14:09:57 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.09.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:09:57 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:48 -0600 Subject: [PATCH v6 02/18] mtd: rawnand: sunxi: use the logical step's OOB length in PIO Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-2-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 PIO transfers always use hardware ECC slot zero, even when transferring a later logical step. The user-data length programmed into that slot can differ from the first step's length on H6/H616 controllers. The ECC correction and protected-OOB write helpers instead derive the length from the hardware slot. Pattern handling can consequently fill beyond the current step's OOB region, including beyond the page's OOB buffer for its last step. Writes can also fetch bytes outside the current step's protected user data. Pass the logical step's user-data length to both helpers, as the protected OOB read helper already does. Keep the hardware slot for register access. DMA callers pass their existing per-step length, without changing the on-flash layout. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user= data length") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index e50cf5b6a730..172c7c4b0ba6 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1011,11 +1011,11 @@ static void sunxi_nfc_set_user_data_len(struct sunx= i_nfc *nfc, =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, const u8 *oob, int step, - bool bbm, int page) + bool bbm, int page, + unsigned int user_data_sz) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; =20 /* Randomize the Bad Block Marker. */ @@ -1069,11 +1069,9 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nan= d_chip *nand, =20 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, int step, u32 status, u32 pattern_found, - bool *erased) + unsigned int user_data_sz, bool *erased) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; u32 tmp; =20 @@ -1155,7 +1153,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, =20 ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, &erased); + pattern_found, user_data_sz, &erased); if (erased) return 1; =20 @@ -1323,7 +1321,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf ret =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, - &erased); + user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ if (ret < 0) @@ -1420,7 +1418,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page, + user_data_sz); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, @@ -1684,7 +1683,8 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *oob =3D nand->oob_poi + oob_off; =20 - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page, + user_data_sz); sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C58B41167F for ; Mon, 14 Sep 2026 21:10:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420207; cv=none; b=L0DAdi/fvZkaW1Z7VnNZsnS5wiY5VoIAOQUfVv+Mc4sq0BIHahUAAux2ehn2cZbbIhVu9/RuOOlktfM2YICHd4vRR6w/2hwSwSnPa5EadxHG25m94b+R5WUP5Ksqi8DAYgt9X1XdXCk4mk4O+2xPIYUnj+nrHeou4ErMk3FAP4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420207; c=relaxed/simple; bh=sEgsacOGRde9P8OKLBN0PM1Bqnp+ZYDx65EvzcaNGcA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DE1bwVLVCENYvMEqNZtFmKjJ1IiHYTY+ETXMV3aqyT6bavECVgHq2obKnBpuZVkyq0ISmYfC8DYPhOF/Wef8U2m7EKOwr+ljWNTT7EtxD4xC7gaCv7OzfYaZD6QlBQDzIdxs+iJKmqCnXSowkqNDdixxiReBS6rDRzif7TixuaA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=B2tbFN00; arc=none smtp.client-ip=209.85.161.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="B2tbFN00" Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-6bc7a8b4802so4254796eaf.2 for ; Mon, 14 Sep 2026 14:10:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420200; x=1790025000; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=a95pnyMUuTP3EJOQCSW0InToPnlbmRSOMBXnRGDUxFk=; b=B2tbFN00djp9L7fLBmsFagRNQmlKBvS1O/J5gy1zvNJ7cYNfQ0hDkfC0cKC0ZunRhQ GyfteCjwn9BrTvd5Fdg8ZHadlY7gUa3+5ixV7WiJPC1gwMwnZaAt+LaBh5rUv7zN4tZh AMrg+WbTpiO2tqOL83AD7dP2PQT3z37KvfWqvKQWfbCS6MLFgqfP4nrwtW22bvDpxu/8 X3fgk86NfBq6JcXuRp7/Cv/oBEoPY9lMFWlSrwpG6l9POPzOwkm6czPudqGi8TG9kZwB K3kBrnPyBsnroqBd9WNh/3wv/dVIBphsPdyOBFqu5wQYEqfz1gydsb2PoTUPSsqoHu0/ syFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420200; x=1790025000; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=a95pnyMUuTP3EJOQCSW0InToPnlbmRSOMBXnRGDUxFk=; b=Tv0uGvHMUV6VJYZle+lqCvBXCsriMvMf659gf1dK+VdUV7nNbUHLEkofaqgjf54Puz tifg6pjdcfSbvqwlhHVi2cPK6f+VISHkXT6XL0NE7kKyapy9QKOG+zh9JB8SiaWkkg1s YDAFJ4InC9/bTux/2/+EJZdzym+ImLNt6OZft4dHtvEdkt/JUIM1yIqmMzG7T+5oGSEF v8MZyqKPmTVLgMb9zJp9WMq4KE4mL92QwAsYZ1r63QUxXnn3hRwTMVJTU8gtfRgsYuZZ dmScDvLN/g98Yh2IbkRowlJCQMykM8afDR0N3SMxMAFHpww+oMv4BB49y/KMArObilME hKHQ== X-Forwarded-Encrypted: i=1; AKwUvBxHhfXG7UNZyc6x8ksGL3cwEfIkk4ONShgSvk3f6ox0N+u3mQGsF43QxyJp93LSOZiGNJMDILLBDmEor+E=@vger.kernel.org X-Gm-Message-State: AFuF++neeqVppx0GJNNuSmxDkyXRwZA9DqJ9vaDdpPqovLz4xKz0NCov 7Sy5kS+KhzB/U1VfFIBOADjmSrj+YKP0ldB0Tn4YzN75JQlU/hdCqNkB X-Gm-Gg: AYBFou3r/7v5rHqep4rYtqbdYXXMZQ5mzo2+8JGyalG1PpOmOOrVrckaQ2PV2/pcg02 MChOeDELvHTiaaYBeCh25B6UTogHEiE1leZpCKEotZ6fX/r8FdftPgqNtXmH4UbraETg9bbcC3l pnvhAJdxaiHyxqQF/LmFFHqDx28qobrzxtgyICojNwo+1rebgw0tr6zzdJAZBNsnP/h2thlVINb dnY1hhnE4DDJl41qJQ9fkCYY2kAc3wXY+5Q65cwd8bmBcwYsf0Klgo8woqQ0cz6BH+4XYwyDdVv zeFofn1SOEor7DtuNJvqzVVFzvIAK/lD4OkPYUaA1X4pFmzdsA3PlaLotkl9MDwBkt9Lij3V765 bINl1kSiB4RY8uekJ1B4oRIEEd+KZr6Og1QE1Gd+Io1m531u46ZFqRB5N+Ncl4ZzGEEz3M317d1 A5Jtoj/yK28QXgpH6KJ5UA6x4oOExlythXCCNkabR0SmjpJQe8bOcDRaQLIa2Ao3Eu+ZGE5z1T4 FJA4MYzclK6GP1KMIyT3UQDzEE6IvR/vxS4jRHCKE6tgW3mpvd+MkkpX/5cPiZKRBVn9nv1B7QP abfqMMb581F5tIHUhBYNmi+3YVJ0+Wni11RGp1Jf5pX96899BdQegnVkniTpDOQ59XCGt+1yQlo IR3fI5Y0YPPgz/Mm0Qw0CXzqlHvlL X-Received: by 2002:a05:6820:810:b0:6be:6f42:3a86 with SMTP id 006d021491bc7-6c544ca9f68mr2776984eaf.47.1789420199333; Mon, 14 Sep 2026 14:09:59 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.09.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:09:58 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:49 -0600 Subject: [PATCH v6 03/18] mtd: rawnand: sunxi: propagate page-setup and erased-check errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-3-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 The hardware-ECC read callbacks ignore errors from nand_read_page_op(). A failed page-setup command can leave the previous page available, so a later successful transfer can return stale data instead of the requested page. Stop before starting the PIO or DMA transfer when page setup fails. The physical rereads used to check an uncorrectable chunk for erased contents also ignore errors from nand_change_read_column_op(). A failed transfer can therefore leave stale data in the buffers used for the erased check and turn an I/O failure into an ECC result. Share the erased-chunk fallback between PIO and DMA and stop before checking the buffers when either reread fails. Preserve the existing erased-chunk test and corrected-bit accounting when both reads succeed. Before retrying a failed DMA read in PIO, restore only its corrected and failed counters so partial results are not counted twice. Leave bad-block and BBT counters alone. Route PIO page and subpage error exits through ECC disable before returning the transfer error. Fixes: 97d90da8a886 ("mtd: nand: provide several helpers to do common NAND = operations") Fixes: 25f815f66a14 ("mtd: nand: force drivers to explicitly send READ/PROG= commands") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 120 +++++++++++++++++++++++-----------= ---- 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 172c7c4b0ba6..d5d8d383b6d1 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1067,6 +1067,40 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nan= d_chip *nand, } } =20 +/* + * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC + * statistics updated in either case. Negative values report transport err= ors. + */ +static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, + u8 *data, int data_off, + u8 *oob, int oob_off, + unsigned int user_data_sz, + unsigned int *max_bitflips) +{ + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + unsigned int oob_len =3D ecc->bytes + user_data_sz; + int ret; + + /* Check the physical representation for bitflips in erased pages. */ + if (nand->options & NAND_NEED_SCRAMBLING) { + ret =3D nand_change_read_column_op(nand, data_off, data, + ecc->size, false); + if (ret) + return ret; + } + + ret =3D nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + if (ret) + return ret; + + ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, oob_len, NULL, = 0, + ecc->strength); + + sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); + + return ret >=3D 0; +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, int step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) @@ -1115,7 +1149,6 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int raw_mode =3D 0; u32 pattern_found; bool bbm =3D !step; bool erased; @@ -1158,25 +1191,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, return 1; =20 if (ret < 0) { - /* - * Re-read the data with the randomizer disabled to identify - * bitflips in erased pages. - */ - if (nand->options & NAND_NEED_SCRAMBLING) - nand_change_read_column_op(nand, data_off, data, - ecc->size, false); - else + if (!(nand->options & NAND_NEED_SCRAMBLING)) memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 - nand_change_read_column_op(nand, oob_off, oob, - ecc->bytes + user_data_sz, false); - - ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, ecc->strength); - if (ret >=3D 0) - raw_mode =3D 1; + return sunxi_nfc_hw_ecc_read_error(nand, data, data_off, + oob, oob_off, user_data_sz, + max_bitflips); } else { memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 @@ -1193,7 +1214,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, =20 sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); =20 - return raw_mode; + return 0; } =20 /* @@ -1260,6 +1281,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + unsigned int corrected =3D mtd->ecc_stats.corrected; + unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; int ret, i, raw_mode =3D 0; struct scatterlist sg; @@ -1354,29 +1377,18 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf if (!(status & NFC_ECC_ERR(i))) continue; =20 - /* - * Re-read the data with the randomizer disabled to - * identify bitflips in erased pages. - * TODO: use DMA to read page in raw mode - */ - if (randomized) - nand_change_read_column_op(nand, data_off, - data, ecc->size, - false); - - /* TODO: use DMA to retrieve OOB */ - nand_change_read_column_op(nand, - mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, false); - - ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, - ecc->strength); - if (ret >=3D 0) + ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, + mtd->writesize + oob_off, + user_data_sz, + &max_bitflips); + if (ret < 0) { + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected =3D corrected; + mtd->ecc_stats.failed =3D failed; + return ret; + } + if (ret) raw_mode =3D 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); } } =20 @@ -1471,7 +1483,9 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1487,7 +1501,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, &cur_off, &max_bitflips, i, oob_required, page); if (ret < 0) - return ret; + goto out; else if (ret) raw_mode =3D true; } @@ -1496,9 +1510,11 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_ch= ip *nand, uint8_t *buf, sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !raw_mode, page); =20 + ret =3D max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); =20 - return max_bitflips; + return ret; } =20 static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, @@ -1508,7 +1524,9 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand= _chip *nand, u8 *buf, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 ret =3D sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page, nand->ecc.steps); @@ -1532,7 +1550,9 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1550,12 +1570,14 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nan= d_chip *nand, &cur_off, &max_bitflips, i, false, page); if (ret < 0) - return ret; + goto out; } =20 + ret =3D max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); =20 - return max_bitflips; + return ret; } =20 static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, @@ -1567,7 +1589,9 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 ret =3D sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks); if (ret >=3D 0) --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f15.google.com (mail-oo2-f15.google.com [74.125.231.143]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C732496D4B for ; Mon, 14 Sep 2026 21:10:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.143 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420207; cv=none; b=uwH6ZV6x4T8mH2DZdHru0+y4evj2p/HBm15Xm1kUavYY3wjBh5UCRJ7DCyLo707dMGfKbuuRq332kDRP7uUgpJggiX+w3/3LvqFB8+DhwJyVj+DfqN9YlrKz332/NOyLU4fl/Wivci494kmFkt+tmJaxyINfYJjfP8jEmqlDz74= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420207; c=relaxed/simple; bh=NlWMHvWo8eC8a5062ul0UGSwTs8Firq1Hsg3xcZzp2E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gjbwSwLH7NK4bnGyXG5mzmpGvnCTXtJLqGU9PccKg4ofoUENtKUWIdElpzaO3k5fWMs5aX92T/gN6n5bqnl7QplRlnXPqjvcOEeoZFH5pDYRdVnAOYarNLY7bTgIv+ukOPVmBkF1cuYgzTisCCPUKNP+IKy5iRgm5YHYvYUmaAA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QLypV6bk; arc=none smtp.client-ip=74.125.231.143 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QLypV6bk" Received: by mail-oo2-f15.google.com with SMTP id 006d021491bc7-6b4bff33d18so1038091eaf.3 for ; Mon, 14 Sep 2026 14:10:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420201; x=1790025001; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=o8noBZbj7C7U90sjdVnrOExXAG4fUCSDlE1zY+ZGE34=; b=QLypV6bkowW9b5a/idvjjP7Lmf1ME+qcN28u8bgC4qgZFtp2KLlz9JlqyCC/Itz6+x PuGHN8r8T2sBvogmsLHOqkWFWGHQXFxY+AHIkCdddqCCEz9xJgQxl0B62E20hDZe8PZM 5vBau6l2gNKobuHMrBLjBkLFx9lN1MIncq6LHr+omG2r9NLaEA7cYU4DheoDmJbaVMal fYm+KoztogOV/PRmPzhTfSdyksYk6bDLooQqITK9S8J31C/lxmA6JoHFKFQ/TNO62hrB bawju7Gw/Pqg9yVwDMGf4vDCrmkCCUo4mwyVt+qfcsWOKQjSZefjeMUzp0mkrrpT/e58 AUZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420201; x=1790025001; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=o8noBZbj7C7U90sjdVnrOExXAG4fUCSDlE1zY+ZGE34=; b=UhlnoPiEhlSlyeRORozB7s+IC0Oe6DgptptUx899aQ2BoQc31EsEW1fSxdtYfeo6/Y T6oUCcHjvzZ5oW4mgECKt339PXisGvVHRjWaE3mb5Pfu1/N1WH4or7UGhNSiM7LADibs cAfFzk6TcP4Fs7OMbX1w06WeXXAijv5PMJTdKUOhm8BKZD3mFDE2xAbjfoemkizRNKiM 0sXxWcoLLn0M1UtB5iHJ717yX8X4DokqCpHhevUExx75n58MEJMtp2lrBL1eDfueqi9k AOqPZeO0qHCEqmF/ujHbVXb3xKi6061IptVWPUznSy9uOXddumovs3lISdEa2bWDX6NU AvDw== X-Forwarded-Encrypted: i=1; AKwUvBxOI3ZJOuZZUb+yxl+sjI0EBwoXCmW8S08uhHjGB4XweTs67Z4CIcnNXRbkGA+M4Ys28Ug1njMn5oKtj9c=@vger.kernel.org X-Gm-Message-State: AFuF++k+jugVqVHjSjYZ86gQ8rV1Sr9mFGeJ+QHKL8M2Qu4wXE6v19UN AWi8c2BCsjoZ8jNcetUY6/yHucmyAHdsnXhybpiXb1AaUx+kAOMgMaLU X-Gm-Gg: AYBFou0xwXkdhTdOKWdTAAFLWAPYtpe4KvueUDCu1lDVXG+68OFv1mNsCaiFZnaSskd jVLKpj0vN0EXNtiKe282CfDAqPDW5XZzBNig+SKANhPUG+NM0TF2ryvCDtl6miVj9xbxQhfgzZk CHk0+aG5tz+Szm00cG8B37M04Nq1jAMHvh3PIPTk5rHERI8NZzSvklz0DMNd92H+UKtuXmX0OU6 H1tKdoCVknWB0BvUmRR9TB7mt9CZPuMW7mNnD9hjXPJJHV/plckuygE00UuEEMmb5J73kfqQ7fv PrForSpOy9IJB6iP5lUtjD6Uda0NolNucJhAnSCoYr7KT40nKZ4hqdsjf/uW8/4UYP6l49wDwAY U18zCnLTeUz9GySjzXKMhgAMc2fzH/VQ1x7xm9SIEOO/TusO/LtRbrw074K0NvdU1uQ9KiPetGF b9Yn1YfwuPLZNyU5lsfEbwXfthi4qkZfpXoLkTirWxKwhi69lCJEIlD2tWRScl9VT4lS0bCI+o4 bWINlAp+qzEj+ylBEzdi94ikKmhT2m3mGGAIhSxLHmB16vFk7gae4PPtTUkVXItecKDhMU1/Ik3 Ot8OEi13RausTBDWRl1xzDiLAVPLKlqb5TJealPTwn0srsJ2w3QID7P1xhNDM72G1MSyO6DXP01 ijME5CFNtw31ejYdiyGrSTMxLuqKR X-Received: by 2002:a05:6820:217:b0:6aa:ed21:6c95 with SMTP id 006d021491bc7-6c53c6f60abmr2434425eaf.0.1789420200643; Mon, 14 Sep 2026 14:10:00 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.09.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:00 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:50 -0600 Subject: [PATCH v6 04/18] mtd: rawnand: sunxi: stop failed program operations and disable ECC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-4-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 The PIO page and subpage write callbacks leave ECC enabled if a chunk transfer fails. They also ignore program-setup errors, as does the DMA page writer, and can continue transferring data and issuing PAGEPROG after the setup command has failed. Check program setup before enabling ECC or transferring data. If DMA preparation has already succeeded, abort the queued operation and unmap its buffer before returning the setup error. Route PIO chunk failures through ECC disable and return the original error. Issue the program-end command only after the transfers succeed, preserving the existing successful-write sequence. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Fixes: 25f815f66a14 ("mtd: nand: force drivers to explicitly send READ/PROG= commands") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index d5d8d383b6d1..5d88ad3b8f70 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1610,11 +1610,13 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_= chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int ret, i, cur_off =3D 0; + int ret =3D 0, i, cur_off =3D 0; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1629,14 +1631,17 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_= chip *nand, oob_off + mtd->writesize, &cur_off, i, page); if (ret) - return ret; + goto out; } =20 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, &cur_off, page); =20 +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; =20 return nand_prog_page_end_op(nand); } @@ -1650,11 +1655,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct na= nd_chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int ret, i, cur_off =3D 0; + int ret =3D 0, i, cur_off =3D 0; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1670,10 +1677,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct na= nd_chip *nand, oob_off + mtd->writesize, &cur_off, i, page); if (ret) - return ret; + goto out; } =20 +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; =20 return nand_prog_page_end_op(nand); } @@ -1712,7 +1722,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct na= nd_chip *nand, sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) { + sunxi_nfc_dma_op_abort(nfc); + sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + return ret; + } =20 sunxi_nfc_hw_ecc_enable(nand); sunxi_nfc_randomizer_config(nand, page, false); --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f43.google.com (mail-oo2-f43.google.com [74.125.231.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3527C416859 for ; Mon, 14 Sep 2026 21:10:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420209; cv=none; b=UvCEl0BYH3iP6X+yYj/TJCFkD4uENyqEBdlan3FMNpLW55oZ6JbrSm4fXzjomkgFm8jmEaY1MK9nlC/veIi6gfieIVn7fJiWy7IjWRwmgQfN+kjBAkCsHIfDnJH21zGEl96WTacqtwbeTBvwdV+Qa+VYZiQEm1vAqUEroBpCQAg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420209; c=relaxed/simple; bh=+EYozN7O+JBkDeCx/hgJ+s4q3FbwEjbXAk835pOjKgM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pjz5CvoRQiKABZlg9l95P7I82w166Owu0wCJ1Ek1vq4MfyUm8HYIaRL6nseB5+pCs1u4JcagORGf196QcYglI6bRunnOxRa+QPE15dyfohmZF1Q6Z/SYnr+qWO5iP5DCa+7LVlBudTPi4bmoeX1Ay5AQeo87qBmJS7EU7rxty4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=i7vsc+j0; arc=none smtp.client-ip=74.125.231.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="i7vsc+j0" Received: by mail-oo2-f43.google.com with SMTP id 46e09a7af769-7f4f0d05c12so1827738a34.0 for ; Mon, 14 Sep 2026 14:10:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420202; x=1790025002; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5tiLR7FZzQsyTOBW2MGeS5ZnHrzID+Jy7EEHyMHP5gI=; b=i7vsc+j0MDzwuy9p8HQ+0B6fX7YeN/OFLSqJ0wix6aKQhWXH7HfuJLbURyJ8YgAGrd qeDei1149SAby/vSYf18AEnUaKfPQti759XTfUMCyKH9IO/qpjnhjiu0arn7ravO+7Yq +DHCbpphQg5V5X968xFadqFfKcmx9AWWnXERirILenvHCfExLXJo+HRBQk4BcgRRxBnp WVvwDPyjJmjN59nC+Cl+UZn7pExjeZVQJP6h3yEAGf+7GoPFuZ/dem9mKTYq619ghJAx DoyoJoBNq5UyPANXN7VskMoQywwqhiBntzftlzs2hu0JOTAmzS9EUiYZgeS9jQAv8+sD xXhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420202; x=1790025002; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=5tiLR7FZzQsyTOBW2MGeS5ZnHrzID+Jy7EEHyMHP5gI=; b=lqClahwsfE+LgAYkGhrwT2sKE4YCOJNT2FqklEkOMNrocPmHyRpY8fTd4e1Lm6ebno Z23gQi539I1PVIeS9gFWIPYuRdV43hRH1ZnE2V4C9LAP6k/n8bH/VnlPH625/VcyCP4s v1Oj/43/qgoq7Q9ceWAq12ItW505oOjqFc37h9rTAg1KsyvV2uW/vEVAosjfjEvXVBvo aNqUhC0MLI1amvd7z0/xIRA815brYD8/ovxgbUzh7ClHXshazPK1djbzfr/B9W1ZQH0M 7v+++GLHL1aneo5YqkWWYidWWrJ5W8Q+uYJyGL1rMvVwofqsc5+I+I2hMa5/1K85UP0W jtxg== X-Forwarded-Encrypted: i=1; AKwUvBzdm6xkxQPgIuKmw5O83V1tRKDZSVg6fB5N8jg0awvKiJ9egELXeox8YR9pbw3hao6YbCBXEdtABjx8CBs=@vger.kernel.org X-Gm-Message-State: AFuF++ms4188Vij2InOaNXyyudasST8U9Q64joij3cUszN42DYrO+bm8 X86xgg3011oLU03bj9cvuBX8/IiPVUKDrxgB5HUy/WY+1x1bMv1CSF5X X-Gm-Gg: AYBFou3Jl4vGG+bMciAbfP6a/Ld8sit3j3pslvTFfKCyJjRYf8ufsTuqjru65AykIeq sTdCDPu6DgjSrfymZSHW95FvfFeVSC9gFqNrK997uYiboPG5dHF+sT1hGbee4n2oh2HOM7zdwLX hY6YMFSMAF3/uzOLhSGNH0P4BbR8rxu3ZMSm4RGy1Mp6+0q8k3U0Nxtt0Kxiy3kFGQrOu4FstIy DJnaSMmcI9SgfLpyvs8Ia+qUmHCARxKfj1eS2I89P+mKkYTrEO7yBc9tL+coGcqErOVYclZpJjJ NegEKuHxw1U85jXBG+aTuHwimC3zNTmkMu1s5/5o6YZB968fueRELGVoUPizW0Reyice/KaGS0I T9GlGmBoRTtsymAuSZGqA0zyPzhJGQinFa/o4QyJepEI6fBeoKGp1EckSp/e1beoWs+l2mTFB+o Exan0ZitH64DKOJlFA9OyqXwNV4M4Ds/9GB8i05WPCfUokfVYaL1QG0SLyLZNYMoucYviX2qjFM 6mQtwV9Qzg+Z1moWc5cC+96qXBEDwXvMTa7HH185l1Wysq/abwzwTXgiE83/xe/qoXi0F2FE+qm MDwj+RvQXEhCbKX6cgCAJeMZu0mwvckpdV7IxoB6pUBN62O/g4XVX1zfcsBXygj5OZc/Scs3fMI exX/xnQfpQhJshM/C72Kdf8p/g/z0Ng== X-Received: by 2002:a05:6820:80c7:b0:6b1:b33a:db69 with SMTP id 006d021491bc7-6c53fb6bf40mr4489299eaf.15.1789420202250; Mon, 14 Sep 2026 14:10:02 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:01 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:51 -0600 Subject: [PATCH v6 05/18] mtd: rawnand: sunxi: select the pattern ID for the current ECC step Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-5-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 The pattern ID register has one bit per hardware ECC step, distinguishing all-zero from all-ones data. The correction helper checks the current step's pattern-found bit but always reads pattern ID bit zero. PIO reuses hardware step zero, so this works there. DMA processes several steps at once: a later all-ones step can be filled with zeros and reported as a successful read if pattern ID bit zero is clear. Conversely, a later all-zero step can be treated as erased when bit zero is set. Use the current hardware step's pattern ID bit, matching the error and pattern-found bits already checked by the helper. Fixes: 614049a8d904 ("mtd: nand: sunxi: add support for DMA assisted operat= ions") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 5d88ad3b8f70..3f506d0666a1 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1117,7 +1117,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, if (pattern_found & BIT(step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1))) { + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 955D648122F for ; Mon, 14 Sep 2026 21:10:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420210; cv=none; b=SxfYAQT/DgIsWvZi65aKi8Ye8vYzLzKWMPm1cGDD8d2FdyIdlnGEzCS8IR9OlenRdeZOlP0pte5z90oizJwwrwv0CKDwX8Pw7blrnDzv7RZ6LsmYqR+az6I9NEB8cce1LUwgbGV8OSbJPXaBrzes1KGZk08y+1buCCVY43pNQC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420210; c=relaxed/simple; bh=QuwwqJoNNeFbRXCees1KSU/os0gxTVKzY6QPcLIi7JU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kf1ZA+h1gB0UQx8BF1QnFlLjMQM/9lDpiuhmlwfHzhoqfZNMNrhHh6eYAKKYhPt8r93yFxyoB6zQCRjYM+aFCAZtgDuXsT1Ui5OZ3TX1RlD9twfYbE2V+hittTa6ogJaDihIYnLSkBH7HbGcJV8Sbb+YgfRsofEw8pIPhPvcmbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qVeCUPCk; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qVeCUPCk" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6bc475ffcbfso787594eaf.2 for ; Mon, 14 Sep 2026 14:10:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420203; x=1790025003; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=j2vD4BC1COzN8qzLeVpRCLcx09AvVc6YiLKflTDkdf0=; b=qVeCUPCkE4NM4Pq7iFWyOjmliXB2aV4hFUHQzTBU4oGew1RNLlJi+wMITi1iXUHUCr xEn+dE8IKmBeasc6ouzRaNMBJgIL0C5MW9DQ9+ZMMMimgC6Od/IyUI9mZZTvV/bUU3pu 9p71Uf6oGFe++3CsTiG2seYu45We4qpcdmma94AGaM6DJdF1W4uwmSpfVSzp3+IQVBMm Ej7jTb9B66/E9NUtBWSfz5vwGtnIB5BfmlX8ml8rdzevgRJGX5j1+RH1aaflG0qHlpNL wR2Vft/H+dTggniSIPbVz6IJVuJW9Nz41lDlcpLmDfZJv2LHtANX8DagEmOY0LWkh+/e a26Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420203; x=1790025003; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=j2vD4BC1COzN8qzLeVpRCLcx09AvVc6YiLKflTDkdf0=; b=NbpvPmSs8gUOkpRsJLcSB4CkdlhvNsPvX0AGWGzL1a0grZ97YYSYx8yN5JVThZ6t6J mTYFSXvHWzg9P/l8X+eM6wJfm9HwfrMfNgRbmHebt6acbVhbivv53qdicj4KL8pgpIoc sokQuavAuCmQ1j76b5sipINGoOGg5/oDj5lAtL59Uxuzt8BwDxtFR3omsQkHjzMEDAnO DfH0pcSThGUMyi4/M6qZ6ftXHMj83A/iB6t2CQ5eD0emE244IS73ny2er8Z9gMaYt99u dpxupo7C6MRXlUsxQ7FfHUa47qAJiGprU0vDQtUX2P40VQKMUZefXDYUedsLabpaPjfa TOyQ== X-Forwarded-Encrypted: i=1; AKwUvBwBCqI1++PPlpjii+rs23mDyTOV8IppZJw3j4TlEGixRGXyKqhgvec8C3twUwN0GQkByZSCDZKnEUEywu4=@vger.kernel.org X-Gm-Message-State: AFuF++l6sz7Tr7Hsg40ZdI7cuSvFwsZWfeAb1MGhbhQR7rTF9SjDMv1t jBL++dLJ/826Y45feOSISBIylhI4OOAmDquh0VVxSD144z6Mbsr4JmZk X-Gm-Gg: AYBFou0hPmKA+ZSDPes452MBY8dfvXIFB8vhqTcLz2NHTHgLdnEFeFg6dx7qpG24dJv ACRSbxG5nM7LOVYpVMrVCU3uuYJDyCOHCIFv6pXtkmsVDjfM9gZh7hsLoWnlWaq3Y6sy/8HdrcC oTlSzYcgEwwMmgQja5zupOI+aKjHgUh2ypzmH360fWkd7UwjJimcc2Ode8LKsQQ8SIMnoGSSbVI UyYkKNkth46SEJRYp2RU9c2lRxZ8WY67e2VHY0fBhtY7/pZ9ucNGfGhCb6vxUrbLI3F+99jA6l3 0wN6OArVaozA6PXV1ibzSvST7Lu/U0/p4rUTroRQoQa1PnTxJWNo1wHPiOmogjoy60AueZeLghw 2OOKR8gqq6rPJArfukXqj+EXbtjOMe5kShAINR3tcPHqboQMvV+XziM/TPlCyvtN00exAs0JW8p zX3h6z6NQKNbMzWCPXRzN9sQqU8aeNnnUm1gu2sosvwpsFOkubDkNT5elrhzvkY2CMSw+RjxuYq ZMQgAazXqKneJSnaQbLOWEDwdF23/k4kNdn1+MXBEUa4dFLGAbvNjh6Z92Pd9Fv2ZbYcqMsMCME eju3P2nyvwNQREXQdrW5CkTzgWfTpkD7NXxW6Dhu47mpcLZpwpzgDCpy6hS/0AK6ZcTDZKNQpP3 vEIqPztABWTL7d1A7t926pUT3O+SD X-Received: by 2002:a05:6820:4cc1:b0:6bd:cb3f:5896 with SMTP id 006d021491bc7-6c53f558284mr2536286eaf.30.1789420203605; Mon, 14 Sep 2026 14:10:03 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:03 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:52 -0600 Subject: [PATCH v6 06/18] mtd: rawnand: sunxi: propagate buffer and column transfer errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-6-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 The PIO buffer helpers stop on a FIFO or completion timeout but return no status. Their hardware-ECC callers also ignore column-change failures, including the extra-OOB paths used after DMA. A read can therefore report success with incomplete data, and a write can issue PAGEPROG after a failed transfer. Return transfer errors through the randomizer and OOB helpers to the page callbacks. Always disable the randomizer after a buffer transfer, and let the existing page error exits disable ECC and skip program-end. Only advance the extra-OOB cursor after a successful transfer. Keep the corrected-bit count separate from transport status so successful OOB reads do not overwrite it. If any legacy DMA OOB read fails, discard the ECC statistics from that attempt before the caller retries in PIO. Leave the successful transfer sequence and OOB representation unchanged. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 220 ++++++++++++++++++++++++----------= ---- 1 file changed, 141 insertions(+), 79 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 3f506d0666a1..72b79f893e29 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -644,7 +644,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nan= d, unsigned int cs) writel(ctl, nfc->regs + NFC_REG_CTL); } =20 -static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int l= en) +static int sunxi_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(sunxi_nand->nand.controller); @@ -660,7 +660,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, = uint8_t *buf, int len) =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; =20 writel(cnt, nfc->regs + NFC_REG_CNT); tmp =3D NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; @@ -672,17 +672,19 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand= , uint8_t *buf, int len) =20 ret =3D sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; =20 if (buf) memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, cnt); offs +=3D cnt; } + + return 0; } =20 -static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, - int len) +static int sunxi_nfc_write_buf(struct nand_chip *nand, const u8 *buf, + int len) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(sunxi_nand->nand.controller); @@ -698,7 +700,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand,= const uint8_t *buf, =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; =20 writel(cnt, nfc->regs + NFC_REG_CNT); memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); @@ -712,10 +714,12 @@ static void sunxi_nfc_write_buf(struct nand_chip *nan= d, const uint8_t *buf, =20 ret =3D sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; =20 offs +=3D cnt; } + + return 0; } =20 /* These seed values have been extracted from Allwinner's BSP */ @@ -865,23 +869,31 @@ static void sunxi_nfc_randomize_bbm(struct nand_chip = *nand, int page, u8 *bbm) bbm[1] ^=3D sunxi_nfc_randomizer_step(state, 8); } =20 -static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, - const uint8_t *buf, int len, - bool ecc, int page) +static int sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, + const u8 *buf, int len, + bool ecc, int page) { + int ret; + sunxi_nfc_randomizer_config(nand, page, ecc); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_write_buf(nand, buf, len); + ret =3D sunxi_nfc_write_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } =20 -static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t = *buf, - int len, bool ecc, int page) +static int sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, u8 *buf, + int len, bool ecc, int page) { + int ret; + sunxi_nfc_randomizer_config(nand, page, ecc); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_read_buf(nand, buf, len); + ret =3D sunxi_nfc_read_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } =20 static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand) @@ -1152,17 +1164,25 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, u32 pattern_found; bool bbm =3D !step; bool erased; - int ret; + int ret, bitflips; /* From the controller point of view, we are at step 0 */ const int nfc_step =3D 0; =20 - if (*cur_off !=3D data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (*cur_off !=3D data_off) { + ret =3D nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + ret =3D sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + if (ret) + return ret; =20 - if (data_off + ecc->size !=3D oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size !=3D oob_off) { + ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1184,13 +1204,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 - ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, user_data_sz, &erased); + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, + nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found, user_data_sz, &erased); if (erased) return 1; =20 - if (ret < 0) { + if (bitflips < 0) { if (!(nand->options & NAND_NEED_SCRAMBLING)) memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); @@ -1202,17 +1222,22 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 if (oob_required) { - nand_change_read_column_op(nand, oob_off, NULL, 0, - false); - sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + user_data_sz, - true, page); + ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, + false); + if (ret) + return ret; + ret =3D sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, page); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, bbm, page, user_data_sz); } } =20 - sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, bitflips); =20 return 0; } @@ -1245,31 +1270,39 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_c= hip *sunxi_nand, sunxi_nfc_user_data_sz(sunxi_nand, step); } =20 -static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, - u8 *oob, int *cur_off, - bool randomize, int page) +static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, + u8 *oob, int *cur_off, + bool randomize, int page) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; + int ret; =20 if (len <=3D 0) - return; + return 0; =20 - if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) - nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) { + ret =3D nand_change_read_column_op(nand, mtd->writesize + offset, + NULL, 0, false); + if (ret) + return ret; + } =20 if (!randomize) - sunxi_nfc_read_buf(nand, oob + offset, len); + ret =3D sunxi_nfc_read_buf(nand, oob + offset, len); else - sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, - false, page); + ret =3D sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, + false, page); + if (ret) + return ret; =20 if (cur_off) *cur_off =3D mtd->oobsize + mtd->writesize; + + return 0; } =20 static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_= t *buf, @@ -1340,21 +1373,24 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; bool erased; + int bitflips; =20 - ret =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, - oob_required ? oob : NULL, - i, status, pattern_found, - user_data_sz, &erased); + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, + oob_required ? oob : NULL, + i, status, pattern_found, + user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ - if (ret < 0) + if (bitflips < 0) continue; =20 if (oob_required && !erased) { /* TODO: use DMA to retrieve OOB */ - nand_change_read_column_op(nand, - mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, false); + ret =3D nand_change_read_column_op(nand, mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz, + false); + if (ret) + goto err_stats; =20 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, page, user_data_sz); @@ -1363,7 +1399,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf if (erased) raw_mode =3D 1; =20 - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 if (status & NFC_ECC_ERR_MSK(nfc)) { @@ -1381,23 +1417,27 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf mtd->writesize + oob_off, user_data_sz, &max_bitflips); - if (ret < 0) { - /* The caller retries the whole read in PIO mode. */ - mtd->ecc_stats.corrected =3D corrected; - mtd->ecc_stats.failed =3D failed; - return ret; - } + if (ret < 0) + goto err_stats; if (ret) raw_mode =3D 1; } } =20 - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, - page); + if (oob_required) { + ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, + NULL, !raw_mode, page); + if (ret) + goto err_stats; + } =20 return max_bitflips; + +err_stats: + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected =3D corrected; + mtd->ecc_stats.failed =3D failed; + return ret; } =20 static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1415,13 +1455,21 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand= _chip *nand, /* From the controller point of view, we are at step 0 */ const int nfc_step =3D 0; =20 - if (data_off !=3D *cur_off) - nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (data_off !=3D *cur_off) { + ret =3D nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + ret =3D sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page= ); + if (ret) + return ret; =20 - if (data_off + ecc->size !=3D oob_off) - nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size !=3D oob_off) { + ret =3D nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1447,27 +1495,35 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand= _chip *nand, return 0; } =20 -static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, - u8 *oob, int *cur_off, - int page) +static int sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, + u8 *oob, int *cur_off, + int page) { struct mtd_info *mtd =3D nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; + int ret; =20 if (len <=3D 0) - return; + return 0; =20 - if (!cur_off || *cur_off !=3D offset) - nand_change_write_column_op(nand, offset + mtd->writesize, - NULL, 0, false); + if (!cur_off || *cur_off !=3D offset) { + ret =3D nand_change_write_column_op(nand, offset + mtd->writesize, + NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + ret =3D sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, pa= ge); + if (ret) + return ret; =20 if (cur_off) *cur_off =3D mtd->oobsize + mtd->writesize; + + return 0; } =20 static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, @@ -1506,9 +1562,12 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_ch= ip *nand, uint8_t *buf, raw_mode =3D true; } =20 - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); + if (oob_required) { + ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, + !raw_mode, page); + if (ret) + goto out; + } =20 ret =3D max_bitflips; out: @@ -1635,8 +1694,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_ch= ip *nand, } =20 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - &cur_off, page); + ret =3D sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + &cur_off, page); =20 out: sunxi_nfc_hw_ecc_disable(nand); @@ -1759,10 +1818,13 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct n= and_chip *nand, if (ret) return ret; =20 - if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) + if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) { /* TODO: use DMA to transfer extra OOB bytes ? */ - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - NULL, page); + ret =3D sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + NULL, page); + if (ret) + return ret; + } =20 return nand_prog_page_end_op(nand); =20 --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 307044A0F0E for ; Mon, 14 Sep 2026 21:10:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420211; cv=none; b=eb6gxL44UaRWsSgatU4TEZJosM4tyoZR+lKWY7GUX4iXKynz63rm1CTzF0HEoS0QdFytXx/Ncqy2X4g/eHWoLw/z8/2Fs+y+PhV2RRaKRi0RLFpsecECgNViZ27idh3J93MqXTEtfVLdse6PU+Gk4HWeynAh2SZ7JePOQmr+wdE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420211; c=relaxed/simple; bh=ovOsliEdUhvhRoeaXGSGPM3LycBRMZNPRXeHkTBG1HM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bMUyo9MQvpOM5RIggUdhK1pQ5pVWIXCbJeO61AOhPtS+/WsaBg+QBLkat0ByKyYjhcKAx9kAcN2f4o63uMnEXh7jrPymP3mcKfQRCdxLPQ+ObIOloDdXSeEwLAhhJizHcgHbRn22XxE3pTqa0z/llzs+BMFYrp/oZwNnZWClnd8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OML/24vV; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OML/24vV" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6b1ae7166ebso1500287eaf.1 for ; Mon, 14 Sep 2026 14:10:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420205; x=1790025005; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=b70jsSBwLMejAy7LligcsivCdZpJr/KiRJCHlaFZ8JI=; b=OML/24vVZv7p98bMsaWSMckNEo8krsuDwaP3JaMi7Rk/boUDNRGM1eBeZS5QG/85ne zMslfwYd4FmRsarS6mSaT9zhS5Wi1b3q2ixkTzxyNGuJmDFSisM1ja/jEj2e5x71P/P9 SI3tK2vC1mW87wHJtGRiOXc3YuFluFz28ZbV2NvbP1kmNqONUs286hk+V4OUQVBIApFk BUyBjPY8KndVfPCvysDfGTsogC9gNflskOTQp/k3W+Ei+P+Wb4AD0wLQMgWnKEtOrLML bPtRa7eYPpXrMyQj1EM5HbhBkwCPq7qS7l0O39A3vkRyyfQm5stZkaoRjo5PMKl63fuV c1FQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420205; x=1790025005; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=b70jsSBwLMejAy7LligcsivCdZpJr/KiRJCHlaFZ8JI=; b=CZc0Yf088v93+tMydoCCo1Q8EBjejYiclJKMltVsQBiGDAXyjgkRucFZEKAtZNj68B JjBmsGlqm36ADZYNqsuRGvmBkYrxHGFvHCDFjSar9vipcqDk4UpPXjX1RiUe264G+t/1 5GE1PU5G3JsZvYX69+Az0v1QRJIb4kfPAggtJ4g0ZZdkdOBBxPt2U5mH/HRLx1e/zHd5 oBGX0Z/cRIpfgRkZIwobGJ1G8Q92Oyp3/JKtUExspVclb8j3UMNy75ifmnbF0VUIwzGY AN5LPUlggIAlzHufXVyJNmUSkuocpkpu2V5HQXg6SKUnwPOQCsmdYhGa6rId/7OA/MO5 smUA== X-Forwarded-Encrypted: i=1; AKwUvBzPJXvOX0WcnbMiT4j0+XecIU9cWAtOeTh/aqWc1BXM8B30n+wgwS8ZbUm2iG2Ws+GjCBjVDTlAS1ObQvs=@vger.kernel.org X-Gm-Message-State: AFuF++k7GmhCj08MTzgo1J531oIaRNtcUWs0W5gAoNnNqWTCaUFaXKSs zHLX/Hy/1Dwg+y5Y3berJiQX1kEteoR2LXnmN0bR+vzy1P9QBfo7tISO X-Gm-Gg: AYBFou173fiGXOdTnltJW8BCkDjAWHtQ22fYWgNVyBh78YQl/sjHscThwzikqScO8u3 eKaoNldqx9C9hOf9WcWHB+VZA2c0t6B5MIV+MZ41UBoJI+DZLLtSP/JkC/LbOwh2aS2ImdGx/oC c0K6PyblZvAYku6IaE1Bz8FrNfMnMn8rcodJ1y0Vd1lroe9gG63irhbyufVY7FBx9ubVDProjyE jxB0cSer6BIcimFysqEwu1k8EZeLaupp50p/gFuR4DUqZ8iOUr6CR/qjkEfQuYrNaKmBx4p9RZz rt6l4QUXyFVkxT7aQvgr+ols4x1+oK/ffezw+dpZLcyQvRTmv6oVCm/RZsbkp/uuJQyTZpa0nVx 3sj45m+qrF9w1tC3D9gE9hp0V+H+BGyLZtxQ6HWeHGqId9zpzZeN8my/7W6Ws3k8tZY70iQm69P 6QhvEHjNyGVdISGzkgBF0J/w5kh7Zd1ZTumMXh17rAzu31F/DiqTZM61+EivaoLu5SVgEGtEmoM fBYFMmw0LZnCPLYOkAaoSVyKikMRkiSsgJJmKUpnBuGRuaP37hMJPXcYFA9a8mZna0ei1vLp6ZB XXI/Q12KM2rbiUE1BAiYRV6Qmtmcs8yfCPAFuWo691SwE+/7QjqGOkvkvVl7ayNia/RIAj2BUtT DL+5kaUycSbJVLpupXduIQfnO0IaK X-Received: by 2002:a05:6820:1626:b0:6b6:93d6:afcd with SMTP id 006d021491bc7-6c540b66d8bmr2665520eaf.26.1789420204843; Mon, 14 Sep 2026 14:10:04 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:04 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:53 -0600 Subject: [PATCH v6 07/18] mtd: rawnand: sunxi: avoid a second program confirm for OOB writes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-7-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 The hardware-ECC OOB writer delegates to the page writer, which already issues PAGEPROG, waits for completion and checks the NAND status. The OOB wrapper then calls nand_prog_page_end_op() again, sending an extra program confirm without a corresponding program setup. An error on this redundant operation is returned even though the page writer has already succeeded. Return the page writer's result directly. This leaves both PIO and DMA responsible for completing their own program operation and preserves their error results, including for bad-block-marker writes. Fixes: 25f815f66a14 ("mtd: nand: force drivers to explicitly send READ/PROG= commands") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 72b79f893e29..41d6560d7df7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1843,15 +1843,10 @@ static int sunxi_nfc_hw_ecc_write_oob(struct nand_c= hip *nand, int page) { struct mtd_info *mtd =3D nand_to_mtd(nand); u8 *buf =3D nand_get_data_buf(nand); - int ret; =20 memset(buf, 0xff, mtd->writesize); - ret =3D nand->ecc.write_page(nand, buf, 1, page); - if (ret) - return ret; =20 - /* Send command to program the OOB data */ - return nand_prog_page_end_op(nand); + return nand->ecc.write_page(nand, buf, 1, page); } =20 static const struct sunxi_nfc_timings sun4i_a10_nfc_timings =3D { --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B63E4A0F0C for ; Mon, 14 Sep 2026 21:10:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420211; cv=none; b=AhW+cuQ+kZ16D3fY0Bjq58zovNvNMsihm66mzy3k0N+pMwI9SPyhXQl+UkkffDQ+D0eS2wfhDPE/4X38ZET1x2L+jIUhr4TTYIbhrwksEQhbXld3pL35TU9Pm971efzJvpVbE8BMeSA0NTmrByxnmNDFRlzr9WKHkXjuoWcSDog= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420211; c=relaxed/simple; bh=YbBF9laHAErhZzSaGZGDzYG7q1LarpeBoJ8ap1tchQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AL9+ObBvOgdc3cCbOA648YiypEmQetFhFJcXq40VBmmBQOW4EVHDaCw3efLLtTSpVQMUpPLIotrEGtaoWxav5VDWp3GGpKPowQV49XnwoTZ4sfbjILSl7+NDwcFF7Jz3jnYF7PnKPWjFD4i4R9XHZvpsbK8wuJgaef5XJpXTEGY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OjFsGnUE; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OjFsGnUE" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6bda350b708so911200eaf.1 for ; Mon, 14 Sep 2026 14:10:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420206; x=1790025006; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=A0CrISCG3enxLUNERhlMVwT+4sBOgXXXdTBmRqqtC4g=; b=OjFsGnUEbpAqGya41cP7mMU4oHk4Nxv6gUrg4eYoUERC/WZGyNih53fnxnGH7KOUT5 sdl/BUlYPnM+W1MYeTmrEqRSCH1/8LOqdmUix7uUNot9/sk1bfytZHZQqkXy6nW9IBz/ dDN5v7ZR2b2Qnp7+Xw5wDGRwNQnh0jwRK14fhZLWtPm8d/Szgz6hKO2vLsNE6skyJBrq y+vLYGVzQ5LPdwTu3iDfqKY3zDM93jAy4K58LlxMrk/C8RCYx/1kqK7KYMhEicSNZwao MCSpPip1VsfDk3qrtfNmWjRXshfoIxM7wLgCAMyc5t9TnUx3+4mWh8iiZTzQW/fz2HPC DRpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420206; x=1790025006; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=A0CrISCG3enxLUNERhlMVwT+4sBOgXXXdTBmRqqtC4g=; b=hSpXOPA4f08BjaO0UM2/9mACS29/EWadNeo7vMMf7Ldt5N9srh9qxuNpoOMMD3umPM lOEG0+YUy1ey0uBU2w4hzZMzFn1frtNbnby1PZuPyK0/H8vX0SgxDMuUGSJVPrOMHxQR 4bfo5Mw0Mji8SLl09KQLd+rCzaPLta7rPbBYEQBinhDqfMzQanpmHjd1UcqWDJjZaYvZ zdZwVlAY2HsGt4Q3Xz5K511DlQKrszpjEA5Poa0ZuqdBsg7JT/SmJ3k7lLQb9Q+kmqLR D9g0SVdEqqRTGaR2WHHambikpHtojDMkvtUXpXNO77OLvNsx/eXLmJWkVYGB/P7RTRGY Z/Gg== X-Forwarded-Encrypted: i=1; AKwUvBym4HH/ricNlTu1WHqcUko5jg7VMGQhtVfr0hM8PdUrktZRS7lfRt6GfqX1Y0I7Wvbh4ge6QP6ZZpwJXwk=@vger.kernel.org X-Gm-Message-State: AFuF++m2/XgpR6FSlQHsP4KIqic42Y19ym0xZNm76ckavdkHOKElAQet S3lFXoHMGj34RiJwXfshcX7nkGuOi/PsVS2jB6ONrPKafRnuuC+/rwvP X-Gm-Gg: AYBFou1wER0ljeyZf1k9elqqhyT1ecMezsymXC+bzUAV96keXN1Wpx8F/IBwHZ+QDSQ nbyltlQZ3BCPFsE8lmUSMRgeOrTAvmZAeoNS2WcjY81U8Rcg022G4z45jP1AgS6fqVUq3cKDNzd 40Zf3nZx37+yQHtZQLKF2/k4VhQzEMusRFVkaBFCoidMIYphoK7loSfBdBS7O0GD+mbKdqyoi3M MGiRpY8KluDoM2ZWcH5MKqkgoft5wBm1sRZupe8egPO2QP/Ocwbk/epg0rTrRHqoKOcYZ9liNqR NuaqxVnjvRzEqeG8Sb0MM9yDRkF2zlwWBQF0l8vG1I1KswkNR7JWI+fpX2ssj+LfG9xEQzXKGXn +N6ymVmkSYvD/g8Sv+vwDszbQV9me0Mln48TLAEGWCJOr0IogyvRpa1KrAK2/A/5emg1oAjnKKW tdjqOP+WlHGqI6sEIrX06RK2fLcBr4Uj6n+13kWsav1LP485nbUnb0orMSwzs0CSY8DO9wGJTng rbflLM+NeD9ObdREnd2qSZWcaPFhMepfx6cqroMbbkTwDPDJn53v7q5oYBGUDYAGvFE9DoSBNb8 EmVY6qRMVqwEyBNET7SjStcGHLNNmNQ4ULaeKZDvYtjd0CHJgaFxBnSWxk+gjEjyqNGeGxLCgOY qpgpxzZGAsyG+h5oSz4oDdAfgHcKc X-Received: by 2002:a05:6820:c85:b0:6b7:8396:f3c4 with SMTP id 006d021491bc7-6c541457fa1mr2615579eaf.38.1789420206238; Mon, 14 Sep 2026 14:10:06 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:05 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:54 -0600 Subject: [PATCH v6 08/18] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-8-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The PIO write loop tracks the absolute NAND column in cur_off, while the extra-OOB helper computes an offset relative to the start of OOB. Comparing these values directly always requests a column change, even when the last ECC step has already left the cursor at the start of the extra OOB bytes. Include the page size in the comparison, matching the extra-OOB read helper. Keep the explicit column change when the caller does not track the cursor, as in the DMA path, or when the current column differs. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 41d6560d7df7..13dc0af56eb3 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1509,7 +1509,7 @@ static int sunxi_nfc_hw_ecc_write_extra_oob(struct na= nd_chip *nand, if (len <=3D 0) return 0; =20 - if (!cur_off || *cur_off !=3D offset) { + if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) { ret =3D nand_change_write_column_op(nand, offset + mtd->writesize, NULL, 0, false); if (ret) --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oi2-f13.google.com (mail-oi2-f13.google.com [74.125.231.205]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC62A4A1DFC for ; Mon, 14 Sep 2026 21:10:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.205 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420213; cv=none; b=d53CVzPvJTXannu4Zfy0XDiN7mWs+BbfGqQXbvhX8x5UWsfJe7U4I/cZdLXp345OqGuIczr6BS2Hdqh+mQh9l96ir5MvYSs/Dyh7UzTkzCR2bJKBJ1VJtGmLQhUVXEZfSET5KjRQcukobNsSzAGwkIdYR7U0mgTCQYAz8dyy7Rg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420213; c=relaxed/simple; bh=o3NPqjDQtjCU8+r59n9WbZaWXsVSsfQ6oMXDXHHDqIA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aRV7HwKlZ81qKCLlEBMAsbbl1b+H8enE03K7M/cC0T1AavFQTeTUXpakI5VsjavJu49ywuWoYmOnEkUThJ/M64L4MzR0kVyes5XNlPYuCmDkBd9EtdEeoNMDV1QHPh/hPpv+Nfo9e0Lze8J8h/j7iNf0kd2X0IziXJuMWIkhfn0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VMGrK6vv; arc=none smtp.client-ip=74.125.231.205 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VMGrK6vv" Received: by mail-oi2-f13.google.com with SMTP id 5614622812f47-4c66ba0b762so455570b6e.1 for ; Mon, 14 Sep 2026 14:10:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420208; x=1790025008; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3gIMuO5LgsmThmwiwqzrGE8ky+825OhMeKFgclE6Udc=; b=VMGrK6vvL/fHg+2LM3PwyFkia5K6WQCN9uBr7YFQ+F2fIgTbtA0ZOSuYRePfbxDi9E 3cfnHAlZ2LMUfPwMjuPqCnWLdyCl30Fr6PzoZYWvpw8ZPevbr6HmEuOOPl28a+SCNoqF 4yrsjl+A24hefg7rc4OerKSMYSkASQejaKTAc+AN661hKopjIL939eFugVuG/2CvEAQt MbN4aFQTxYrAmpqwbCQTD1BOhjEK6nqxq5xG3QBqKfuQRDDR2kv5SZR+QWPcVDD51xga 5hJj4TCs3K75Km+Rf+X49Zsmm5GluboG425391Ag1N8BwB4iKSUFmZrrm+wnd7/nptvd hLow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420208; x=1790025008; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=3gIMuO5LgsmThmwiwqzrGE8ky+825OhMeKFgclE6Udc=; b=ThDN5tZTZGz0VDvVMbufgfZowd0EgG2WKeEaCg9N40EPT2JaNR5n9/7ZpNplLlB4Vl 9FDRYvvkdlSBVwPRZLJBV8z8Pr99i1ZqNNZBqEUO2v4A+o3zb+GRujtxc6z8Myxvbjiy wsLmqLTb4a0olh9CWDuzN0ij5GUAybtJ6yuHJyQmrgZSacpBX78fA233mxRJErfI3+4U RPSeqw3PAUYKi7CN7D8Or3y1CgneeTN41yBh/MUD0SVM1l5DmdnPDdfQpsd5Jv6IdEMr dgg5LDQq6/11ulJLm2RDsxjTI7O2N+6AD1lREJjxV5zERkiwiZKPXOY+RFrJHzC+kWHK akxA== X-Forwarded-Encrypted: i=1; AKwUvBwc2b7y8cmyyoifL6B7Mhlb6kDpywfmbIuRhk15vsDHEvGWMXP556+neNptc+KDScsonT2kI709NWPIt3E=@vger.kernel.org X-Gm-Message-State: AFuF++kVY/JbMpH1q7FKc9gPPUlGv7tBzR/A6hiH5UxubpU0BiBQ5hfZ HRTlcRauQwrcx7fxOTPk6p01EP1dlo3Y1QXn4mdzGiDaVeUn8XJ/JYtn X-Gm-Gg: AYBFou3spxZk/NNfsD6Vr/VLFzxx7Gcf3TafjfUW9K0mg8NNO/FgFtdfi4VKbUPkHNJ XsMQqw2MBG722YkPeHwxiExlnxPmg8BBwH3O5KD+Uxtypc7j2/76eqyg9dbG1q/bcFQ3fWpjcjp V1rl808pjGqerbSLUjPrpM0O52nUrwbduFUvuOJI4vc0hGGloo6hoI/yD0hk37dHmye7CoYnJO3 1BayBSFE1VMeqrtTXPW+1Csv5NhND8+O4kymO3C7TeNVqFWpHhNf6xKI1ygmEzL6MHChAD3o32a tC5bGn+x8QhKCx3pzia3zKIBGMuT7lsKFHYVhLpXw10B+FagdpAh2/wiyYRXW5/vY2p6hP42XIv ksU5orrgDOKoLdrMwcE0n0QqUAwH3BC17/Wul4CDtNKT2ZIQKHqaOkToAyrXQFi2X8Vx/zQaSw+ yWWdqFnaL7fwK9Oy34X5h2NtxMUELk8uszCmeShVSNxxAEhTPFGroruZU19ElydG2wBr21Vpkul 1PGegFX81FuUWRoHH66imBuBeyTv1STslSEZAbNfQ2c6jyPCGotRD8qizaw78N/yUWCzZxB+l3A p2vDrwG1nCsofMLfbhUFw9DiPyGQ5Cy8ejYMjTNSYHLgjUVr6TMkPq1DPbzfIN7wic/kWGQs1b4 DQlVhnkG5c7O6CNYhm0MMMxjaGc5t X-Received: by 2002:a05:6820:1899:b0:6b5:ec3f:4987 with SMTP id 006d021491bc7-6c63a55903bmr501376eaf.34.1789420207811; Mon, 14 Sep 2026 14:10:07 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:07 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:55 -0600 Subject: [PATCH v6 09/18] mtd: rawnand: sunxi: use page reads to reposition small-page NAND Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-9-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The hardware-ECC read paths use random-column commands to revisit main data and OOB. Small-page NAND does not support these commands, and nand_change_read_column_op() rejects pages of 512 bytes or less. Ignoring that error does not provide a physical reread: the erased-chunk check can instead inspect stale buffer contents. Introduce a read-column helper which starts a new page read for small-page NAND. Let the NAND core select READ0, READ1 or READOOB and send the row address. Keep random-column commands for large pages. Pass the page number through the erased-chunk fallback and use the helper for normal OOB reads as well. Retain transport errors and only classify a physical chunk after all its rereads succeed. Read exactly the requested region so the tracked column still matches the start of any trailing OOB. Also select PIO callbacks for small-page hardware ECC even when DMA is available. The DMA page sequencer uses large-page random-column commands; PIO can stream the single 512-byte ECC step and its OOB without them. Keep the ECC geometry checks unchanged. In particular, the usual 512+16 geometry still cannot fit the controller's minimum 28 parity bytes and four user-data bytes. This fixes the command handling for small-page geometries that pass those checks, not a demonstrated regression on a previously working 512+16 device. Software-ECC and raw callbacks, large-page DMA eligibility and the on-flash layout are unchanged. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Fixes: 614049a8d904 ("mtd: nand: sunxi: add support for DMA assisted operat= ions") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 40 +++++++++++++++++++++++------------= ---- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 13dc0af56eb3..e29638c828ca 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1079,6 +1079,16 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nan= d_chip *nand, } } =20 +static int sunxi_nfc_read_column(struct nand_chip *nand, int page, + unsigned int column, void *buf, unsigned int len) +{ + /* Small-page NAND needs a new READ0/READ1/READOOB and the page address. = */ + if (nand_to_mtd(nand)->writesize <=3D 512) + return nand_read_page_op(nand, page, column, buf, len); + + return nand_change_read_column_op(nand, column, buf, len, false); +} + /* * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC * statistics updated in either case. Negative values report transport err= ors. @@ -1087,7 +1097,7 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_ch= ip *nand, u8 *data, int data_off, u8 *oob, int oob_off, unsigned int user_data_sz, - unsigned int *max_bitflips) + unsigned int *max_bitflips, int page) { struct nand_ecc_ctrl *ecc =3D &nand->ecc; unsigned int oob_len =3D ecc->bytes + user_data_sz; @@ -1095,13 +1105,12 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_= chip *nand, =20 /* Check the physical representation for bitflips in erased pages. */ if (nand->options & NAND_NEED_SCRAMBLING) { - ret =3D nand_change_read_column_op(nand, data_off, data, - ecc->size, false); + ret =3D sunxi_nfc_read_column(nand, page, data_off, data, ecc->size); if (ret) return ret; } =20 - ret =3D nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + ret =3D sunxi_nfc_read_column(nand, page, oob_off, oob, oob_len); if (ret) return ret; =20 @@ -1169,7 +1178,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, const int nfc_step =3D 0; =20 if (*cur_off !=3D data_off) { - ret =3D nand_change_read_column_op(nand, data_off, NULL, 0, false); + ret =3D sunxi_nfc_read_column(nand, page, data_off, NULL, 0); if (ret) return ret; } @@ -1179,7 +1188,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, return ret; =20 if (data_off + ecc->size !=3D oob_off) { - ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, false); + ret =3D sunxi_nfc_read_column(nand, page, oob_off, NULL, 0); if (ret) return ret; } @@ -1217,13 +1226,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, =20 return sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, oob_off, user_data_sz, - max_bitflips); + max_bitflips, page); } else { memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 if (oob_required) { - ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, - false); + ret =3D sunxi_nfc_read_column(nand, page, oob_off, NULL, 0); if (ret) return ret; ret =3D sunxi_nfc_randomizer_read_buf(nand, oob, @@ -1285,8 +1293,8 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct nan= d_chip *nand, return 0; =20 if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) { - ret =3D nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + offset, + NULL, 0); if (ret) return ret; } @@ -1386,9 +1394,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf =20 if (oob_required && !erased) { /* TODO: use DMA to retrieve OOB */ - ret =3D nand_change_read_column_op(nand, mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, - false); + ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz); if (ret) goto err_stats; =20 @@ -1416,7 +1423,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, mtd->writesize + oob_off, user_data_sz, - &max_bitflips); + &max_bitflips, page); if (ret < 0) goto err_stats; if (ret) @@ -2305,7 +2312,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_ch= ip *nand, ecc->write_oob =3D sunxi_nfc_hw_ecc_write_oob; mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops); =20 - if (nfc->dmac || nfc->use_mdma) { + /* The DMA page sequencer uses large-page random-column commands. */ + if (mtd->writesize > 512 && (nfc->dmac || nfc->use_mdma)) { ecc->read_page =3D sunxi_nfc_hw_ecc_read_page_dma; ecc->read_subpage =3D sunxi_nfc_hw_ecc_read_subpage_dma; ecc->write_page =3D sunxi_nfc_hw_ecc_write_page_dma; --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo1-f47.google.com (mail-oo1-f47.google.com [209.85.161.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96A7A469826 for ; Mon, 14 Sep 2026 21:10:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; cv=none; b=EYEQh9B8tzF+QiDn1WMlwYkfYHZMQC+qFAzsAdmRBMuATvRMbTVIWYDNFa+IBetje3bDD6Ys0zChKzeW0ZDfwF7+zLe19yRgXE+LIG4Y+0z7gPl7cHdQ8/cLB6fgkqLENuKtuTxgR+5+zcMo5luE31AsP696Y+e7vSh8gXpDiEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; c=relaxed/simple; bh=vtg+z9G0CuAdSRbu8cVWZ/uIsLBQGyskZGCo/vbBtVI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EQCbaOi9qIvibiXSVx6CN6FCF58myHwCWDBLVIizLoIAXMmJm219aAxoLE2AMLXzonxn2jhfUmdhs2GgYYS2xOubMF9oJ6yYeDlbMhf/PIRAxIeigCCAWdXEXDq382rWd79MIOpP6AE7dZDvYcpo47Dexpt54nFQOR2EPePM4Mk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OUOIBzx5; arc=none smtp.client-ip=209.85.161.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OUOIBzx5" Received: by mail-oo1-f47.google.com with SMTP id 006d021491bc7-6be1f18687bso2199796eaf.2 for ; Mon, 14 Sep 2026 14:10:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420209; x=1790025009; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=y7F79jQI2v9SHnTcdbLyHrKpLzhqd8SwLgrM0tg4BfI=; b=OUOIBzx5OdQOtnVsXhTi2zmlLZ20h6KzxlY9f9l0enRFZCXcNHopvJtYJbfOs4G5F6 zN9cx9CmtP6SVwnzwUiu+6TyYCziQHUTpXUPl/Yu1wsBrTA+h1HmHUq03KKuRi+O7vLD LSHDKixzsCpjKgWydDiV1yK5h0qdoimx/mA6b06Z+HK7GBa+NLhacvFudSo6iCsIHaa4 QKNbsW5aXV7mxBoYURh2LJ1aiCFOy8svA+oD1L141gJFwHIK4f+Sf7OZxYcEvkGi3fJn N6L9spkKdnsDr1zmj8UXx8bRaZ2gUf8ig3oAheIH6t/cOtHOwmzqOrTVZJVkHZBxBft5 7LJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420209; x=1790025009; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=y7F79jQI2v9SHnTcdbLyHrKpLzhqd8SwLgrM0tg4BfI=; b=n/UzGzKO63cHc/XKR0NnSNxmYp/XN8rF7WtRJKPOw7x4wz1iLnvUIs/R9Hn4TfgM03 CtiI9xm7EkbqqmnR4nN3hjo5rGikSwXFv9ZaXzh6uiN7u+WsPD/RmLFfsZYSzt3fy+QD er0tCkb/9TsoJnl7EyBNKnY19dKKQW4w/8IJ+S7TgcujAPj/EB1fnoRrljZMkLbtK4z6 /5vLCKgXCPl9opluCmBS8VJ+lhA4EJqnWilHVw6YsGIIxmpa69ccC1fxFS1vCZIfW5uY mT5pMVE26DF+5B4/5+iPKZIFXxYXsFMq/9W0EZKK2wwZOq+WqFsFPTWhX5/3BkADymvO Pn4Q== X-Forwarded-Encrypted: i=1; AKwUvBxjhSbiAIgrpNegiOSNKBEhGhZI6aeAuuY1KzEpVyyZMM6Ro1ugcIsPJuHY3xF6MMZldZFAlA6GlKPWmC8=@vger.kernel.org X-Gm-Message-State: AFuF++mWT/C5P1GAwHFdGotqbnhg97FvdeGO14ATGLpxeaHQf6KCgHjY BXYjbrDafLLhZ8Dis3lIF1Ff6IuPK2xieZsrf7ew5HQrn6Hn5zaVawAC X-Gm-Gg: AYBFou3QSsCvpVbbBJSLQki8FAazb3kiqJ30GhqxxY3ZHgcGbO+dE8I4AA0xJs1+M1g DLeJgafM5/HiAHUdlaZRHS1O89agRw58qIJXNV1TaFyEQ8ofB75sukKGUEkKgJmx+X8b5I0jWDr iJwoBGBmEDBW6sliGOXI019fUr1NP8i92/4VoBs6AB1g/WlYmHJPkrf90eVeD4pFUJ8qN4gmyWy KL4yNlY7sD+6F2vr2LSHIEOQwTJ4KDcV8+GJYZVMg/HSGL7lkTdacN/tc19Y/nGLGomKPaGzMtX yR1nySsr2Lye8QKarc5GC6v0egaQiVdv8fDmOoQHteHoqbdGsSifrH5W5eiBtNHvOO+FU3sSODc 4RNeGIVAj/lkAf2uH6cgvT4wWHvlj8V0SeeEzjb1HEU9H1ir5Jgu8r6kE0STT5xhrKgPBWmSSES nST/gimbVjX/NZX2Qw9RVJfuBgELOFFGMW7Bn9XS+YwIPlRvklASsLRGc44x6VKQcFvsVk5bgB7 9wRzaHfAWMfaBpeUxREEFiCcymu80ZpqiFUlWgJin57Tt1QvmPfMJJIWTr75zMUG2+l+kMYXmqR kZ5611dL3TFaI7Z2AxzXIqhiHDJhtXCHw/E0Mpi15rFBpnIfr6vAsF6FxOHnfrDbU1N0O8tCWzA r6qowbociO00W5fauYajNx2Rr0yNsbaS9DJr7eeQ= X-Received: by 2002:a05:6820:2204:b0:6b1:5c8b:c0b9 with SMTP id 006d021491bc7-6c54008880fmr2485081eaf.3.1789420209405; Mon, 14 Sep 2026 14:10:09 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:08 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:56 -0600 Subject: [PATCH v6 10/18] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-10-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The H6/H616 controller concatenates protected user data in a bank of 32 four-byte registers. The default layout can allocate more than 128 bytes across a page, even though each ECC step fits its individual length limit. DMA transfers then access beyond the user-data register bank. For example, a 16 KiB page with 1280 OOB bytes and BCH40/1024 has 160 user-data bytes, while a 16 KiB page with 1664 OOB bytes can allocate 512 bytes. Do not cap that allocation: changing the lengths would move ECC offsets and make existing pages written through PIO incompatible. Instead, split DMA transfers while retaining the original logical main-data and OOB offsets. Fill the first batch up to the register-bank limit. Transfer each remaining logical step separately using hardware slot and user-data register zero, repositioning the main column and spare-area base first. PAGE_OP generates the second and subsequent main-data columns from its hardware slot index, not relative to the initial column. Read and write probes on H616 confirm this behavior. A multi-slot batch starting partway through the page would therefore return to the wrong main-data column. Single-slot later batches avoid those internally generated column changes. Pages whose user data already fits retain the existing single-batch path. Pass the user-data register index directly to the protected-OOB helpers and program length fields from the batch's logical starting step. Collect each batch's ECC status and protected OOB before reusing the registers. Keep ECC accounting and trailing-OOB handling page-wide, remembering whether any batch found an erased chunk. Discard all partial DMA statistics before a PIO read retry. Use one page-read setup or program-begin command for the whole page. Only issue program-end after every batch and any trailing OOB transfer succeed. Do not retry a write in PIO after a batch has already been transferred. The allocator, free-OOB layout and raw-access callbacks are unchanged. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user= data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 284 ++++++++++++++++++++++------------= ---- 1 file changed, 163 insertions(+), 121 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index e29638c828ca..18a4d1cc4246 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -54,6 +54,7 @@ #define NFC_REG_H6_RDATA_1 0x004C #define NFC_REG_A10_USER_DATA 0x0050 #define NFC_REG_H6_USER_DATA 0x0080 +#define NFC_H6_USER_DATA_REGS 32 #define NFC_REG_USER_DATA(nfc, x) (nfc->caps->reg_user_data + ((x) * 4)) #define NFC_REG_H6_USER_DATA_LEN 0x0070 /* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */ @@ -932,41 +933,47 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_ch= ip *sunxi_nand, int step) return sunxi_nand->user_data_bytes[step]; } =20 +/* Keep the on-flash layout, but fit each DMA batch in the user-data bank.= */ +static int sunxi_nfc_dma_batch_steps(struct nand_chip *nand, + int first_step, int end_step) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + unsigned int user_data_sz =3D 0; + int i; + + if (!nfc->caps->reg_user_data_len) + return end_step - first_step; + + /* + * PAGE_OP generates main-data columns from hardware slot zero, not + * from the initial column. Use only slot zero after the first batch, + * so the explicit column change selects each remaining logical step. + */ + if (first_step) + return 1; + + for (i =3D first_step; i < end_step; i++) { + user_data_sz +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + if (user_data_sz > NFC_H6_USER_DATA_REGS * sizeof(u32)) + break; + } + + return i - first_step; +} + +/* PIO uses register zero; DMA concatenates user data within each batch. */ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8= *oob, - int step, bool bbm, int page, + unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) { - struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); u32 user_data; + unsigned int i; =20 - if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); - sunxi_nfc_user_data_to_buf(user_data, oob); - } else { - /* - * For H6 NAND controller, the user data for all steps is - * contained in 32 user data registers, but not at a specific - * offset for each step, they are just concatenated. - */ - unsigned int user_data_off =3D 0; - unsigned int reg_off; - u8 *ptr =3D oob; - unsigned int i; - - for (i =3D 0; i < step; i++) - user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /=3D 4; - for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { - reg_off =3D NFC_REG_USER_DATA(nfc, user_data_off + i); - user_data =3D readl(nfc->regs + reg_off); - sunxi_nfc_user_data_to_buf(user_data, ptr); - } + for (i =3D 0; i < user_data_sz / 4; i++) { + user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); + sunxi_nfc_user_data_to_buf(user_data, oob + i * 4); } =20 /* De-randomize the Bad Block Marker. */ @@ -1022,13 +1029,13 @@ static void sunxi_nfc_set_user_data_len(struct sunx= i_nfc *nfc, } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, - const u8 *oob, int step, + const u8 *oob, unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; + unsigned int i; =20 /* Randomize the Bad Block Marker. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { @@ -1037,33 +1044,10 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(str= uct nand_chip *nand, oob =3D user_data; } =20 - if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(nfc, step)); - } else { - /* - * For H6 NAND controller, the user data for all steps is - * contained in 32 user data registers, but not at a specific - * offset for each step, they are just concatenated. - */ - unsigned int user_data_off =3D 0; - const u8 *ptr =3D oob; - unsigned int i; - - for (i =3D 0; i < step; i++) - user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /=3D 4; - for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { - writel(sunxi_nfc_buf_to_user_data(ptr), - nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); - } + for (i =3D 0; i < user_data_sz / 4; i++) { + writel(sunxi_nfc_buf_to_user_data(oob + i * 4), + nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); } - } =20 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -1313,27 +1297,35 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct n= and_chip *nand, return 0; } =20 -static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_= t *buf, - int oob_required, int page, - int nchunks) +static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *buf, + int oob_required, int page, + int first_step, int nchunks, + int *raw_mode) { bool randomized =3D nand->options & NAND_NEED_SCRAMBLING; struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - unsigned int corrected =3D mtd->ecc_stats.corrected; - unsigned int failed =3D mtd->ecc_stats.failed; + unsigned int reg_index =3D 0, user_data_sz; unsigned int max_bitflips =3D 0; - int ret, i, raw_mode =3D 0; + int ret, i; struct scatterlist sg; u32 status, pattern_found, wait; =20 + if (first_step) { + ret =3D sunxi_nfc_read_column(nand, page, first_step * ecc->size, + NULL, 0); + if (ret) + return ret; + } + ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) return ret; =20 - ret =3D sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, + ret =3D sunxi_nfc_dma_op_prepare(nfc, buf + first_step * ecc->size, + ecc->size, nchunks, DMA_FROM_DEVICE, &sg); if (ret) return ret; @@ -1341,7 +1333,12 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct n= and_chip *nand, uint8_t *buf sunxi_nfc_hw_ecc_enable(nand); sunxi_nfc_reset_user_data_len(nfc); for (i =3D 0; i < nchunks; i++) - sunxi_nfc_set_user_data_len(nfc, sunxi_nfc_user_data_sz(sunxi_nand, i), = i); + sunxi_nfc_set_user_data_len(nfc, + sunxi_nfc_user_data_sz(sunxi_nand, first_step + i), i); + /* exec_op() restores the page's spare base during column changes. */ + if (first_step) + writel(mtd->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, first_step= ), + nfc->regs + NFC_REG_SPARE_AREA(nfc)); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1374,15 +1371,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 - for (i =3D 0; i < nchunks; i++) { - int data_off =3D i * ecc->size; - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); + for (i =3D 0; i < nchunks; i++, reg_index +=3D user_data_sz / 4) { + int logical_step =3D first_step + i; + int data_off =3D logical_step * ecc->size; + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, logical_step); u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; bool erased; int bitflips; =20 + user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_step); + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, @@ -1397,40 +1396,64 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + oob_off, oob, ecc->bytes + user_data_sz); if (ret) - goto err_stats; + return ret; =20 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !logical_step, page, user_data_sz); } =20 if (erased) - raw_mode =3D 1; + *raw_mode =3D 1; =20 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 if (status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { - int data_off =3D i * ecc->size; - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); + int logical_step =3D first_step + i; + int data_off =3D logical_step * ecc->size; + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, logical_step); u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 if (!(status & NFC_ECC_ERR(i))) continue; =20 + user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_step); ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, mtd->writesize + oob_off, user_data_sz, &max_bitflips, page); if (ret < 0) - goto err_stats; + return ret; if (ret) - raw_mode =3D 1; + *raw_mode =3D 1; } } =20 + return max_bitflips; +} + +static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *bu= f, + int oob_required, int page, int nchunks) +{ + struct mtd_info *mtd =3D nand_to_mtd(nand); + unsigned int corrected =3D mtd->ecc_stats.corrected; + unsigned int failed =3D mtd->ecc_stats.failed; + unsigned int max_bitflips =3D 0; + int raw_mode =3D 0; + int first_step, batch_steps, ret; + + for (first_step =3D 0; first_step < nchunks; first_step +=3D batch_steps)= { + batch_steps =3D sunxi_nfc_dma_batch_steps(nand, first_step, nchunks); + ret =3D sunxi_nfc_hw_ecc_read_batch_dma(nand, buf, oob_required, page, + first_step, batch_steps, + &raw_mode); + if (ret < 0) + goto err_stats; + max_bitflips =3D max_t(unsigned int, max_bitflips, ret); + } + if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, NULL, !raw_mode, page); @@ -1761,69 +1784,88 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct n= and_chip *nand, { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; struct scatterlist sg; u32 wait; - int ret, i; + int first_step, batch_steps, ret, i; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); - if (ret) - return ret; + for (first_step =3D 0; first_step < ecc->steps; first_step +=3D batch_ste= ps) { + unsigned int reg_index =3D 0; =20 - ret =3D sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, - DMA_TO_DEVICE, &sg); - if (ret) - goto pio_fallback; + batch_steps =3D sunxi_nfc_dma_batch_steps(nand, first_step, ecc->steps); + ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); + if (ret) + return ret; =20 - sunxi_nfc_reset_user_data_len(nfc); - for (i =3D 0; i < ecc->steps; i++) { - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); - const u8 *oob =3D nand->oob_poi + oob_off; + ret =3D sunxi_nfc_dma_op_prepare(nfc, buf + first_step * ecc->size, + ecc->size, batch_steps, DMA_TO_DEVICE, &sg); + if (ret) { + /* Only retry before any part of the page has been transferred. */ + if (first_step) + return ret; + goto pio_fallback; + } =20 - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page, - user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); - } + sunxi_nfc_reset_user_data_len(nfc); + for (i =3D first_step; i < first_step + batch_steps; i++) { + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); + const u8 *oob =3D nand->oob_poi + oob_off; =20 - ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); - if (ret) { - sunxi_nfc_dma_op_abort(nfc); - sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); - return ret; - } + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, + page, user_data_sz); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, i - first_step); + reg_index +=3D user_data_sz / 4; + } =20 - sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_randomizer_config(nand, page, false); - sunxi_nfc_randomizer_enable(nand); + if (first_step) + ret =3D nand_change_write_column_op(nand, first_step * ecc->size, + NULL, 0, false); + else + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) { + sunxi_nfc_dma_op_abort(nfc); + sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + return ret; + } =20 - writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG, - nfc->regs + NFC_REG_WCMD_SET); + /* exec_op() restores the page's spare base during column changes. */ + if (first_step) + writel(mtd->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, first_ste= p), + nfc->regs + NFC_REG_SPARE_AREA(nfc)); + sunxi_nfc_hw_ecc_enable(nand); + sunxi_nfc_randomizer_config(nand, page, false); + sunxi_nfc_randomizer_enable(nand); =20 - wait =3D NFC_CMD_INT_FLAG; + writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG, + nfc->regs + NFC_REG_WCMD_SET); =20 - if (nfc->use_mdma) - wait |=3D NFC_DMA_INT_FLAG; - else - dma_async_issue_pending(nfc->dmac); + wait =3D NFC_CMD_INT_FLAG; =20 - writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | - NFC_DATA_TRANS | NFC_ACCESS_DIR, - nfc->regs + NFC_REG_CMD); + if (nfc->use_mdma) + wait |=3D NFC_DMA_INT_FLAG; + else + dma_async_issue_pending(nfc->dmac); =20 - ret =3D sunxi_nfc_wait_events(nfc, wait, false, 0); - if (ret) - sunxi_nfc_dma_op_abort(nfc); + writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | + NFC_DATA_TRANS | NFC_ACCESS_DIR, + nfc->regs + NFC_REG_CMD); =20 - sunxi_nfc_randomizer_disable(nand); - sunxi_nfc_hw_ecc_disable(nand); + ret =3D sunxi_nfc_wait_events(nfc, wait, false, 0); + if (ret) + sunxi_nfc_dma_op_abort(nfc); =20 - sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + sunxi_nfc_randomizer_disable(nand); + sunxi_nfc_hw_ecc_disable(nand); =20 - if (ret) - return ret; + sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + + if (ret) + return ret; + } =20 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) { /* TODO: use DMA to transfer extra OOB bytes ? */ --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo1-f45.google.com (mail-oo1-f45.google.com [209.85.161.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64D564A2076 for ; Mon, 14 Sep 2026 21:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; cv=none; b=JXzmR55MrDH8Dl+ZTMrvAVw35D1k5+NzQB/E3MBv+Ag+vgBZOtAjpZjv+CHCA72r519sErFqD6Of12ywFlvZEy8sjGHSlyYkXvff1O4JmlqXOaaJraB0iLFVK5898WU5X9vrGyMI7QC9OBQR2+dhwLHUXpCjj7RIdhBmt5pZDac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; c=relaxed/simple; bh=ksccExueJsIuwGCb0dZjS0SLEa92Lo+4Eg3nzx6yLIc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=erZwziYb9rD46FsJ8cTI4FNX6GZmH9EEB57AXglNPOKmTWgo6b0WRH/FfoKzhCedCqTayUCjuRqUlMA94oTKfNquBWCxMCYhJORbEUVXjPG0vHH9FnGGZk3HGJaM601KKTcR3SdMSMR26sueia9lWmr/1sGwEZw9p16hECRoLSo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=g04ESolK; arc=none smtp.client-ip=209.85.161.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="g04ESolK" Received: by mail-oo1-f45.google.com with SMTP id 006d021491bc7-6c16080f8bcso2612356eaf.1 for ; Mon, 14 Sep 2026 14:10:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420211; x=1790025011; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Euqh3OGD+8WNOg3rzaOTiHhaf1O3ybQtEVQQVF9+898=; b=g04ESolK742Su2R9jVBzVb7DVxejpxbdUAC+TVaaans0koYZ795Xu5mTKEQF5JHgu+ VBgBjKBQimVXlDloCh+uZ3SuO7fVVCZVe4+rnwsydV1HeBQ5MPS7i/rIDQvVm/HWknsP 7ElqE1J8r9k/g9UYbguNnpF3opV0BjJEV8jIjpTre78ZCYrVDsmAHawR48n1LJxr6voK b0QQP3XsoXQZCWK0e3SrPGj4e4gA4Bymwb4TK+D0f+seFfbIAyMgZkZ4gNiLULhWT2ia 0/oRc/L/VWpA0g4Ck4XCOVKTNl+TEDNf8IRG8/LAxYnWI0b6syVdow+k4mUiMBeJ3ziR OKaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420211; x=1790025011; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Euqh3OGD+8WNOg3rzaOTiHhaf1O3ybQtEVQQVF9+898=; b=b5sayjhBxeTu9VVqNIHV3dOcHlJu307gSPZnqTc/wZUtc+h05hxWV1UmSjArmEAWMc K64P/dutkDU8DaIUQBPEbcz9YFxlnREwK70dIPOnBKH+7y16E99+Ns654bgCW067NaR+ 0pLLl3oDtkwNpmaGYqQg3jdERRJOHlYxRD9OSYhmbpGrRCSdEpznLKi484f+CsJ2JOUe 932v0jESz6B56ccnkKSU/ykBJVZrUfGvVWCpmmYKaAycRyEZOBu1XvlQtVPTcisf+SyO CFSXNMbYyCYtIw3dlYvLNASEJMJJLhs6ufRNKunK9PGzyIycswdEQ7peuEAGg7Wrz/yH i/pQ== X-Forwarded-Encrypted: i=1; AKwUvBzcGVq3awzruhZcuIO6qDHcWWfYRtmM1RTdDpp1mYGOCZvtYrFqVBTeF+c9EPfg0CKkzruI3mWHcvvt81w=@vger.kernel.org X-Gm-Message-State: AFuF++kv9ARjVtus0iyCtfdYK5OyBrG10sH+GRaRRjKgHjF8g12ek6/h 4D/ol/4/OoQGcc2ONsC4XsSDp1XbmBZaZ20+EU3q6QFNIyfuiWLBRx7H X-Gm-Gg: AYBFou2l/BcxSSOsMMo9Ymox1kVw6K+OlVozwYiaz2OXZXkR4FEl7jtdRJMyfe9M9LD CxXsd6QEpyvUI0CNk7sv2DqI31fDEDzLUWNqG823HDcmAI8E9bFyrH/uKT5MyMge2r39vjAfu6/ /DQtIhXFhnnxP9KhBiBwcqoE/WRSm+Rlt2kaQt5BeBCd03J23ewvYS/t+6KP3fzBljmCA6KFbjq 3Akcl0TjeIAS1p+yFYUWMbLo9Hd135t7B+3+vAd7+WFg9xHR0AuBNPvd69UR0P5M8t6Q7a5Q4rR DTDQrIapSP8c3FRJxHpmiTW4KpPEiDSuwhGzNSRm61rjHB7nwDfq8U9+muQENdriytjZoF1vPjX cSZbq+Mx6zOZt9MemLRduxodeRg32j+581HjZjjLuj1e/TWcNdUdI545liKnT5O+cmu3w02i41j av6RE8O5Is9v+oT6fFBg5du76JvLXNtPpTdWJfXzkPo2bzelgjmaJfhjhAPhCpP0wDJK17EqAVa puGRlttUMoAeQGZKYVQMSpXghrYv2iHed+EZtq0Bct3eY/uB1so4TaduQY3ZKCz8QzSp7D5jNUB bBj2rXgRq23WUTLHmzNsGkaLFp8Ma7rvZZ/b71z9C2pknke2ElHr7enFjDfxtuAy8QtNr1KXMiC MhVr1EAJZcNvKKhdHAFg4vHEcJcfE5LQ0y2uF+58= X-Received: by 2002:a05:6820:180b:b0:6b7:8415:d78b with SMTP id 006d021491bc7-6c542734c78mr2067060eaf.54.1789420210653; Mon, 14 Sep 2026 14:10:10 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:10 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:57 -0600 Subject: [PATCH v6 11/18] mtd: rawnand: sunxi: clarify OOB register and step handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-11-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 PIO reuses hardware slot zero while the user-data length and OOB offset belong to the logical page step. Name the two indices explicitly in the helpers so their different roles are visible at each call site. The protected-OOB helpers already take a batch-local register index separately. Clarify why the plain-marker format compensates the bad-block marker around hardware randomization. Rename raw_mode to erased_chunk_found in the page readers and DMA batch helper, using a boolean in both paths. The flag suppresses randomization of the trailing OOB after an erased chunk; it does not select MTD_OPS_RAW. No on-flash format, register-access sequence or ECC accounting changes. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 87 ++++++++++++++++++++---------------= ---- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 18a4d1cc4246..c55537bc71e1 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -925,12 +925,13 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8= *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } =20 -static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int s= tep) +static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, + int logical_step) { if (!sunxi_nand->user_data_bytes) return USER_DATA_SZ; =20 - return sunxi_nand->user_data_bytes[step]; + return sunxi_nand->user_data_bytes[logical_step]; } =20 /* Keep the on-flash layout, but fit each DMA batch in the user-data bank.= */ @@ -976,7 +977,7 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct = nand_chip *nand, u8 *oob, sunxi_nfc_user_data_to_buf(user_data, oob + i * 4); } =20 - /* De-randomize the Bad Block Marker. */ + /* Undo hardware de-randomization for a plain on-flash BBM. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) sunxi_nfc_randomize_bbm(nand, page, oob); } @@ -998,7 +999,7 @@ static void sunxi_nfc_reset_user_data_len(struct sunxi_= nfc *nfc) } =20 static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int step) + int len, int hw_step) { bool found =3D false; u32 val; @@ -1021,11 +1022,11 @@ static void sunxi_nfc_set_user_data_len(struct sunx= i_nfc *nfc, return; } =20 - val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); =20 - val &=3D ~NFC_USER_DATA_LEN_MSK(step); - val |=3D field_prep(NFC_USER_DATA_LEN_MSK(step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + val &=3D ~NFC_USER_DATA_LEN_MSK(hw_step); + val |=3D field_prep(NFC_USER_DATA_LEN_MSK(hw_step), i); + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, @@ -1037,7 +1038,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struc= t nand_chip *nand, u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; unsigned int i; =20 - /* Randomize the Bad Block Marker. */ + /* Pre-randomize the BBM so the hardware writes it plain on flash. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(nand, page, user_data); @@ -1107,7 +1108,7 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_ch= ip *nand, } =20 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, - int step, u32 status, u32 pattern_found, + int hw_step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); @@ -1116,13 +1117,13 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chi= p *nand, u8 *data, u8 *oob, =20 *erased =3D false; =20 - if (status & NFC_ECC_ERR(step)) + if (status & NFC_ECC_ERR(hw_step)) return -EBADMSG; =20 - if (pattern_found & BIT(step)) { + if (pattern_found & BIT(hw_step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; @@ -1138,9 +1139,9 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, return 0; } =20 - tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, step)); + tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); =20 - return NFC_ECC_ERR_CNT(step, tmp); + return NFC_ECC_ERR_CNT(hw_step, tmp); } =20 static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, @@ -1148,18 +1149,18 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - int step, bool oob_required, int page) + int logical_step, bool oob_required, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; u32 pattern_found; - bool bbm =3D !step; + bool bbm =3D !logical_step; bool erased; int ret, bitflips; /* From the controller point of view, we are at step 0 */ - const int nfc_step =3D 0; + const int hw_step =3D 0; =20 if (*cur_off !=3D data_off) { ret =3D sunxi_nfc_read_column(nand, page, data_off, NULL, 0); @@ -1181,7 +1182,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -1198,7 +1199,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), + hw_step, readl(nfc->regs + NFC_REG_ECC_ST), pattern_found, user_data_sz, &erased); if (erased) return 1; @@ -1224,7 +1225,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); } } @@ -1239,12 +1240,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, * (it includes the user data before the ECC data.) */ static int sunxi_get_oob_offset(struct sunxi_nand_chip *sunxi_nand, - struct nand_ecc_ctrl *ecc, int step) + struct nand_ecc_ctrl *ecc, int logical_step) { - int ecc_off =3D step * ecc->bytes; + int ecc_off =3D logical_step * ecc->bytes; int i; =20 - for (i =3D 0; i < step; i++) + for (i =3D 0; i < logical_step; i++) ecc_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); =20 return ecc_off; @@ -1256,10 +1257,10 @@ static int sunxi_get_oob_offset(struct sunxi_nand_c= hip *sunxi_nand, * but it skips the next user data. */ static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, - struct nand_ecc_ctrl *ecc, int step) + struct nand_ecc_ctrl *ecc, int logical_step) { - return sunxi_get_oob_offset(sunxi_nand, ecc, step) + - sunxi_nfc_user_data_sz(sunxi_nand, step); + return sunxi_get_oob_offset(sunxi_nand, ecc, logical_step) + + sunxi_nfc_user_data_sz(sunxi_nand, logical_step); } =20 static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, @@ -1300,7 +1301,7 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct nan= d_chip *nand, static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *buf, int oob_required, int page, int first_step, int nchunks, - int *raw_mode) + bool *erased_chunk_found) { bool randomized =3D nand->options & NAND_NEED_SCRAMBLING; struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); @@ -1403,7 +1404,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, } =20 if (erased) - *raw_mode =3D 1; + *erased_chunk_found =3D true; =20 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } @@ -1427,7 +1428,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, if (ret < 0) return ret; if (ret) - *raw_mode =3D 1; + *erased_chunk_found =3D true; } } =20 @@ -1441,14 +1442,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, u8 *buf, unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; - int raw_mode =3D 0; + bool erased_chunk_found =3D false; int first_step, batch_steps, ret; =20 for (first_step =3D 0; first_step < nchunks; first_step +=3D batch_steps)= { batch_steps =3D sunxi_nfc_dma_batch_steps(nand, first_step, nchunks); ret =3D sunxi_nfc_hw_ecc_read_batch_dma(nand, buf, oob_required, page, first_step, batch_steps, - &raw_mode); + &erased_chunk_found); if (ret < 0) goto err_stats; max_bitflips =3D max_t(unsigned int, max_bitflips, ret); @@ -1456,7 +1457,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, u8 *buf, =20 if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, page); + NULL, !erased_chunk_found, page); if (ret) goto err_stats; } @@ -1473,17 +1474,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, u8 *buf, static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off, int step, + int *cur_off, int logical_step, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - bool bbm =3D !step; + bool bbm =3D !logical_step; int ret; /* From the controller point of view, we are at step 0 */ - const int nfc_step =3D 0; + const int hw_step =3D 0; =20 if (data_off !=3D *cur_off) { ret =3D nand_change_write_column_op(nand, data_off, NULL, 0, false); @@ -1507,8 +1508,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page, + sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | @@ -1565,7 +1566,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, struct nand_ecc_ctrl *ecc =3D &nand->ecc; unsigned int max_bitflips =3D 0; int ret, i, cur_off =3D 0; - bool raw_mode =3D false; + bool erased_chunk_found =3D false; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 @@ -1589,12 +1590,12 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_c= hip *nand, uint8_t *buf, if (ret < 0) goto out; else if (ret) - raw_mode =3D true; + erased_chunk_found =3D true; } =20 if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); + !erased_chunk_found, page); if (ret) goto out; } --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oi2-f12.google.com (mail-oi2-f12.google.com [74.125.231.204]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 368134A263A for ; Mon, 14 Sep 2026 21:10:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.204 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; cv=none; b=uxkvTJGo4RAelhO4jzVhZFJ8pJE3vFGmQjydFmrDvCykuHx9U5i5wprllrJWXOFS3du3EMbYqeBsxqeXDKM5KYwQmqvmVEhaY0OboY/c9DN3+gMF2iUKu4vubX6m570hhkUqOXgefGCO3rzqfPPjLB6m4s+jnA15M1GvnrEVVF0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420215; c=relaxed/simple; bh=TnmhAN7UAS2ynuFEOPQLlzD2wvbIo/yeVWwhOMqNS58=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IrSOYprOPSa5RVZidhNIXp9PMq0jtNu70yhzmRUqmfzPY8tA1dyq9fHpsmNmtZOHFW09d1G6Y4Pd4NjsKSBHVVw0lRpKRNoec8hkcYpoDURHui/Qu+9bWyFRyUWiIqg019gbGzdnX9KrKYz5P4eJCgBmLg2CUOvZqK/8MdxfRjs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ouj664Ec; arc=none smtp.client-ip=74.125.231.204 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ouj664Ec" Received: by mail-oi2-f12.google.com with SMTP id 5614622812f47-4b37a2ffef2so1042875b6e.3 for ; Mon, 14 Sep 2026 14:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420212; x=1790025012; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=SP5FgDVql885MI97WgCQyPWKLiok3M5jguE0MrKj3qI=; b=ouj664EcdpP0t3B/OjlhZAUIkPQnmb3M1wgCNnYPfS7qSsxM3bRei1GQKaRLkRlA62 oI/1kxXvPM4Rayru5ipeUPGlYgWGC2IiWT53O0l+L75+gRtfgJg+KZXdMxfwJc97sc34 KNGeZymhUg3i/uzjl7tFi11f6kbWgSbs595MDObX1dM6lF9PBTwBgnzdeAInzUMJbUfi ygJ3A7c8r74M2wjM1NE+32BDOZdVnPu8ybCtSvys40O49hIDGUpA8UHgJLkM5BUJoGk6 e4OxT9S3ttsIVNWUJzq2T0Js640tu3bMOF5waqJDlSSeHo5Uj/Q0RWPVbnPEZG/ffNL8 Vcaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420212; x=1790025012; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SP5FgDVql885MI97WgCQyPWKLiok3M5jguE0MrKj3qI=; b=ZP4zk2zDF9eCsq/RgHixdretwQWQDc12sPMZco2Sk+WA1ZqjeFPdjQJ5szYbPSSo53 TvXlwvdQlWzQAA7+AowD74FuDQtdmcqAI8KVZ1rHaoJj0+hHqwMorD0zHnHjLbvX81nP 09Tdo3Sfly+NQqSsC6VMNS6sGGj//huwQvBJvqhBYVOekDzufQiWxTNi21l3I64V7aGl 4y1VC4lsasW5Aq4OyOqgsJ2rX1zkXKg+L4ghoby/DMIGOIQF7/i4Z6VkVsSbcRaBKIlv 9Y0WlJXSWzC924bTfdiurw14yQDgRqUf3T0ARYXLvpJw9xpJRt1qfHzQCazEs8Ynr2C7 Jb2g== X-Forwarded-Encrypted: i=1; AKwUvByyndPepDDzyDnwnzsMwsus6qHdageCq8SzMjvuKxJy5fmlh66E4pY3Kk4YDdt7VYWb/Y/F/bw5kyhaFA4=@vger.kernel.org X-Gm-Message-State: AFuF++loct6RLJEwNzOSwwptk1baK7FA8iy6YFBsi87au+G2gA4KjSpt GzKSHjSZ94ervGnmgHSXYdTE3lPx7sEKqA/ejAJgs+NFCO1fOjzrlovH X-Gm-Gg: AYBFou3F/18ef9S+oSy6phw6oXySPXDyNAW3h6h0Op8NXnBE+V754zgB67JoPff6Yzv aTp0a4Cv9mQmCS6DvZCOD9VzHeg/PhG1X49V/I7r7hkFMg6Gv0bX1sARCuMrevgcvzSNmJbSRbj 7NLiAmbQ8FOgrMsVn7f1QYhBKKCXmLcChfb5LUInOP5hzKAa3ZtIgj91VjpZL6VhkG75TNuXAhT YOcMD/AfphIlyswrI8etAhNSHzgmIIM+0CJbcdQ0r7VM5AQkPXynBRqr+NK/UkYOOz8AC8SgFCw eN5jGhaHmPCVZPmKT/YL5R2R0FeBO6etRyBAFsoWmr+FBEzME9yNQH19aFgc585C+ZrC5FW+AuB WS1S4LGkeJyQ5H89h5QYamWYtnQOmgvK1LzKtNo0GFvBVgZZCVtyCvAgQfGVROPocG7aVp6mT5o ybdnd7/f51EFQo4IGyn6QlFoA1Bw0vgjbCoSOMBwDZNPwHUH/xx4Q5KbCyvZbMr0YwngnwWwTjy e1C6EkRTX5FUD6anJpsNKpV8E/cJslGFRMZ4J0vTXak7SGe8RgWJ2rk9MCKC4OXpNbe/k9BSJ+E xK3i7QedFKJrEaEZ2FI0K1+WMGyLRWZbuyf0xf4isRNNcKePNxYTPv29GuA7gXUC2qVpb9elY5R P7zlK69Ede6u+hFqoBif5dl5L1t/H X-Received: by 2002:a05:6820:1609:b0:6b9:4557:2722 with SMTP id 006d021491bc7-6c53f252fa7mr2388952eaf.3.1789420211667; Mon, 14 Sep 2026 14:10:11 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:11 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:58 -0600 Subject: [PATCH v6 12/18] dt-bindings: mtd: sunxi: Add randomized OOB flag Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-12-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 Allwinner NAND firmware stores the bad block marker through the controller randomizer. The mainline driver instead compensates the first two randomized bytes so that the marker remains plain on flash. On H6 and H616, the firmware also uses a fixed protected user-data placement while mainline fills the OOB space left after ECC. Add an opt-in property selecting the firmware's normal-page format for the configured controller hardware-ECC geometry. This covers the vendor-specific randomizer, bad block marker representation and protected user-data placement needed to access BSP-derived images. The property does not change raw-access semantics. Raw operations still bypass ECC and randomization and expose physical main and OOB bytes. Signed-off-by: James Hilliard Acked-by: Conor Dooley --- .../devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml | 10 ++++++= ++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand= .yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml index 9d061e2216cb..8ecafc40ddcb 100644 --- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml @@ -79,6 +79,16 @@ patternProperties: minimum: 0 maximum: 1 =20 + allwinner,randomized-oob: + type: boolean + description: + Select the normal-page format used by Allwinner NAND firmware for + the configured controller hardware-ECC geometry. Normal page + transfers use the controller randomizer, the bad block marker re= mains + in its data stream instead of being compensated to stay plain on + flash, and protected user data uses the controller-specific plac= ement + expected by the firmware. + unevaluatedProperties: false =20 required: --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f40.google.com (mail-oo2-f40.google.com [74.125.231.168]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C35AD4A2E19 for ; Mon, 14 Sep 2026 21:10:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.168 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420220; cv=none; b=BsNHglgzEokG7B2ptO//OIkhFkFAjJVnqrXtVCu2ziHkocPuinAxW7cqZj/22p9DcC07hcQzaXXNBUvcUNr6aU2a8Gpa5XgVpZCTl/Gjcq45EX2UypkAE52keFW8U0n2IMxM73yRpHHOxtIlkF3QfEPrgPf9lR0ROkv0+D7Zqbc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420220; c=relaxed/simple; bh=pkxkYvAECUM2dxAA9qSlcoZx37otQGFTR85S/Ac1keQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DrYWvIoKBMu/6Z5BEZs/0Se6XEasmtFdwphxuQVu1PYBXACfFmWOdWvTob5t1mqCO93hIK1p9vXBMPrHlu5G4pcT7NTXfvdLckURuXuNztSkQ8GbYPUEqKS3UhDvMHu9lOmLgrpdWO6+oekbXobVs+PUfZi4I0yU0TCdZyhMntE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iUbrTshp; arc=none smtp.client-ip=74.125.231.168 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iUbrTshp" Received: by mail-oo2-f40.google.com with SMTP id 006d021491bc7-6c24d19ebcfso1395793eaf.3 for ; Mon, 14 Sep 2026 14:10:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420213; x=1790025013; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PM3/kqI6jzm2niMT/a23gQ0WVuxg3p+u/T3bZIK5RE8=; b=iUbrTshp++bGGEC0D6ArCJ9VtSxdZAvOjP/ZJLu/2NwTA74kfMtxTM6F0b/Udh+Y8t IrB36IeXoAi12hwTdxVrnA4g6mwiHu7FfmbzQLvwILqLWkUhbicCgBrnZZn4B4JuDcCQ Qw86fNNOt8Ne3GuMeRTB2R+MR6UWc0YDoLmoThL+RGfb/TG0GKw7nmT1kjH9scfdvECn VoixjET8NJPs2ygrbkoNfUmzhHnpGqyF1M4dVqpsUCryy/v7cpiZDdaBqvL51d1NchUx SVzhF11lFvy7rbtS9XAQXwyXN3s0p9o2rieR3Yx+lThlrsICqP8ib8w6Pk9G5SL/i4Z0 D9bA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420213; x=1790025013; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=PM3/kqI6jzm2niMT/a23gQ0WVuxg3p+u/T3bZIK5RE8=; b=iShrHKZ0PVmSeDG5N19tp/6WXRIOT5Ki2sENaoNIYD9ykE2cSUUWI7gAO6ApL/oBz6 49DOXX1TmyGr7xU1adsaecWvtDHEfYt6fNhhuyIIgx3Az68mCeB+gHfaQnW7XdJtVfoI zACv1X36tIn/r2bgzUF3b5pZZeS1LK3joDISq7eOgXcsojQh+DFeFN9Ga3Xn7epDCa4q rZR2xt5aWfEmr5iu4/fuLL3tgoeKrnVtMs384J6kEfqV+6TQx4dzArcC3G9bSaJy8qSQ zMzeAh7aPLiGpVFSkxY+kZhfSmpyhHP1M1+I4P1kowMPwGaQrtCucnaSJkkoXCABX19K f0aw== X-Forwarded-Encrypted: i=1; AKwUvBzgzjj6xnX3qlfnmrdHGNylphpWhXnCrdcU55CTK/1GuiGixbL8rpuq1PblpbRmSzrqWEhHeXAFYGDty/k=@vger.kernel.org X-Gm-Message-State: AFuF++n/dCII7bBKuKoansjjT+M+SLnVamGT0TQYQE8GqWhocWdF1pHj oVqKGSToX4/9mvbIsSK4nyFfGBQj4jTdvt8tbFYs5U+rdvK78WFLj4AU X-Gm-Gg: AYBFou0FbuZqWtsjktXZz2LKKEsCEJySIcgyx8sVjuNNjCGWfOdU4UOyXsGHx0KQFFk ujPMew5U6zmES2nnuAAaXA5GE23QZL+CwZ78NYJh1CAOEg5cCPRkSIQYFDusX93xDVw0IYG19ry skQrJCI7fBdtd2bcgunVMwcrd26PTx0oMkx7CkZ8O7dd0dfEqWFjHL5XXi6i+CPS+iyjyBYZR2m aD8/9zdNUwG4J2QreYI2EMIU1eTjGgppix3BIklLbY1O5WpTA3NUp0VTUMGUfNvIRWjJh0FJyf0 zIGMqnlVQCK6LCO2nnbXTAHueiaIwoJLd1otTV2LrIhbeeoZLhu2i7oaDf5AVBBF/fkQz1mJVOf wnXCHEBtAhvqaFDISB1gRV8++IvPTE3Q0qywA4DETpTMfB0xI8AuG7FpXqUeEqrMPoGRu/EIwwq ZX/RyA6/USKyNNqEgMtvQyL+4LBOa1S6Xbg5W9sUGeK5HQ6iKBoifmsaIvMWUKpW37/Xt8Q5kV7 5Z/8lv0ZS/YSqTasiKR+ipEiSD+/2RWr9T35v506HfKYn6fTJDQfP2CYP1X2jarIEN8PwwRm0Bm 52QOkyQnZYZkzzBPgmyvf5THmQln/V6pNuS2hgOgoNBmP3IB/DEhIh2sUmEVAOSDEl3GMIYKSqS wg+Rj91GIaXoqo92XfCkBU05D3oC+ X-Received: by 2002:a05:6820:3091:b0:6c1:e01b:3b32 with SMTP id 006d021491bc7-6c541f45b17mr4443872eaf.33.1789420213021; Mon, 14 Sep 2026 14:10:13 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:12 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:09:59 -0600 Subject: [PATCH v6 13/18] mtd: rawnand: sunxi: support randomized OOB formats Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-13-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The controller randomizer covers the bad block marker along with the rest of the OOB data. The driver currently compensates the marker bytes before writes and after reads so that they remain plain on flash. Allwinner NAND firmware instead stores the marker through the randomizer. Media using that format appears to contain bad blocks unless the randomizer is enabled while reading the marker. Honor the allwinner,randomized-oob property by marking the NAND as requiring scrambling during normal hardware-ECC transfers and leaving the marker in the randomizer data stream. Keep the existing plain marker behavior when the property is absent. Reject the property with software or disabled ECC because those paths do not operate the controller randomizer. Also reject an ECC step larger than the page so the NAND core cannot fall back to software ECC after the driver's initial engine-type check. Select the vendor's erased-spare predicate through the SoC capabilities when the randomized format encounters an ECC error or physical pattern. Older controllers require eight exact 0xff spare bytes, with the vendor spare-scan shortcut for four exact bytes on the first page and pages 127 modulo 128 within each eraseblock. Apply that shortcut only with the vendor's 1 KiB ECC steps. H616 requires byte zero and at least nine of ten bytes to be 0xff. Reconstruct the physical spare prefix from the protected user-data registers, padding unavailable bytes with 0xff. Each ECC step restarts its OOB randomizer; account for this when gathering the prefix from fixed four-byte user-data fields. Accepted erased pages return all-0xff main data and OOB without an ECC failure or a raw reread. Also follow the vendor's all-zero-page override: when every ECC step reports an all-zero physical pattern, return zeroed data and OOB with an ECC failure, even if the hardware did not report one. Keep ECC exception mode enabled for physical-pattern reporting, as in the plain-marker format. Uniform physical steps can suppress hardware ECC errors, so treat them as requiring page classification and do not use their correction counters. Otherwise physically erased pages or mixed uniform/encoded pages could incorrectly appear to have decoded successfully. Keep the original hardware-decoded main data and protected OOB on other ECC failures, and report the failure through the ECC statistics. Bad-block and BBT pattern scans inspect these buffers even after an ECC error; they must not see the physical randomized representation. Preserve the normal per-path representation of unprotected OOB bytes when they are requested. Share page classification between PIO and DMA, including subpage reads. Read the whole page for randomized-format subpage requests so that both paths see the same spare prefix and all-zero-page status. Defer statistics until OOB reads have succeeded, so a DMA-to-PIO retry is accounted once. The plain-marker format keeps its existing physical erased-chunk check. MTD_OPS_RAW behavior remains unchanged: raw accesses bypass both ECC and randomization and expose the physical representation. This changes marker handling on all supported controllers; the H6/H616 protected user-data placement is handled separately. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 280 ++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 270 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index c55537bc71e1..42c5f782db40 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -266,6 +266,7 @@ struct sunxi_nfc_timings { * @clk_rate: clk_rate required for this NAND chip * @timing_cfg: TIMING_CFG register value for this NAND chip * @timing_ctl: TIMING_CTL register value for this NAND chip + * @randomized_oob: use the randomized normal-page OOB format * @nsels: number of CS lines required by the NAND chip * @sels: array of CS lines descriptions * @user_data_bytes: array of user data lengths for all ECC steps @@ -278,6 +279,7 @@ struct sunxi_nand_chip { u32 timing_cfg; u32 timing_ctl; u8 *user_data_bytes; + bool randomized_oob; int nsels; struct sunxi_nand_chip_sel sels[] __counted_by(nsels); }; @@ -329,6 +331,7 @@ struct sunxi_nfc_mdma_desc { * @nuser_data_tab: Size of @user_data_len_tab * @sram_size: Size of the NAND controller SRAM * @timings: Controller timing characteristics + * @spare_is_erased: Vendor erased-page check on the physical spare prefix */ struct sunxi_nfc_caps { bool has_mdma; @@ -357,6 +360,7 @@ struct sunxi_nfc_caps { unsigned int max_ecc_steps; int sram_size; const struct sunxi_nfc_timings *timings; + bool (*spare_is_erased)(struct nand_chip *nand, const u8 *spare, int page= ); }; =20 /** @@ -862,12 +866,18 @@ static void sunxi_nfc_randomizer_disable(struct nand_= chip *nand) nfc->regs + NFC_REG_ECC_CTL); } =20 -static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *= bbm) +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len) { - u16 state =3D sunxi_nfc_randomizer_state(nand, page, true); + while (len--) { + *buf++ ^=3D state; + state =3D sunxi_nfc_randomizer_step(state, 8); + } +} =20 - bbm[0] ^=3D state; - bbm[1] ^=3D sunxi_nfc_randomizer_step(state, 8); +static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *= bbm) +{ + sunxi_nfc_randomize_buf(sunxi_nfc_randomizer_state(nand, page, true), + bbm, 2); } =20 static int sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, @@ -968,6 +978,7 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct = nand_chip *nand, u8 *oob, unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) { + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); u32 user_data; unsigned int i; @@ -978,7 +989,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct = nand_chip *nand, u8 *oob, } =20 /* Undo hardware de-randomization for a plain on-flash BBM. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) + if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && + !sunxi_nand->randomized_oob) sunxi_nfc_randomize_bbm(nand, page, oob); } =20 @@ -1035,11 +1047,13 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(str= uct nand_chip *nand, unsigned int user_data_sz) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; unsigned int i; =20 /* Pre-randomize the BBM so the hardware writes it plain on flash. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { + if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && + !sunxi_nand->randomized_oob) { memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(nand, page, user_data); oob =3D user_data; @@ -1107,6 +1121,43 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_c= hip *nand, return ret >=3D 0; } =20 +/* Accumulate a whole randomized-OOB page before classifying its spare dat= a. */ +struct sunxi_nfc_ecc_status { + u32 error_steps; + u32 zero_steps; + unsigned int corrected; + unsigned int max_bitflips; +}; + +static void sunxi_nfc_hw_ecc_record_status(struct nand_chip *nand, + struct sunxi_nfc_ecc_status *result, + int logical_step, int hw_step, u32 status, + u32 pattern_found) +{ + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 count; + + if ((pattern_found & BIT(hw_step)) && + !(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step))) + result->zero_steps |=3D BIT(logical_step); + + /* + * Exception mode can suppress the ECC error for a physical pattern. + * Classify these steps with the vendor page check too, and do not use + * their correction counters. Keep their decoded data until then. + */ + if ((status & NFC_ECC_ERR(hw_step)) || + (pattern_found & BIT(hw_step))) { + result->error_steps |=3D BIT(logical_step); + return; + } + + count =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); + count =3D NFC_ECC_ERR_CNT(hw_step, count); + result->corrected +=3D count; + result->max_bitflips =3D max(result->max_bitflips, count); +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, int hw_step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) @@ -1149,7 +1200,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - int logical_step, bool oob_required, int page) + int logical_step, bool oob_required, int page, + struct sunxi_nfc_ecc_status *result) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); @@ -1198,6 +1250,16 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_c= hip *nand, pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 + if (sunxi_nand->randomized_oob) { + sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, hw_step, + readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found); + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, + page, user_data_sz); + return 0; + } + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, hw_step, readl(nfc->regs + NFC_REG_ECC_ST), pattern_found, user_data_sz, &erased); @@ -1298,9 +1360,156 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct n= and_chip *nand, return 0; } =20 +static bool sun4i_a10_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + struct mtd_info *mtd =3D nand_to_mtd(nand); + unsigned int block_page =3D page % mtd_div_by_ws(mtd->erasesize, mtd); + + /* + * The older vendor spare scans recognize exact four-byte erased + * signatures on page zero and pages 127 modulo 128. With their + * 1 KiB ECC steps these correspond to four physical 0xff bytes. + * Other pages require all eight spare bytes to be 0xff. + */ + if (nand->ecc.size =3D=3D 1024 && + (!block_page || block_page % 128 =3D=3D 127) && + !memchr_inv(spare, 0xff, USER_DATA_SZ)) + return true; + + return !memchr_inv(spare, 0xff, 8); +} + +static bool sun50i_h616_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + unsigned int erased =3D 0; + int i; + + /* Byte zero and at least nine of ten bytes must be 0xff. */ + for (i =3D 0; i < 10; i++) + erased +=3D spare[i] =3D=3D 0xff; + + return spare[0] =3D=3D 0xff && erased >=3D 9; +} + +static bool sunxi_nfc_hw_ecc_spare_is_erased(struct nand_chip *nand, int p= age) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + u16 state =3D sunxi_nfc_randomizer_state(nand, page, true); + u8 spare[10]; + unsigned int len, pos =3D 0; + int i, off; + + /* + * Reconstruct the physical spare prefix from the hardware's decoded + * user data. Each ECC step restarts the OOB randomizer; H6/H616 pack + * the entire prefix in step zero. Pad unavailable bytes with 0xff. + */ + memset(spare, 0xff, sizeof(spare)); + for (i =3D 0; i < ecc->steps && pos < sizeof(spare); i++) { + len =3D min_t(unsigned int, sunxi_nfc_user_data_sz(sunxi_nand, i), + sizeof(spare) - pos); + off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); + memcpy(spare + pos, nand->oob_poi + off, len); + sunxi_nfc_randomize_buf(state, spare + pos, len); + pos +=3D len; + } + + return nfc->caps->spare_is_erased(nand, spare, page); +} + +static int sunxi_nfc_hw_ecc_read_unprotected_oob(struct nand_chip *nand, + bool dma, int page) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct mtd_info *mtd =3D nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + unsigned int len, off; + u16 state; + int ret, i; + + for (i =3D 0; i < ecc->steps; i++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); + ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + off, + nand->oob_poi + off, ecc->bytes); + if (ret) + return ret; + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + state =3D sunxi_nfc_randomizer_state(nand, page, true); + state =3D sunxi_nfc_randomizer_step(state, len * 8 + 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, + ecc->bytes); + } + } + + off =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); + len =3D mtd->oobsize - off; + if (len) { + ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + off, + nand->oob_poi + off, len); + if (ret) + return ret; + /* The unprotected tail uses the page seed and its 15-bit advance. */ + state =3D sunxi_nfc_randomizer_state(nand, page, false); + state =3D sunxi_nfc_randomizer_step(state, 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, len); + } + + return 0; +} + +static int +sunxi_nfc_hw_ecc_finish_randomized_read(struct nand_chip *nand, u8 *buf, + struct sunxi_nfc_ecc_status *result, + bool oob_required, bool dma, int page) +{ + struct mtd_info *mtd =3D nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + int ret; + + /* + * The vendor treats an all-zero physical page as bad, even without + * ECC errors. This takes precedence over the spare-byte heuristic. + */ + if (result->zero_steps =3D=3D GENMASK(ecc->steps - 1, 0)) { + memset(buf, 0, mtd->writesize); + memset(nand->oob_poi, 0, mtd->oobsize); + mtd->ecc_stats.failed +=3D ecc->steps; + return 0; + } + + if (result->error_steps && sunxi_nfc_hw_ecc_spare_is_erased(nand, page)) { + memset(buf, 0xff, mtd->writesize); + memset(nand->oob_poi, 0xff, mtd->oobsize); + return 0; + } + + /* + * Keep the original decoded main and protected OOB bytes on ECC failure. + * BBT pattern scans inspect them even when an ECC error is reported. + * Read the remaining OOB only when requested, not to classify the page. + */ + if (oob_required) { + ret =3D sunxi_nfc_hw_ecc_read_unprotected_oob(nand, dma, page); + if (ret) + return ret; + } + + mtd->ecc_stats.corrected +=3D result->corrected; + mtd->ecc_stats.failed +=3D hweight32(result->error_steps); + + return result->max_bitflips; +} + static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *buf, int oob_required, int page, int first_step, int nchunks, + struct sunxi_nfc_ecc_status *result, bool *erased_chunk_found) { bool randomized =3D nand->options & NAND_NEED_SCRAMBLING; @@ -1383,6 +1592,14 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct na= nd_chip *nand, u8 *buf, =20 user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_step); =20 + if (sunxi_nand->randomized_oob) { + sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, i, status, + pattern_found); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !logical_step, + page, user_data_sz); + continue; + } + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, @@ -1409,6 +1626,9 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 + if (sunxi_nand->randomized_oob) + return 0; + if (status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int logical_step =3D first_step + i; @@ -1438,7 +1658,9 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *bu= f, int oob_required, int page, int nchunks) { + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); + struct sunxi_nfc_ecc_status result =3D {}; unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; @@ -1448,13 +1670,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, u8 *buf, for (first_step =3D 0; first_step < nchunks; first_step +=3D batch_steps)= { batch_steps =3D sunxi_nfc_dma_batch_steps(nand, first_step, nchunks); ret =3D sunxi_nfc_hw_ecc_read_batch_dma(nand, buf, oob_required, page, - first_step, batch_steps, + first_step, batch_steps, &result, &erased_chunk_found); if (ret < 0) goto err_stats; max_bitflips =3D max_t(unsigned int, max_bitflips, ret); } =20 + if (sunxi_nand->randomized_oob) + return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, + oob_required, true, page); + if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, NULL, !erased_chunk_found, page); @@ -1564,6 +1790,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nfc_ecc_status result =3D {}; unsigned int max_bitflips =3D 0; int ret, i, cur_off =3D 0; bool erased_chunk_found =3D false; @@ -1586,13 +1813,19 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_c= hip *nand, uint8_t *buf, ret =3D sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, - i, oob_required, page); + i, oob_required, page, &result); if (ret < 0) goto out; else if (ret) erased_chunk_found =3D true; } =20 + if (sunxi_nand->randomized_oob) { + ret =3D sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, + oob_required, false, page); + goto out; + } + if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !erased_chunk_found, page); @@ -1638,6 +1871,10 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand= _chip *nand, int ret, i, cur_off =3D 0; unsigned int max_bitflips =3D 0; =20 + /* The vendor spare test and all-zero detection classify a whole page. */ + if (sunxi_nand->randomized_oob) + return sunxi_nfc_hw_ecc_read_page(nand, bufpoi, false, page); + sunxi_nfc_select_chip(nand, nand->cur_cs); =20 ret =3D nand_read_page_op(nand, page, 0, NULL, 0); @@ -1658,7 +1895,7 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, i, - false, page); + false, page, NULL); if (ret < 0) goto out; } @@ -1677,6 +1914,9 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, int nchunks =3D DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); int ret; =20 + if (to_sunxi_nand(nand)->randomized_oob) + return sunxi_nfc_hw_ecc_read_page_dma(nand, buf, false, page); + sunxi_nfc_select_chip(nand, nand->cur_cs); =20 ret =3D nand_read_page_op(nand, page, 0, NULL, 0); @@ -2308,6 +2548,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, ecc->strength *=3D 2; } =20 + /* This format requires an ECC step that fits in the page. */ + if (sunxi_nand->randomized_oob && mtd->writesize < ecc->size) + return -EINVAL; + /* Add ECC info retrieval from DT */ for (ecc_mode =3D 0; ecc_mode < nfc->caps->nstrengths; ecc_mode++) { if (ecc->strength <=3D strengths[ecc_mode]) { @@ -2391,6 +2635,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_ch= ip *nand, =20 static int sunxi_nand_attach_chip(struct nand_chip *nand) { + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); const struct nand_ecc_props *requirements =3D nanddev_get_ecc_requirements(&nand->base); struct nand_ecc_ctrl *ecc =3D &nand->ecc; @@ -2400,6 +2646,14 @@ static int sunxi_nand_attach_chip(struct nand_chip *= nand) if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |=3D NAND_BBT_NO_OOB; =20 + if (sunxi_nand->randomized_oob && + ecc->engine_type !=3D NAND_ECC_ENGINE_TYPE_ON_HOST) + return dev_err_probe(nfc->dev, -EINVAL, + "Allwinner OOB format requires controller ECC\n"); + + if (sunxi_nand->randomized_oob) + nand->options |=3D NAND_NEED_SCRAMBLING; + if (nand->options & NAND_NEED_SCRAMBLING) nand->options |=3D NAND_NO_SUBPAGE_WRITE; =20 @@ -2629,6 +2883,9 @@ static int sunxi_nand_chip_init(struct device *dev, s= truct sunxi_nfc *nfc, if (!sunxi_nand) return -ENOMEM; =20 + sunxi_nand->randomized_oob =3D + of_property_read_bool(np, "allwinner,randomized-oob"); + sunxi_nand->nsels =3D nsels; =20 for (i =3D 0; i < nsels; i++) { @@ -2907,6 +3164,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps= =3D { .max_ecc_steps =3D 16, .sram_size =3D 1024, .timings =3D &sun4i_a10_nfc_timings, + .spare_is_erased =3D sun4i_a10_nfc_spare_is_erased, }; =20 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps =3D { @@ -2930,6 +3188,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps= =3D { .max_ecc_steps =3D 16, .sram_size =3D 1024, .timings =3D &sun4i_a10_nfc_timings, + .spare_is_erased =3D sun4i_a10_nfc_spare_is_erased, }; =20 static const struct sunxi_nfc_caps sunxi_nfc_h616_caps =3D { @@ -2956,6 +3215,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_h616_cap= s =3D { .max_ecc_steps =3D 32, .sram_size =3D 8192, .timings =3D &sun50i_h616_nfc_timings, + .spare_is_erased =3D sun50i_h616_nfc_spare_is_erased, }; =20 static const struct of_device_id sunxi_nfc_ids[] =3D { --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oa1-f54.google.com (mail-oa1-f54.google.com [209.85.160.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED28049F128 for ; Mon, 14 Sep 2026 21:10:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420222; cv=none; b=Mo1hn+R2AWs8HBSLwN/PAGcyewFg/GWoTV+DRB5W5vHmFeIp/kmHH+petgQXmORCQ0KA2IJJCE5pMin5VQ5bKtamqfXrvhdS+7t6udQWslUpwI5qFbwmPohyR+7EUOaOYp9FNzBmxfGrjQ0Bzm4pYBi2xSsNvpxAO+dMwfcss/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420222; c=relaxed/simple; bh=RYMhZUroOg0vuK6FzRQ8q2eVSn0RelC+x7nX6I7sGZ0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fize7pYPv/DWpgyal+1auNuHuMUUtarxydon9bDPldCfHKBGng1prOw1Sl0vDeF6QtbB974nm/OH5xXHwpA3tUhx7neVUZXhWEG8B8gsAHsy2TXwMQwERIt/T2q4eeJrZrFedhHer3cBlH9my2C90/kTOwsIBDoH3H4c+n4EteE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DRzb40Mq; arc=none smtp.client-ip=209.85.160.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DRzb40Mq" Received: by mail-oa1-f54.google.com with SMTP id 586e51a60fabf-451a49abd8aso3485321fac.3 for ; Mon, 14 Sep 2026 14:10:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420214; x=1790025014; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=FDb8CvIky7fTL8ZHKUM7VSBHzZxqYVS0jxwrplOkME4=; b=DRzb40MqaAk2Ua5hl3ymkEsKc1AzNoTRfd5iw7SLhfknWEe6gvFN6KFBwcGdMFNyw6 D/aTgmTI/j6FuBXnWs3rOsh0Vmv4I3dbYuEj7ZdlPbIueVKN/LeRwGbEkT2Dc39Uc7Fn 2QinkxrdOl5fhNUaRQSL6TtQHzotCX7byy1Ozb1g66o7TQ/s8x7fA9TJNlAIGf+aYGv4 MLd3qUhPj0c84MzlkMls6PRl8Xtt4jeTtWVVLpLWlKQ1nxbcdnGtWvfXRsNEdeR59Oat ieXPtKfLqQmZ8K3hmhThGua0B7fSU0YTnUwSYApzdvz5feUQ5naAx/DGqdi1HqS+/zOO JA4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420214; x=1790025014; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=FDb8CvIky7fTL8ZHKUM7VSBHzZxqYVS0jxwrplOkME4=; b=UaE4WhVyD+iyjakxhvJPHslkQwsNGQHZARgpetUoFfSegN8+XzkG9HKJ6qBwvCq+ps BfxEzdScXF/pmGVsCButvpqtsW0eSsSfJ0DM61ARDsRMOnG6zAcxtqRnlQ4j7lAFuRSV 7p0Cgt348iktJo9wEXj1LN4O/YFK3tbFPfxjTBPguDXuE9nKWDGAwDV6wPq3Unmlis8J a36phqofZsJInhB/gMOoBLPvdWGzkHh6SyvdRG5VK6pFqNGcvTRYoYoZtJubTTdsIAF5 mPG9+/fEwG3mp+qjyVyuWRHN+lJX4IrtuEnwoJ7jSLkqfEf2j0SoxZfTaxZrrNhaO+e8 RkPw== X-Forwarded-Encrypted: i=1; AKwUvBzRHZH3mNVZDjnVyYSJIAIhB5gZE91honmHBXrcZRLxegHb0F+YibZUZxZbKBcT2o9Wie/ZkJpxPmizpsg=@vger.kernel.org X-Gm-Message-State: AFuF++nW8s7ymhDbYwjdkkVysBCTJnMN4gCJvH+rN92JJvvVkkNjb6Ic ZKXn9+uGb5xbH6wT8Hdh8kTSxVnkrMTSsLWcvT1n3BgtJ9camkah9EEP X-Gm-Gg: AYBFou0V4e6EWtr2Rzk9LxpUQim2dgMueqMqgFUPASURO7ILjjLdUccwZwo1/p3T1Dy v/yL9MIMCLbU+PJ9KLhv0d05vUQg/ZfSuqow2raebOTduo1VZlY/wPzkY5v9WV/6whQDMli60zv JliimN8VsRaHBb2EHu3GNLuiTVHe4LEmZEA9iIzQwdOrMJN3obZStJw9ALtahbShPtv/+f2JPeg NivFEWzGmMFmt25BHOa+Yx4KNN63Rcya23LcT9w/CNZDHNTINfPLf3VPbKkHbsW28JKwOIXYmNN Itcoi/mStmak/2KklROxcfF6RdelSbx0AfJ/F/5Zal06ueUsSRY0QLJiKdlflusOcuu/T7vtwRs ppwPinq5GcB0Ivo8UaJh+BxAj/jmphoByBA18PXz4WJw5QnuUs/d/tYjHD3Wwc+DioXWJ3cjEdX qMQYfSN9bOEqmH9dZmMgUk8FNx1V+6JbQ5OXlLl+UtPIwNwdWMmT4jV/lCDq+17zaecLJkhYezt uV4KezKv7s5gNaUrT83kdKcC8hnGAicaNmN+MwMnpHaZFSFVJeiIZ2NL5dCS8ckt0RYzexz3+3N ka37GE35Krxpf4RHlcMWqIMWa+yQ+aG2Pu7IEnR6B25LHvjj/2VKF8gWV8ms6ceEfRWbTuqvmhQ rYTPipf13sNNSPT/4XOPEmGtYlo3E/uT6HgSzE6c= X-Received: by 2002:a05:6820:200c:b0:6b7:83c5:fdf7 with SMTP id 006d021491bc7-6c5451a9095mr2847169eaf.56.1789420214324; Mon, 14 Sep 2026 14:10:14 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:13 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:10:00 -0600 Subject: [PATCH v6 14/18] mtd: rawnand: sunxi: select the packed H6/H616 OOB layout Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-14-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The H6/H616 controller can configure a separate protected user-data length for every ECC step. Mainline fills all space left after ECC with user data. This changes the physical ECC offsets from those used by Allwinner NAND firmware, so pages written by one layout cannot be decoded with the other. The allwinner,randomized-oob property selects the firmware's normal-page format for the configured controller hardware-ECC geometry. Use four protected user-data bytes per 1 KiB ECC step, cap the total at 16 bytes, and assign the entire total to ECC step zero. Reserve the same total before maximizing ECC strength so the selected strength leaves enough room. Keep the existing maximized mainline user-data layout when the property is absent. Older controllers have fixed four-byte user-data registers whose placement already matches the firmware and need no additional change. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 42c5f782db40..8b0d0620e1d9 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -225,6 +225,9 @@ #define USER_DATA_SZ 4 #define SUNXI_NFC_MAX_USER_DATA_SZ 32 =20 +/* The randomized H6/H616 layout packs at most 16 bytes before ECC step 0.= */ +#define SUNXI_NFC_H6_MAX_USER_DATA_SZ 16 + /** * struct sunxi_nand_chip_sel - stores information related to NAND Chip Se= lect * @@ -2431,8 +2434,14 @@ static void sunxi_nand_detach_chip(struct nand_chip = *nand) sunxi_nand->user_data_bytes =3D NULL; } =20 -static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t o= obsize, - int ecc_bytes, int nsectors) +static unsigned int sunxi_nfc_h6_user_data_sz(int nsectors) +{ + return min(nsectors * USER_DATA_SZ, + SUNXI_NFC_H6_MAX_USER_DATA_SZ); +} + +static int sunxi_nfc_init_user_data(struct nand_chip *nand, uint32_t oobsi= ze, + int ecc_bytes, int nsectors) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); @@ -2448,6 +2457,12 @@ static int sunxi_nfc_maximize_user_data(struct nand_= chip *nand, uint32_t oobsize if (!sunxi_nand->user_data_bytes) return -ENOMEM; =20 + if (sunxi_nand->randomized_oob) { + sunxi_nand->user_data_bytes[0] =3D + sunxi_nfc_h6_user_data_sz(nsectors); + return 0; + } + for (step =3D 0; (step < nsectors) && (remaining_bytes > 0); step++) { for (i =3D 0; i < c->nuser_data_tab; i++) { if (c->user_data_len_tab[i] > remaining_bytes) @@ -2508,6 +2523,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, bytes -=3D 2; =20 bytes -=3D total_user_data_sz; + } else if (sunxi_nand->randomized_oob) { + total_user_data_sz =3D + sunxi_nfc_h6_user_data_sz(nsectors); + bytes -=3D total_user_data_sz; } else { /* * User-data lengths are encoded in four-byte units. Reserve @@ -2578,12 +2597,12 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_= chip *nand, nsectors =3D mtd->writesize / ecc->size; =20 /* - * The rationale for variable data length is to prioritize maximum ECC - * strength, and then use the remaining space for user data. + * The default variable-length layout prioritizes maximum ECC strength, + * then uses the remaining space for user data. */ if (nfc->caps->reg_user_data_len) { - ret =3D sunxi_nfc_maximize_user_data(nand, mtd->oobsize, - ecc->bytes, nsectors); + ret =3D sunxi_nfc_init_user_data(nand, mtd->oobsize, + ecc->bytes, nsectors); if (ret) return ret; } --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B48E4963C3 for ; Mon, 14 Sep 2026 21:10:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420224; cv=none; b=JOegCfy9zlJCIa67INq6/GyozWw8d/KYfrmAHV/9xpoOcgRVX4ftMuNS++u7fvZFwbf955k1waF6k3KQu8uo+D9R7uUE6S7RnkYdKh5NJdqyduoSn77q/NM8VWyM04rMg+nmbmeWxQHTnDG+M+WLZMQ0VYv2LkJfNhJn47SUBC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420224; c=relaxed/simple; bh=bniJ2L4Tvp9lAApOs8qjlReFeiPBCiiQVEC33ZRnv2k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iOUpHyZEx00DGcefNSAUyGfpC0pcNA+0CIbPIItK6QmX/EY5PzVg0k/DXBHezGC7PAZotpwW1VjZv2/hSGVMRsCbL1jAL20DSYWqkSrTK6bbtcfbduln7TQKFKyqeGjB1QzpFIQvJ62V4fP8d9HP6vw8YtfH9V+sRpq7ufwBBXQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VNAxY3Bl; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VNAxY3Bl" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6bc475ffcbfso787670eaf.2 for ; Mon, 14 Sep 2026 14:10:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420216; x=1790025016; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=akH24Z1lLy7buBHyV5efDWLsUp/yg44TnSGfRiXVwiM=; b=VNAxY3BlJ5Vt6VYYxn4+frTvTYjOwLeKHWG1ZV+K+2dTEoHyhD1KWjPQJZebW4OGQH E7qGEtbmj8XCST9BCCDDvDbSlJmZKkjqKNOOAvGnyNmhMSLbHI3YBF7EUwnZ+dpqkMSq 1WD3JvqScKIQCLysdfvwc4KIpmdI0dJEbVwx5CJtC/+vYsUzwQIcXC/el2xQOVbTtL+f lPpsLwP/c6pY5UCgByV48DUgWey8li6N2zgOZoKXh9NHNAy07boELcUlN+nW6tdl1Qbk 6rH8VaDRI5fbLk7XAbHyRVh73XPEGmYEWjX18ApMow7xeRpKMvOWa4wTIAxRySOMD4LN YI2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420216; x=1790025016; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=akH24Z1lLy7buBHyV5efDWLsUp/yg44TnSGfRiXVwiM=; b=Tu53Sn8ukkpNfszMMX8UAMEbp7xX/gSUKRO3bXWCyjWBIDsjtX5nexICC5w9sUsLtn +Jcd62KP/UHN59+os4SwaqDgpEwD92X5NL3oXwwqq/BJxbGZLsirRfzju32nPOnApoC9 r+9msYkhTEgJCDidoKx0U5cfA12AypMI4Kc6uFwI1znXAZLN72K8EQN3CVl1fFnJNTGy jV1lDiE/4CI34mT4KEDbVBxycWyVDfU1MjOrtw/cYNN2SYatji87omellDBMZkMuFojE A5ggqWpxINm1uMJYhcTQnl5OnbbqzdJD286e/4L5n6VgVZrYD/pIAFYxxk5MxagpWlIW u7VQ== X-Forwarded-Encrypted: i=1; AKwUvBysByXWm3YSfGHRVXdKuBVKhoCrsXgoOzeVVbwo9meOjLqmmS1+fsr4mtRrs6opGiN1fUtW6ziqjMD/KyU=@vger.kernel.org X-Gm-Message-State: AFuF++nAb4BTsmR+DHIseDHfdO5zjBB8TXRVzfqul/FTyNStkEwScWYO Mh3lDjEff814tXz7IyYwzUoqktkvC8a5cvMd5ReEHkJlKDGjS0uZxpg+ X-Gm-Gg: AYBFou1OiynuK2f7VvpZpZOlgrg1SMnObj/mkCI45z6eeQmllKVx0IDfVEoDkEjt4ck CGeI1XdRQGdXDrB82EH2rHSMXjelu3vmIXpaQeZZjnC55IgWiRmtOvbbjnyDTIABP2mCaVnpTTJ C+9R/Fw3fM9FzAo2ixkpFB299Wgi4NUr6MJK3L2hBxd+WOtmWMRyUcycfJxetJf6gaoaUBOLl5M v1L2MoxuvnIKpjUrbEymZSyl5ltOOcui1NCO7IM0XiB6civkgUNY24JUNyTWHjsJUHacQjwWOLb l8GqUpujHxvIRRfq6ko6ssPkpOl23MNHxlmMD+T0DtHJXFkRzZOIwDVVr7ORMXgcVidJZFEPQsZ N6Ac2ZrDO2/4wQUIzphbpgXIchbiZp9iprYjBObv6UbovUNR/rl4EFSxH2IUgBtlhxk2fZaB8vI VAEToCCTcOaUCg9g9W5XqGWVrOJSuMzN1BT+vf2poySrpDUY1LU1iQg7F4m8IVplDUjfYSKRDpE yJFdjX92KSi8Yb0mLk5nV3St6W0chi15rZwRK1j3NbbJ0hRncG9MPtNx2JnRJ/17MW3iMVrwV8R 9mY3gz7hQ6HAMrYi6DJI340r/1z1ty38xQDIdLSQiZuC/k+AwZ01egApVgrJPjhzUy0+afeBYHL fiwTW5UQ1FUm7nLCp+urhBuU6nGa68n8fgQPWFwg= X-Received: by 2002:a05:6820:8c5:b0:6b1:2843:1312 with SMTP id 006d021491bc7-6c53ba3546bmr2248641eaf.0.1789420215927; Mon, 14 Sep 2026 14:10:15 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:15 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:10:01 -0600 Subject: [PATCH v6 15/18] mtd: rawnand: sunxi: combine contiguous unprotected OOB reads Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-15-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 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 --- drivers/mtd/nand/raw/sunxi_nand.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 8b0d0620e1d9..f3234d2831ea 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1435,14 +1435,28 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(st= ruct nand_chip *nand, int ret, i; =20 for (i =3D 0; i < ecc->steps; i++) { - len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); + len =3D 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 +=3D ecc->bytes; + i++; + } + if (i + 1 =3D=3D ecc->steps) + len =3D mtd->oobsize - off; + ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + off, - nand->oob_poi + off, ecc->bytes); + nand->oob_poi + off, len); 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 =3D 0; i < ecc->steps; i++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); state =3D sunxi_nfc_randomizer_state(nand, page, true); state =3D sunxi_nfc_randomizer_step(state, len * 8 + 15); sunxi_nfc_randomize_buf(state, nand->oob_poi + off, @@ -1453,10 +1467,6 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(str= uct nand_chip *nand, off =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); len =3D mtd->oobsize - off; if (len) { - ret =3D sunxi_nfc_read_column(nand, page, mtd->writesize + off, - nand->oob_poi + off, len); - if (ret) - return ret; /* The unprotected tail uses the page seed and its 15-bit advance. */ state =3D sunxi_nfc_randomizer_state(nand, page, false); state =3D sunxi_nfc_randomizer_step(state, 15); --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 299704A0EEF for ; Mon, 14 Sep 2026 21:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420231; cv=none; b=NhQSX27Q6ELJO+FZ8a0KjKOvRavlVQgQlAMGzhL8IBHqpWO6/Jfdq1yuBPVWVGVtp6EdV6dO5t2oXSJJiX4UX+gsLKc5XfvZuFCK34BNo92/0Rl3HLm85/g8wZXoCKSjH1FF7lUOApD9yGmIwvClo2cFecVJGDXveH9zIEsJ2Jk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420231; c=relaxed/simple; bh=ZhwsgqB5mjFiVy7QQ4USypPx8q5jZF5EM5tixdJx7b8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EmiF75S+AY1DJuo7hmoPyj7YO/0NQT6ZO8qjRudWzjTR9FM9rTgxH0jqrqDOfpDKUZ7fH11Q8HPL06oqhPE1QEbbAXkOsaY3fSgoYPySyyBnp1ct3b3skSwF4C2aBkmi9xWjQBXjsl0+Rjf4Z4E7vu2EWQhOgPwSjUwOMVrRJ6s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XdX4kHcQ; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XdX4kHcQ" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6b1ae739df5so718599eaf.1 for ; Mon, 14 Sep 2026 14:10:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420217; x=1790025017; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=7XwVosOtOADwbw6wxbVAGv82uPNwv85si6C2vLS4JkM=; b=XdX4kHcQtohdE3X3AuuhPGwwYmZ38YUCF1t8fH89MNMGQ5RPhYSd4eTz7IzaPWi/hm JxTUqdMpd1xbqwV4mIIW7SsBM77AEAnBVTwzTREWV87z5lLqQoAKjwPYol60iW5B8fcZ rpQ51CAAAMufECzX4/7Ib2Vl38IuPA+6YpuGC6El8VjgUToeDUCX1vFUPzBGKj6wjcBk w/K0CiyjYANDQFZFLohkks6BgXb77ElCC9wdaNMlCua73JmitCgSsTP6zoREsnqYLxc2 v0C3P1mL4clfuShcgbm1lUF+AUvGbGN3HRvPw4UxFKA0EgLEz4tNaOAtYVR95PI/5dfh XFUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420217; x=1790025017; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=7XwVosOtOADwbw6wxbVAGv82uPNwv85si6C2vLS4JkM=; b=qkoOQuunvNtqE2jBcDiWaCvDAIRtatI3zsXMb7DNnen43+ZTxHvk1F5zQXUrZ2Ewwx D9UTx5kOIcAVq+8F0ezIXo0mt28UL+OR46LdoXX3AaVuWUv+MZN+Crbur5Tk2dhUOfZj PD/9ml8Fa1mgRIgqYxZVOd+15/F07uyM/4gKbglOU0o3V8SotJbufRiaG1ogl0M1BPJu BIIcXPr6AdnSzJAGlw6bH/ZoXAQmzDFtbaQNIx+V0swK7iIEAAMNt7cmO8b4/hmbuVR/ MYyz0DNstWZazlqgyqAUom755A1mxYdOMcz5/T5fi3bLShsPW7hWTmoLRTd7x21zovvz 7GlA== X-Forwarded-Encrypted: i=1; AKwUvBytA9IZy++aTa1INOuzYxL7zI/sJmB2t1CeUsspGGclRy1ofvl0CT1jEJRNYKTA8IiBLisOo1K5qiFgdXY=@vger.kernel.org X-Gm-Message-State: AFuF++lwnZxciXz4mdFFsxHDs38Vz43gDdNLwQkOLP2atyoIIGMV+EyE gp6ts+2nvM1TA+6HOkFhnkQjYpFACP1AigmiRCSbQkuJWr/8lZw0L9WX X-Gm-Gg: AYBFou2ZjXV2BNH2D2A8+CnVzr9MAUP3NDXxLiuDRBpToRJGzaD+0OSjOcukLa+pZF0 brs7/H3bvmH19lyCb5DTmaDuwr/gHUxgYOddpGC+fuOLdnu33+Cr7/bnijiH1lepeL8qRi/KjBm AtL+AT5OHKciGqzp12q7KZsDSBwHzAyWrg+06VeOM+BlXWbAUHb+ldW5NOQSmDk4dOIOp7Aexaq Q06mZHJ/4CvuZ3yWGhWLyfHkdx3c2FdkpTy0LWnkdOoTaPo6upJY5TLeFLqaLx/+p72PdsFdzvM QJFEfDZU7C7KNEcsiY/bzc70FsZYRPA3nN3BhkrSaEPoikB/raGhCMfTHF+6B9vw12pH1X4DJFe CxSsoMTw7ON6kGc/t1unA94wP+HnNZbjSzInQgYLQVa2LudYa9nn4wks0JqqSPFtsv1GF5e5N9o 8n0mmdrY04U9W3UZaoU3udCdPEPORYlXGq82xM4gjC5z0RP62nMNV7V8j1iPHGKPIUUhbg3bwbf QAEsl1El0llOc2LSexEBKTQa4T3Tq2R4aiDdgJl1CNJcxg7RWo3J/eFaR2+iFbBpb+kTgVSOehg vvjnzapfqvAUMK5a7Nk4MVKsuoVvGqafwI0QuB0vwhxKmmU39i1yXkKs75Z/grZuPDqbsn59buJ ohOaewi5oUai1n6f8sDqxZ4EskFi/ X-Received: by 2002:a05:6820:1890:b0:6b5:ec3f:497b with SMTP id 006d021491bc7-6c639498c9bmr552266eaf.22.1789420217054; Mon, 14 Sep 2026 14:10:17 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:16 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:10:02 -0600 Subject: [PATCH v6 16/18] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-16-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The page helpers invoke exec_op(), which selects the chip and programs its timing and spare-area registers. Remove the identical setup directly before those helpers in the read callbacks and PIO write callbacks. Keep explicit selection in the DMA write callback: it accesses controller registers and prepares DMA before issuing the program-begin operation. Do not cache controller state or change selection after a controller reset. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index f3234d2831ea..773ba55ecc07 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1808,8 +1808,6 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, int ret, i, cur_off =3D 0; bool erased_chunk_found =3D false; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1858,8 +1856,6 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand= _chip *nand, u8 *buf, { int ret; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1888,8 +1884,6 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, if (sunxi_nand->randomized_oob) return sunxi_nfc_hw_ecc_read_page(nand, bufpoi, false, page); =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1930,8 +1924,6 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, if (to_sunxi_nand(nand)->randomized_oob) return sunxi_nfc_hw_ecc_read_page_dma(nand, buf, false, page); =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1955,8 +1947,6 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_ch= ip *nand, struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret =3D 0, i, cur_off =3D 0; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -2000,8 +1990,6 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand= _chip *nand, struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret =3D 0, i, cur_off =3D 0; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oi2-f13.google.com (mail-oi2-f13.google.com [74.125.231.205]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AEEF146C841 for ; Mon, 14 Sep 2026 21:10:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.205 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420229; cv=none; b=oLkNB36QI1Q3ehHhOMRUrfeGsDgwZS6HGa/i8KhE05yTHwzr/Vv/OYV9Uf80GW+NF2oWoACJBFzSlcujhIlermg7zy7zuUlNcIqt8DreCJEXQdL12Wm21iDP2TmPP/+b0oVIAjLQvHTUT7D/N7163Ncs4OkpEFuqCBwwUTuIQgo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420229; c=relaxed/simple; bh=Izml/kmhnoiBi2LFA6kerFQHV26tFgrWjsTUcd1Th10=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Vdm41p/vcOciudMC2E0AgP7242ShW3WV0NODx6inxlK0NTxHBgmYLLDUxouqpZw4lflVYhj9gEjM8KcIWWdfjTRtuPWDVedwr+eJo6zUM/Vy5LQWJ4yAz+hbSQ5+VPrb+4qu5sVR6SBy4XxY8EoPjlPfZr3AHce2XsqlduABEfQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G/kx8L1c; arc=none smtp.client-ip=74.125.231.205 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G/kx8L1c" Received: by mail-oi2-f13.google.com with SMTP id 5614622812f47-4c537df4daaso995123b6e.1 for ; Mon, 14 Sep 2026 14:10:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420218; x=1790025018; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+GbSlDHSjNPM9B5dSRFNO0YLnNdNTULtbcSEuiC7wJc=; b=G/kx8L1c4pN4ncVrVdEVAm2H6h86EGaLdaQjybD7kAaHOreWO+ArbwK7VEnChiWOMx HJ9u9nWXhmZVGQYCUHWwPiuASISw4sUOXAuDcjidnlxe11M0oZCGDaoXCXvr+9v3pSnv slGYd5a2TlnXU42zxcTXs8CJOA4vOh6ejoQdAlhM7FQVpCWCjtaHl2uYpuHrDZYQMV2L yO+8SDNqbWaJ1iMExsUWsN+UZvMyWYnGCmX9GR3lJJMn8N4MKl80XJPwry2DvHlL/jSs 579q39mGojyEi2G8vicUfsh09kveph9fTs4Q7n2btPsXxA7LezHASwANlBIw4hckD6G4 s8LQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420218; x=1790025018; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=+GbSlDHSjNPM9B5dSRFNO0YLnNdNTULtbcSEuiC7wJc=; b=TlRk581kFiL184AxmAxftNgiKDhDGp2mLeIoHewE+8rHcRpz9uXGM1dv7Yk1f0kLlL Q6H386S4x3BJMOZLZ5i1xuKDCYhtb/AvyxONflgHnqy0io1X9rNaZ770ZaC4JEnbOK0l Eb0A0MRUkV5QnaQQRNlc77YAp1LvXM5ovZBWSxF2UrjwPzlhPrXCwbCBa68D8GsgeUUR jnNjfGGrk/nbygTHweKBH7VofmWCR8sBEeqqVQ8QBMVssHebh+n5cyCPQ1OlrBSN5m1c lEoZ3vIKVX7EuhXjEuLqCjNhSAhJUTVsQFL61G39lGTOcZgdyCTMhSiZzthTLVdQfeA+ 7ipA== X-Forwarded-Encrypted: i=1; AKwUvByShm+mOXH9k0ibHQpBy8puH56Rxa0lMsMa7PmH+wwOWuGrNDgISvJCrtbecCG0tsgnZQyf4sIxByCsnVo=@vger.kernel.org X-Gm-Message-State: AFuF++ngR2PS3L8t0goRK/BKDJl2N0P/ctVlZPWN57NKpjYEOTiCg84r NraSPTxOv4jOCyuzqUcMZpvScvzKe805kRCZTfdnrECTWq1oqfeSy88Q X-Gm-Gg: AYBFou10EFplcuXU6ALLbI0TuvaMLhP/TlkftxUfGbvC/9Q/dRByKJnxx6KWC1tyM13 wZnEJEjAukjZ2d3fLPIPaR8ys+ix3+ctb8wbKjjAk16xdLdQz4pw/S7x9zPRHGscrMEEftBA9JZ sVLLzBBlkzoyxJGJrsm9o8yhA2j3ESPTnCoXlYIUWvYNi+XoqLIO8OweCQrsYgmm4RQSQfmAYty U4IQ5hVfmXPiw1/Gv++aK3PTr00XOkBIzbDBlT1R+qBHwX2/8CBj00xbo+p426HFqkjgiWl8KrK LhYUfJ21tEEQ+a8rQEno1kSVTEWDttDZIjFGtlnOkTLhjW0IlwGD3+p+FXzulEN/uXTYW7VXGbN bzuTuA65LQYmFrOHrjJU+GqfIiR8BrDlOA5xtfEGX7BIc4Yf6LiSy/ZtIf+GV54HY51V2gA33gd gMGQ00bBPeSaL/k9o/gWk/4OfCKdpnaKnX9FWcviB51VNiEbp26ZwFs8C866rufafC/OdOzZpCW PA5Ou9cypImb0rbzXTcKD0ACH5/QxqcaCZSNaQPRp8V+ckD8kdDWHj+pAB+4rDnpSlsLtA3cZx1 ePr9R2aQ00v76wBHVl36P3EmzDgCvrYyeBn61UpSnVC8WoG2l7LNiDREBxClE3qJlAmt1rpE2Xe gf8y+JGx733+UiQvYYWLczihZe1kY X-Received: by 2002:a05:6820:1893:b0:6b7:8396:f3e3 with SMTP id 006d021491bc7-6c542249981mr2544577eaf.69.1789420218531; Mon, 14 Sep 2026 14:10:18 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:18 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:10:03 -0600 Subject: [PATCH v6 17/18] mtd: rawnand: sunxi: reduce user-data length register accesses Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-17-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 DMA reads and writes clear every user-data length register and then read-modify-write one field at a time. Multiple ECC steps share each register, so this repeats MMIO accesses to the same words. Build each register value in memory and write it once, including zero lengths for unused slots. Reprogram every word for every DMA operation instead of caching hardware state, so controller resets and switches between chips need no special cache invalidation. Share the length encoding with a PIO-specific setter. PIO always uses hardware slot zero, and its page callbacks clear all length registers before the chunk loop. Write the slot-zero value directly instead of reading and modifying the same register for every chunk. Keep the per-operation clearing so other slots remain zero after DMA fallback. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 75 +++++++++++++++++++++++++----------= ---- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 773ba55ecc07..41d6ef31ea3d 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1013,35 +1013,60 @@ static void sunxi_nfc_reset_user_data_len(struct su= nxi_nfc *nfc) writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i)); } =20 -static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int hw_step) +static int sunxi_nfc_user_data_len_code(struct sunxi_nfc *nfc, int len) { - bool found =3D false; - u32 val; int i; =20 + for (i =3D 0; i < nfc->caps->nuser_data_tab; i++) { + if (len =3D=3D nfc->caps->user_data_len_tab[i]) + return i; + } + + dev_warn(nfc->dev, "Unsupported length for user data reg: %d\n", len); + return -EINVAL; +} + +static void sunxi_nfc_set_user_data_len_pio(struct sunxi_nfc *nfc, int len) +{ + int code; + /* not all SoCs have this register */ if (!nfc->caps->reg_user_data_len) return; =20 - for (i =3D 0; i < nfc->caps->nuser_data_tab; i++) { - if (len =3D=3D nfc->caps->user_data_len_tab[i]) { - found =3D true; - break; - } - } - - if (!found) { - dev_warn(nfc->dev, - "Unsupported length for user data reg: %d\n", len); + code =3D sunxi_nfc_user_data_len_code(nfc, len); + if (code < 0) return; - } =20 - val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); + /* PIO uses slot zero; the page callback clears all other slots. */ + writel(FIELD_PREP(NFC_USER_DATA_LEN_MSK(0), code), + nfc->regs + NFC_REG_USER_DATA_LEN(nfc, 0)); +} + +static void sunxi_nfc_set_user_data_len_dma(struct nand_chip *nand, + int first_step, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + int first, step, len, code; + u32 val; + + if (!nfc->caps->reg_user_data_len) + return; =20 - val &=3D ~NFC_USER_DATA_LEN_MSK(hw_step); - val |=3D field_prep(NFC_USER_DATA_LEN_MSK(hw_step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); + /* Write each packed register once, including zeroes for unused slots. */ + for (first =3D 0; first < nfc->caps->max_ecc_steps; + first +=3D NFC_REG_USER_DATA_LEN_CAPACITY) { + val =3D 0; + for (step =3D first; step < nchunks && + step < first + NFC_REG_USER_DATA_LEN_CAPACITY; step++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, first_step + step); + code =3D sunxi_nfc_user_data_len_code(nfc, len); + if (code >=3D 0) + val |=3D field_prep(NFC_USER_DATA_LEN_MSK(step), code); + } + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, first)); + } } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, @@ -1237,7 +1262,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); + sunxi_nfc_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -1554,10 +1579,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct na= nd_chip *nand, u8 *buf, return ret; =20 sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_reset_user_data_len(nfc); - for (i =3D 0; i < nchunks; i++) - sunxi_nfc_set_user_data_len(nfc, - sunxi_nfc_user_data_sz(sunxi_nand, first_step + i), i); + sunxi_nfc_set_user_data_len_dma(nand, first_step, nchunks); /* exec_op() restores the page's spare base during column changes. */ if (first_step) writel(mtd->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, first_step= ), @@ -1747,7 +1769,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); + sunxi_nfc_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); =20 @@ -2051,7 +2073,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, goto pio_fallback; } =20 - sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len_dma(nand, first_step, batch_steps); for (i =3D first_step; i < first_step + batch_steps; i++) { unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); @@ -2059,7 +2081,6 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, =20 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i - first_step); reg_index +=3D user_data_sz / 4; } =20 --=20 2.53.0 From nobody Fri Sep 25 09:22:44 2026 Received: from mail-oo1-f51.google.com (mail-oo1-f51.google.com [209.85.161.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E29E4A3F21 for ; Mon, 14 Sep 2026 21:10:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420231; cv=none; b=DMii4NUIt/n27XFbVROfbGnUzGSlVgTUfesslneX5iTSF8XtRV+Spu2TgpGSP1aWGgt0ZqU9o6mNrBg608/2GjY0rM4WqUqre6wC8GBmWvun2lNmR9VJkB+6UNDvDfoIqf40H00tqMUAfG0ThAlqzGw8ir23TMLdjGRDXzKLxYc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789420231; c=relaxed/simple; bh=4xHXBQvwmVz0oonK9wMD8Zxqf2blrn3tsTPZp69gKzE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NuvsQKkw00sz8mVqRzZcJtvR9V+FNJ2Zq1EohuNo3og//AwpJRglPitAXEFNQofEGlcGkuKOs1tZ3fDzwhohpvbh1aUHnPGPHU2RPgoW6C9TeDf/QtVDlidGNYwnbENLxkeGTWj1we2SycZHi03qosKVralj8R66cnzJoK1Meys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=pvHkQM6l; arc=none smtp.client-ip=209.85.161.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pvHkQM6l" Received: by mail-oo1-f51.google.com with SMTP id 006d021491bc7-6c20a9c464fso2484155eaf.0 for ; Mon, 14 Sep 2026 14:10:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789420220; x=1790025020; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=eqAKP8KvklWhrAanMl0NJZL0/+j+O7CDNjnmlHeKJxw=; b=pvHkQM6lEGsfDdDCNkizMdllXXAKs0/n9za3WSDfZeVs6pmHPr+hfHXzYYPb0vjGZn G0ZhUWdLY3tHyk2xiZwb8tr4ilIoVXtpid7fYiuSrHYvpdgA58vlE56Zv95wkCYw8pp/ MNJFYJyHdsQUoG8rsq/QMCQby1draNmqxcrpYuP8p933Mz5cK0Bg3ujqWLJ0CBvI8Sxj M5CdcCw4qGtvM+E4jJDTwOA7zZ2rLpMRqMrKauTQRekkVibbNNGIdMPWinPidBgWiT1y uNXJ/NYwpsqPghkZlRmujwmIAu4QkXUmlnvorCJwyKPyTxKoL1CwSS+HHhAaPBesq8Qp opZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789420220; x=1790025020; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=eqAKP8KvklWhrAanMl0NJZL0/+j+O7CDNjnmlHeKJxw=; b=tWX9bLCigEt6n4/Z+2TbWZJO6PZ6Kupu9uhuBXUZXCLXMctg5wfGlKegN9ZfJ1unCc n4lyLyOMY1esbh4AS/34Hn3O3X7GeOlKg1CVEns0FtRx8RsRZgcXg+GoQhDzn5Ls0NLT lFfWzZzzfINvdnYhAK4BG7/fXfHesDp1kCk9RiCNDufPf13jrQL0pN9ECeSk+VQbtlOg XWIiD5g3JW7uuFUF7gXqKms/mszkY1/ZNKtHpOCVlpxh7NLvdMrvXdPySnZzoDgPamiY 92ArGsygHcTRMX19QHRa1v5mjZadvqk5p9hSJoF+a9MwjUhZbNNaNbwgd7pnoY8FcX6t 83eg== X-Forwarded-Encrypted: i=1; AKwUvBwX7wyhHxDKG+MQDSIp3PR9cmPbxOLB/BTLg3M8Kino6Qhgzd3Mt93CHMp4UbCyo2uHkXmgJvs3Ep6HMpc=@vger.kernel.org X-Gm-Message-State: AFuF++mnyI849ezANVxjiUhRbLQD/KeQ+Z3BZfRsieQlPSDZTT6Ys4ou goEhtgSUgmdnfujH73jcLoCBOD8aFQk6Km0h0p7CND56Gak0fLSqu9Yh X-Gm-Gg: AYBFou0TpEZGuqmoCbwCeaGbUUOuToO0BuwLGhXdSIxfhXLwvYpXdJgDcvjKiVvhZX5 ejjEoIffot5PTr4iiPpNMFc02MrCzGT4K8dpEOHejaEai1dfi6BWdfIBqyJqPr6WlrylIRoVD5G 2In+phhH63ZBorCRptCCJHcRuTCi3ub1pRlcOk83Rk7WnrJirq8Ro65SSOWdsI6POIRqeoD8drq 3rBJAcRUEELKgtxhO/GYiLCKxZyij6u1HFvw80gX+t5cZPKumCk2ruS+E0GfHHbeTb+OI7XTGCY ua3Jma25ZFXHQmEJAtfeYe84McZDMJ2T7y6+M+7yvp/XN2mfpLjtLpLtdGQ5IbjEZMQVcxLVpxe KZVhaeRg3x9LgEKiYm7Ntn5l5z+hoznssqCrV7HDG570t5X8+GP6K6geD6kMobALWE2mrRovgzf cFAjnV+aZUi0ZDTJv0vR/IkdB/qUQhRhKvpOKW+99J0klcZgIKxEctpofIYkWIYT3Jr4yhq4fA1 lVhU2qlDsebIYPBfGjdtz1xUcU3myVzakyS7xNjjYstKyV3o6gvgmIDFA9qvmxOGX5/fTFHx89O HkPsCfeFkF0G5hwCTfcwDtOEexYpdJR+El3nHa1Jf+RsVY8gKu8irO4mKMrjogeqNPCAUYSifdh tI754BffMlj2NLLJ6FCaF3mO4kuNH X-Received: by 2002:a05:6820:1628:b0:6b8:ef7d:e181 with SMTP id 006d021491bc7-6c544daaf8cmr2777294eaf.54.1789420219820; Mon, 14 Sep 2026 14:10:19 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6c45bfc3fe9sm4698544eaf.15.2026.09.14.14.10.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 14:10:19 -0700 (PDT) From: James Hilliard Date: Mon, 14 Sep 2026 15:10:04 -0600 Subject: [PATCH v6 18/18] mtd: rawnand: sunxi: reuse ECC status within each DMA read Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-18-2fb084fe0751@gmail.com> References: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> In-Reply-To: <20260914-submit-sunxi-nand-vendor-oob-layout-v1-v6-0-2fb084fe0751@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The DMA completion loop reads the pattern ID repeatedly and reads the same packed error-counter word for each of its four ECC steps. Snapshot the completed operation status and pattern ID, and retain the last counter word while visiting consecutive DMA steps. Read counters only for steps which use them. Reuse the shared status register value on older controllers which place the pattern flags in its upper half. Keep the existing error and pattern priority in both the plain-marker and randomized-format paths. Start a fresh snapshot after every PIO ECC operation so reuse of hardware slot zero cannot reuse status from a previous step. The snapshot is local to one callback and does not survive controller resets or DMA-to-PIO retries. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 103 +++++++++++++++++++++++++---------= ---- 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 41d6ef31ea3d..b79bf13f3ff0 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1157,16 +1157,60 @@ struct sunxi_nfc_ecc_status { unsigned int max_bitflips; }; =20 +struct sunxi_nfc_ecc_snapshot { + u32 status; + u32 pattern_found; + u32 pattern_id; + u32 count_reg; + u32 count; +}; + +static void sunxi_nfc_hw_ecc_read_status(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot) +{ + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 pattern_found; + + pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); + snapshot->pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern= _found); + if (nfc->caps->reg_pat_found =3D=3D NFC_REG_ECC_ST) + snapshot->status =3D pattern_found; + else + snapshot->status =3D readl(nfc->regs + NFC_REG_ECC_ST); + snapshot->pattern_id =3D 0; + if (snapshot->pattern_found && + (to_sunxi_nand(nand)->randomized_oob || + (snapshot->pattern_found & ~snapshot->status))) + snapshot->pattern_id =3D readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + /* A new operation, including every PIO step, invalidates the count word.= */ + snapshot->count_reg =3D ~0U; +} + +static unsigned int +sunxi_nfc_hw_ecc_read_count(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot, int hw_step) +{ + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 reg =3D NFC_REG_ECC_ERR_CNT(nfc, hw_step); + + /* Four consecutive DMA steps share one error-counter register. */ + if (snapshot->count_reg !=3D reg) { + snapshot->count =3D readl(nfc->regs + reg); + snapshot->count_reg =3D reg; + } + + return NFC_ECC_ERR_CNT(hw_step, snapshot->count); +} + static void sunxi_nfc_hw_ecc_record_status(struct nand_chip *nand, struct sunxi_nfc_ecc_status *result, - int logical_step, int hw_step, u32 status, - u32 pattern_found) + int logical_step, int hw_step, + struct sunxi_nfc_ecc_snapshot *snapshot) { - struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); u32 count; =20 - if ((pattern_found & BIT(hw_step)) && - !(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step))) + if ((snapshot->pattern_found & BIT(hw_step)) && + !(snapshot->pattern_id & BIT(hw_step))) result->zero_steps |=3D BIT(logical_step); =20 /* @@ -1174,35 +1218,32 @@ static void sunxi_nfc_hw_ecc_record_status(struct n= and_chip *nand, * Classify these steps with the vendor page check too, and do not use * their correction counters. Keep their decoded data until then. */ - if ((status & NFC_ECC_ERR(hw_step)) || - (pattern_found & BIT(hw_step))) { + if ((snapshot->status & NFC_ECC_ERR(hw_step)) || + (snapshot->pattern_found & BIT(hw_step))) { result->error_steps |=3D BIT(logical_step); return; } =20 - count =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); - count =3D NFC_ECC_ERR_CNT(hw_step, count); + count =3D sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); result->corrected +=3D count; result->max_bitflips =3D max(result->max_bitflips, count); } =20 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, - int hw_step, u32 status, u32 pattern_found, + int hw_step, struct sunxi_nfc_ecc_snapshot *snapshot, unsigned int user_data_sz, bool *erased) { - struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - u32 tmp; =20 *erased =3D false; =20 - if (status & NFC_ECC_ERR(hw_step)) + if (snapshot->status & NFC_ECC_ERR(hw_step)) return -EBADMSG; =20 - if (pattern_found & BIT(hw_step)) { + if (snapshot->pattern_found & BIT(hw_step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step)))) { + if (unlikely(!(snapshot->pattern_id & BIT(hw_step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; @@ -1218,9 +1259,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, return 0; } =20 - tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); - - return NFC_ECC_ERR_CNT(hw_step, tmp); + return sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); } =20 static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, @@ -1235,7 +1274,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - u32 pattern_found; + struct sunxi_nfc_ecc_snapshot snapshot; bool bbm =3D !logical_step; bool erased; int ret, bitflips; @@ -1275,13 +1314,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, =20 *cur_off =3D oob_off + ecc->bytes + user_data_sz; =20 - pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); =20 if (sunxi_nand->randomized_oob) { sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, hw_step, - readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found); + &snapshot); memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); @@ -1289,8 +1326,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, } =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, - hw_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, user_data_sz, &erased); + hw_step, &snapshot, user_data_sz, &erased); if (erased) return 1; =20 @@ -1555,11 +1591,12 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct n= and_chip *nand, u8 *buf, struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nfc_ecc_snapshot snapshot; unsigned int reg_index =3D 0, user_data_sz; unsigned int max_bitflips =3D 0; int ret, i; struct scatterlist sg; - u32 status, pattern_found, wait; + u32 wait; =20 if (first_step) { ret =3D sunxi_nfc_read_column(nand, page, first_step * ecc->size, @@ -1612,9 +1649,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, if (ret) return ret; =20 - status =3D readl(nfc->regs + NFC_REG_ECC_ST); - pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); =20 for (i =3D 0; i < nchunks; i++, reg_index +=3D user_data_sz / 4) { int logical_step =3D first_step + i; @@ -1628,8 +1663,8 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_step); =20 if (sunxi_nand->randomized_oob) { - sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, i, status, - pattern_found); + sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, i, + &snapshot); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !logical_step, page, user_data_sz); continue; @@ -1637,7 +1672,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, - i, status, pattern_found, + i, &snapshot, user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ @@ -1664,7 +1699,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, if (sunxi_nand->randomized_oob) return 0; =20 - if (status & NFC_ECC_ERR_MSK(nfc)) { + if (snapshot.status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int logical_step =3D first_step + i; int data_off =3D logical_step * ecc->size; @@ -1672,7 +1707,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nan= d_chip *nand, u8 *buf, u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 - if (!(status & NFC_ECC_ERR(i))) + if (!(snapshot.status & NFC_ECC_ERR(i))) continue; =20 user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_step); --=20 2.53.0