From nobody Fri Sep 25 11:08:09 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 8298226A0A7 for ; Mon, 14 Sep 2026 03:01:39 +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=1789354903; cv=none; b=ePY6gjOhHl3/ns3+iuQ8WyPEIqBRyzBOY7XtBikZdqBZd5uSXJopbNoKnu9TNIoQPGco0R1CGMLdUVYKiYsfCEmlAsZ2YsEj7b+ODK3ZkLQM6qL+farJVOLbZfVgBAvT+nYInmV/JxcKUXnmv5f4WgSQWmz6iWoV1B/HP7yOBA8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354903; c=relaxed/simple; bh=Lpu8BYiYZNteYXFlDSxlBr4C2CnU/Gx0SiTFgcn6nP0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pW+a8ljyTNdIh7y2bScqoH9kF347OddognNxWOEF18dixUbb7xWs5vMRs/FOnFgW6kW9lCDfggXTJDDA1dT2n0RFmXL5nvQHTv5BU3wq608jCJr0RMP7qAVDN/wX/6fVBQm6z0/Fh0ADKazR0ayVDE38kJWrucBBm2IlCu37W7E= 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=XboecROT; 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="XboecROT" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-7f4f0d298ccso453882a34.3 for ; Sun, 13 Sep 2026 20:01:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354898; x=1789959698; 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=XboecROTiiF/twGa3ijeSfV3GI9qYzxHiizXpeYKaNNYEozshQN7YpoqR5QuZyHp9F qGjRb7Cm7TW/45XLJnHDpXnEJ6dSxml+ZFo0J/I9uQ4Sl1CcCuLMWho3zR2Nr4gexS5r ILu6960jwe1ayy+QyledRYw6OomzOGjE3ic/3nlNgHcjMkeKEvoAwV0A2A7dNmJpFsOk 14QyoLMQwEfJ7pMYl363Wm+j+FITaeQF/jXNESG8H4Nuqo69HV/Q0sV2NtsZUotLTI+L chFPWHoDlN2JdgQY+RUjlrQMCAp7FFTYufJGeo9FmYtoDW4pnO2TUQV+jYgutLiHqJQf X//w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354898; x=1789959698; 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=a9WgkTQsA6j30wYpDFs8OdbhM7NV4fJ2cDaTmDvwgHA8cU4a0MZuOjXYeLyZwdTFuY hKhVLZVEoshUfai9jo2ODbtSBtiGUsVkbkYtZz/bKQnEMesbQ6rjuzDwXNRaP3pzPQRm aZF6I0gZe8nj9Hzt7ro2mMOQ3yAl9x6zjbiVrjh6ztJXk1JnqzUPukUc0HmIwiJ70wB4 RbUHD6YWWHmyWtofwyGIALqg4qFrsZVI0TpSKXnaLMnqUV5VeexFxJ/pRJAlPsUI56fM M9RIldIyC59cMvcUwmzI0EmNFmKcMaDPiWYUWyIisN/NySV0KokjHW28jst8cEFRD/0J 4yKQ== X-Forwarded-Encrypted: i=1; AKwUvBxTLwkvKyGLwLDzE5yPa6/ypzqDV+6HJuQpOhqp/pUum/9umn3VEpJXf3Zrgb0oIlZZ58HsFvBdmONTyto=@vger.kernel.org X-Gm-Message-State: AFuF++miSNBvi6oC2l5xGqkJurvAZ5aUJNFAZf3Rp01QHzc3EPu/zHj3 1GpgVxejDgSe2yVWUrDztGuYCAb4S3yFg6Zl88pDXD5nnR3ldKCWjD2q X-Gm-Gg: AYBFou3SWSAjF/Q8vp1GT8Y8k8NedbjYU198MQl72mrDrNzYIroLP9sCwapdPazjDjg HkvpNed8SUxi/1A6+LLn+peere7116cwpq1v6Uk025BRSjPq4cPJI4tBS2AK8Rrw5lZ+VKH9PXe 195eyNx/U0CmX/lBbMie1kOxFGMbTuPv+auLr2OEFgIVPS50WR/XqIwIEbLWhgNST4OjusmA7eL DoLqX0XRdUUY+jMure/NIRbjpRjcRee0zuvyIQx2DntnSvEvLsBIKArYirBToalTnIFFPLYyFf8 Ea7Oq+0soNe+lmfIeSqrr3Ec6TQDcpJsDc1GXfbuxOfxbnRCnzPjTFmPAVAHS+XRTzgp8Lk4aL6 KIHieix/cv/72uRBr9bXA0qgjzTTK/rKw2oNDYfur95SJKEKrc4nrG20WEgBI2w2ObR+dJjvAP3 ct8i2m2gjWTS1H2tkFVs7nqmapFFfKAlomMpQxorfNOANK8q1q+LDuUPF2eZxbIzzFORDF9ctrd pSe3iwYntJwJ23ZmTh8ymXJoc4hZJOT92dJ3PG5zOC+Bk/kipLbJbvY/iJ4FmqsDzSThL2ND+jo 3oDltehIEalTwjeJ06auM0hfQJ3Bcu1zGxTl23eH2fjTnldcJgFpuuc5TlvoGX+c0PzqwPLu7Tr WfPxeah56EW3ERbqVNaL+BVNZNxHQX79QfqqUJO2V X-Received: by 2002:a05:6830:81fb:b0:7fb:547f:98bc with SMTP id 46e09a7af769-80897394cd9mr261168a34.5.1789354898430; Sun, 13 Sep 2026 20:01:38 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:37 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:07 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-1-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 BD9B833263B for ; Mon, 14 Sep 2026 03:01:40 +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=1789354903; cv=none; b=hbl3D1oTkr0vbqMY3b6rNBLxQ7bRq72hg/xo7I6e+oQXQPj7dOC10vsNo5aqbZravbaRKC/TLkPESQf1oxNorxQ3qxuqrBZ/MnUZkHBwCfJiQK/Zobok6iwr/TXAzd0QGRmprlo58LUTbtvoon3MfC6M4hKdUdmlpshQcErTd5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354903; c=relaxed/simple; bh=QNBt+pFeHHzCr6qyz6aRzEV+o3fccMFb5SqOxfos0lA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aUQgNbIF8Rnaq3S/pj84zTPqGeCElQcxtl2GzTOYNHGf5N4wVULf422xGRRL18rcud1aJ7lfIZ/7zXJIIGh53YMPl/EdyFTrJK5Vkq+FnoLLqcv/cvePXvEufE97GMlGYenV3Sh6wYzhZM1DKxJnwvptRmRpSY68V9KKBeJkgLs= 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=OAICENZa; 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="OAICENZa" Received: by mail-oo2-f40.google.com with SMTP id 46e09a7af769-805c194bc92so1207133a34.1 for ; Sun, 13 Sep 2026 20:01:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354900; x=1789959700; 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=OAICENZaoz4K0XlI/9aBA/4R/RD9KIJnyHqDRASJd552gvF6fPZczws7IuPc1IrqFN VV0r1dUjZFUgKOnyrmjg1bnjeVv1zbONy/0iBWfgh4EliM+VP1h9V9czGMgSAcqLJXgj /l6xLzYgA7NUKiWYys11WKreaTYL8zK2bSzIm4Cv69scg5bemO0DJ8KJbN1Ar/G0xOst rgnC0ZG7HInJEJWaFyBr9tJxz0NaJePRfi+MjKRmBSgJcy4jUyxRVWS5q5rOouDYI4Qs +7c5DA0LqYs+94GZ5VMcaY6PQHgEK9WrUQJIBkg9sLY4PAxSWY+Eb/RvgylXWsK6agkQ 45pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354900; x=1789959700; 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=ss+IEwCew1PQTwjVmMX22VAHAzjNIDf0/pfz9e9ND08IOVw6JpCluhZY7TKEWftZFr MnmxZ+3oDKsbvKd7Se3zYquVJ71ox32IiWJbuCpUehquLhSv0gdKmnJDSd1Oy4F8ljVp RKHPUkRqriWIsasSqgfeS/ocFeuXqgf+pjXpRjX0+fjdzhZaGCjRnfA7aw9F/rMOw8gY 78dk7lsG2l0O6d1G9nVizaqsB3cj0zSRNxXzjlDCGsw+37zXRL+nm+dW7qfEwft1c+RZ B+mVOqxZu11dflsfe8mLsHyQYJzfZsvoYRrNk0qsbexI0pZTdYjme0d7Me/WbkAV8ccX gdnA== X-Forwarded-Encrypted: i=1; AKwUvBwY+Uocd57hlacjuPTuUppErbi60R626DA2ycwZoDeQUE146AWGQSyWgkqZvZ/PapN4SCYb9xpGDHZ0BoQ=@vger.kernel.org X-Gm-Message-State: AFuF++ngVQizYy6LIKPYjcsHekLPWDmCbh+YzVa0GgvGb0H2b5b2d00R l/s+fU+xv98yGnOV72QiritIgFgHM2oFvNM3q4Raz8LYAW1D66anNOcq X-Gm-Gg: AYBFou1ZQJAGcZtS2dcLx8PQ5VbhpujEpg3CSmpYS6vYsE4bwcG+4AVbdtW+0jBWiLB rFDX3GxyFfQ9NkUjF2CSdXZCENTIoczDkQrBkAik8QUDXj66N3gmmLBrMI8QLD8roa8T3CLPm9Z ym8eSoJtwkWI6PIZT55/J8+tWgqKwpQ9/uti3yXuxYSL9AdV8AcdG/GDf+PT0sTFKTukJGYAe8v bUG6GfNiztVHDjIM9sSQ3xpvO4fd/q0xK7Y3XcbYDXqLvl5Y3UuzvKdFnNOHDw7bjVb2XHLoFDb xaRFigBOxW0WumYI9cbf1fmT4KNU6WSO7/jU4yJ/j3SbrTt2bMBHc04PtOk8I3JE+hE9fd+lnMT Ic6DULhX2Z7M8YTvwVpQnP7qTSf+Bthd3VGLHlAuxK2lTWyfiL+dDzkdlZ0AaTI7AhYNmL/HYhh YR102bTb4iyz98omy3hyvcChwZbWYxXfISaFPAjPxtVtXg2Jz/nItfDe5zSN+/ZZJnFC/2grI69 Ny8n03rEg4kEip8ZoTHedDsRI44YWjZ4Dp7jPN6L1W/e+PWfsJXPrrw7qAsgiIoov23Tr9PS8Ew /ngRCejn8CLo0lzKlwkaJnYzdgyoBUPFCZXYQS2PtFq8n/E2w3nTMLmvZo9uxos42C5v45EgoJI IfSfoFDBLzIC11jX+Npeb5m3xXaSoaBU= X-Received: by 2002:a05:6830:3892:b0:7f8:4ac8:bd2a with SMTP id 46e09a7af769-80899a529a4mr493322a34.12.1789354899758; Sun, 13 Sep 2026 20:01:39 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:39 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:08 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-2-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 883DF334C05 for ; Mon, 14 Sep 2026 03:01:42 +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=1789354905; cv=none; b=lg2QdRM8x3ck6V6DVvocfzGnvbQW0Nz40EiH96hog0mBkZqltR5ANamOxpb3gsJIKc68AkUvbBwjFtDMKJ2QaiLhdKNFZxSt2GRQSbrRsNrnNo+iPQGVSsoptaEI0YvKWO2v/BSQXYVPrAvr+FMDlOBE4YH4LCL0PDfu0diZzYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354905; c=relaxed/simple; bh=sEgsacOGRde9P8OKLBN0PM1Bqnp+ZYDx65EvzcaNGcA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jUVHjjq7dPKkLxo+wymwVHUxlK1cYkTOT7FWHUQ7EaUo44zQ+CIb2fS6QtLvgUK5JKXvaGxL4c3GTnw/JNl6yMbqitHGeqqmS+sCFutEGcc0uLFs/su6JcTf9UqwOE8wPe4LSPNCGlE2Kj3UA3L57du5FzopDxS0KqYK5uabRow= 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=OmvPd/F7; 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="OmvPd/F7" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-804f7045f3eso379659a34.2 for ; Sun, 13 Sep 2026 20:01:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354901; x=1789959701; 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=OmvPd/F7fcFX05wMoexYsEBE09q0SuxLYbTphk+jC5Po967Jyeg3e8C6HOmsYJF9vI PMrL49ll7AyvLg9c1ReAIW2rgrQPYkUdE5+lbff5Zkt8TQZriJfJJ4hWHwvCb5UbkLq3 Um3KnqgsZU5WOBc5KpoY6QBtgfBwLuqYgohiICYo5Ybvd9TTsDn+36cQTRY2FGbK+5oK bswlYufuuMaGcQopHjWn9o+4vxaryjaePLvy0LYGl6ox0MCDNnwPJKJY24yuH6YeE4F9 f4jrG7mTl1oCghOJ6TzfPYoMb8PFRct2SVrj0CZ9q1M/zT7R/UTJGxl7mghCPW8hxpq8 9zQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354901; x=1789959701; 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=E2D2gtQMxZxCwYyU2n69F54gcUEnrj+Lqs7QsdEwdG7zFidES3Ji6wi7ej5JL5HNfc H7WPKFokcpGxnVZkREwGmtSTUrZj9sDhBS/WQ0Ykxl9ahNX+Oc+DkGm304T/JNpthY1C f2Cfl7BVqTtUxoHNLwEYazpCs3XWkB5SFWBnGOknDFf/2nkF7yp0SbQeGHGMDAp54+1A EJQw6PSNqv+lateGWr3ChUAvXfF2X4ZPyM2kgRaEdEOWLctgPiTNR0o0ZqG9exlFmZJO VqJM+RgwI7QJWRLflomeg/AX/qIcOxCEpyBpRrTwzVe5Rzhh2Cax2Xqndr8r/W1uOiPh bwhQ== X-Forwarded-Encrypted: i=1; AKwUvBzzyilX5f6dPYm1yDCR7QuEF008j8VaAS0OYu9vQh1jlCsnAi4mhsmlKUSqtignIrJa/7VQkICgNWWyETU=@vger.kernel.org X-Gm-Message-State: AFuF++l4q62BW1fkAhiXChcdJ7nFjpLeCKpqv6VXoadDSfUkorTcBHuG Wmmik46lu73zL5Bwbai128Gmmmh6gYAXg//oeoZpDLMCtHH8Au9QfBHC X-Gm-Gg: AYBFou3b9Kznb95W/2NZIBwtCcCt1Y4Ts67NTMmAyhh9Kcv4bvoACAVLeF/yvtuji4s 2axf1p9AE233J5ahjZILfILwPJ+og1Dq0nuGlHdDUcyajUPU78+bjFqSBUwEgmujD5wYUfgADeB Q2UNa7qofbNelotTQrMovMqsFnbeyeFTel4Pj0yV9atQgW6HCagnngXp7SJ2I1r0hsSjO0jGCXB 10EIBJRBLJnKxXJv6BF6LBMT4y43aPACRVYrqSNj9C7Aq8rCyjkbxwCgO5se4Av8pEe+bLHCqVx BdVkXr7capDj2KUQrxVtbFHlkx++3aZSDwhPR+70WzO558+LA2RJfGrMAPPPv/iYeFFcIFqkyH2 LQaJs2n7b05zVvfUXwTHJiX+U7Z6Ebe6dr+j2TuSjzZFcHNMTdR7ha9UIirUhsboNJ4jdT+jHPF niCuWPV4VsAv/WS1lfDQl/E3uOwRiCvzbXN8g0mFz+21mUA/6DVqe03760I/3sSmFCqrd4lMBsz MLMZq/ygSbHG2G39+jcGxAurSd+ao1ZeKI+0LfEn7aPYLrvWyE8c75wxEFMPEYlbRsy7iGxhQVA JzTpvvdD939tBK6jsg36T53uvuQnKj+qpsOFx/O7MuolZSsDrE5El3Ol3nfxiPjPLPvzyvsaScj 0wkNI+hr/5jWK9TNOE6lqkfaSSbfeVw== X-Received: by 2002:a05:6830:2a8f:b0:802:68c:1b51 with SMTP id 46e09a7af769-8089798d600mr284960a34.11.1789354901016; Sun, 13 Sep 2026 20:01:41 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:40 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:09 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-3-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 AC68B33D6F0 for ; Mon, 14 Sep 2026 03:01:44 +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=1789354907; cv=none; b=QBlWSnhF/MXS38a3Hvh9uu7kmzs8hVY+2ZnDd1iuFRuVyDoOECYRbg7ohTM0tnMjabBgREDVdvfiQlk5cQvP/REDvkkpRx+yyrlVc2YrDQhd0W4T3dCRAUt02uhwtxeoaOulfPCPEcTDtyfVJJxCoUStwHJeV0r0+HxJAT0jfwU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354907; c=relaxed/simple; bh=NlWMHvWo8eC8a5062ul0UGSwTs8Firq1Hsg3xcZzp2E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hkH3bIHs/Amx/Wcy6Cnu2Ql0qkPH4cDnnIltQjGK4IPf87GLt5EAPrKNjInSo2oqpo8o+ZjcwvbgzbnQ1Yp59RoeMVXzjeM1+s7Ih7fl4+i5F6z54SfZ/udkHUva8TvHmCDC25IXjJPUucOHOTpkDlnkE+cxEIJiieMIk3pu+4I= 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=GSOS9ipV; 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="GSOS9ipV" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-8050801d337so1103174a34.2 for ; Sun, 13 Sep 2026 20:01:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354903; x=1789959703; 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=GSOS9ipVsEkoWjZwrv4Y7Z/wqjFeIMJ14k4zhVlTUwlhCjW+GUWwXbbLQLkqK+jCJt xu+HfbM12yhTxmsSzrMDop//Vgs5QIobkOJiA9OUcu577xBbxJ0KQAGBZ153dijUrDZ0 B2JDz2a3Jk/fhX0eLhCIbPUaZjTGhGcB/9wOnpECEPv5AE6f4HlcIH9kixmZopCAEFyt 6RojfNE0tmdl3Q/40Ebv/07dhVXf3hJ+04U3jl15iYY7FvwgzZNoXGLzZBgEoV9vYJtl YVn++5JAiryUwIVQOQ7dKa7HMXTo4a1KtSHEF6BTpbKRaaM1my2oMOae6ogpAMrm4GRC cCLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354903; x=1789959703; 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=i8s+X6vhQFK9J+c8lSr3Du3/jTQmxdEcTJ0suh5/yPU3WxcHI9QbpJuhmZYROa8/PJ TCGgqFTQCGezrXldkHa0P0csFNubPlQ4vdX96Bvpx91XSVDiOa2wcSHZkUPgx6dfc55+ 0AC2gNSTJvhgcqbRtnznDD8Wr7ZyUX0wwFB6sIM7qOzZxES9ykmBALsxS5r3btCuev8G HKAJm8Iocm1YWsWpPxVr6tauysF6v7V0VmL47EOGaTb2rO4FjaYUgDTmZwnuFXxIJwof ZzGYQU/lHoUFftaJB1U+FmGVSI7XYimS0we1Tf1f99r3QWNWSGd88yl6wVAPVrJG9oYJ AuDQ== X-Forwarded-Encrypted: i=1; AKwUvBziC9vSsDQi4U9GdirDTSk18upAPTS429KvPWPXTrvAEWb8furbewhb7rdInEOhVHfdwJ1BHygf+4G8tRc=@vger.kernel.org X-Gm-Message-State: AFuF++n6uZmbG09TY3Ry7Cs2nZB2VYqoMR+GCi8/qrY7cvI4dqQKOsws f0Os1oRMwuGKbXejwZL15CsB/L2x7QXtBUHoCFpL/ITVU6Q2HFr1EWAA X-Gm-Gg: AYBFou2+ZeVBEjcHXUjhbANP+qga3azyZipsslwORMugs/IP61k8+5pRsrhn8zJM83C +Ok7dnb1kXFhXAW6ZoSQLao5dWsRwxzvBgtmGi/KfdMfAnyx5zgdf4oeKY1PypKPs0pYy57ewS3 ytnXXxQAB0dM6jF2qtpawZXRTjY/NGGKjqhUxAHs/2nIMieHot7mO9HX2rQqxDbqyfAvhssmiMs 1cm0EsnhTRv9+gTSmNcsUUZFJA6JsJ8S5ViiBAVUmlqPed/RSZP6/dzr2l5Tf56RDJmrX6GCNNi oe0OPrdUVWgtUINlaOsRS8OUtwphigOacsfrPvLyoxLBR3P/YqEa0KfoOkNNFxTmpHrNkw2JRlx JeZoalEqss6jK61hef7YumL0s1zy268byc5RSAeqVwIa7J+rgO4YgiM3I4pJuktW1I1EXbKZJcW 0zNQ8weATHA3N5lY5FCaR574rxKOFb/QIYGutCe4bIOBLlAUPwxE7PJ0JDK1yofQtvU6Xrn+kjS 21dHBEfM6wJX8GnyChKAgPPVlijCDb/h/qXIHgPUcrDwmVj5Sfm7esciaowR/l/uFYiKZIykmBD Em5YnSeS1YswziqlOnkRe25iax9MjKELU50EeNKvKTMj2Kl2RvTwe5fU0X1pI3n+VpnVBgnUJeT foSRPGNENuz5cjfVJ5ShCKvCc6XUTPA== X-Received: by 2002:a05:6830:3894:b0:805:9f8b:bef8 with SMTP id 46e09a7af769-8089974baa0mr554382a34.14.1789354902809; Sun, 13 Sep 2026 20:01:42 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:42 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:10 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-4-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 C143B30D406 for ; Mon, 14 Sep 2026 03:01:46 +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=1789354909; cv=none; b=jWh5NO9blEXmogYWZwhX8/4gGEiqBmJVwSvYkRYGPn+NJR2ePoQznXiwu6QcGx+dKdR1VUhl2DfIOh1StKl6e3bvVITHrsi52dHzPoRQwyawQVsXyvuIWojpJosBUG/5VDBLoB0VGiOYOBV9ui5V3XiTluISMXfZ0KQ2GOehUV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354909; 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=poKE8MYrW+yhqDCfz4pwov/piSZhSj3QeyYQilUF/SqQdh3asq73KgqqH/0cn/0/G/l65EAgVk2bDUYW4WbS6ao5wI+jZI+yR6q8wyTgmArwrr9DNzHL6GLw/MImmL7bF/jfE+922xySZaO49pcqviBZimFLSTfO32Z7dHyHxN0= 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=nQaKRqXb; 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="nQaKRqXb" Received: by mail-oo2-f40.google.com with SMTP id 46e09a7af769-80527255583so409293a34.1 for ; Sun, 13 Sep 2026 20:01:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354904; x=1789959704; 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=nQaKRqXbxKrCQc5ucgj4RBajMhwEyd4ArqWujybyPQ/fOBf9SN8nXpEYDHp/B37Nh1 bagLBQRdqh60nS4c00hAkfKsBnjyynpSSqEOzh1wLOF9630KkPodJzMnYnRRxQe0lg1E /S07zC+83w1TieKGxLd+o1VBrYUCrfhO6ed82VlGNxepGHrgDtU8QcAoHekjJQ/ZE7eO ilrBPF9JB6GyhLT5iM2WV/wrfMT9EtBJVVbsKGxH/C4E145OtiDh2beJFQllTrq0/jD4 nG0GNCvpw3Ou8rFk+sLiq7Nss7H6NT76pdl8BN9LrhHLXz9n6C4fVRI92WuOFK+gPYqT VKXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354904; x=1789959704; 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=OO8ZuZG/MIYjca9EbuA0zSuECdr6nqYJL6ivro3lP0/kySjAk/dyrFygnNNQQLetPc AT2WApsrbkQaQYFaLCyH2jya+MQkmBJUXPH4bHgqBcMOU3eBMNLxPRBTYSy4hWK+zoSz qNP/IM8OmwOfUcTsWkOh9dBkEFTxJYHPKUhv0et8/Cc+hqbhYVHaNyZbuGrkJBqNAGnB daMjhqij6NVMqHFy344CCd++hc/ocm0dyAerShN7gJaJbde0JSxWJQ5FMxWPeXFtqTnf 4mj1fhvhw2AqeFvnVUQZdcnyIWVpMCpV+sChVWTCZBNQigCFJlzv8ENLo2eVPq68U3AP aSvQ== X-Forwarded-Encrypted: i=1; AKwUvBzAIpRhLGWOfGHHDtnxJ1hfyXTa3hueQ8N4CN3rIarlWY1tMx3Ird540t2Vn0tniLhSy/1eGo1zVNX4Ms4=@vger.kernel.org X-Gm-Message-State: AFuF++k1I9qSuXIBaeh5yOi6gtMlJ0g5/EGEQooSuBO2RHU1yG5Hnp1j EDuVzRZw0wYXrt6Uw6LPJ8dbS2OxFuEkIrB9HhjJHlo0Yx7AhTK84dCx X-Gm-Gg: AYBFou2TqWb8Z81NPy5y9WXd+6JYCTWTIHO/7Tl34zEaJz9avJ3M6+PqfMos3SyPMQg Y3O+E2cN1w4ZjCZp/8ChmkJSda/BfycmFYLTWZJ9YA/R+YPkaQB0yyzrm10YabDkVImFE7y/H+e xpkvK6dhEAc49QqSYJQFexackks4mVaOx86A+C1xMR7D+lnccWSsvBSlgr413lThk8c5e1IZfuU B6jEIk4+JH9ga1RLGRu9M0WykTgXxezgLX07BnvwzU4T7G/sFAGxeJ5wq1Qiabrr6R1BuCcSEKs t4NUen083NdLAOxT1Xzt5slPhp1VwMR4tVcPelAkZ0p+6F3wi4QxFdNFLmgezRg34HnmXDqfZS1 FDnJrj9onOSF1twfXg/DcX9h6xb/rOxRVGt28Pd8MbFvpumVdot87JVRAduh9lJOkSRK9a4HeRR 1+N6OdThuFxAklAfxpEeNHhzHZwvxR6hVqgEbBreohqec/1Y2zd+Nhv6NxPV4VIYvjJkfTjn8a9 cech7hGlV0gi+KPalQC/V3m+GCG9+FPHvWIDugHMEHMlOhwfVrU3GP7ws6Dp0HKZ4myv62mOfUW t3++wuIq6yg/KgbQHslTC6j+dPSK7q6YrDBXdlRm77Eqf4cDz8LAZMTSMpeOSa0xiFQ+RkOlvZR /uyBw67HBN2gYKd2I6SO2u1JWWOygfg== X-Received: by 2002:a05:6830:67d9:b0:7f4:eb76:8820 with SMTP id 46e09a7af769-80897e81b85mr306525a34.13.1789354904353; Sun, 13 Sep 2026 20:01:44 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:43 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:11 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-5-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 2026 Received: from mail-ot1-f49.google.com (mail-ot1-f49.google.com [209.85.210.49]) (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 E521B3382EC for ; Mon, 14 Sep 2026 03:01:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354911; cv=none; b=S4VEcc3CrzulUkSr8YY3Gc91TGVPhS4IL1QfHUPIqG2frezYG/8AYfESG9S0sWzn2P4ZBIRZxa/+0aKTN6XON1VsFLTVx2ERztz/apjbNTalXb9owLDk+tjijw0Qe+7s1Zcltk5KkWMdsGyAfxHpvhcoEWD32lhuVQs0N8N/Yko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354911; c=relaxed/simple; bh=QuwwqJoNNeFbRXCees1KSU/os0gxTVKzY6QPcLIi7JU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qv+Zzyx50FY7NSQXzYsfRtk+MBebFdIpmisqjBMi5wdjmRPMqg/9CbGcrVeTS90OacNai/S0Qkp4LW4XXhCNaHT6O04G+Rc1CwZp5+tQXh/aXmLpWdqocYzd3lBvbHxUSjuEP7qMNaq2zGFmxsPxUyDAIsAKpbg/KyfiIAMDylI= 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=ipd0HEMp; arc=none smtp.client-ip=209.85.210.49 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="ipd0HEMp" Received: by mail-ot1-f49.google.com with SMTP id 46e09a7af769-7f4e729368fso2938120a34.0 for ; Sun, 13 Sep 2026 20:01:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354906; x=1789959706; 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=ipd0HEMp+LaYBiL6cJ2/ZzxLz5Ee9DXf0RvAhQgZ+OBWRLcNOhx881bk8TnmnCpaab sfBc3zZevIup/XezsFBtEtAvEZH/W3myPA9t0QzymyAUfGSpASWfFsOIuc1uR2GBu2MK iyOZhxlor2NzDYUd9HPLyvXGXBSFlk8O8I96Pf67n5l+WhtOYOQ+zVfsoNthpYGWFd6z fB+eXN2bTjrMJZ7RugaikTsdU//yo56jvmuEmopa8jE2GOkFgVzxMQ1l3HSQEW250NO/ 5uO8TfKeaoJnESbFuC6iAGaVL7Vt1PaXMKZuMroy9A3V0/q5GUM3Un6ouhm1/RsPvSnx 296g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354906; x=1789959706; 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=Ts1xBMftZ1AiFVbgtURoubi1pVJZ3SwZ/NvukmyDRAtGEenH6bNkRSB55kriZHt1xi nIX28morjO7a7UD0RPdeCuaLA7UstKESuGEnC7gQZS12cbSeDWlb+k4tbymBO6sGTchC ioNkrrALCVaVJ7UVer46mbNFc7KhNMSDTiN43+NoK9YfnwUAmsVPxVvH4yKs8Vmqk8Re ufJLcgy3XmJYyvMjCwsQqx+5ch5NtAB4uDrwJLfjJwEEN57y2kPAEsuk6ecdFDRHIIqt QnjwVrTkPAj6fvrD0hT4siauS4ApbgVYwTxpDPujiYH57yj0JXHKOgWIl2duUhWO4+nW 3eug== X-Forwarded-Encrypted: i=1; AKwUvBwqn1tswSwZhniyY5HSqAUS639BBul9omuIxUTIIX77AScsLqe0wBgcayBtDYeGOlDMoDf8l6Ct9YzMNaI=@vger.kernel.org X-Gm-Message-State: AFuF++lAx5LXvW73x0RSMg5fxpe+/IdDMx7k5IV1LRFSIH/U8r24hJVv Mfjx2B8pwwsnq65aQHT1HkpnXen+wL9PWLz/0n60SAMFd94rNh6urtms X-Gm-Gg: AYBFou1PlyKn6KTJBFtSk4WEJbslD9b5QG7+SIriJ8JKlrR1k1p99f7RauTsuqnTSgn 4kyKnrOy2fp58p/Wzeoqc1YbHk3I/DGUT1Iz2RiohBusivegmeRpAYe3RhC4aTUrahOXf62f63+ eVPUyuqwP4hOtDNmJkZLndi6SEIJ9/upu5tZtMOjeEVyOzFfOPhcyGcDTor2Km9e/ckazuGCSNl WnE16vQHTPHZReFIuzeDtkORXFxVO8uC+vazqWl4zoZxBqBV1dz/mUq/NTUeVWcGo4W+6UkyzRU QLpkVROfmVYXtUMcxZx4nfF9LVEseZ8f7Skj9MDe4YE2Dl2IXSvOkI0qBtBx31HAiVSV95+ZP8a bhfMQ8EFtS+6D8o49ibNnO4V0MUGMs8Bsd7U+7y+/HGzg0tOvEs8fhjE23Soa9bvztRNQ7hYi5D Q2vDssy7OqCcpU0yOO9AlPntPUBqsUC5R6v3BACfhD/lukWvHeB+i94wazqRDVOcI3rZRFfAmuG IOrFxqkjGUKhD1c9o792gyxkgPLTNltPciKZKFwUkvFB65DMrlDXpN/mL9g16j2lCDAWfuzM5EW JTr3QwYc5GUZug1sT1vvHtTCeCUokp889PE1GPe/c8jd9eCE2BTI8htwNIgkaHmPSuVireUnm8q qCe2rBS1wzjFuBZxK+7J0no/ZXSwmvw== X-Received: by 2002:a05:6830:3886:b0:7fa:ac4f:790 with SMTP id 46e09a7af769-8089a150dcamr251581a34.28.1789354906207; Sun, 13 Sep 2026 20:01:46 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:45 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:12 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-6-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 3B350345741 for ; Mon, 14 Sep 2026 03:01:49 +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=1789354911; cv=none; b=N7E+I/ahlA2G8M2YQZs3C97jnwbo0/Lval3uBpsX267nnZdikCgSFSmYDlxjga6EnkhVL6Vcdjiy1yjDxY76CGXDetBnXwv19phTc5QSzLbKFUeTFkSQ4WT/H3dFOpVGa1pcRss+DjVlGnEa+zHY6H+H20q1gHIzgh3oK5Qk0RA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354911; c=relaxed/simple; bh=ovOsliEdUhvhRoeaXGSGPM3LycBRMZNPRXeHkTBG1HM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tigYZ4WgkB1OettC9Wlnd+v0jNdinWMw4GKg2tMeB//MGG1jwjxOn5DITvEcTFag/l5tjyNxHCHOacxURGUa45I1Vn7G7eESNS/O85gdIRVSjC8qKDwDVzfATnMTLxUWg5s2Utua+5sv0k+s+ISEUGkKaYJgOEUSIVjeLpyuWFE= 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=rwR7hW9m; 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="rwR7hW9m" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-8050801d337so1103209a34.2 for ; Sun, 13 Sep 2026 20:01:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354908; x=1789959708; 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=rwR7hW9mIvGADlnH8wTrvjByc14LhkUwac6f06ukK1bpURHR+B8+1+HG40klkTftan uYfzALM4aX3HcWJOiw3nlcc23/GzlQhyisWcstzBsBOIAXuOP0PEfN6/REEw5sD8vMOZ Bzz2qEmng58Xcgi49e0yVxjM3G788g6UMyj+MeZNDzIILZn9Ld7RMRiCtCqvwhLY/JSB AcWKdOM/3hU+wquQWrofI1GaK9aszcOgQad8vVS4r3tgr4fXc9JD5GsdaaAEgnImXDqY 6RQOPbsm/8d/rYVmObuq8C9jnW9q+DhW5Xp/XLY707k7uK/AnN+DV8VNHxG37WQr2jrH KgJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354908; x=1789959708; 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=fsoHDQnPFhIqGXfFw0zJUi2nG1PJ6lyAYdgiKu2CgoDNPbqQ5gcZLz+vUT95AUrGSr dKnJjIPUMG9iuMIsQPnCo16K2po3w1wjCV82mN3OhCEaKgTpt47nqZymnzedsvM5QHyT AaOCJqstvac0glPDIkGwwLvUbxzFCzGpekWvrcG9ZxjIfsVwSl40pwo3LzLnpp17hEVc kYxdMWYOtTptN+Kuvwit2jPmeQUfX1mp8PzmmuKCYSVHU9W82iKl9Hkzbld5aGGOwqGx SVRYlW+3hmujD/6GhbdU8XtyIJvQRmrTXuTVCbIfqDxaL3u4Awe0Z6sprBjoV2Ifw8sL opAg== X-Forwarded-Encrypted: i=1; AKwUvBzidUU8Wzv7/tTD0WEmtFJtKsIf2x2oZcL8kg3tN8FD8Wp5I/c25/XVlEpOgA46iHoAk55Z5byQyMGHOCo=@vger.kernel.org X-Gm-Message-State: AFuF++mCKBegTalt0LKbdw4yWEB0KhAAI3RMsR1qZWrPOEI3kppX/5nN n/TavUcSPyH9LKoENbpna87DbX8TQqjOYHD0UqNlR3GmO7/pzUwQMQgw X-Gm-Gg: AYBFou3KjpAHrTazheYBG7cd6Sws6lIkJC2D34zmrpxw9SoXBty9zPPJcdecH2x1I2V DdkDvXrx8bnOlNpITXwEGGLSwN2K+sbE8AtwdJcraAKbhb+73BsDU3LbKusZ7hVGUQWKB8QT2ar h7WU8nZ/scAnAQgZw4nt+mChHrEV/oeXDXhwr/aQxHFGixGi02h60I7QeXB700pRrkyDkONw2KQ 7kMyd5gFlDTyJ5eifAGabWB0IjsZnekRz9Ul8PAJhYy/fvmhXeDPSnmaePqj+omyLdIY74aFOLK bfJdHylqaOr9pbNphdXTp7pI2lfJwxgENNehdCmMnbO0TTXEzmVBg7LXUle6Oeq09tceiV98qKx 53E0X7ZtQuX1DNEXPVebwurHHVjm4gnq5qMvyRVU1Tw/UhVjaPKKcDrClw12X2csXTsz5yechlS zCkQkhUek/j55LQx8l07k10pt2tKlgV8OXG90wmQaookcROnn0GkypS8NDOX+z7KjpnbewwGjwg sfajX8bmcFtEI0bj4qbmWDLSpqapgZp94Ki8zJKY+4+wduaeV2M9zyY7QFiu9BSYc8oa7vBpyjQ iwMDOPzFtx8Q7VdEWMpSUs3QtHAIdhOSiIlNqZAIATv1JmSl7jeQb5CGreN//gaoVHOQR055hXD Zpjy+Rt2Yzx4P9vEe9NaQzh7wMWPFfA== X-Received: by 2002:a05:6830:4c18:b0:7f7:f55a:4bcc with SMTP id 46e09a7af769-80897c868f2mr541126a34.8.1789354908010; Sun, 13 Sep 2026 20:01:48 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:47 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:13 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-7-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 DBA6D348C4B for ; Mon, 14 Sep 2026 03:01:50 +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=1789354913; cv=none; b=gv/E0K/kx7vx9hicmKOq8jc/81r7gAEQAd68zqFl3KBkIXRZitVm5jeFG3sEg4HWVfNw4gcZ6VDT94qQjBv1Zy5ubCl1GA+VpIZKhKQHC1ksP2VIRLoTEDYuNZHYMO7vDbvW1Et05rAlNSo0BJXgBXufhlxRd/qJZZzF+PYIOjM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354913; c=relaxed/simple; bh=YbBF9laHAErhZzSaGZGDzYG7q1LarpeBoJ8ap1tchQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GoB9a2eDDNDa5apsW6CYTD4UroRClBxu6kS520EQP/k0a4El/RcxdVfpJvGdbasCVTf2HwqYXD5+awXgDQm7beVt2rhx0+xDLdQvZ/vti6dmup52gBLSJVd7nQE/5lsaGGvwM6bUAxcoNjgNrfgwc7MX5eLue36QRV1qtD9d1Ys= 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=Mom1tinH; 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="Mom1tinH" Received: by mail-oi2-f13.google.com with SMTP id 5614622812f47-4c66ba0b762so192758b6e.1 for ; Sun, 13 Sep 2026 20:01:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354910; x=1789959710; 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=Mom1tinHZz2SDqXo7HhMUZSwWMktQvIvDyG5owl8Irc29i3PircQuWNMMthhIxPuA6 qcQSzfhxUIrYAbQcg2Y2K/2MeD+lH7HLMWaDOyHUz5QKVexwKnU+KLnITQj+2Na36SDG 2dGzUGkOYS8FUX+feywlrrYAkCWLRJbUfL/TkJOxucm/kM4ajMj+fWinczN7pjDJLdHa x5QTJrNy0QoqVo9ycsod8NQARvzgSIoVUcSUid2ZcHHEGNpceJwiDo8qaE712egHKu2W jo1EHxRkrZ4A8Aw0ukokiFZCMdB/nyM3I8/PlfMsN6+OTOcfo4bmn4hHSzDQcl4xcpLW 2bVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354910; x=1789959710; 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=YtfI76EYXf/mJ/z4AGSPA+hFSZYkdJ6iuj0sR4PSXwCABypjYnn4alYsy5WluoE09e CDoS2mqUsdjHN6/uOSTWJqroS5D6gWQp4dkEF138UsAto8kFw5BDDJK6PNzkwHFG+l9G cQ5009U0GSbKqraXaqW7QEW83EfSp3F/ScqaWhACVawdlyd1YgoiD0LZkJjMtse2M0MS 9I+7GbzJGb9KXidTDSiqg19My5l9/CPXsIU8LqZcxZDB0a4nhpgar3H5/1I2nYeHv7Lj Acj2lARrf+hN5YyMnLvg4APf34DjQWZNXP1Ql05Jd2dgDZiNmbQLdnVkVBkDzX3yCtYn pHnA== X-Forwarded-Encrypted: i=1; AKwUvByibFm74zgDeoj2AWl1G6sR6DIC2VnwuUOTq2OQ+Sc5UyNpKF/5rFGAGr05i/+G4eI+nPNIqiyKNg0/o88=@vger.kernel.org X-Gm-Message-State: AFuF++lBN5SwuNoPCqbc3J0iR1RkzN5buTEIJ6FANRjgYZmw02PWaNd8 RjgxNU/tR39zfMYfsPL55yQJqC500e4RHX6MAxNElDd9SYFy7Y8qFn28 X-Gm-Gg: AYBFou1suno/qFX84UNRzLN5IVS1JhOg02Vdz892P4gUEHBin2ndGakRJX9fWO/3n/x jcAzyyKLe0jTsvGtbzVqSln1ZP2zsiMLx7VRZIlnmSNAPYmYZakIkH8r+hU3cbIQW93FSQp0FY+ vAjhhbTG//1BblK/ShNZxWFCB/c/PdN1+zxGb3oxjZvv9zwMm/0j+7AM4w0284lFKvsiOFqYlB+ l4dzhyfd2ngGv0toAVXrw8EwrklColFVHTi69VGcvyA0B44OYtQ+zIi5cFQuC9erVXU5CXH4ts0 RHGaVMYq2URAG3yDROAXi2dI0APjGU+3eF59Ttpt7KHZD72TRxn51i2U7QK2dZYFS2KUZ22DkS+ wCyx/uorsF1eYIiR1QgGxb7lV/eGKCzgc1d+/2/buApFTczhPcaVaIx6P9ym0Pede+m3JF7QdrX 8lFh3J4zeFugJO9gaGqWE36MOdoJky9viqeEi2FiyjRgAh7WEk8F0qQIKse5PB1GMGezhI7o/dK XfDxx/qK4o5JOQBb3wP9Bu6shHjt9CaqUmhcH2buL8XFHBEwo/vtIpBAXNpmbaNiw812JWYsElb 4kk71+UbiMd0oGDRZWJYSJepMMjLIUKzpPqfVbD2OM+Y5E372Oa9/pwkKC6aCJdqpGiMg3bjvAB OQRkO9uhvb/ynlAK7MtjOa88gFpuMb0Kp+uH6iBLFrw== X-Received: by 2002:a05:6830:4486:b0:7f9:555:1def with SMTP id 46e09a7af769-808863d0ac9mr310838a34.11.1789354909720; Sun, 13 Sep 2026 20:01:49 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:48 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:14 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-8-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 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 51650345740 for ; Mon, 14 Sep 2026 03:01:52 +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=1789354915; cv=none; b=Ay9Wb2VfUo8pk5bR0fnCcaj8wgMBNtbmLhtMdiTzB+AbE0/c1k9us/0p0srqBPW1Pd+ny8xKAASvipyfRyDAudooduspEC9qWvNuX7MbnwfTdgDbmO6doWMC0x0ZtW8yFxQ9jRMq8j0tjRf32jDmVxuKLTBV1JfEKIYJpD0g3V8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354915; c=relaxed/simple; bh=o3NPqjDQtjCU8+r59n9WbZaWXsVSsfQ6oMXDXHHDqIA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pb2xV1ERej3SuaxT4BxFKI+uigOhaoqm5wnZapoYaLw7Ipj8pyzTptcy9xaKvyE9ihl0jrmTAiJBf0wgV5kAkciIeSlKkSW8UpMyVwBpUC9Kavbj1DC+b3t/su58ASynJv5GHgsVCSbAZ7XPIPPrhLvQWSfrAY2eO0waAvWPxw0= 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=cfU0BMBL; 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="cfU0BMBL" Received: by mail-oo2-f43.google.com with SMTP id 46e09a7af769-7f4f0c89e33so1052419a34.0 for ; Sun, 13 Sep 2026 20:01:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354911; x=1789959711; 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=cfU0BMBLz4uo1K4pMSpFV8FIayvOSvvTFpZsoCpBOujfXZVZ4lRaR8mD+YfdtfwBuy HGpzAISljytbzEGd0eS+lkpBe7OFZX0g/zgXRoSsmuuxygbfWINExR/r5nZgs9V5S2GX mg9zhqGtD7bJH6S129WFCMjohIoDGONRdWpGE90r8J/GX6MqQh83WPufnZseXtdAKbRb 8+/Hiy8x12xC8kttLnoblkVHKJQdie4jj6Q2g6QB3xHw007BiRw0H80TIIAxY8N3EX+4 jdK0LKXCokmhTKnelWrxyErLIrwk4JvdAk02G5WI/WImvV4V7kL4UZKBidlrqjGM2FFv YKbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354911; x=1789959711; 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=CwRdQ1bvKWVPiPcZ4CUgQm+em2tuGfYQ9XRmKnYYdlZ1MHZOo1DMDxEmD+GKm6Msvk 6e0ZKtlZdzyvx7xU05CbxPc/vI9mz53iVy5W6kFMKa/uKO/dAoJXQua1PGoBUEsZ3YS9 w1WaKR1if8PoHLXqRv6yKhbTTSQ5ClcDdROgj8DTDUK3poXCRtThSrotJcJHJ2k+PrOZ zTwrnuoAONzjUnxTfEZr/SAuS5G9j1GXgmDs+bmaBYTPusaVd10Y4qVaLCbN2U72/23B McD1CrlWLIM2atxjXaZUDownO4QrJShfKA4S2cd/gPxgrjDZ79OcXeUX94gBb8we/pfa vGcA== X-Forwarded-Encrypted: i=1; AKwUvBy2HG2AXoZJD2FAQr+TzIjORHMpxfsGIiltrSocPDVdEPdHeNMBsExgWsdpZ4aHYTnnvfzjnhzH2+aLGC8=@vger.kernel.org X-Gm-Message-State: AFuF++miejDFIpJ+JEcmnQFIPPdzn2FQ6QoazvVzVaRSqqTYPxMMs0+6 7xxjeh9ggAzG1i/vfZ94tKjoJZJgpVg9ffnwfX0hf0otc7w+4vyvDzvP X-Gm-Gg: AYBFou1bpR4sHekv/6RiRhSwQWAiemRf9oE2TL88nELMdAf/gtXy4THRtBz4gCowghe YYq/n6prg3ycHni15jo8l7iapORQosj64u+k/0J55f05loWoQzUEnNUkeMcVwCIN/NE6mh9bqur pU4CIuohH9/OJ6E/EbD9TEwejgrwCvneLkkBs7D8yC5DiJYlWxIOFQ2ybMiG5zm2pek3snglXzB 44FMael0gHEaDqiRFsRpdOGu/D+WGLe5kwj/zXc7jwzLEPoAeOpXnbHdfW8fB7+N5Otlc7Bktcb +4KiWiPJVR4uzLR/XDEZNNww4QagWWiiZXOrM4OitfOSN0+BEWUpJoT4Sfe2/cef3kF+qLaeadE KDoMnMWaATtuhOtuoI8Wlz8g58oOr0LoOw6LTPLP4a20OFa1mIw3R7JSGvyyDaV4tLhdNtj+oTh MKt4WG4HhbpQ6ABcYWYtwFpuE7Nhwhqxc/8+CjJuT8VBFoceY9mI7dW+PNdDh0qpilB84vV3lrC bwjx0RmwLIhisSViPOFPI5HlCLtcyh354jVV0O1zU8z+dyC7lFLl4xoAdAWEHL2TNvpcvVNeGnU aPh/YdXz6cVAK3GB4Aem18rlrRI2M4l6Wr4kDLqvpg60u7NtilTBdwL9bLAQj6zfKiSfMmchudV SUVWp0N9pq72cnnGUrl8FWiFfttJBTg== X-Received: by 2002:a05:6830:2a8c:b0:7d7:d524:bc88 with SMTP id 46e09a7af769-80897c891b2mr304523a34.10.1789354911083; Sun, 13 Sep 2026 20:01:51 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:50 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:15 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-9-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 11:08:09 2026 Received: from mail-oa2-f12.google.com (mail-oa2-f12.google.com [74.125.231.76]) (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 D7DBF357D02 for ; Mon, 14 Sep 2026 03:01:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354916; cv=none; b=BtPXAlArbCdzsQLFeINNrT+J82qeGMmJjkK/VGPVEaYc/S2m0REGabrsWb/hrpxZdiuGWGYZdF//CaRVK6x7sUL4E3ca9AaxMp2eFbt1YJTa2ZjtG9d8qQpfg+HzV2kiqH1IVF+np27U4xSe+iaVhx+RddrS49tYVotx+Po+pd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354916; c=relaxed/simple; bh=8iWGfrxZbd83xo/SM/xyg7dUuKcpNxJMOXno5pQpLKA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZxawK5nFtoPxUOMWLEzW4W1gdlvizgl3O14R+MFIUndlpAYlq3RoXj+RYD0K7uGNxGHxH1+fQM+o2z4Jm5oTEXeppH8zQ2v4xeehIs2ofGm+oKSeV7C0L0OCIl0xZ9mHKJ0tMAwFaEx8hO0sy22zpmJWmL79BZO0YdhqCaBdNA0= 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=gUVPN2yM; arc=none smtp.client-ip=74.125.231.76 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="gUVPN2yM" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-466cc9b2f1dso1214202fac.0 for ; Sun, 13 Sep 2026 20:01:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354913; x=1789959713; 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=+fPDpmxms4ltLqy8HoVcRfs0if/gr5P6/mMAZPDSTxM=; b=gUVPN2yMZpoEASUm6doUIyEecR6aYzBlPGltQsQcv9H1SywyQoYU2JOOsRANOPMQRt feyqqG9KVMEPQzQ7K/epZXC/7neKMLAuY2usyrdL3jjpeeGDqVGVeE+1AHlD55QkjgyH amX8kc3h+cgJuLRMSc+4bahmIJdnwPF9uzkMOy5BmIxVncjgQ/2X+N7rJ/AsEyA2UNgu TUbXovIrlHJ9xct8voswjHouMiQGoFQaaXiXGYmh0NscXk9LC78S7tA3Q94mJ0FSQIJz zBJxGQTsMcIjVVdWwteZrhq9o25PFJkvVGzMLlPgO2PQwsC/kc7+p147/YTbAsxkcnDO o0sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354913; x=1789959713; 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=+fPDpmxms4ltLqy8HoVcRfs0if/gr5P6/mMAZPDSTxM=; b=AV5UGKxQY6hmPASY9/qlhDr1XwRmCYThRhTh/b5rSemt7Tg1wAdpDMJt4IybaoPpK0 Y6+pxahMC6rLZ9FoOu/P5YfYBWVLfVb9ByeGQVBD6QCAatpoJ+ggqaQZg1OZnmoIFWcO ptrsz9Q9n/U8dDgEecI/F9XbQrpdtlTuEqJi8SztM9tuXBWyMWzPqS7hHkTHPgQWSM03 rH+75x+zyKY/Fsr+4oFlr+m3A2wlD/ULyOSyh3KKAwrawO4WWUErm4HyO1d68iXUErIW MZDOp4Zuq9cGBDaHeSHne+Ia0knMW6SH8wkvA9ogn/85fBYHjgh0fI9FpgxZcMeWs5n1 F2iQ== X-Forwarded-Encrypted: i=1; AKwUvBz98UzAOCDGQUHBttwbgNWsYPF7MxQmOdGYWoJDVMq5hBrL4KV52gz71oL/H8Dyi8slTpKQdKs+Idi1ChQ=@vger.kernel.org X-Gm-Message-State: AFuF++lXnqkg8IG4MPWuoR4o6EcHMVL5k06st1NrsLRToa615ADGblfr TqctenxmL0GWgTji96tIzlex8G+St6n3mP45H6eKe+d4FCtY9pZmVjKz X-Gm-Gg: AYBFou27S2HWDnHzmQ/9Qhric1vmL/G+GHPR6PWLkguoAZmhdxlvtMmCQc3avVB9hwP ywY44bUcluY0l2Q27MHgAqQZ+tJ6wyc9BpHmdK/67NXxx4EGkRANGDvsrZp2Gw+gKtCWJaHBmoZ 6Xx7T4X3J19Bw1HTgdqyBlLOkZ0P59XT5dhW2z7l2RkGu/wK3GCxnYebJZ2K9S1XOPjWH2osUpl RdKQWa2cv0HgFmeYT4kWZKURKM3MCbBUHOOsG11GgsMb6i+G8QBakaZhiERTw3i/08Ktomk4fza LqlaaD++etbYwlQ8xySPsOAK7tWcbJpl4DqMGo+VeAG3/vnujRxg8rizuMbqDPo1GafQZAXQR78 +c7r/Z3AvWTeOvz9u4vX5GRvnupki1J93CWRuqSNNg4RPnSx2e1312djrPShEf2Ji9B9w3FVPDe RE+84qO53JOpqBei6FAcpTRMYsvXuXUa/tXhqgYpxBKhapRAu2FVRWdKg5O2lk0KgCITWVDERE5 uEooDngjjZ8HhGkJbFNwvsnO/oe48YqMsH178rftlvKpMicis1kozaxnjTFiZ1WXQuA2zqbvCg3 LBRith2BEOx9Ddec+bWq+73zfFoQDU7MoyJHkOXbNxgf1m3H4SA+jWDoQW01mD1S90PimzoP4wc BtEO0wnq5s3qJ+X09dpUOSADEHjrQMQ== X-Received: by 2002:a05:6830:2548:b0:805:b4a8:724e with SMTP id 46e09a7af769-80884ad0cb3mr373073a34.6.1789354912706; Sun, 13 Sep 2026 20:01:52 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:52 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:16 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-10-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 into batches whose aggregate user data fits the bank. Reuse hardware slots and user-data registers from zero in each batch, retaining the original logical main-data and OOB offsets. Reposition the main column and spare-area base before subsequent batches. Keep pages whose user data already fits on 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 | 276 +++++++++++++++++++++-------------= ---- 1 file changed, 155 insertions(+), 121 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index e29638c828ca..fbea6f16ea9d 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,39 @@ 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; + + 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 +1021,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 +1036,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 +1289,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 +1325,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 +1363,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 +1388,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 +1776,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 11:08:09 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 89A10332909 for ; Mon, 14 Sep 2026 03:01:55 +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=1789354918; cv=none; b=k8AS3NGY9SDcsGu62S3OPFc6HFWTZqbVTxu/hYX3RcUJ8cMFcs19hAiiORNya16Me2X9/4uWE1UExchLMVfHS1bw4klKwXzNk3rilt1DmYgmrsOjCjUDZzoVlK8uuYjFV7NhR4DbxVjCLCAXKEZUpr/TeX3FGZhATb8VK53esiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354918; c=relaxed/simple; bh=0vst0CVnlry03ftKyPut9wNxD9SkwAYgr+pMgxkNU28=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ju44kmsb9RfcKOJ32HAENzWK9FGfbYP1+K4X5brb2DiI0ijJWC6nB7nw/SK0U7RUkHmO2fd+GhuIeKKzpSWgCg2xk76Bf1g7Nl7iocyka1lLl5nK6uby54tCA0M+uJ7XmOymibuaUhuZPpccbZsZVbqD1ppGQnSCQi5pM5WJ9wI= 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=SXBJhTuE; 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="SXBJhTuE" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-8050801d337so1103249a34.2 for ; Sun, 13 Sep 2026 20:01:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354914; x=1789959714; 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=+Wt8ZYJ1+YeVWIymrCDD1Zyg4sGrqRQe4OCsHxO3n6g=; b=SXBJhTuEq8eqNsV8ttE38AOaYjqDyYSQRYO39Mvriu/q90VQLIbAAmfCx0C2IO2Uwp hLfXZk0NptGSE1g+/eDEeOwoT36qT2zqrlOqVFxyXs0bqBknNzFdytBWYyL5qdqe3SI4 XHo2GcwT4z4YrFnTMFxwSyJmSN9IxmHhrR+owkKfELzRMmAisli5jaF5NkrDph9oB3uT g8OkC0Cps3rMsbJKYPzo7j9ZJYVN8U6J4yo2Hp1zDvW3X2OCK2oy2krUXrGvU5bcBa58 ivFZQPBBB/q7PVFaUxpncbO9dyNOxTArM+CPc4oGkRx4r0WFKpo7AOs/50Cblf1bclae 1V5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354914; x=1789959714; 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=+Wt8ZYJ1+YeVWIymrCDD1Zyg4sGrqRQe4OCsHxO3n6g=; b=dDiqFSrvksE2UC1g0Bs20UvZeccrizq5ecPEKOq3XrX9SHuihTbR72GqDpOocj/3CS cfBTJ+o1e4DV+Ew0r5dZPh2tV8SBjSBHMg/1AMUtubX/g69ITjGb9WDORxCUKLo15NGV 7pXYm1G73CZ2FDkXMWaPX/IpZB5+Gvter9llCpcrKWG67u8wL6zEC/uEfszegeviAUHN hDWiAK+wO6MronBRw4Kasr0oejN9kWjRC470X2hgVmnb47dnJjqDpJDn5tBoD3QI1MVF Fa+FrX+YXjava1w6Ek6vUYYis+5M9gI/jB99XfEHTIUNtfgxmdB5EsGVJEOILSlel3a4 4t9A== X-Forwarded-Encrypted: i=1; AKwUvByeuRw3ocKwjMO+yafyYI2KnHtvmulyZ/0yEf27UQA2D3Axcro+awEORzaqcGaY9MRFNVL/QlFGTH8S/FI=@vger.kernel.org X-Gm-Message-State: AFuF++m6yMjd2c/uDwSLXLw+wnOsjqRwnKzj2uT+rW0Z+1s5FGjSiQ/1 BYmJuEiR2uxArkFkdRpcURz5hqzQUYWii3r2sMyk8vjhKotKkDGXr5VaTq176Q== X-Gm-Gg: AYBFou0OJF6aH1HDPhDuca1M/54S8jPHBCkmyPkiEYyUdVhe1+88iV21PldbOV+/zlU l29zRUZ9tTpYoq5c8HVtNJPbt+6UoPVc4A3MA+meEXS66wli/YtNDlDX1Zluu5c2NEsSm7IaNLY YEL0VSt9lk6Y2Hi+bjGmz/BBcKm+rzXTb581ok5ZOUl2R6eLKjj5J+qIgwXjmZX4vRjBtKrOAJi QVeU/NwXn6FqNV5o1sGlmwtG1ZKO8209kBQ6ae783XcAuTB0wYMXPzH/VKU4hEuU2phTnAh1e0/ sIfG7MTnLCX/Zg2x/FJZOM8CcG+L3tXhs3PXibBpKsuDzL9liTIKeJ1qbnjCBtwVsTbbyE+VEoX mjQEIFPmP6fWyWAN+Zq+ytnuTZEbkom8HuwjWLW3G6eoCnt7IFAqLX412rXQwN6UJhfntjfD47S 1uMOqITfxOhiDoGmj8DbSfFi4DNs7FyZYufwiMwyDvoDCWt4UB51LmZpUtUrr9CGe4KHMwF4jnd ecJNjUiRTEJf2s7G60IBxJ02xnStKpIRsngK5RF4QNselsjMx9bA4qjuCQGjCOvw+qSV+n6TmRN WVCSsGETXc8Au3sZuaDysB4Rc2NFoRD2T7S4vDkhVNsI13OHEHruHpTDfu3fKvULWzLVgFwvSwe Qi6YChB4j+lWWGp6IXdE5fOjo3S+yrR0ZU16i05+U X-Received: by 2002:a05:6830:6a98:b0:7e1:cbe3:bb1b with SMTP id 46e09a7af769-808942ffab2mr584784a34.0.1789354914222; Sun, 13 Sep 2026 20:01:54 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:53 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:17 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-11-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 fbea6f16ea9d..7cefb4d6951d 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.= */ @@ -968,7 +969,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); } @@ -990,7 +991,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; @@ -1013,11 +1014,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, @@ -1029,7 +1030,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); @@ -1099,7 +1100,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); @@ -1108,13 +1109,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; @@ -1130,9 +1131,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, @@ -1140,18 +1141,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); @@ -1173,7 +1174,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, @@ -1190,7 +1191,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; @@ -1216,7 +1217,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); } } @@ -1231,12 +1232,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; @@ -1248,10 +1249,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, @@ -1292,7 +1293,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); @@ -1395,7 +1396,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); } @@ -1419,7 +1420,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 @@ -1433,14 +1434,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); @@ -1448,7 +1449,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; } @@ -1465,17 +1466,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); @@ -1499,8 +1500,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 | @@ -1557,7 +1558,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 @@ -1581,12 +1582,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 11:08:09 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 E0FFC35E1D1 for ; Mon, 14 Sep 2026 03:01:56 +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=1789354918; cv=none; b=ujjd2Obt4bo2FR1PI71FUr0cqEj8vWxwnYbZ8cda6vj2SQ8N3MXM459oVwM+74UFN9C6FYSUH4z7IgCIG3sl9nWK1C96Hv1s/ud5eY/yeibTREbpGP7NAKjFTNsMVJkTvJZq9O8u11Wtt6XLww+OcjCcPD9NjjZ2tTUKSgE3TLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354918; c=relaxed/simple; bh=TnmhAN7UAS2ynuFEOPQLlzD2wvbIo/yeVWwhOMqNS58=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W5G1KOf1LeUnQTK6D10+nzI4MpFu4pgQoY2/d3nCkDOcB05V0wRPn9Y5hjCbs2rwGZc3ezK89x6NAW23RHuXG55H1OShjPrbQXCG8PgD+OilUZwDEtLMvwXVoZij414KqPDSK+kf8jA7NOAB9ag+cxF8xqrMwTDCWPNGOf3Zm5Q= 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=X25CkXnr; 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="X25CkXnr" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-804f7045f3eso379765a34.2 for ; Sun, 13 Sep 2026 20:01:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354916; x=1789959716; 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=X25CkXnr2G9ChMCHY56iFoSQrjUdOEfiWomCRHt7H4VdZfp8L/rSsZYD0sedFScZpB MxTzm3Lxt+QHqYDnLsP13PRLVbdVPRT6rSa+jrv+7jmDmZQSo/O9JlHYbbfA+FubZn5D eaJyfelpF7qw00kFTyh9RJSh1qxY8QW3DKIWYCLSPzAkYoUFXe5h6txZKj7Z34++NgYP zDdcc61HAwcy9MrclO+odKkhMsTbEMDn5HAbQM7UGfJ32N0xaeAdr/XG+T9QmZcAnV5M yvaieOmLVAs0iIjW9vxdSIUzFLL4ko9X83g7QGrrw6/SG8RWoNg7rW4c/71MAgDnHX36 cy3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354916; x=1789959716; 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=WEXVvvEbSF0EbBBUUJ/S9UKeJjdMsX9hivCJGQM57WT6frBVIcG7DeJPaFgJIcfIjF 5naJPkYGqQMrTFjOEVNRsIebdAEtIb721+Zqvk0H8UhhsZpan2FIwZHxby3PwNOOZ/1/ brZPmJK71Jv0VMqKnIvoPS0/bIeuwb0+OfagrFvp1ubqCQbW0oRraU36ezhWJxv4Wmw9 3s5Mmc8VUxIyhwvpS4nkcwItfb83SXtr9CU1b+adLJjSAWgwmCwEJwKvHyC/jrOCKEKn cM5ikyCt2x3LIa2p8NprwIMBOVo9cNcXnmDIJZWVcn4uhR/vtOKTFagW4V4v+vJq4F4N gmuw== X-Forwarded-Encrypted: i=1; AKwUvBwVVIfbUVEZ39wbfIZLYpslrVML2eRX2cDkLe1fkNRcIlmoRXy/4eK86kb5rdXWRlgctkz0dzOirwwrO98=@vger.kernel.org X-Gm-Message-State: AFuF++lvo4CD+b3gG6Flf7al2T8Sp3Hs2So5xNQGdX5YcfvsRo7IGsi8 YqwQOVO3DgmdrHgmoKPvBzpzwMkGbiox1N1PBaJZ2NraG0QRVpnRH5E5 X-Gm-Gg: AYBFou1QYrC6W27ipyL9XwrKiYVJf70uR+lxokA8OetO53jtoVxpHkvjFKIRKO68i8D Au2HjCDj2eU3uDPvBrvny/MWWEJxyx9PiMTj/wyHf8lNEHHQFhrB6TUna6fLMucQS0X3tqMxKao OqHYc001+1b9D9O+fRuGPvPLFPnDCzSUWz5xEVZBHlFjEbYGIxLB87V4TxOa+WzLWw68z7g9pcJ H5e6CTB3rcoeJMMO0QnhFLvnzcBwWQeKIxRvzeG637scLhTjOPv97enrG59iRC2YCH5vg/8QQ50 ivi6PA9dO/crEEYG64RhTN2l24BSqf3801IV+lWwjj5/IkROw7D4LNQDeLz3V9zbiJKWK2yPors ErluJMsSJyDKl9VQjDv63sqUuHUVWpDY4yZi7FIP0Asz3CBDXRA9FmKzaqiUBtPkXA18IBpzdeS tC+jJngCoaJ1R1QbfsCnuCPBw8kgCPyzgz8TFrbh4a4nsjKN1Lr0NmnB8Opcu7q36HoZouWRMP8 I8c1CaJF+6ZtzZZioaFmczU0oDpSLRRXcmSwLSAottxEQqXSaJ96IBXlMTx8pS9j1pCKslNBObD lx2JYHSa7Z0A+a3R60ZYRfF/Wm0p6hR0uOgy/EZsxtjDzONj9QHZgsK+OqesFGb1fRIIf2DLuJB sC2WtBSFysgD2bTIL8RLl5XMB8/bNwFtkMiWkgovZ X-Received: by 2002:a05:6830:230f:b0:7fa:ab72:9dfe with SMTP id 46e09a7af769-80899b4c24bmr292105a34.22.1789354915667; Sun, 13 Sep 2026 20:01:55 -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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:55 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:18 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-12-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 --- .../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 11:08:09 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 CE50A362156 for ; Mon, 14 Sep 2026 03:01:58 +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=1789354923; cv=none; b=VGr3hhQ5kh5ot10hrPbC4AZiiR+BkdJrDRA+Vdqm//KBHk8zEQBglHc8WnJI6/noZksH+rQJ4hbIJUuV+AiZ0KOzSduqtGgWdbUK38lIGX9itBoxH9LIwotTShMmtqW3BxevoWCXEzEkY80FgwyHeDaG1nruSsmbkf9d9VEQWQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354923; c=relaxed/simple; bh=JL832aI7r2nbG2mOmURmKhPmxaM1LefN/qlKvgE7hoE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZvW5X/1UPJxRyu2JTtUecyNnGH3gZd2RYNzQl0V4Q7xqHAazKeVxb5QUl5aZFp//cwaRDBnjU4/Vv1JSzZX9Bvss5bxnou9qL+wEf1rmc+lBK83EVIuTkDu7STQ8aFnLB/tbAzUDXzli4J4mbj8CU9skxmwETi4iPyeJPbMgJh8= 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=tJoxxUs4; 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="tJoxxUs4" Received: by mail-oo2-f43.google.com with SMTP id 46e09a7af769-7f4f0d37f93so683530a34.2 for ; Sun, 13 Sep 2026 20:01:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354918; x=1789959718; 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=lG5iszPYAhZghbK9DA7AX9OFRia7hTHj4HATLsgwf3M=; b=tJoxxUs4bieqhoE9c2SeoAzaEn1BXlHSfNmI47dXgtsKJ0AEHsYDjM84dgGgTW8dLs E7hraQ22GNp2xw9MZ8r3aFT6TG1CF4t9id4ybNKUm7o2vwl0dMAsv0Jcqw53Qt3kOg0m ahrQtXIQurD2aBBlCK8y/ioOvb0MXrjDAS7udAMk3PlhQIrHHvHI+8MU0b235jPEhDDp yXzKuSJUG+u6ArDxVgNRhBOk79M6Mc7rclAvPKtIQqrX+ntka+6K+TCKU830IEtBxtuh BzmfU2ChM/Wxw6Jt5v7E/vDgHA5uvf3iaml9pso3HgjH/uKoApBX6dDd8E84G75D1zot zyIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354918; x=1789959718; 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=lG5iszPYAhZghbK9DA7AX9OFRia7hTHj4HATLsgwf3M=; b=S6bumPbA72lVoXA4irRJm+20ODHMWFAy0Q3SoQJQ6dIlx8upmxcKx8rNZR4aIIG4ug TwRR/6O+t8T9P0YjesspZCzEFnPOOUplByV7duHBVAQs54E+/OmMJ79392mC31PsOme7 bFSwL0m8EjB8/4hQ1hU895gXumlpyGeQhc4I6qKOF3vHNLCu+e5VdDpcXH8BkmOmrPcC cHxrhnllgVxBVySSaJfeg6GtWK+9PRzI2VeCxU3TPQ4PbgPHGQoqk+4t7s/7I9t+bhVp 5wVOIBnN/fKEinZvJccvPKIXwgu7evJwY8Zh5+aNZdKzHyujlpxG8rNaqFiOVw0oA09i qe4A== X-Forwarded-Encrypted: i=1; AKwUvBz9Ku6qPAK0jAx//tJoQR/qt4gE/VDNmuCE1OV5b7fdsSs0rHsvLJiwzkd523aoaNPvffbv07BRgL+o8Jw=@vger.kernel.org X-Gm-Message-State: AFuF++kZCLie6Itb4UQLowwBH5AWMnXZUD3Dc2Vgadq7sYTiNkR4qi0z a5dujTRfr8cxjImN8JK+nYpVU+pLs8HJ97galVZJ/jxQZwEU5btD2H+t X-Gm-Gg: AYBFou1a7v7VP31Sg4qC+ItcG/8yDODmjNF7q50ZEPbOgNWiCGMMvW1tuvQZYS5vZr6 rsQ8A/Hotr08t872kUYFKKyP60hVs6rGqHseW0qoUXOg7MKtqqAjsDkVNnrrYG+N8TQNv7aNlxw 7S6iQWpO1esDM1aRXpBTlk23R3OQx0z5ErdlPuj6sdo1ayO1fWpMlYba73ZuqcJoBkxOzRTl/6E oFXED8WSmGEK0rsmzBkPrLQeLo3PTTcZY4oQYyj2qG4CilsLUzfaZII/TvXzUvWfSwL809MdVBq hp2htqzgDWugi9EGStIIv0eUf1sVdtLM9moo7dzRSuyhCxfgFIzSZ/WjYruXjfsgW1iKKWOl3R1 piS7vpnraApuUHLXThlFAS64Z/BeMpt92qnJgpGGyssORXyWkOZ/lcfxIljJesdYZAn/SakCyQA YVVi6XYqHVeb0jK3vj/L2MRqpY5aZm4zVlDUV4dmCVohrNsnnJH9349fPEGTw3UoVcypYDFkRx1 YbU6t5s0KtHc2nGHf2oRfNYUmaFSqNH+iQAtevvDXzNZAoKhLd7Ttz1abEH0i1MP+Z66Dha+U0r ba8eSdbahKEuGFSTCWTMYTVHu6/Jp7xRM7RiuWqF/BX1dQ31bIU3ulhMFyI7jRq3nL6QM4gKJCr lUki0jJLg60l1n4CoWpo5U8nj4IN/1g== X-Received: by 2002:a05:6830:8554:20b0:7fa:5c49:524c with SMTP id 46e09a7af769-808991619d0mr147343a34.19.1789354917616; Sun, 13 Sep 2026 20:01: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:57 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:19 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-13-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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. 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 the ECC exception disabled in this mode so uniform data still undergoes decoding. 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 | 278 ++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 268 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 7cefb4d6951d..0375930042ef 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, @@ -960,6 +970,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; @@ -970,7 +981,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 @@ -1027,11 +1039,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; @@ -1099,6 +1113,37 @@ 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); + + if (status & NFC_ECC_ERR(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) @@ -1141,7 +1186,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); @@ -1190,6 +1236,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); @@ -1290,9 +1346,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; @@ -1375,6 +1578,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, @@ -1401,6 +1612,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; @@ -1430,7 +1644,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; @@ -1440,13 +1656,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); @@ -1556,6 +1776,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; @@ -1578,13 +1799,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); @@ -1630,6 +1857,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); @@ -1650,7 +1881,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; } @@ -1669,6 +1900,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); @@ -2300,6 +2534,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]) { @@ -2369,6 +2607,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, sunxi_nand->ecc.ecc_ctl =3D NFC_ECC_MODE(nfc, ecc_mode) | NFC_ECC_EXCEPTI= ON | NFC_ECC_PIPELINE | NFC_ECC_EN; =20 + /* Run ECC on uniform data too, so the randomized spare bytes are decoded= . */ + if (sunxi_nand->randomized_oob) + sunxi_nand->ecc.ecc_ctl &=3D ~NFC_ECC_EXCEPTION; + if (ecc->size =3D=3D 512) { if (nfc->caps->has_ecc_block_512) { sunxi_nand->ecc.ecc_ctl |=3D NFC_ECC_BLOCK_512; @@ -2383,6 +2625,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; @@ -2392,6 +2636,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 @@ -2621,6 +2873,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++) { @@ -2899,6 +3154,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 { @@ -2922,6 +3178,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 { @@ -2948,6 +3205,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 11:08:09 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 44990363C5E for ; Mon, 14 Sep 2026 03:02: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=1789354922; cv=none; b=Yrxp2qFXHvfIpJMWQMAZxc1NCfW1uCQF8OnY5oPpIdA6bbkSN+DlZFcYRaMXyedISYmO3ki6cuo/rIrwtL9cLBEHp00eknoq5LYZyQKIUvXg+TmfWPWRRHIUlcNWSWCgJX4mBMEe7d+x9dIv4Zttwa9rGtZK0qcZuRIaDWFazOI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354922; c=relaxed/simple; bh=InyBxnnGJUHrfGks0KD/ITzfsd5gn5CTfPJ5EvLq/i0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pKtxXM+LtscGnUU4BVSdKrh8FycKaweLeNZsJs85KEX0FHZcoSDhOePlyPv7JLaGwppLO5+EIx0O399nGkZj7p2BIJT34WHIinnGR6Qtt3A/4wnkf0IjpgGKjKDWWm02ifJJmloYPeQofQI50cDNmKIrWL+hjR0wXTTchwK4Vk8= 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=kfJsYctc; 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="kfJsYctc" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-804f7045f3eso379800a34.2 for ; Sun, 13 Sep 2026 20:02:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354919; x=1789959719; 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=wD0VAfBnkJ1JCjUlJIh8uFV9v+cdt2HXmo4JRu4mOC0=; b=kfJsYctcxo/x0PXZmO37cKtYMundVPFy8+eLFK4gf33alvh86B23jLjv44D62J1ahr 5fFrvB5DKR1bPlntgBtLeNqtSApWqonRxhPDcMnm5fzmMHF4opfolhil2FqXlrJgEVAR VkQrRaGTU2YTB9bSimYQWll1i4g3q5SGaPw0N8OebKK8deKnW+c8tUvE/vqsToOtELm9 VroKiUGoBHvLEf7pGqrtrBc+k3GHDdkpFqK+egYrNWlujCPe3c/M3EiTQcmqez6RAjjt p4UKAGXgcFFZZV6VPd8X2gzKsjRRM6OmfJWUdACS9AnYUFNmIhE6wlLS/ujn6ZO4gIP/ XwLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354919; x=1789959719; 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=wD0VAfBnkJ1JCjUlJIh8uFV9v+cdt2HXmo4JRu4mOC0=; b=IE8Upm0qxe6mJng8i8PgyXYYNN832SzEa4p2ljvSBA9OYYA6L2uqS19DiOsNxqy1jX zCZzdthaP/Xcrjmm0S0TFBTQbiMFcbdZgvE75Yh6bXGj4duTV987+T+VdLdQ5Ves9bmA GNh1A+axZbHzlEB6kikQEF7QIyPGmGFGV2DNL0EvLrKyCsjmswb/AMwsqpV1yO5IJJzL jSpz99Jns3trKqwWhsC1HHxgRrwsv+dOHlDlVs8+AQVs4Sa6XZerG2iqd4yOM6OibTSL t63vcBoO+33OVwzbHgbpkCv7BjIHqNyWWUpFiwHHyzNRnlTlXl2gTv707jgIP8TkyruG UpMQ== X-Forwarded-Encrypted: i=1; AKwUvByY6PMdkX6SdIVYXuDdhIO1VqsSx8Iv8GgnXLG5bJzVUVwyWsDr95KMS04YkivAA2G0U21m7VO4Kg6u1Zg=@vger.kernel.org X-Gm-Message-State: AFuF++kW/veq+GImfWavoVSuulogV5CiTC+Mn1AmiZ/uUK2WPmkzm9T4 s0M6KOfwlS+q7avvkUf3Q5WnzZVCiRHiNOzAZJzGfTTn4laTPybLPcp7 X-Gm-Gg: AYBFou0ntmca99/33SO45tV/mQ8u2YrUWdzHrAXzoWlyw/QVt0i2bzutGKiWjDthn9W 1OQRwHfDV4bwS1exfoLMlwGnj07SzfoaT9BUkkyWrQfYWtw1Guqd2DICOosAMXG0RoRK5jinBnA dCKIazq80k+tBomgszpWP3VCFhF7wnRkzPE8r5SDqjHIdtdtw+qk7pjgwtC4Fyc5a9eHvGsJ1mA CWswXsfI1+4oyJbo9rkZ+EhmWeIxeZVgNYLCSBYBBNQmHjklmHaAuuklHKSlqavbMLq8DZmDg4Q E+wulV/m2adVQK+teXKAw2i5K2IXrHJpmZhUNXqq8SjC54iQUyjbk4HImrXh6fJkULWAvmTbFm7 rrr8pNr6rXcwNliYjmK6n0IVTGwTHrINDFJQRgyhJiNg+WBL9pwNQ32rLmxX3cSHfMl4us9dKn6 dp5UZ2pL3hBCdlIyAUURLo44mRTY2DU0L12w/H+e7rWPpJm6N5FIehmtr6pQ/HP2ScGk0iykCFc N7vBnrrUroxOFnL4MJ9Zy10A/iEmsLQbS+kC814/wYWuE0nOgqzH/lXqUBX3HhSL+d91SBIqTkl bXMafx5GL/FB+a/5+O5n2GicEBgocKlVpi0Azh6liBi+lSrEx2vnLuoFq5NUbVVtL1b0+WmfBCA DQG2bTHJJTvieSwvELVEJgoF2yX30Xg== X-Received: by 2002:a05:6830:67ca:b0:800:bca4:5626 with SMTP id 46e09a7af769-80899266b51mr285872a34.19.1789354919239; Sun, 13 Sep 2026 20:01: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:58 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:20 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-14-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 0375930042ef..3fb61a10a441 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 * @@ -2417,8 +2420,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); @@ -2434,6 +2443,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) @@ -2494,6 +2509,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 @@ -2564,12 +2583,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 11:08:09 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 DBA783655FA for ; Mon, 14 Sep 2026 03:02:01 +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=1789354923; cv=none; b=VonmB/tcBvv0qrmFdzd56qXWGGDisjagHlOUvVY3+kTVgDxEgNlzi0kY9T4iHp8AGiND+Y4rlOcgFOXHCzFpIy8sBiV3J9vGKo1nRX6KEE4wBRQiPI8yfHPPExD5K1S1duijqltDpTCnrn7tSgn5aYw7LQJQSHEDxWCGc6Ox/TU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354923; c=relaxed/simple; bh=9yChzot1ui7noQKhTCzhe1/zvJdG1xELLE60VMQMFlo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AQQhN2xA+34CeqZ+IyTXUrfR0ngv8ITQvsnZEcgxkKkNXUV4wsMP/gisacWzDzpWDaXcJZloTx/VcbWpjWG08ov9sjlPDvl1YzCMS+V0ZwlHNZ/vzd8hKwcet20ZMeWSvK927ExuBoG1itafznkrG/mLPGc61l84EXSDuCLaDOk= 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=T12uBWq5; 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="T12uBWq5" Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-8050801d337so1103288a34.2 for ; Sun, 13 Sep 2026 20:02:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354921; x=1789959721; 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=F7keaBMI7wLNCHL6SSgnL5KT9FmlTHx9tj/k5MQYbvE=; b=T12uBWq5gfywAqFjPOno9Szyor5FeGw5rajKxKOqXylGoxWBadMR5DI5bcIazkk/8y kapDCyBrW+iNRgkgJ4KBtVbnNoFR7w4nqzAyHat+rGvV3MRAuQvlpVPTGAJ87HAvX+0O O1g+l2B1k53ouQA3XzZaGamXKmtJ8hMFg0ePUpobSqBMW4wmr8jRvfUqir2rplTdIXMW VVg0taukSAsSQsyJpCLHhppvz7TB2N1XZn0OmTr6e8qmY0A3zqqEs1h0zRi/Dm72IKPQ dkhZq8u5Vv0TAkuV22QMUOyrPP2DLmxf54TVRJya23WhDY5ZV/te2PiDkOb2qgPO6BXe Qsrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354921; x=1789959721; 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=F7keaBMI7wLNCHL6SSgnL5KT9FmlTHx9tj/k5MQYbvE=; b=k+4D8vwrrJehkAaESVoR/tPa3UP1wfhGWeIKQByN0z5GXYUQen6URrNwMimSotfKnN nUx94ese4N2aqQaZcineDJFbmzbrJM3Z1a+Jvl/eSPF5cjNHyv1jLgOVDDKf9Tio8nQf /ysr+ms/f/6vwaCwnYiNcj3TA8m4Zp8QirPpnuBW268j8uPktJcCKD2mm9F37nNEMLdV YUIHsMHcbYMs/XTCmNUCxxK3B1pytKEu8hsdopobJU3oVoJfO+WGi8a/hCX6T7RkWfMH 9KQNILDk1ZfwoqqaejwF1hzV6GL3NSH8sNyI1eqA4ArK4NwRelLylL2mxV/4nxOh2D+A M6CQ== X-Forwarded-Encrypted: i=1; AKwUvBwgzbcaCCRdfNysv2pvuBNjK7l5e7YwDNoqPcQggYrjVlyLsF7Kqw8ddWIKA51ASKo8K7GsuZwVpMbOwTU=@vger.kernel.org X-Gm-Message-State: AFuF++mM9zKjY8cMq1nmEOuK7Ojyfo5h4ui8JMhU8MLay3+rOPCLwybf 9wLBo3m4jK4sNx36oT7WP6TVd/fzzrgmMvM+F8MtHzgI7R8AtSJ2ZtVR X-Gm-Gg: AYBFou1P392mGB5ESohh/B+o0Wkw3DO/T9qcKhv4T9Bg0hhXW8tJm9fjwaUspIs498S CmU8lmYQzb8KGjXBXecNTGyXeczNAHmdlAOD7WfWsu6pnQaL5XrdzxG+9Og04LdsenDo8IN4LWP 85dxNW60rZ9aP2LcKNQqE0DprXwSrLOpdxgQ8i7ftuBseelDRALrguJYPGM4GkMHu3WmJDCwYOq QBYCl4FuPfUjz4Dol6XrquCZE4LoV7wuLKOHcvouwJrl7HjfIuslg6puaQfLNCE7sqq8io1MWtd DfNWBeXtKjDc2hO61Rq8V+dHqir0ZoRQDUuieNZuYPN+9V1QuXD2i5wL7Y3MJ2/VWA6mzjLz/aS 9hJuNQ7UiWIfkzCXcyrQlIY04ipZiuSQNO5bxZ+42Xjk4I0Yz8l/mSz159kmzznGuL3/GnS4RvQ Cowd8fMLbnImlIt6HvvxqD5k4Lz5vftQ1re2ySq1ClDbjSUqftYMScoPA0byi0XgiZcRBa6wyFt mccqoM9G4AndXmTjIIgMCmWnGW5beIOhFv967K/w2pS00aEDS5h6FwVUyLrrtGVV8vMY3Bimzg8 18FXz4hzWJjJc2LW3wQwEEmNpGPBDVmJhMTZqseHL0zEWYu5hPTWjdXKX86sKVoGgSownwFNmaU HJ7H+SXa5vv8p3Rz/VaCzO2oR5F4ixA== X-Received: by 2002:a05:6830:81fb:b0:7f6:ec23:7956 with SMTP id 46e09a7af769-80897097a7cmr492616a34.2.1789354920841; Sun, 13 Sep 2026 20:02: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:02:00 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:21 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-15-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 3fb61a10a441..b7ac8d7b0301 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1421,14 +1421,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, @@ -1439,10 +1453,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 11:08:09 2026 Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.43]) (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 341B8367F45 for ; Mon, 14 Sep 2026 03:02:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354925; cv=none; b=NpH/cYcliunKOkRTnZw4ZiStzWGzuNaLMBnwvUfeo1diMR7wYbQgFaLaNXAoJEII4YxREs8XmYxvBpjN2GJk4IWNyjnEQJgW48WctroeSyK179+GU9a+oqRs20JPmWcq4x6fHGWJTEEelo2pWZQYQVeJiglVHSPkiiLRFUMZE/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354925; c=relaxed/simple; bh=NZw8JcFCedJgacAoPkTIc+LEMQt5mQHzie6HVHZKZUM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dlejboJqi5t1u2rk3bbSzaWKHfKIOkTLkaOqDKs7fXuruaypwiXOW4MRuqBgeMImpMnNImmKnsiYyCaJXqAf+E5xu933/F2/mso5C9++QuwXQMnQWoswUWqfcLRtvzz/LOJgH42zKw+9ItYLXNnbRiG+vB0KGHwK0/gO0E3rinw= 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=GLF7stn3; arc=none smtp.client-ip=209.85.210.43 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="GLF7stn3" Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-7fccba9c675so2923029a34.0 for ; Sun, 13 Sep 2026 20:02:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354922; x=1789959722; 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=OyRFeG3dg/KDzFyQJutH2zdFtVEXygh+smPcYHYkDoA=; b=GLF7stn3uFUaxYF+6rQ++6ncVTH3tyEGVbMBWfAVz8eEpmRa5b00Tx3ZDHy0K5HEFw r5GlREbXNPJd6EuYcp88X6dhgwVmc2eOvGv6h0cFCInr7w8M2t9DFxcNsYAPXZT7f+TD HEUey1n4Ge+75lXcR12u7fP0aRZkrkBTgDK7/rq3LkJTw7/+rAp4BEwSv/mU3UY/DgGo RN77dEFlTKHVeZDKuooa2khyiQlYktGOrtmAHY18mkU1FLXO/abtFdwEpsEyT8/X2PBH o48EjoHT2zIr1M6jXm+4Ew7rgn+juo6v6x+TvBWqbvJDO0fTrQoEBsLEjlcVmr1UZZnE CjtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354922; x=1789959722; 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=OyRFeG3dg/KDzFyQJutH2zdFtVEXygh+smPcYHYkDoA=; b=NFNKEJvmEXLzqcrDdYOYlXNBkd5Ch9kq7xCXSTaTEFEi9hRjONJaqJ7dZICTWnZ1Kg AxlP8e8cyto+yfzpGQzbfD5A6DRgZKcxS3/1/auGOX8Hb0a5Hrymlkqaw6RqCuMBZw2B dh2TYvydyrgLVa+gwQ5ZsiWE2cZ+l8fa5rQmTIkxfC+DkOGTTiU6si1Y12yeORHr/H8g X40Yw0/wwwPrHDSMgjyskXlRrL5cBC1/5xUKOjdj/mehwAib5HBUZxH6pagp/hoTO1F/ +xm0wwjtQZTsZZRtJThhEJGjqXa9i0wpM129h7U0t8br/A6scTvR9pfi2UAHHGBzJo7p d4zw== X-Forwarded-Encrypted: i=1; AKwUvByQE1DPwc/ftmOZVaJo8DCZ+Jt5syFCad3Cg5XwoefS7ZFAICwcV97Ugb1hSkmDquaL94IDocCbZ0Wm+9A=@vger.kernel.org X-Gm-Message-State: AFuF++lthO9HEFcye7Wq2mId6xaDsnZEb9tXOAzOjy1m0p+VH8ZLPKq5 rpXLUjcfkRL0V7aJyR1DBG57kg6UV8eQ2U4NyLen+8F3qxcXppd/dtNl X-Gm-Gg: AYBFou2VZRL23zYN8zOllgUAeXwl9utp29+zXs4AGZw97HE9lB9Csq4TRuWk9cqB2qr qnhvwbU9/bmd+xEGZM1WrPSelD4Z6AohW/ICRYoCTuiatODVyjkl5NfMUoc9WBTZxPgHlCRdm9g gJrkhvLvjTTaO6U/aDH7Q3XAaXv9eWeABpSbSvwJgbUldGLVcsXMPp9C7wMc++oqjttE2BfcqoI CLVQOOdo3g7eOA7m2H1ExCDsBs63FId0+xylY54sg+NJs4kmZF9B2kgkbHDlRsB6sbBsM+moACS THoHdDBanck29xq0EBkvv4M0NZnYVYLmnvsz+xzIwv9pTS7U4UQiUK5G2j/tdOWEg7+4er64Ifi OAVbs9O6VVf/X2LTKurQNy57rdaMReiczshtHg0yUkeG26yH1j1sSRgOJyExS63fo9gURWrraoX w8d9bPOppIGpJ8cSNmYXfsnFJAObkyH9Ra5EO256M5DeQl0SnN8FqglVCUx98V0kJyA6cRzBG39 F9rwtapo27uSuX6koJPfdQsu1itYn7CYwxA9EFUPVtkqCniZU1LJIp6g0fb7ql1TUw+rfd8JyF4 PTbEeWYemZXpMQOugWDlVKrOgGbvxyfcszAmzVPvhrlv+v7HVczmDLfKMdL+jQg31mSRmqUp9vr 8ywr4foE/n+4vwE1AbIorZAmTb0Bymg== X-Received: by 2002:a05:6830:6d2a:b0:7de:9b99:a8ee with SMTP id 46e09a7af769-80719632b97mr1941438a34.9.1789354922030; Sun, 13 Sep 2026 20:02: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.02.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:02:01 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:22 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-16-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 b7ac8d7b0301..4103337f6a07 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1794,8 +1794,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; @@ -1844,8 +1842,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; @@ -1874,8 +1870,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; @@ -1916,8 +1910,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; @@ -1941,8 +1933,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; @@ -1986,8 +1976,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 11:08:09 2026 Received: from mail-ot1-f54.google.com (mail-ot1-f54.google.com [209.85.210.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 D603536A36C for ; Mon, 14 Sep 2026 03:02:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354927; cv=none; b=f1NVGcYp5Un3OQsvdenKOG1wYGBM46sVxmZm+6ZJfVdYR+8vzJu5eDWHs4qre0QcEJKEmaW4vOcMYw1NMmHENU2xVU0MvJ2YTjmmOluS/TsXuT/C+5IYLJH5ConiSOXZdhtBMIvHO2guaMXBchsrLLy7jJgPDz62hNj+bvZIkYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354927; c=relaxed/simple; bh=ySqoYQ1XnzlLitXctoBmkfL5K98OvUxXEwUoBjaPCPg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jY8bSocQgMcYP6cx8BUMcBIlhcgYXqRXSSzaP5SjDlAt+IE6iU2jjG8kG5Anvj93t62c9S6fIUd8AHCgxSaRXn7U4bH2Z5SoTL8ejHj3NUtqo1n6WkVhlkhkRUmfEDa7sOy3jqDq2DCDNXyqeq599pDo+UfLyAZ6vw77RpcopyM= 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=VcXjYGQr; arc=none smtp.client-ip=209.85.210.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="VcXjYGQr" Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-8049e44d0c3so2350417a34.3 for ; Sun, 13 Sep 2026 20:02:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354923; x=1789959723; 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=IWbz9jOOwHMkOzJhcyeNlTXZtZx9bja+bTwtbiwOKWk=; b=VcXjYGQr5EzSNkheN/pgerTEtwxKzp7tQydtJpRgumjy1HOTLM45D5nu/feXGyVXDr 4ywL/K4sKCk964w0F/u+bJ4ovFON5HI46vAA3vzuxsp69HTAcYEz3JXEQtAGR+C6hRfk qvhOqdlTy8UqlJ1snYPEgLLL91QlOPbdsCsK2mFxzvC2TUZkQQqp0klIa+4/YqQu3rA4 bR6dwZxSWB1ItpCWqDfWTXmEQNIToa0jGMa1MvvN3TBg/Ff9o/0U85vkD4tHtmtv/MW4 s2+3CNiVTzp1hqQ/Zqb+gbOoELq831HCq5YZavOuWejeqvlRnBPuOeNOlgBV2horHoGu oz5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354923; x=1789959723; 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=IWbz9jOOwHMkOzJhcyeNlTXZtZx9bja+bTwtbiwOKWk=; b=lYap7bKEvlrDAlz4/tLPbuLM5hVwGFjK7tLOmEeDjcLLg8oLDfmTYyNyNlwbGhamQ7 6M3b8YWUT0YlWNH34GGnUmzumyegYeyGLGRfWZLoIeh9aY02jFt9hbdKLexRh/uBnWf/ l/hpnOaBhLirPE2yfoZPi9lU78WKFccBRpCNPh09TpizaNZW4wShGpLsXft1Ya8af60i ZZY3T/zlUK3upxBzsr0vw6Ahw7/tE2sm9TPZOtqT5ltBgVfsqIBHWiuiLJtBVKtLMVD0 ifN2rfLtK0RYEQ/Vt03GFjWZxqMXa17YhhjprOTwA+9Y7LhLusbIUU8MgjiSx87PzYsw E2TQ== X-Forwarded-Encrypted: i=1; AKwUvBze+3eLysI5RqpCHqmfFC0K9G93vce0pCl3X53ulR43wLgIBFbU+BMvpbxszIVlK/srbrw0bUCQXOHf3yc=@vger.kernel.org X-Gm-Message-State: AFuF++l3oXxU3Aqsr83lD1iCcO1k7PRiM0FoVwnv2CUnoalA8N8HMSMX el8TXC0oHZn1giMoiyFPjV/imyDg2Nfpf/RWT+oXdJzjjBxPiaiYX3GL X-Gm-Gg: AYBFou0EW5nGeCp/Su6x1dXesPIgSFIcA5vmRKUOd9VxtKa6ORa4p8HaGvTLL8yoRga mksfQB7jmDu4zPoRAuqbqnrPLyv20y8KMLw0gwfYy+gMnNkqXQZ9GdAMzWleyAwcAzwO7+94RNS mW0VQ03Huzpsw0nngPczaa779kvsxSsidjaQvChfBxVrj2hWpHiZBXD+5H1T1sHSx7YK+mz+NSb LRfrCCGMofjD1nAtE1PMr4RuTIIw2oyvbxTtf07TmmLSsiMXpBOYA8qSVti7DhFBKs7IRnLyazT 7oQ49R1NMy570Z34mBoL2oDmR2Z9XAPA8IOrkD9MBKI2zT2wlyQp/c4WntJO3bhgwd0KcNhaa7a YzUyz42E3QiKbl8W0Wb6GoQS1fvSH5i80a1eQE3vNFCadvh0EgA+Y8bjTJS4A8lZPxjPA6+DXV+ lcn4tNrSaqArxXeMrWSRkQeCQtLGNxhyvo9CVpXuGuDsXB3ByOse9G0KodY9R+N6eSbqqL7JtE4 AIuWQJxO4X2CN9sUISNhVyVOpFSMY5oQBadcRa+qDW3RdnVruYrLwiRyOPvxRNVATxZfnyvEfCg o9Ng8ouKT2ryvqisOJVUoNUJY86ZTeDPaGGHLXswfKFCEw8UNyE98yy9++aahhy98oIYZmHhQPz 1Yyu5jTKGCDQsD+X/aCdUARgnsk+1tA2sn3SJmt+X X-Received: by 2002:a05:6830:3888:b0:7e9:ead3:4449 with SMTP id 46e09a7af769-80897489f75mr263437a34.6.1789354923503; Sun, 13 Sep 2026 20:02: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.02.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:02:03 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:23 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-17-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 4103337f6a07..2b8ed142c9bf 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1005,35 +1005,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, @@ -1223,7 +1248,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, @@ -1540,10 +1565,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= ), @@ -1733,7 +1755,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 @@ -2037,7 +2059,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); @@ -2045,7 +2067,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 11:08:09 2026 Received: from mail-oo2-f16.google.com (mail-oo2-f16.google.com [74.125.231.144]) (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 1D38416A395 for ; Mon, 14 Sep 2026 03:02:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354928; cv=none; b=MsBVIakJqEdlhFWWP3y6ke2vZB74vd/JwERszejKOAT7V6rbaseiN6K/W2OhiqSUvzACgmJ8LUmCT/eJ7jIXDJlUyjrzx4p/mjmfNgawp7p5meX5328b3mH/UIPKSSN9gkoj3LCcnadXfk9OEmgEAO2f3ybCl54/6EI19qzTRvc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354928; c=relaxed/simple; bh=kb1Gsrib9J7X5Iu1bioEkSbneNLgmuqapwHKJriwhEA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U8yTph9xXBC+uZs8JSYgkwD+ZnPCT3R2R1WunIXesm9MQkaGcl61Bb3tTVbKHPSC/8o0livumjpdtY+spJjEndUyHU4lfuksa7dEY8/W2efRBxmSw0zFzUlj/orwkN1bCRqQHGc7lEwKRZcOQSGuznoShaYjhzkb028SlF1WfjY= 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=XSQVn/s+; arc=none smtp.client-ip=74.125.231.144 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="XSQVn/s+" Received: by mail-oo2-f16.google.com with SMTP id 46e09a7af769-805bf8c2661so909908a34.3 for ; Sun, 13 Sep 2026 20:02:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354925; x=1789959725; 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=gbdzTooPdY+KDhtZ/QzGrAlPMdYJpYAben39hMkDMIQ=; b=XSQVn/s++BYV5iTOpxHHS28EUnxCvMPD2NXmFkr4Bxhmx6Flw5EdK9yY0PUkArJDMR ZHgAfoyWwPugUeJYwy/rbcwdLnpRnFhiaaGH+4s/N/LpVp/gxOqOcIx73EXiXbbCIZHe amtl7ivLwEn/TOhv0oxZ5R8ngqi6ycPNNJtINj2/hrswKt9F3TO6rQGR7nmh2d71S746 sg9sYVPNZRdxYoorcFiWoGkVRyULsH1DBQD9YbTtqNHiL+zSzBph4YXAw8CM8pyrZC9U EihYVWncdNoSH7W8A/0mgBg1gNHM/GaBzNfUe7OkbWMYxBvILefkRNNOpIQSl0bhBlMe nrUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354925; x=1789959725; 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=gbdzTooPdY+KDhtZ/QzGrAlPMdYJpYAben39hMkDMIQ=; b=X103WRHn2uvYw33kiG80Fk0MYAUJ809nSMGx3CkRsPg9RrDEaJftUMHXc4st3Pto+k FczpLNm+/weQaPERt1/YPf/NuxjtMjG2EqnhYz4hhtM9M469liIj11XOk2SIMS5KJ0uE dDatQ9c9YaFlJI9qQjCIuP2g+IeeFhLfBVxAIL9qZyzC0VWTI98rbMLBIRas+GHazGKw dSSsvNRjwjPQH/GYvCo9T8NrKZBXyZo0WcxYI36faN/NANULRdR7CmvLLugY092a8nV+ pSvJCwuHh4nll2OKyZ89+Ao+FbNZsShtkzCEVPp6WHvgS1wSYkjnvTAxv7JljztW9lHk eCbg== X-Forwarded-Encrypted: i=1; AKwUvBz5T3dAbh19nqY4q8nopaQjl4U+47lFj+cO6Gs3fq9rdkzjXNzL1QR2LbOZp2Pm5xA8EqMFIXfi9ApN7SU=@vger.kernel.org X-Gm-Message-State: AFuF++lHYt3j/n+KmxzXBXWEm3vNG2r49mp2/DGQ9oKFooxKsGifbD2p YNnm35VwdlE/0UbwuPaNFqXoIFkt4QM0fAVPVafB8NJqhn9XnfXj8F9L X-Gm-Gg: AYBFou1dUhjLrQtB4NflDpgYNF9MIAiLFTQj9kuzdzdsJz1cvSCrE5mqUI0NRR/EXU/ vfq3zgdK4LuNl6Ql66yejPALsMOUdsjhcujx2ETnTmDYVcu92U9GmT7Kdue4qjxyi8BMn8EkfUo rOoY3YCpLKr/SxntsX+5nIxrlBTWTfmYi3j+Q+y3Ah0DVL19IhHKDls+b4saYxgQFQ7y44vbl59 RYQr3NI83eOhfsFM8TvDmYeDVWfnjrvdR1p1MH+4yD2zBGDDGV85O19qQllT0RSajnIXepTXALI 3fAmQM1bc24eLxs8Z0nbOm08lG358adVLqFg5O7q8jGwMKUCBxwokYwQi5bSsS/vky3yC7TCYil LU2bTQFhAxvS4RbKDAq02IFbWdTvjhxfy5qHWLx6A57JtI8dHg6Yq1h6kA+DtqyfitcTrqQrCA3 iaB/ml1Y6EhFlsNs97STRbby63qddQ/Iye+zvdarp1kV264ttoD4MX0GbvDrdW1jXcJBYeIQ+4b yQ8rPwaBCrGGDHtLxwWJvBvvGctZYxPMIVoyfZSi63TxNf3XMnh9Mz+n0IuLrY3SsXFq/85rz0t VaI+jIEdgBkJsPjiYn52oPFy+45Ncu5M4vAYWONZ42tz1fNMgn5hc7qOjjNqT85NnSM4OVWDfZC IPW3IpJNBIhoUEPJfipNLyhsdFProug== X-Received: by 2002:a05:6830:719a:b0:7eb:3af8:8c09 with SMTP id 46e09a7af769-808972915a8mr274412a34.3.1789354924870; Sun, 13 Sep 2026 20:02: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 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.02.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:02:04 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:24 -0600 Subject: [PATCH v5 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: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-18-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@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 | 101 +++++++++++++++++++++++++---------= ---- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 2b8ed142c9bf..4af2a4f36d2e 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1149,46 +1149,87 @@ 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 - if (status & NFC_ECC_ERR(hw_step)) { + if (snapshot->status & NFC_ECC_ERR(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; @@ -1204,9 +1245,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, @@ -1221,7 +1260,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; @@ -1261,13 +1300,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); @@ -1275,8 +1312,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 @@ -1541,11 +1577,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, @@ -1598,9 +1635,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; @@ -1614,8 +1649,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; @@ -1623,7 +1658,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. */ @@ -1650,7 +1685,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; @@ -1658,7 +1693,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