From nobody Fri Sep 25 12:04:12 2026 Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EADBC383339 for ; Sun, 13 Sep 2026 04:05:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272311; cv=none; b=jmDwcakcCmZSY6a+r0Olnu3xxbOEGXRvQc4ukSsm/qhhJNiNXVJ0itYYzG55udwDlaF4IO8RPN/Aw8QeYHSngq4l7h8PiCPKhmx1HPjpiaj1wfA+FxKJfgKTXIPzQZ13tD1VpLhlPa0uySHUUYlZM6M7dHjRYnRL/V0xuePx/uY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272311; c=relaxed/simple; bh=Lpu8BYiYZNteYXFlDSxlBr4C2CnU/Gx0SiTFgcn6nP0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kB+xKqVDOI2PsGX6jwmgZRAg8dZndv5pMf54Py5CD4DvvmP2y9yafnVA8752T5LzFiuQkfHzNCIZA5I1Gk81/x0z/kAy5MvJvcR0iu+yg1LyiPeYKIIgkbREZMkp3Q1fqRm+KOAeS2zvBy0dUWkPYONWbU2hc03Bl/MEU/B54hA= 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=JVA9kFf4; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JVA9kFf4" Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6b390bcab0cso496588eaf.2 for ; Sat, 12 Sep 2026 21:05:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272309; x=1789877109; 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=JVA9kFf4U6G9eQBDRF1dMDwojUBtxmSAbOxiQAI/9Vn6az0en11BUeP2JXB0SGTz3c EFWXkK6jkzymQfz1ro0r0tALG2fvn2Xv8FXB4s7KsAbBoEJ+wx2zvvo0ckVH+BYLlPKm Qc1xKJe32AvF7+0QY7ByA2wyn8N6ErbkBhd42K/xJtQ+WufNppRu7ZL0x0/AeFAIwv0D uytNSDHCqK4V7DzQL7O4twTJ7duTlnDUTW6DkOiuQHSDaXztH90rMDt6RYtPepNAzESR YUdcRGkryJojFEixNrQ8P1/c4njP+vo7s7VME5Yvnoahk3zJYYuf9kxtdl2APm7aNziR gNkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272309; x=1789877109; 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=l3Guk1ZXQ7eJDy7uNMeG9RqwV8OEIVXIt+NA4E1UcwDnKc6UKJP2vyZeNny3/BAUBV bokZfnWXLCry9gHUdER+vcsaELHv6obB5DiEnNC84LwdTsmvUWWTeSvwL3O6oXRjA/5V cX4aIgn1TsXY3DSRLKIehUoaAW0Rx8lWRfXJp9bejLr3HebA1ccYzkw5KeFDpstDYHeX vTvHH0zJlexlApiTMtlhmYSpOPA6pM0cjchp6ee0WUTvR1tGTtnN2UPXch5akIQi32pZ NBANpl3OVup4Vs0IF6hdUCgIw0yyIZfdXjB73fPDRyDxFJQjk8MO6Ak+m7a1oSdT/mE9 M5vA== X-Forwarded-Encrypted: i=1; AKwUvBxTyBPLE29J0nsv2YY90deI78NvKKqYeEt0szqpB2SxdRO4SxwDniNjNOBmZ80yef3Xbt77zVo+jchiKho=@vger.kernel.org X-Gm-Message-State: AFuF++n6iG8Z9kquUXBF3bjghB6wWD/toUop8NqeMxsILsmVtQ+rQRi5 aKe71U14hPP1P/r7UxoFYVzPxtOFynRpspogJr5sJ37ooWkCczdIUljf X-Gm-Gg: AYBFou1yve2bh4rJkqhlgt9RvLWY1/FpkeFgm7k9C0Anar+riRjmcaKBcLX/25SkkIY sHYpZETVSLsYK23INWZiGCCaDmpobpMD7pk7dcR1YFmD+nPJBfNmlgDQpwUKysIIDi0D09Ruj5n umAvCVE3lEfg5Zs8DOUPn0sDJRsiIOyPbWpYwEHTKoINEl13CD0KAa0ldWjuQ05GdEjEINcSKH3 94i+2EM/t+3hct/+TmWXRMoCcV400gm1yVcVVI/INadsXhB44g8j+ibvytv4Bab3Jwzwkh5Pw5Y uzvcuVp/lRepJRakJfP/1EHdAvL+SnX3iQceyCewVhzZuuH21+hBwvAGQtpqnxQyr/MvlFOZ2Y3 EqznL31cZywEXYY2qjV0R19PM1788VjpIGjK7vmK0DuS7UUwVARDelV028lB9rmlVd2z9iluspo pAv7JYTAQCcbFwZZ/iEWiZHJat/BYcEo2n9f0AoLpyN2vlobDcKKtYWVshS4Txn436Iqjl1465D a3mYA6W871uGae3sS43GN9cX+XbgOv3XL6ullvGtRnGxpccRe/huM2v3EK3ivlM7OWHsvV/Rb2q 2pMcVaE21G2j8bB8TlCSYPk3Oq1k3JWBnn7bA3I/ukrh9NRR+ficccvj9KGgp2n3ywLM/P0SV+l IUMhmhiimv/e22r8N1lkdD24QzCTM7A== X-Received: by 2002:a4a:e90a:0:b0:6be:8d11:a077 with SMTP id 006d021491bc7-6c24f2660eemr2474010eaf.67.1789272308682; Sat, 12 Sep 2026 21:05:08 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:08 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:52 -0600 Subject: [PATCH v4 01/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-1-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 12:04:12 2026 Received: from mail-oi2-f12.google.com (mail-oi2-f12.google.com [74.125.231.204]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D7F4388E4E for ; Sun, 13 Sep 2026 04:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.204 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272313; cv=none; b=cwhcyoFJOpv7uQLDBIevdC/1D7R963TCjQu2r0rwM0LiJhV1yWgJksG1ENRJ9k+Lv9ga+EtZ7f9Bi8rc6u+pYgYtvrbHXaZXWNuXx2IKTPMcwUUV7P2VmlMjwgqcIYnksNhFjMyvfZoklD0Kftg9QDRtYP3hZmbAThJdKITLYdM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272313; c=relaxed/simple; bh=pCshx7KzarhNGja6hjwZgV+xF1fwWKykuklNPxmL+JQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=e/0SiMa+Ih3OW/EdIPgp2o9sewTivFUJusl4ZKDLbrPpKzh8BDrza3sLz+KNXqwrPp6Xy1bQOVfHX+FQRawdNyzdv/lcgimK8mxZ1JX/2h6RtueGpsGUxGZYvSeUHWuEUhLKYczYLFK9mP8XAk+42nKC2xrryL5ZCr7Ny94d1LE= 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=Sp/tvFuV; arc=none smtp.client-ip=74.125.231.204 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Sp/tvFuV" Received: by mail-oi2-f12.google.com with SMTP id 5614622812f47-4b37a36887bso615209b6e.2 for ; Sat, 12 Sep 2026 21:05:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272310; x=1789877110; 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=2jxU2MaLD6ynlliV/V4nmXeQrG06Mf6j7bRrOAd0XuY=; b=Sp/tvFuVlFbD4b35xlyAKhUd217P8aP5knPQuKC4FWwd328S6+AzfQygKBD1juXdVG t75Il1yuRi4HdqncDY1QX5jOs8nZ29/6ekFp3CAuaGgyUz+6u8UxdKH970ZlFX5xpXwJ HwrucUROkh25gBtQ2jc46HlIRd/zNv5X7trDHsAFaSRgFYtsCzHMb+ZUOIcDcSVL2lFG FiJiWQt0youwYd/o9dZEgOaBe4yWsdqKhiBUCn/p3S5uymVkVoe6RWyO0ZzRHD+pqlvX nv2b5pmBv/O7nTvWe6v9chrEj3JfJW550ki8HeP4mqg73MwMbZbV53oDfsA1MxKByWq5 94TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272310; x=1789877110; 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=2jxU2MaLD6ynlliV/V4nmXeQrG06Mf6j7bRrOAd0XuY=; b=SUBD6kyST5ui3tbkPXoYEJT5sspTDlH9GBNkMv97ND9BAfNgK0wJ8rICw1yS5/KFTF 12SgZs8tv2I1hCPz0sm1Qhy6aV0JBorOdlq6HAKwYErYTMTjCsSH2mLqlQkkWS/45J4t hmVnc8Ezx+zb0eV/3QKnaG2ZPVoaUYsnFajHIo6o7SKtJI0biv95BLOwiXrhV5M/AVx3 tVKXr1MwQHTrQNHk7ENVJSElXDnDfY4ynKurE2Drjldb507+bwAVfwdVOL9CW5FzfU+v rXSy5AVUvZyFQDRKDKJy8zYipP6+fJl+JWrqzsCBvWm15avxtpi46jcKe4kD2un7dBWJ QsrQ== X-Forwarded-Encrypted: i=1; AKwUvBwYIEJtYisVmw9LfLFDjHxHa0/Cvdc6Rs1iZtyTI5RPuU0m9dyJ71ZGE2Nw5osPgGEzqGzCzD8oSbgg8rM=@vger.kernel.org X-Gm-Message-State: AFuF++m6AzhYO5YhZmCkUOyQIbUQSIwrrkyILnDV2nI+7aVUcm3VhoCN ZtyE7AG9v0A0WHGhhFNm+EvNxGVdCKjmyN4f8PwOumMIh/xd3eFiVd6w X-Gm-Gg: AYBFou01vhHu4mMV/PT0drwOYVQQKcBMVeP8hXB5boRYGI5b1T79eQGrwDf+qlcD1Sx +oO7PJ4IJl9PF8F1XFoOeOOdH2OizpCCsKnSKQhXnka9eiNS9cIWHR34wtRRZjDV57F50ilxJ/6 pVl0wSerRyC0B0ZRnO3om9XUb7d/Ec+i5/8HyyBO4jo/yw2WuZUjS4NvA/Si0ZqcavPMptLwQst oJxIFdddh2u+ZozXX0Mpnjo6eB+PbjQlr5vxmDhYTjp6/3ntY4I/PUkHpzorPRvt6rsDMVhCfVl enTUNBy8hjRrsOp6BffcaGi3nJCYa0v/OKX4RkudZKA4l2+5DhMDfai6tG18H5tgG5UgfCsq4B3 aNMx9TR06EmEvGMEXh0Mobl/kzz6x0ZKS0C7V4CAQYYEE0/3z/Frxq5kBvwUYqbOD6chi7o+gY2 TWQKZdxYZCIuKC0SVvd9P/Uj5yv4c9ksWKn1X4SZl3RW6oHChrWQ6jUdts4mdRoQPpwzdLroPFg d/yVXObm0zBNmWXBjOcCdHX0rfEwMgEzYroNUPUUMxZNmqS4o830hkTp7ppnwtqyOzD18U1g49e IQw+laCKKVCxZGA0PpbLeWJMbDhagb4NxMIK7O11mpBlki6LzChJbo5IRvr3qCTzjGYuuRg1o6N YLkUwY6Ey8FIyGkpcnYlh60mcZqo5xQ== X-Received: by 2002:a05:6808:13cc:b0:4b9:a8ac:489 with SMTP id 5614622812f47-4c31c8306c5mr7319934b6e.39.1789272310145; Sat, 12 Sep 2026 21:05:10 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:09 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:53 -0600 Subject: [PATCH v4 02/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-2-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 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 8DC24388E43 for ; Sun, 13 Sep 2026 04:05:12 +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=1789272314; cv=none; b=EGpXZO6ozHABAn2ocQIxUZuBDEO6M5pIAWL/2w45klx32GfLvHTJzeyx1qM0+yQNsQD41GYhrheKCtsf7fSwIrKS0BREKn/fCCKLyGChFietREHfcXrnNaVXCCSXULw1G58N/pSKnXCUSUaQrt0R8NEbD4SHmwBTqN00Rjxnb9k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272314; c=relaxed/simple; bh=1ofTSNVZqDsQSHKXpbBSZfkmR0m9OTYZB1KI3A7Jry8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Yjf4YdsGxFWngFsQVufIocD5jeCo5tbrUJABgQ4vTKLgPEYWMDrEvJx6oRZ+n+MK0AwzgDGig3jcQW97Bcw6ZWJgdvsqNCVztQlds30egqwv7Zn2gg+SH/k7IgikRjIBImusF1SqOxX8DERs6U15pnCrwPHA/bk4Y70DyehTXho= 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=THfDJXeO; 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="THfDJXeO" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-466ccdd7695so229858fac.1 for ; Sat, 12 Sep 2026 21:05:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272311; x=1789877111; 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=hXoUvOv6OG+lMdZt6DQEcnmCosxaVhf33Z8ty81lQ6w=; b=THfDJXeOduyFlKP+etrkWvcYOjZmGpWftB2Y9eJPnr4eMaFU7+BE8ZXxqUSbN/azxA x1sp2h1sSKRnCBzV/tzCCywQdQ4OtoKzfT/gzb/x6MiYXB9KENQObRAQwKx+QIg6TG4V pg7HX92Sf4zRN2mrBO8T4421q/TgvwqrMG/tLE745pvtoqQQVSW6ooJk1RaQ4u9CxKBK gT4F0v2EQO3pltj0N3oTJ+jLEsNlUYVZx3MRFiVCITsC16J9D+o7DAMjtMBOlUEGJPuQ E3nl+QUY1RG9y9CCmhkB74Pl+bq8y2sTJcQqZvZHO8ytqGrM50Q2VKAZJ0Tz+qrj2DmT VwhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272311; x=1789877111; 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=hXoUvOv6OG+lMdZt6DQEcnmCosxaVhf33Z8ty81lQ6w=; b=G5wkd67qu75nZIqyufRygySbVywVrucOZAfTV5gAqtrzeGa2vvTW6iw7j1IuoSxulB SNEJiWhvj+xa4/FsxGtxCJeA5nxsR6dqNBoakMLRRAM+EWQ7cr74otXsVzxUmQYwICPt drJ0yNdIGzRKS4wLjz9jpq3Z1VKWN8JTTPuX4uRkQF6RGoYZBobqJrTIanO0LHDGktnX EunBbGsLm9geOWXQZwL0hdCclct2s4P3gpiF8Dx3LEyBbEJHW9T27JyGwg/cEwc7ao2b vUchTARS51aCI5jSHht7fK8TCoGAN1DYyPJ1eUobB0zwLI7QAOifiqyWZErzFKNkb4dn 5sDA== X-Forwarded-Encrypted: i=1; AKwUvBzIoPWIfUYxFgGlfe37txNX5bavtd3DLbeMbdaJ71N+PuUlxLaPeVn8aes7kZILpA9GeNfFKkbP3trQKUE=@vger.kernel.org X-Gm-Message-State: AFuF++klwuQydihaCh2wfTjr037v/i7BQjqi7nNNdL8daXaHsV7iwTll rXiDl5jMXPb1mQFHqdogujMRneMBfErlIPdrr7T4LoqMK8xdLws4QIKA X-Gm-Gg: AYBFou1KbbIUIsS1j6HkNrbwWWcdcwXGqoIO/YXft4wacx5jySY7IdDXd0GrbHm/qVi lZBVy6+HAT38d/4vwDU4Y8ZKQtzCKVrxvFe3dOadetQeKZ7IXRp3kojpmO2wMmVocDeCntGQiXE cSmL+we9nIwpAoJBulBv9W07shno1GyRznI//SPqTyCSMJ/gjtiT7tC18oPNI00YNw08ZMlLnBX qJro4iYXG5ajgzGeR3QwAAzeEAQPvPJUjQDHfyivHcIL+BF67N8584tmukpJK3NWAl9cx3VKiTm KZCs/tHc1LwPgbpzWOP79DH6nuyij7HddOStuloDG+Qt6w1IpK48FEQC90yho0tx6jYDIiMMzH1 1cffMfhj+3ejLuSE5pOIofEt4SXHXWXZJ2+Ow0NAUvnav/qOa4+atwL1NBTDPdmHDB1jt9OE48I Q0LhQN6QiqDcnR8haNsblKmHlRlYtwH5ixVfdds2FJ0o06F3C2V04mI2kRIKTjQwqP+1UygiYLM i3pXEAa5Jku0HjuR0fF5DVGToc+VgQQCDi9vkbqxyhZH3cOvXgjEAeWWSm/fNIWLCyVx4nH/Ibg WtNDLWBN1it90NezPjsXaIJHeo6G6t7zFQKk/V1MBN4Ztq85hwMZw9oT43E9HgS1fOe1C64Mklu 5i+0w0hEfCCBnBqzyvh9G+4iksbhYXQ== X-Received: by 2002:a05:6808:13c2:b0:4c3:bc5a:def with SMTP id 5614622812f47-4c4a7a390f8mr3678679b6e.6.1789272311396; Sat, 12 Sep 2026 21:05:11 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:11 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:54 -0600 Subject: [PATCH v4 03/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-3-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 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 1B2CC388E7C for ; Sun, 13 Sep 2026 04:05:13 +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=1789272315; cv=none; b=o2qUTP6Qv9rJ/YF/w/Vk+T2mGOjK2yclpVzWc2TiFsUtpXO73Cg3ZwYKaDgqgPKeQJdsUIP2zMkQMnz6scsRdRbmrszgl1HnEiodJjNm1KxWrElO3y19RCjMIM0BgLS1UeVvZI01fw1pRB0nfgcD4yWOitzGloM98twbqxt/qPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272315; c=relaxed/simple; bh=7ad0N1K59n1v3Jr94aTA8Zx53dMLKuYLMcOiZWOAZ2o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C+qIIzkQV4BgR9COuFsv+DWvy9mBrlDw6UUx5g60aUEJAol0aU0UjtPWkCpkvhrGBz2VTqVt2MgJ91tS4KTV9q/ElVfrnFJj678QlROUNy/yOVYJGb58iG3Me6J4LohFxO0anay8RYnSQ8BZuJ7a67Z7jZopN9GC1krA4UOh2dY= 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=ISJRY+iV; 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="ISJRY+iV" Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-7f4e729368fso2426526a34.0 for ; Sat, 12 Sep 2026 21:05:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272313; x=1789877113; 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=zvSS6wjgtzp/kp5vxvE4i3FisWUsufvg/JdfpaRzj0w=; b=ISJRY+iVAMHOvV2rxFgZZbY/U+8/EyUo2wrucZPwTO2RpOOSNOXDVEDSz1Ybfce1ya Nmva23omn++omdYXMi1GpfYEIXdl7PwtcR7oFfY/hctytNH1jz+S9Rbmb5hSFHyC6dYz uRxRZNMXKZ7HoFwXQQyy9iwNIVZ9pNOnXyTxoCTzAyz1u3x73hLGvMhrvYaT9+jS7bAi SuwjZw3djysqXOUS6nQ6vUS9pzz3fDg2EZblrH+5Kw+cnT72tGp9gwVDB6DGZatyM18P jimsv12mVEayAKTsH45+7nvbAbINJ/WBS79Y2xthaSH4tNxcw9Oy7J5rwyrdS2Bw8QhD dpIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272313; x=1789877113; 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=zvSS6wjgtzp/kp5vxvE4i3FisWUsufvg/JdfpaRzj0w=; b=i1Q5f2dTVzqdSxozk4qDdKTwTU7i7H7vm1k6wAr1SjDJTi8kOzGhVuob/+H0rtvAFH HbPvfL5vsuGATfB2CaGvZjswPHnWtboPqmccgL3EGDIwAHXtHNJOH6bBJQoVUbrLR8os 3kngaICJRkFaLcIjmNBnpcmB47SnO59Bt+ScdUOx29zid7Sne8uDywtn//hjSQbD8YAs fFewJMGn3BowKuDj1ZEeBcjdlzORhJPAIhV91bCKjO0RYY4sWD7F+I5uS18h6yNu/u3X hKCkAJ6X7kYxNoD6hX3yi35DBXXG/YM1LUFQ/++68CaiVFeX0xfwKyGNy5PAsCJ/Fh3u xCyA== X-Forwarded-Encrypted: i=1; AKwUvBwlRmbtnewwJ3kAOmQHm2K8x0l/IvjQeEodAafzddW1fGziL0PPhnDO0Cq7yJM6qlrYVcjad9+ki1biWJc=@vger.kernel.org X-Gm-Message-State: AFuF++nOOnrBmrcZIZ9/E5NPwCFdMdbnzwWGxecv0qFzrWWCKbesRImZ sYkDxFD7NznF5fK0Vdr14fWfMVIFNCVlJP3RLxGpIXUGSH3RF1HDf7Cx X-Gm-Gg: AYBFou3f3n5It0keDypb30/qCa6H9y1k81IS5W8R5ut3L9+dBkvgAdyaNSz55vdEfB0 NInxomhmCdPOFHsPxED4IStKnSyMqNkMOgDhHwLzAVfihi0OwQs0Rb4LkqX7M1/EhJludpmt79/ +715WHybfinkaEX9nInFlqAFWFZdFUm9R/3B8dhjB1dnIZ7IFOaIIS/rqU4JwC6SmT5v5WxiNfC Ipc12e+wNwniWEylPBc47tpLqSG2vATdtVEnNhmNj/zSUjURkwymhO52vydOHFxARzjbvY2SDX7 U3KiqAsZofurOyvimXiuKNtGz27DWmmxL8jCDJTJlKHt+XxMIJ+cr7L8HLCNunHN4rV3r1OTfK1 q3B2B5gHH7T03H+diyxL00CHwoaEi71mhKEhNJapQ7/HcHEpOafO3Rhu62EDbeVAap7qmFJ7Dvo u/gYsQwZg+A5fa6cJ3TqCdE7WxN077FHpRwek1KrXL4J4EDo6SwpFGIEQvRm/RnhIe9DAabofo0 g3LcKMB1Mdr/mMtHTWI0ntMOV6IIUW8yp0no+GXvsw9gHxTgrR0NiRO1PVit/uEtpzTf6UtcBnx W71OvlKTspbRMmeGkBBsbVOhHUpUbK7Yu7Oq5LixUw0IVVKYhjsUn2szaL0hEndTtRSTX2l3Ang UlgUy2hrHVnb5puqTiLXjmfnMyWzkMw== X-Received: by 2002:a05:6870:6111:b0:475:e235:902 with SMTP id 586e51a60fabf-47dea515f36mr7446958fac.32.1789272312951; Sat, 12 Sep 2026 21:05:12 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:12 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:55 -0600 Subject: [PATCH v4 04/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-4-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 2026 Received: from mail-oi1-f176.google.com (mail-oi1-f176.google.com [209.85.167.176]) (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 0005238F630 for ; Sun, 13 Sep 2026 04:05:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272323; cv=none; b=f9H1xT7XE3juJM1CC4O9DPn0+iC/FXlfIUEJ61qOTU0LlAPoJPmaVT8SwWZ6wjqKvZApC0ymAiMllNKJY8wV0JrbJ8L1HpcmqAivu0uKNqTOYxl+fol3M2XO/inSujqS68kP2u75bObyu3x0BKsnKQ/0uLZXUBdEw41lM8cbDzg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272323; c=relaxed/simple; bh=ZVisc35YlAHASgRL9Dg/dczoW+VnaymOjG/nj+ZynBM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CUPSwpl0fehXls7HAyCTBvz4wvABK0TvcUfdQW3Y1T+9Q3Xm7up2ONBR4dxdil7HVzsNChVklhB/j3bQXLRCmQWgIqDvhthoTnKiPcdiuOjqkPbUJ01d3MtruPall00EkesjwlZJQHM2EZPt9MBWEt0ip4JoQ4Nv5IbMSpYjcEo= 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=MM2FXVbJ; arc=none smtp.client-ip=209.85.167.176 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="MM2FXVbJ" Received: by mail-oi1-f176.google.com with SMTP id 5614622812f47-4af173320f9so1657270b6e.2 for ; Sat, 12 Sep 2026 21:05:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272315; x=1789877115; 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=qvHpZ4p+GIyvL8ZBW88R4SfXXqB8aP1HME4Kv/dMBls=; b=MM2FXVbJasFx45zvbhckhYsR37nQ008G57Sag+vXx8WNk1TCYS1pUJ5cFJqJ7/LqtJ QNbVb22LwNitmLHesFmdpuHYGNEetnA0/GxCOvSSqFaunOokmRLoU4NqRRqrvjDXXi7p k50lIuvbwWJ/7pBL5oJvjix91HDMb7KVvvBRbT88KsaZUnHsdbVmNG+c3xGIdsVi6+ND gjWwgcHP8eFLxKgCLYlyqOwtfZpkSNK+4oFbtDs5ALZG0i7yLBRx2Tsdpvk5MRynNhwD 1B/XFdgB5T7CX/VNc1wwAUsr4At6Bly81hYMXdXjMWwDeddGCRyk1KCQEGvCr1EL+CtM 6UCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272315; x=1789877115; 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=qvHpZ4p+GIyvL8ZBW88R4SfXXqB8aP1HME4Kv/dMBls=; b=ki/p4d7gpFplWfpKkdcGO/TvSHAF5/Q7MObIayomzmWBtxW1jDwfCa8Nx5Q4dP/anO NZotmRp/rhZlpyITTMiafx8lLDgPlowC/W7pwqjGhwkiaqxiDJrasoHkXbQUWEGgTkZy 6LAzAF+scMNhQ5EQ0WtbtDtWRXt/QCXphWZKYphq0UWCjMy/g3zAoBNNUquvoM6zNN9s S7y/8+9W4xWK1ur3GaaoAhz6YIikB9n9B6YCa3IWsjtz5xr7D6l5VKDvNAWjokroFab4 MuP9evAff5NedXoaP+wgorUUUqF8gb2TabhD6czFXs8HqXZGwBy4r0pJx8pJ+Q7Z6Yrr OVAg== X-Forwarded-Encrypted: i=1; AKwUvBwK3/uEg3hWPu6s1ROBZ4lA16nCgIw/wL2B7rFU7sqgDv9czach13SH/HA8WR17omnqilWGgFdIgY9i54g=@vger.kernel.org X-Gm-Message-State: AFuF++ndfwxe3RqXsjhCR36nN4ABqkNYkrVpNkVmUizRUhFCJtr140L1 g7p+R9u7tx/rx6k0WliNEbroisY1AntaE09bPiuSigYVSr8hhhh56fxm X-Gm-Gg: AYBFou1dZDNSvwzCYlw4y2wKqx4CegJiMVRBhkDwnys0F9HsIWa/ABrGQg49QdB8a7O nvaIgr5oeOqDKQmI90hfC5cqebkeXWigmQKfyB+rKhOSj1W6A90X8c0rolAWyTTgutEi73kmwOv RC17alE1olXD0K7Bzgo1F4N5UQXm4bgkllR5rmIC0iKqWMSWQfPdlBfWixsUa5CG1A68KRf15hh tCXSuvun/65hBRfUqK8cSwhX1Odg0qh3u4IukfwZqcY54yEByAr5RsSK8btaNEUHG3MZioFIj30 lVdoqlzai1oimGIHMMyjrSQi8/ULTaCdCIa93w04C6DgDCoBeXqyvTKiTi+CBOLn5B1sJgmXNo3 zvjabYcSA2C3ATkbF9UU9SzwsTRmbW3ldNq+ynWWwqj+/WJj3ZDCCktcAiiGwlsNSmeL/t0fusq dD6+cZacDQJPOVnxtS7RJzDYJsgNU6Xo85L0yW0Gg2RTPkklxxZ6z+NRxOKVK8zRDK42jCKR6I1 +RE5/rqz5zvRdlCzo9CrJ1XEvAHRI08ywWkyaYeTxBbB6RkTRsS4fsd3NsO0q9B2snD6ofAhApt ztfqVHb+8oHtjktCJd/47cIBDNw/RP0oRl7Tq+0lYU5IGmhs+/dT8Q11tNat9LlVZxbFx41b8V5 lPGut7QkKU5jfY5EzXJQDKq0JG+Ndkw== X-Received: by 2002:a05:6808:d4c:b0:4b9:e5fa:8907 with SMTP id 5614622812f47-4c31b4c5e8amr7737916b6e.26.1789272314888; Sat, 12 Sep 2026 21:05:14 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:13 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:56 -0600 Subject: [PATCH v4 05/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-5-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 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 7E90338DC67 for ; Sun, 13 Sep 2026 04:05:17 +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=1789272322; cv=none; b=E3+vUU+Njzf7CA/Z8kXU2eLprVMVlcUDeLuJ6kYT4VbwqbmMBuTcgUCjIobdAbzHVbSMFdW7S6RgftiUInzPzY9lhP1iJCoavYSrc50P3lEmzRp8vvDJwt6kr6Jv82m+SCW8oVHhzhM7D2zVA3nkF2shiUPohzRXwEd5g9sxYTw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272322; c=relaxed/simple; bh=BwaJyFzlFHttOpzQWC5cJaXOsCB26F1Sbm59Qoabces=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dHSm4lYfLRppIkLW39zeXaP6BFpHoPeCt1pVcm0yL03HpOT+sC1tb/5gnzXxChH5DBVw4z3wP+2vmXRyyvFBYz/sou6SQle6F/tSM/OtJSIpFhkIhWtWe1V6XhBWESClnrBRJGAZm9i884n9MwyBFtCwP1lpGL06wRJn33KJNRo= 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=S1czLI3r; 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="S1czLI3r" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-466cc9ab667so1501846fac.0 for ; Sat, 12 Sep 2026 21:05:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272316; x=1789877116; 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=iXMUiYhcNcQU3o5YIAteHcfA6in7/WsaQMspzMho3uo=; b=S1czLI3r4SUW1EnfIRzfIMUTfnvdL1A6mwshH6gKMjEtTmFmZC5MZ3JEnGcsekb5Mc /5XHBEPVcyntILOaXaaDGwTF51pmnF1tdA4iPSFRAjgeuds3Amyl4DbQRyW1HT5lIEeJ c+dqHH8j7xeyVKCre5LRHD0EXAxSNHA1twCRAg1/1JlEk+r/jfDjlPCoOHieYnl0zLMy qarVjkzeZwlhMbdqvLX6s+MHMkF/R6o2YyrR64laqleWrlfB9xB6ilvQL+TN5/nkilvJ 1ZypTTZVh0y4FSKIOV4fT83lpi94zRXKU5RdhWnGGlgss7jLmaNquq8cMBtxzEz5KRC1 hPZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272316; x=1789877116; 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=iXMUiYhcNcQU3o5YIAteHcfA6in7/WsaQMspzMho3uo=; b=snE4beHaowyEX7qjHxsc51R2wUDJ4tMhBPUd4U9AZvkZrXLK3hTcrmbb869oTVgzFe rrvzIP3UHg8PgOvyZJxWN9sMxcVP6MKmZPodEi8BWw2v+PzjPr0Lk61eZkG7mkbv24L5 l6cSvuy+jB+4En3YA8iLgT2I3b1Cmcb7WyoUQvkGWboP7whgWmpHSoD9SBhcR+TrQdAC WA3Sz0VTZeWD30cIbtdhvSmXtEFttmkmSKh54oRPEJXgqhAoo9bvlqkvDO5MwOHEtyhp GhAcp+HUKY1FLxs6vUxrJd5lxG8/4RdgIWOvKnECl9fq9FaEV4JWmUmCPt9LjI4BuR35 Hg3w== X-Forwarded-Encrypted: i=1; AKwUvBxVPP3NG3J8ZvU5VqFVEAbYVsEXS3CtFzVjDFfGiuWwZD46rXsW+0rFayoUCRrJuKkpCEWDHNSfD9HQShs=@vger.kernel.org X-Gm-Message-State: AFuF++kQRQ2jBd5jFk13ykVF5e8SVYGKhISUOV30vIWEswaYfqJFZrBA nFVj/ZVwKJhC685Des1V4ciHc4Afp2YZBEt6L8cgcrxp82KbNK7/qTy1 X-Gm-Gg: AYBFou2h+/8M/XQNYsH/CmQGlCoh3GqezxKINwNG9R/GcciEOiVWULqKKQmacnLud2q 7wvniZo9s3s1HvEr1JB06xD0e+1ej4TIC3H/n2o/v8Xh+EWzsBz6IT9gaDXJDUZ7P/vDXI18ktQ Ntwzb1sfA4GkFb12kqPKjTIK+y/nLv3WwXLBcdwJZXK5HPlaBC2DRS46IXrGH3/y+svxKdWTvhP qimZCTqRmShqSUbDV4JC6NV1jemns0TggeeFQAI9Q9TVU+6LK8jTh9RC0OPkfCgRMpqSzdnpWih XZYavBNT20XgmfTko9d+dhv761jblgZy+r1VelSpeXLexTuhAp9gf3ci3G1R4FxQwkvpsz+ThPc r9uJ8cQO5M0LAF0YnE2J02WAK4v59UPCaavgCFO2bvZMNMmPvM0d4yVs+w0MmfftjGi2DNr2x8u Vrd0YG0VW+qPVXzcc38IH9xwlZKYFDI0e0RLIC8R92yUX7f2wO9FQVqKC+KqcbmErfsjjvhgc9I IIyY3cu8PP00q6xV3SoUIM83y0/OBZlmyP/H+001qH5Rso9QU27PWV3qlaydTtO2JSru2bDjHOL 5OleN96V+OrodVqf8hpH0c+zvXGCV8DmbiwNnDUK8gXA3JvbzsG8vhfzyjPgZz4W8S3iYPUj9Mq VJAChYMih7yCm5InctW1KV//LHaQKMg== X-Received: by 2002:a05:6870:b40e:b0:43a:c6c1:e40d with SMTP id 586e51a60fabf-47de8fa793emr7029141fac.16.1789272316328; Sat, 12 Sep 2026 21:05:16 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:15 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:57 -0600 Subject: [PATCH v4 06/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-6-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 2026 Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.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 E665F38E5DF for ; Sun, 13 Sep 2026 04:05:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272322; cv=none; b=jzNONbxv/2dwmoECLPpcAoT3UO8VNR9Cqa3T7BtXgXhdZ6WMF2HNYT60lnx7xUAUOCxDpZ0/j60XUa7drc+TIkDJifQy/IJtNCk7+XPFc9hJ7u0dByRDX5MA4YkDbNOgFOmExmwE3h8kAt+r+JyGjG/cmuu+I0MgqSiV3Gtazuo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272322; c=relaxed/simple; bh=6QXvhJNkBJWcV5Ntyx9Vdimd7EE2MpJdJCkLfrX8lRo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=k1mwezqcgJbBzEXWcyZQUitaatFELwCO6J5IfZJW7MniP8UPXJEDzYVHu6Vh5pXSW5wzqTezb2fG+jzKscV9+W6fQ2NVZwrAEsIvJEVu0rlw5BFLddSo9ukvQEtr/jiAOFV/k9uGpzdFTvZ06VmjKk6tv8inBzVNLIRhw4oiDso= 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=ci+DbeK0; arc=none smtp.client-ip=209.85.160.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="ci+DbeK0" Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-4765ce0573eso1370157fac.0 for ; Sat, 12 Sep 2026 21:05:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272318; x=1789877118; 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=hb1UAgJ8R3xqyuxnkYr/GKcQBuP99rDSmeFz/RErrU8=; b=ci+DbeK0LNidhy3MWpW54gq/c75b1E4mjWHmJjVEN2iwR2+NxNxsiY+QEFVqGHFI+3 tbOQADtbKqe7LqYKjlX3+x0wlzb4PLpEt5kyZSalaQSDIXJiZMcz6eOYY/1KazaTik1v s9GT6Iy39mrcvDF1OnPcL8epaWUq0wzi5eLGcusZaHBNErMfBQSPb9qJbB/IEUjcnOa1 1sAm/Opxjtmu4kbaOLK3UCiZtLIl57MC3BOtff5uX7bNAN9C3nneox0tuBdChe5ByEa6 m2tRFb1g0zH8eb3FPJsuPlIOTBtjawSX6fb9GCUmmpdzN4mO4IhT/89nHYiudaUy4O4K nxTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272318; x=1789877118; 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=hb1UAgJ8R3xqyuxnkYr/GKcQBuP99rDSmeFz/RErrU8=; b=IL5UVNV8A1KPLg1c6dVdR6ZJfCbiLuVA3CBEANVRn1e5nPP/jV3Wfl2bQE9HLLnMZn KH67o2/yuhHHa7GG9WdlUR3oGeMo/1/TYOuhtIxbpiyhUNT+R36XlcPajDO0BxxQ9DMa UnKZsCMblCBc2MqQpWAUR8mBZI1AaoRyq3RpkIsHF+XdSvBG+Vurz/ykxFwqggyoCXNX U5ckiPZRU2d0sBOI9nPLUWPMuy/V7ZlRycw7viFYpI0SoOfUgcVC9X54HrbsfpnzF6A5 2zp7diN0B/EdPAZdPdwA6/B0o0k9XFAKJ4Al5jgBapG048OxUhn3n0bV3S6OmFuVYR5s eItA== X-Forwarded-Encrypted: i=1; AKwUvBwgS5ZaTV6oXs60B8ei+qvFovD4rMm6q70ACtmOiQCHLoSXrByJ4hJGar4pxbkot8cLKSXvHTEu7vYckIY=@vger.kernel.org X-Gm-Message-State: AFuF++myGbOu+moH+T/2GhxAnXPevKhHncgWoTr7/4MiZhr3jV1A3hhF tZfhQPtMOr0kJHmuTVRwqI1zKTWfeZW98Iu6aqgvQqCH26iDF7rpCNED6cJk2w== X-Gm-Gg: AYBFou0rmQgKkONylIbiPHTU4DDpsDq9uvjhUXVrgdnfqIwmQa336cMgjJxLTSf+QGO cuDrKuIFKILqqSnkAOFMKXvr/kTlMUZPTJjXdF4YOfYzl4WidaBz0Hb1QgGuz/rHCY+AwcueCMv nl9TSU+3d8ONLF9VweDxpLOJ/6WHm+ltnqzPgwmqKv3wcpbvWsrVOChwabhhLVHuTy78+z+EhGy H3P3YnNbqqeVagzifzmt8RMYxujPlIUmqE350XxDN2DzkReVI8e6n+UMEUF4DXzYr3aSsttDdhy mQIDOv1YZJgbZFMkQK6qstAaTDS0Ld0ok5DeiJrODXE6svYgFZFtExulXuqcsaHfRcqsc4UXz2H KgXdM302ynLhHUk/tsLhj0kHz47gRi089ymLShQQoKTxhoXcey9vMl1UochkZINhFlUN5l52HPk NIyEdfeQTXKa8tRjSCXmSJE12V/tgapbuAqGNBRz+h6ObQd/1IWdGK4nfdwvBlBJ4CVxhqE0K9s FkAybKOmafBCQG6UBC9wU3uICHRx4vUYrLJ+5E8S8rlEGNJwHE8UgD4EVC6s/n1lWYm4A/ikRmT lFoxHklw+C+H0tHp4VUzaoxwkBQiXiraeWslxrSB2d4eA0++SLAYKjoP/nwBobbyc5+TgegRSG7 jmLp/L/MkDXDfz9KMAQX4ajkmfm5JBFNfjcbgd1tx X-Received: by 2002:a05:6870:8306:b0:469:fb51:b351 with SMTP id 586e51a60fabf-47de8fd0c3fmr7839424fac.17.1789272317809; Sat, 12 Sep 2026 21:05:17 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:17 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:58 -0600 Subject: [PATCH v4 07/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-7-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 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") 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 12:04:12 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 7A6C1389106 for ; Sun, 13 Sep 2026 04:05:22 +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=1789272327; cv=none; b=iN0XIIKTDHKJyheXxLRtvxSSBRfYMH2BXNW5mqcRD8ahmnUn2kX61AldhyGfuQWCT1NtGRNfjfbnq0277naCcVM/+WIHY49vDbKmNIAlDN7oOxBQmtb4aBSL4ruyAQgyyja2ZJMmlmwYffXSepy2CKhw41PItZFinw69qlqOSVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272327; c=relaxed/simple; bh=YbBF9laHAErhZzSaGZGDzYG7q1LarpeBoJ8ap1tchQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XeRnlJZ+PZOeBlH76hVOYR74aR6JBE9pEV/VTEbhk7GZNxyFqGU/x1RpAxSO085cMTWmgOltuWYlEGFKFumYKadDoz0zH1OwDPD0Qzvm22ATANrqK70WDrg5G67tCS7Ab4vckUHT71hyh6YyiSMIPt6xf+lfwXh48AU6XoXNAOM= 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=TBahPvoM; 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="TBahPvoM" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-469fdb78b1cso627127fac.0 for ; Sat, 12 Sep 2026 21:05:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272319; x=1789877119; 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=TBahPvoMU33zcyiu7G3nfeGUiv6lrnzRIGV2FcLK/oXV3yblTllYF3GurMd43GyhPI 1tQzmAqRyfjQWIiZJPaApiEbXcHUtX997++KanuKqhmOwdc9o+0AK7lnJ1qou2Wxo0gk H/L4V2kKZ7AvPaBQbsMlS0mg0KAoaBxMDlzQ7uO+N3GJCcFu8nIqX+RS5a1YVkLSge4i bL6tOdPOoIh2lgRClQCLZIiF52lxPVhdHoA4XJe7vBHWy5Ozvt/OCNduJZNLsT6boKSB 0K0cnmQntbB/QMYi3Bpz6WT7fQ3NFSDcPjkqXPJwniNUutUZeonU1xg+cFXDTUSfxo0g guYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272319; x=1789877119; 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=T7P24Rd8WYa05YJsfGXSyKQ5jGQWSF2RmozNj7IeGchKr63J7rcJ0SrlQQY1t4N+w8 9uCEb9HHhKUVKu2bSZXdg7RJL8CwLu3XYnmBA9vGts/FYx5h9GuwVZxigOWno/ImZym8 TX06NtPfHngrVcQvplURFmJheEyj2QyouK9mjYls6l3zKWp04oOeTQRH2Fe/W1fpVFx1 8e1P1WuX2imDxq7Yejf0HqdN1nBQukY6LajpFs8y/YtR5iD0M/AdyLiKDJxwLnPjkaHv +Z3R+20tN2FAzMNtYCqK6X3j/nNo5DBJGcO1unYBMQvxuRo7n0OfWgXzW9HxGb+ypaRK AcTA== X-Forwarded-Encrypted: i=1; AKwUvByptXeN+7qFbpshmWlQFP5n4A0T6obIDgH9+Hes9krWyMO+lMlXEobeHTaZ9ZPZD15vqAXGHeGVV5ezj0s=@vger.kernel.org X-Gm-Message-State: AFuF++lg5CwkBwxh8jpEJayiN/XDu9+cbMifzXwdyOyum7gJiIEo5fTP 54EdLU2jBkyrpfSnOYxhjUa6F1Qj7eoU1uk2Til6zrSlRweqJwq7nNYP X-Gm-Gg: AYBFou2dg6dxRXLaeBTVg7ZnDXgGX7Fca0a5kfNAXRXHjoF0wFXnFiZvOxpiIB0SlSF XhDtiEKyWhHMyy8Bb5lUtszmAbQMnr3us4Dyux5vjiLyJdi301ncroVwkcFMLZsjI5nDQQHpYZq nsoRMfmD+R7jZ8MHPSWDASd4Ex04eqhMuzaiZEkYnyh/Ld1BPVAt3gGP41qtnCimL+d7ZpfGzuc fAO19qAq+Fcl0a5rAAwoNmcaqfHARJLgjUzUhRgIoJZfLgpC2g960bzZfXaFgkbmjQbEpI8dbpg puOJuYDoiiPzrxUOLae2I5IVk0WHSr2ASBF0MNn3qkJ4qKO/m1Je+9Zxh9i+FhKi6DB9HcjBk2q oQ9qAgiVdqHy/7EOPS+NF1eRbTTaghBt5VVRrAocMZGBFhLYqM4vE7qt8Ns2PYn/dLuM6DJoPKP y6oDo3/AA6EsX/yAFtyt4RZAIgujWQ1yowuAFzsjpIMFyvZAaHRAoh7U2i7Nv08FSq+UfVs58fk nECO3BoWk1bQcMWCq+vnURvp2kCD36YqwX3cdPFQ7+kybLeqWAEYy+KuxWLHs+nqL9nggQ6JTWB cs7rPOLdjHQrFjVf5I8FwGEBvfwYFRWFnmEJtJbj5CRharizQ6HPMkhRM+016m3RzMwTlp7YOWY cKw7WyJZlR8pCD+XeRPO2xt2K4VOhqVFrPihWWIFr X-Received: by 2002:a05:6870:9386:b0:47b:7862:c1c6 with SMTP id 586e51a60fabf-47f59a2cc34mr2957205fac.23.1789272319247; Sat, 12 Sep 2026 21:05:19 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:18 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:04:59 -0600 Subject: [PATCH v4 08/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-8-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 12:04:12 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 051BC382380 for ; Sun, 13 Sep 2026 04:05:21 +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=1789272325; cv=none; b=ojwhpb/3Ese0CVCRITaiNGSCHRJDaKIzOhWLBnsArMhh6rztOqbJFDqSsj9V76erRyP0JkcGyLfMdMlWTT/K91Yx6UpAU2bNgbsIJSODS+eiYowGIU0CmUJz8V8Vu3V0pFSz5H/q5yw2PmwSRn90Kke0otgNKfzI9jF/r2cyiy0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272325; c=relaxed/simple; bh=IwH5UB17e0EIm1Uov1vUqQp+kI4MV0xZU7BoJKOPdug=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p7F8bbkmGAeWD1K0iIRgWl47rvuHBC5nZOoJtEPGfiOKuAU23r3zHLNpgmBXUt4njjgSFQwRfN4ZcY3IwYXF8RHQ+KCEiyKokeQMs2oa1E3pBjm3VtoL/G1+DJiiNpp+AnRWsVm2eYiLbZ6a96+dN02EGnxP+66+sECgwOkkbAA= 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=rCWzYLRf; 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="rCWzYLRf" Received: by mail-oi2-f13.google.com with SMTP id 5614622812f47-4bb359e6878so230463b6e.0 for ; Sat, 12 Sep 2026 21:05:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272321; x=1789877121; 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=mVFhsZOFWXOaaokEcxhZoL5Z9W04LeNellBPPg9dCY4=; b=rCWzYLRfl9/jZfLr0LniHfdcEHBlnL9UbQapDjMI6QSIpJnJ0vCQOO4VUcrmrILxtg rZbuyg9v9NCkTPOuNSfIquZTA2Hk2q5UazUaLGdWoeZ4BYdR/ZuG6aFsqSAjYI0rmWcF ZeK3DUOD6NkepUrpCgRbelbgi+7MVBa3uBfcjl5s2n5gEdySRnnycRJxcFcsI9K0stW5 dXJx0+ipOGMBebPAQ7SKCwmFfXdU09fovn0SqKs4GkHR/SK6FIU+0ZUuuYLxTfeNeqHI 1AGWdxRl8GCT/uyQisZ7W6j5YhY401uKJHj5W2SaYMymtLCKMeCe5tZXMhNm3L1icwky /kQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272321; x=1789877121; 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=mVFhsZOFWXOaaokEcxhZoL5Z9W04LeNellBPPg9dCY4=; b=ChZktTYJ4A4Qx4ZexTV87oKw1gpm4uOx8OfSV5glQrgoHxUwDHkedVMFbTxyq2iDtX 0wjonX1fWrQIbuRE8jcW+/Qhy4wkmP05GTeyBKGGUkK5j/Q741zo1Qm680hBHoLAQboS EcTMfOdc3UurlAWwFXZDtdNVb4y/GzZwBj/il20KomkHCjSypwMqfKlPIUXFqiwN9SHe OoFlY/ck/OrRV4eCnF7viUtZLHpLoge1eOrCvuMbO5mE/0Z1qrVEJQiqRRg5OCWbXcoD pFe6YeqF/C4HnpgHofO8MvtMZhXkAhBxKmlV1grbiAh5lgqmI3bj7ZPuCI/qU2tI3W+H qblg== X-Forwarded-Encrypted: i=1; AKwUvBwEulT7R48dlgj2wWl7O0c8wAmx9sGMQmd/U2M8ieQtP4cADq48Y5tyh7L5+c6kZHtMf8HhIMaOVR/m2/0=@vger.kernel.org X-Gm-Message-State: AFuF++nRaVI8HYEoartQ91MbxERRybXjN1RT5mwQ+n3h2Tj0OSuiq6Qu 6yxnvG8jfue+TN7LC3mW2gj6wNBtQ5UTDxWdYVJO38qSzudUrR0N2LYE X-Gm-Gg: AYBFou20QPR6WkrVSL423KN+W8bE3vHlFfHKKi90dwn33B8ohCVjl4Jjfyx58KekVVF ruENFi9nE8hW41vOgE/+ZmwlroacWW//kaueVhssupZrrCqqV7qt8EZ8M0BaaPfNxs36nQvDZwG 76Kt5iWCxUSDpJB7loiFbnawx5/BYWl9Y8lvY59bERjIL1wQvFIpMewDPr+BPsqTf3cwmuRcxX2 NpQiVYAzac1VshG1ZxZqVEnt/s55HZci4qmsmcaAl0rmxuziieWGXYPv/aPskUgubSC0cgGlYU3 +cELjuhlmxlnK0Nv5LFPi6Mr40mINwRPrQ997NGCI7sBCruTkD7MYLVJDUe4515cGTdM4VrmJ9D H6jx9A96bW5gts+d6MqO2Vh57mJTQSa5W6pyAEVhw22QbHI4t2qI8/uyL/7TZ9Rzy7lDmTrtm5A lFdg8e2YuYNXc7qUEQzJ/8qaesRqUtuwpldmYNpU2bYmB71JAUFvIT6PsEzlglTNqUh2HLg1lBP Gw/0WEEEY/+TIakCfjUbjHSTaeb6r4okN3WQxMEHgrAS0O1wVr/36FV3VYKS42t4BWuDnn0NWCG C9ByeDhLd1zxf+mmiAeXpbfCrDvEQn7Rt7BlCEm+eFQ0P1Sp/mWIBNoGSfKMJQsaUMgzaHIchL5 QygEmvK12iNJOxgHYd9ZWQyphc1vXyQ== X-Received: by 2002:a05:6808:1385:b0:4b9:a88b:8892 with SMTP id 5614622812f47-4c4aa8e6f34mr3706612b6e.40.1789272320822; Sat, 12 Sep 2026 21:05:20 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:20 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:00 -0600 Subject: [PATCH v4 09/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-9-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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. Share the variable-length user-data register-index calculation between the protected-OOB read and write helpers, keeping the separate MMIO loops and existing fixed-length register accesses. 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, 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 | 143 ++++++++++++++++++----------------= ---- 1 file changed, 67 insertions(+), 76 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 13dc0af56eb3..40746686142b 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -924,16 +924,33 @@ 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]; +} + +/* + * Variable-length user data is concatenated in four-byte registers. + * PIO uses hardware step zero; DMA slots follow the logical page steps. + */ +static unsigned int +sunxi_nfc_user_data_reg_index(struct sunxi_nand_chip *sunxi_nand, int hw_s= tep) +{ + unsigned int byte_offset =3D 0; + int i; + + for (i =3D 0; i < hw_step; i++) + byte_offset +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + return byte_offset / 4; } =20 static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8= *oob, - int step, bool bbm, int page, + int hw_step, bool bbm, int page, unsigned int user_data_sz) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); @@ -941,35 +958,22 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struc= t nand_chip *nand, u8 *oob, u32 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 - */ - user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); + user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, hw_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_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); unsigned int reg_off; u8 *ptr =3D oob; unsigned int i; =20 - 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); + reg_off =3D NFC_REG_USER_DATA(nfc, reg_index + i); user_data =3D readl(nfc->regs + reg_off); sunxi_nfc_user_data_to_buf(user_data, ptr); } } =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); } @@ -991,7 +995,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; @@ -1014,15 +1018,15 @@ 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, - const u8 *oob, int step, + const u8 *oob, int hw_step, bool bbm, int page, unsigned int user_data_sz) { @@ -1030,7 +1034,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struc= t nand_chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; =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); @@ -1038,32 +1042,18 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(str= uct nand_chip *nand, } =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)); + nfc->regs + NFC_REG_USER_DATA(nfc, hw_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; + unsigned int reg_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); const u8 *ptr =3D oob; unsigned int i; =20 - 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)); + nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); } } - } =20 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -1114,7 +1104,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); @@ -1123,13 +1113,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; @@ -1145,9 +1135,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, @@ -1155,18 +1145,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 nand_change_read_column_op(nand, data_off, NULL, 0, false); @@ -1188,7 +1178,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, @@ -1205,7 +1195,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; @@ -1232,7 +1222,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); } } @@ -1247,12 +1237,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; @@ -1264,10 +1254,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, @@ -1317,7 +1307,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf 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; + bool erased_chunk_found =3D false; + int ret, i; struct scatterlist sg; u32 status, pattern_found, wait; =20 @@ -1397,7 +1388,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf } =20 if (erased) - raw_mode =3D 1; + erased_chunk_found =3D true; =20 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } @@ -1420,13 +1411,13 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf if (ret < 0) goto err_stats; if (ret) - raw_mode =3D 1; + erased_chunk_found =3D true; } } =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; } @@ -1443,17 +1434,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *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); @@ -1477,8 +1468,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 | @@ -1535,7 +1526,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 @@ -1559,12 +1550,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 12:04:12 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 6C52338B15E for ; Sun, 13 Sep 2026 04:05:23 +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=1789272325; cv=none; b=vEZ8x7jjVGnovfyQvD1Nc/zW1eMe7LuuhbQl+0WxITCyRcRNAqR8azsRHuZ+jR5QAEFozcHF3EfiMLUva/koJ21qdzMtNCxhLEDpPSASXbdECzhvEVFV+oL25e6UEaZKgnkvIjCp8p6Z2kXJ15TcEiLHvo4sVMtpzCD4SO6omGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272325; c=relaxed/simple; bh=TnmhAN7UAS2ynuFEOPQLlzD2wvbIo/yeVWwhOMqNS58=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lSKeM+nh45n+ve/zdK0MZbeZzBPKVTgTFAIXCvkOm4of3nusp28s5gU5oEKsUpAP0tupn2VFSXuTIAI9hSO2jzHqrHXq7Fxxhj+Egvl8bUmjb1T/wDiSrnvWDvVWtwLMzN9HqFvI4Hz1GFkyMkzkUmgDGGeBwz1vW09iCDfQs3k= 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=CmqLCzDO; 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="CmqLCzDO" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-46ac6e5d8f7so345854fac.1 for ; Sat, 12 Sep 2026 21:05:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272322; x=1789877122; 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=CmqLCzDOCu2p0HojwwpR1/zb5q/OFzzSc020JhWJBWm/N5wGyFAp5CSQMtGslLQudI IxjMYO75GY3DDfTrDDfvTB5+hpGSRiHkUl6LNSJUtPKqB/cD2FgFVt/IJ+E0fp4zJc50 TFKGScYeKSkkgwutnwDdXONU+2rTC/d6XHssEjc8Ho0DV1VCmHKz57ypJRTkXTsmgruS 3OLEHQryiZ4RGgtrwPrzoQCLXhzZtN+EtOmsR5YA0Dk0eV1g/9UyedeDRkHurFTFjAKy nxI1AoBbqInKwOzzZWVs4Ka4g/q13HfPnTcL7kSvSwTU9d1CnphFIAy4toNbtcN5SiJC FCSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272322; x=1789877122; 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=PLEwCGH7lvtPDnQkDls34RrW6wHxzUZbVZhejDTN+gdthErE1U5mea+USWlo4P0ECl ScerNdx2LbypDTSCIJv2rEMpVqWMXE3m5MC7RpOCO8JRTxJnbC6LV22UMOrT/3POe4Co omDrhzcuwJktKZKJ+JKzeyG2FhF88ZZuU5LfbKTv/xNWkns4AubXimFN+ER52DlJhGHN q0lqO0JuGPsTxjxIb+RfDDtUdUAFUIbGPTckuWbKYYfYgi2mhaIJak3Ohc8pvYJEf1KZ Ommh8GwBrfS5GFy8FVv0broe2NxLuOpNNM7BXXqxiscjGoBpv5+wIg7NPQkNyIRtLlU0 iJhg== X-Forwarded-Encrypted: i=1; AKwUvBydDwoyLYb+6GfMkiG3JP9m9oK9nxmaTCmLnXf0L3aK+YM6w0PNezYlTb+81yf/poNn2hr4+8PBDjQ+FmA=@vger.kernel.org X-Gm-Message-State: AFuF++ny6Z0yyt19/onH8LAeJb7s93M+HFnr7z6RqFRz3zM0JNWAtLGh OF3eJ058JyhWAYDW7n2a4D3GOB+DtdUsb2trbrNouo5lJeKZSq7SZQGc X-Gm-Gg: AYBFou0tzvb5tlB8NQ430uHtZFEuQ3DNRKUSlFyLIJrt2fw0TQNr/wRR8PaPZXSo/CE e17AZXhEmUHBwsytg6oGUCH/4+YQRns1In+t+AgF9ZnO0aO4/2jcAeJaZ4zCFlguvM3Qv5UOEl7 VhpRdQexETAKa/TZlbFCgRkpsLfetPNFxePRU4g2diF/mghb0tkfjbGPQYM0gZsqlzhMWyUA2o1 dYFMo0oxF2pMHJdtjMipDRowQXHt2tbYjvDA15jgXcd0Eo4jxz5mBGq3jBIdULxfroKZPbuvy3U zfO/GAVdNHG3bJ2N9Fa9NBrCaRBCyKqTHhW/Gom46+koUplJZFRfUuVeS+KHm1kakENQuXSCqN5 7I+ZHz1bbvbn9t90FskH8f8pW9TiUzvhK0I88IFsFjOPG9hvnc057hiCo53FMOlnKhsXIO5eBy6 3bw7lFYK8kUDmfwj+fYTmK6VeCveTwPj/9h05GWgqISUJOzcBfwqLV2UYlhei4S+w1Si26D4dpW xW6aXFDXgVqxkLfBysoEdulBRS6dkDKqSi0Zjt+z4HD66NAVdGR59W//++FFkV5mUTnnkNi0Hnv tcR8zU7ha1JigeYuGrSYfFnwRsDwVexLmOHQ/8q7iQN6EqduSi9i/Q2/du8nNwNQOW6Okx+Sqjj 3p9ZV5ktk+ULyA5Y9kpyrGgcje558/g== X-Received: by 2002:a05:6870:82ac:b0:475:e0a7:9f32 with SMTP id 586e51a60fabf-47f59ca2579mr2988460fac.32.1789272322076; Sat, 12 Sep 2026 21:05:22 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:21 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:01 -0600 Subject: [PATCH v4 10/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-10-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 12:04:12 2026 Received: from mail-oo1-f50.google.com (mail-oo1-f50.google.com [209.85.161.50]) (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 C08AC38E8A4 for ; Sun, 13 Sep 2026 04:05:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272329; cv=none; b=Co6oSDae5VOToPju/OvElbmzA+ILHRafSXAvZdYQSFLX4XTxKp74JiYOTQaOqDU3UgU0ymKFPBpJ4sVS8v8v3z9QQG6wpLeT7l0pRoX8xM1VQZk6tbY42kmk9LmqqORH/qQs1GbNNzQRQNd7ZoEkoYG0u0DJYcA3rCdIYLgqNLg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272329; c=relaxed/simple; bh=ba/GKgzDDScyMYA9/+L/r9vJQ7auFMFBC5kuQrceT2w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JtHOROgIChtfAFpLmW2HMZcM0NJoO39jVFYSRDzB0Hm5/40obtcdgNn3InOqXwdY+4KoHQ2/TtP8wnPyaD46uUK5H3Zqn5izaiHG5SclPbInXxhc4nGqktVSF5dhlziwDaEaUhEFQDKh0RPTwOTxspbbvf/jI+rPqzC4dhO2+/4= 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=pjLembeA; arc=none smtp.client-ip=209.85.161.50 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="pjLembeA" Received: by mail-oo1-f50.google.com with SMTP id 006d021491bc7-6b613d3e19dso1982842eaf.1 for ; Sat, 12 Sep 2026 21:05:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272324; x=1789877124; 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=EoqaJxRX3qT28aClhgaCfrfYghT7IZdjt0FxLg5X70U=; b=pjLembeAD97qbKETPVFjOJNtl00Rd5myhDAoay/6waCmm0uOOe8ZS5VYdn676wwqQy imbiA7w/o9BaeTT6kBSwFIPc4wP7Cz7EZosy3PIUvQMWjSMtGa1aMFA6oN0e2BBMIdOd Yd3KkF+oMbVyZnSwAReSPPp/39kYnDiVPW8oPp2bMAhfV8NvW1ZV+ZXoRuUma5c6wP3S 0wYMHoBzLbqlWkFNWVyL1hV41jJ77zVydog8OXh9yGifiHWimZ324sQD8MhOQqyMJ5OZ r2MoSfJc2g9A7+Lr9K7B45ybR/gdjNiobAyRSpIayduoIa4RAXWT0AEk4ybjAJDvlKBd p8Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272324; x=1789877124; 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=EoqaJxRX3qT28aClhgaCfrfYghT7IZdjt0FxLg5X70U=; b=sAWXePvpLCsc0Y5kC5swFChlaOWJ5Czp4M8bR82obBjCaLkw/VWFmk6A5nUQM61/g3 mhO1RuP0KTX0o54N36lIat38FvKXlWKAHKTaN51TstmxUboxUOily1H8wByzGEumqI1x GYBdLWfAbwBJywqNWjdpgteJ0e64mgY5ZXMcUVacRyZm0xRRmrQAAxE7mucLuhMxIaJj sZOzmpnBMeS5fc0MiNjA9knHPYGyFCMDqDPseu6qV7BI1+EDwcGyRp6cutgV6Y2Qj5vk W7/Vy+3y9z2JKkB4tFcjpviXmW13ojQf2Asp3LFwkJEY1aK1rmoATtdh1q9eg5jObKgl CSmw== X-Forwarded-Encrypted: i=1; AKwUvBwXksbJ6e4rpzd0DhL6FZ0whQK9Y2n76XHeHPK78rGbCz977QvwvNtcBQ5HJffJpB/aVGS4KwrVAI/4lQE=@vger.kernel.org X-Gm-Message-State: AFuF++nCxYuz10ilqgUWBS2LKBg0I1Xg8peyLzk6LbikiQxUngLrM84F 2h0+f+XvbHBzh6q9psiXTD41ZFys6zuIxMa0+ucpuX8g2naoW2bxhSmZ X-Gm-Gg: AYBFou1Pb8KFvWvIrieN3wGviX6BEbIep44v4M7v4UV6MO9R0sdhI0g7L4yR7ixaAJh 3Bq+tjxqfaVQX0zyVi+JBI/KCuXt2qPiDg6QwcLXotrFav5aJu2P987vV6Cv1nw7rQ4ESwkuZXp 1Mc4+AmS3nguNOj5h0FVVwERxeAPjv4Z8HayECpREBW2AM7Id2QAHnVQRjMZ9NNx78EBXQcCJbT zswFmV9rIyPc3yK93czDyJRjI6B6YqZ/YNWDgAUTervO0UwRhVdnGN+x9HKnzD6z10LI4SFWTmM o+IEM75kK4F6j8S9+dOmg74UO0Rr8W8Gb24Sbjoz90VsGTbe1rTXP9rwDcqyHbzDPcSZlXznM16 3YVwirHj792dD9hM5FPbAq5TZC7O3l0bCdCNqhPbbcbmewZxpRvCrhst4Ay6FhQWHwTnEo0fSzX ycGu3ATgOeS6ou1EBHNeB0CjnssUteeITcgHZ46nEonbQ39lkLafzOPkRhZOTsF9szFZyRuCyVo S8paHALRnDudiY8UoG95h7Se6QqLRTKJnCIvILBP7GDT4R9xhDzmZOGENht/rqMa7FKk5t/vPtP vY+41EbjBdjTbIG9xMSlpfr2VrRqbdZb45+IfINlhAPmMvg9FysGuNTy5e18PBI+iv4zcW47lp9 UIRoTWw9i86bA/ZzVq2/hpRyxGFHtTQ== X-Received: by 2002:a05:6820:2907:b0:6b5:ec2f:356a with SMTP id 006d021491bc7-6c3ce8c4c5emr400751eaf.27.1789272323609; Sat, 12 Sep 2026 21:05:23 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:23 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:02 -0600 Subject: [PATCH v4 11/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-11-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 | 270 ++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 261 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 40746686142b..725cc302df9f 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -265,6 +265,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 @@ -277,6 +278,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); }; @@ -328,6 +330,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; @@ -356,6 +359,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 /** @@ -861,12 +865,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, @@ -974,7 +984,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct = nand_chip *nand, u8 *oob, } =20 /* Undo hardware de-randomization for a plain on-flash BBM. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) + if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && + !sunxi_nand->randomized_oob) sunxi_nfc_randomize_bbm(nand, page, oob); } =20 @@ -1035,7 +1046,8 @@ 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 {}; =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; @@ -1103,6 +1115,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) @@ -1145,7 +1188,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); @@ -1194,6 +1238,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); @@ -1295,6 +1349,153 @@ 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 nand_change_read_column_op(nand, mtd->writesize + off, + nand->oob_poi + off, + ecc->bytes, false); + 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 nand_change_read_column_op(nand, mtd->writesize + off, + nand->oob_poi + off, len, false); + if (ret) + return ret; + /* The unprotected tail uses the page seed and its 15-bit advance. */ + state =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_chunks_dma(struct nand_chip *nand, uint8_= t *buf, int oob_required, int page, int nchunks) @@ -1304,6 +1505,7 @@ 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; + 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; @@ -1366,6 +1568,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct n= and_chip *nand, uint8_t *buf bool erased; int bitflips; =20 + if (sunxi_nand->randomized_oob) { + sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, status, + pattern_found); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, + page, user_data_sz); + continue; + } + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, @@ -1393,6 +1603,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct n= and_chip *nand, uint8_t *buf sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 + if (sunxi_nand->randomized_oob) + return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, + oob_required, true, page); + if (status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; @@ -1524,6 +1738,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; @@ -1546,13 +1761,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); @@ -1598,6 +1819,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); @@ -1618,7 +1843,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; } @@ -1637,6 +1862,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); @@ -2249,6 +2477,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]) { @@ -2317,6 +2549,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; @@ -2331,6 +2567,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; @@ -2340,6 +2578,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 @@ -2569,6 +2815,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++) { @@ -2847,6 +3096,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 { @@ -2870,6 +3120,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 { @@ -2896,6 +3147,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 12:04:12 2026 Received: from mail-oi1-f177.google.com (mail-oi1-f177.google.com [209.85.167.177]) (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 49A6438F927 for ; Sun, 13 Sep 2026 04:05:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272328; cv=none; b=jF7AQiL7ez2eo7yb/GOHjPVn3UDsnWIJKHr7iPJtoGCWbx80ugTQdea9JUdRFvsbLW6b9yXsGLkJwbYUE9R5wJMAQRNvukWF2z+MlUs0jYf6D4vqathK4CTM4aH47oK6lW6qajJm2VR9P9Maa6svqgaQAr5rATbQhHvwKvFAWJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272328; c=relaxed/simple; bh=/U35JMG7PN0VQxPSNjTNdzYGYwq4m+xXswxlipe9peU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZH80HF2KlXG1uf57wFm/S3YOTq4oJem7/+72kXPa03lEAt1Havu8xzzUNBsH1gR96+TzoSEIkPY9cgs7NNUo5jFwPTvb+4qeTqgpN0ZvojCYoEdvl52ELqJtav/h6b/G97qguER2WpxPWhjqBaCVwiLSjUq3Imzrf5kNr/N3Yv4= 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=gZ3lTwEx; arc=none smtp.client-ip=209.85.167.177 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="gZ3lTwEx" Received: by mail-oi1-f177.google.com with SMTP id 5614622812f47-4b381337e1fso2320533b6e.1 for ; Sat, 12 Sep 2026 21:05:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272325; x=1789877125; 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=l3fsd5mFSYNbCICE0q+20FvucYtRM3opmhA2nF/SNd8=; b=gZ3lTwEx2a4as1p/vS6q8A+eHuOLhZU02wK04KUj7UpmDJd/cxXGgb2i6XINjqcssk 5nIU4xjLe9mPnzS3oYKOLXs5jBpI+L+KsSRZbBv1RK6Q/3l5U+w8BQiAyxyEqnv53Wsl 5EyK1Fm/EW0QGaGhpjEMwrA8S0at6C3d2V1uRF1oQ1sYUXB7a95MXuR8GpAA2EdV9CJq eJWKEt8y2f8asjLLWvQvJBVDYsesNPnMf0QtjVA67Uv3sZmuMn6g3rWhPzbDo1r37hIH sDR2RihGtz2YzRCoOcLZqBzVLs9b3ch9KV9cLpMYrFNqLcT/26l18TnFp2kTqRY70iG6 M5GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272325; x=1789877125; 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=l3fsd5mFSYNbCICE0q+20FvucYtRM3opmhA2nF/SNd8=; b=K0RFvDh0jf9ed/EPC1ljeisrE7Ztda8oVIBQTfw6DnWgnOGAekOUAXimzDQkT2YnhI CY+dMP2GYiHTs/Oma1eFrfzTqYHpHM2eHFm5erfgC3IVIu1+LhuDwXTHvDWlXl5BvUHw 2rj9BnREZWV9ul+UqRdP6nkUUyUt4tzMcDrx/ks7rxxJMUbjI/LtZKaKr0z3uyKxSoG8 4Wcc0g8n7JQsntjEj6uH3xCnZPo/AfwoQAiQqztdzR7WLk/QXnhi/2Rlr2nkg0KkCehW h99lKb+QcWmCuvSqIjCBSJx1J3RJFFXg9GZ4yEB3i/rz4lzY/9XqswxPewVqelTeJt7m 4rPg== X-Forwarded-Encrypted: i=1; AKwUvBwwrjLgLaUKv9IzP1i9/7udV989xPVRjdO/TqO6nbMX2GCrZAAd5hyDK6Ay8HnOCn6ECCDiYWa+A2CCexY=@vger.kernel.org X-Gm-Message-State: AFuF++kMuyq0y6a9zgZNfHRSIHjYpDMg1JO7I4cwQ9a7sBLkkd+sOgai kymtdIaNcEYRTadrOHQXssp2VXju+V5O5l3GzcjVQ3p/i7SUXkxfEWRQ X-Gm-Gg: AYBFou0qqBIDbJZWOauieN4/aB4bkg4iYHNlqVsggsdgEbLyEbgpYOZmOL+xkKwWF75 CX9zyWOGzAh3YHjhH3wl39qqwToFqEVn5T2BWCdwCX3OTzRzQJV4qKWSGn0VaDtXQRLJrbUin/I RsTcgcGJw8tmF7pYRxe0Ec6zZWiYj5Q/5AIhVXcDtbj/V0LuAjkPfCVvKrGAtGpgiMUl5DRfACm Od0zvQPQXY2DFEtYLvMcLUgehfS/NBLuYdluwFTASd957Fqw2dx9kdrVPOGyXKwEYViwLtqDbUA 0e9ZuUbQCGfYimG5vTRcFURF5kJwVNKxQoIYGb75nDSxF12D6wSVtSLTzsJIN1x+OGCKteMIU9/ 6B/fJlvhOWH8ZNg+db052T1QRBqlZ5fqSSrdNRjzOHdVN3yJmZ14SOUoi6N3vjXGWoxyv+l8abK kiAsZ+YX5Wa2rcHiCaSq72NXeHWKxhVv18CL9QKh8US5PsyOVCr1p7gMNJhFWVGLFs03+LFSJ0T PsRmdDvty0SouVLyBcmME+a8rDrsIdJz6SJwqCwcJvjx0Uh41jZPVm0Dn/EkYD1p3v348aB7YYF sEQcdmQjZ2l1psisSl6Ro3nY+xar/0A0pXcTNHjgvCgMpWyr56gIPqbbSDf3VC7fwp+nHztw0Ru /Q/H8FD/Pn2vccoGw72lRJChcnYpVyRU= X-Received: by 2002:a05:6809:28e:20b0:4c3:7af9:f497 with SMTP id 5614622812f47-4c37af9fbbemr4704298b6e.38.1789272325105; Sat, 12 Sep 2026 21:05:25 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:24 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:03 -0600 Subject: [PATCH v4 12/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-12-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 725cc302df9f..97a4b4470dad 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -224,6 +224,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 * @@ -2360,8 +2363,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); @@ -2377,6 +2386,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) @@ -2437,6 +2452,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 @@ -2507,12 +2526,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 12:04:12 2026 Received: from mail-oi1-f171.google.com (mail-oi1-f171.google.com [209.85.167.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 805FC39099B for ; Sun, 13 Sep 2026 04:05:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272329; cv=none; b=T+JMsnpbvZ7X1MZCPMgsmvej/jmDJqDJtgbw2NVnuUrdedUFiOJ+dTx1NT4wmsts3MuBdOm3F2VzqZJYx6hgNVfzN5jIRQFdolhsKW9UG7o6jSg2FNzhtwVdCJG0FWwMZySIyBxZPbJ3alMf3MYHMOnU61Au+F32sZ96kVAcjqQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272329; c=relaxed/simple; bh=z2BPI/pmixq5cvuOueHRhY4+nASimyd7pRom7zs4YWM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hztKR4nB8p16WJ2RH9yP0W6luKF3+CuWGWkcDe+zjYdSliDrGhS67lmtYTkFOHvsJXe198RfkizBJUAwwnoYR2sop1tnT1k+2HZl0vMzWtGWgDm3bkMhsbNosgBbqvmbYskPtohPwlRO+9JdxPDzLg9YgqXvkmGyuAQQAzwxXPM= 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=G0mC7oVB; arc=none smtp.client-ip=209.85.167.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="G0mC7oVB" Received: by mail-oi1-f171.google.com with SMTP id 5614622812f47-4c6006e2428so358178b6e.0 for ; Sat, 12 Sep 2026 21:05:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272326; x=1789877126; 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=4QAhKpDJSEoLKbSmhwyQO7+fj2kwJfhM4m0kCMZtpNg=; b=G0mC7oVB97qiFJZshq1cbmBnqqgxl09weKf82hbCoFvDr4a8AO8brwNLKvbTEaAcl0 BROANUkR8412GPBf4RRHiROm0M/g/+vvLjziMqUBlcaNRNbi9tHs+NC7YWXxKaWE4YiU 7oFXHUSufFCFJSNlVCz6+QKJd8/v/a91Tcl+X8h0mYb3ot4yKQKQrlPt8owfOEWXolX4 vET6kzzpkU2wKs4p319zgraQuMXt9z1F9i7yMeFokFcomrHmCvtgOlzh7Oe61G4speot nHopnHSody4rky8dgN8z1+CTXOD2nNvDuEyEHQlAlcALO6bi6/ltEUt4qzbiSaA6bCng LD8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272326; x=1789877126; 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=4QAhKpDJSEoLKbSmhwyQO7+fj2kwJfhM4m0kCMZtpNg=; b=dXsFWgMWh/QzaoRKPL+jIIZ7l8VMXjXuNNNOEl7sJCubsK6BADIM9w7j1hKwGGe8ir M+OAUdGA5sVr9xJ3OzJHaQlzKOsGZWnV6jU0EyiQ1EvuQ04EyIZn9rsw/40506ZhzrFx NrTyNJny+60BzWXSou7EpXkeig/d83HlETRV7Ew9lKDKT+5lDsbRof5gIWAwBg5JEzOX hcKPk5IrKdau6f1Qf16l3gIlKEMbxyZoJdPt2OE9dcdbb+0SCzef0ZEv7Zk1fHjPu1Wh u/n+TYIT5EqRjWPnpHB8dFmxNejyGspFoeyTPGvVktQD1ogfolvb3xrjpBy4ouGx7JQg K50Q== X-Forwarded-Encrypted: i=1; AKwUvBwIsQsqbO0Lju7sIT8feFG79Ae9lq2z1Uz5XA8NH0Sp7pfwkDoSNVtbMcI0+BxfwWClTE6kqJDfLQeGdvw=@vger.kernel.org X-Gm-Message-State: AFuF++kpvaiuOUXcRHTpeP2Avt/EEo55XtzdpSduACAKoLebfghDZJBy HRJUEldUNFc+WoB2F7hPX8wSdrRYicwosLAkMltNzViNTePwbscPq6Km X-Gm-Gg: AYBFou3xEVHSUTB5X1+FO1u1Ai3ivygvtvBbCN98qhdEs1Z6vbWQ9J5ueWYmcFbeeLN BMJ3RIiOmg2WLZdmiOXJE/ylTruhSsuGMmBPWd3+kuz5H3u3WYvdyBD/BIJw6ymzGo0QvNhpS1x b6sWthAUgZYAcgNK5sy2nNYWjQYMAGizqirroDHNAdu24VKZt9F8FzLTtUtw9O8tAXzr4dvGmir VQ3/iIzt9ihUWJcPBNpfaXGRP6SnSIpmDSa6SDmicwqkL1rk3N7bctPYEAWI/t+kPVutpw8nvvE l7ovqFpp5mASDOhJFvGhRC3aarliu0zzRLDoMIDWIH70akBfoZGbTMDY8cboJgGfuk+rc64Dab7 l8RmB3t5MA7htiEzWTYG/rVtJA/z33mIZMH2NcnoXV+E0Ve8dxRd84MsFqP/ZTbkR5HrMD5X5g6 nUdi0wM5zu/cEyEZtIjQbPOBi6lAtG+It8J/LVskR50mtDSugRZZmUVkj8M5BAjo71R3miXNWx3 NsTaYU5KVJATXKSewZVc2JFug2ARUyB5l9S+RVpWnT3W/hxnwUk87kw0rbImCRV1V9eXukcuuB+ Ny5q7hWC/gdxFq8cazMLY/Q5Qv4IOmzqeJ6lkkU3A38+/uKt9IY8YTnmq+SgfQ7T0Zm35R3KTMC w9r1YIpxKnEK08nMhz4veeEHlop/Xsw== X-Received: by 2002:a05:6871:4082:b0:479:a30d:60e5 with SMTP id 586e51a60fabf-47deb6b21a2mr8028318fac.37.1789272326342; Sat, 12 Sep 2026 21:05:26 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:26 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:04 -0600 Subject: [PATCH v4 13/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-13-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 97a4b4470dad..5fba3c111a4b 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1424,15 +1424,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 nand_change_read_column_op(nand, mtd->writesize + off, - nand->oob_poi + off, - ecc->bytes, false); + nand->oob_poi + off, len, false); if (ret) return ret; - /* Preserve each path's normal representation of ECC bytes. */ - if (!dma) { + } + + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + for (i =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, @@ -1443,10 +1456,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 nand_change_read_column_op(nand, mtd->writesize + off, - nand->oob_poi + off, len, false); - if (ret) - return ret; /* The unprotected tail uses the page seed and its 15-bit advance. */ state =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 12:04:12 2026 Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) (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 EA7D125B093 for ; Sun, 13 Sep 2026 04:05:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272331; cv=none; b=NNVKAuvvHJSpS9qb2xVZsLvondW0cym9a9IFVbS0fxEXpqdAryC4Z1EqKwarc69GNu18Q7OTNxXewi5IcxkMJE0Mxg3fXs6UwgaFoTKO89jUbxBwJtqwp5SjyBh9JuOmKdB70bOozvPklAIZA5eTDm/VR9ptuODaIyJPmi/bdVM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272331; c=relaxed/simple; bh=sHxgZAC22jRN5x+cGiwyrOUKu8MIdzjliuwZEPvI6DI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B8ZiLHNPxfSHCHuwf7OciubwXtitGmnvyNhN70EzP2uOjmHj5Z8FfhVO3ZmuhPEY/9QI3TnqVzVuxqc3g32rFJhT27Mn5RAt4ijrSX9wL3z5Vo47AvA7xkYu+bh4bUyhjgc+izuayMcOm4LGhHQxIhuJWcZi1SwauckNTnsIenQ= 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=AxbJIMSl; arc=none smtp.client-ip=209.85.160.50 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="AxbJIMSl" Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-451a49abd8aso1815424fac.3 for ; Sat, 12 Sep 2026 21:05:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272328; x=1789877128; 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=I96nTr3z4iUIosSghVQixbz9aFa+jjKeIwLd+JYqRDI=; b=AxbJIMSlE96AdxQwzO4lIX3mWdTw4sIUV5fkvZ4mIY9fQkhDYJYhTaycqHsxTL3yKU TQ3XvvI4HfE/DhOXuVIPTqq2DTMl3DHgHfuTe6PQJMciNh0KxLajmHxkhvJfmUoOmcga s8eB7rOKS+62d0KJEihQ96eTRrC30gIGV4Xxcv8SW4CmKKrG/yeH1bJ+4z0Zduco5Oiv Uf0Fm+TI3whL1uR3tsvsCtD4rxlQi028Wzn1w9Ve2FCXm+QzYqLJY52kTLDdyIDJN9kX 9+SAGpatOX+V2GcJ50vNuQoP+2V6fKe/d70eA9S3NmVSqK1tajykj38TsF2tXo70QgVp AfnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272328; x=1789877128; 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=I96nTr3z4iUIosSghVQixbz9aFa+jjKeIwLd+JYqRDI=; b=EnPQHmB9qYzoKesWQDj9A/mAyyNmh0wJaIl9t4vQ4r0DSdEEqBC0PVk+Gnc/f0IMTD FIL2z5vPaWemfHcfZ0cEy25Tks9kSQtd8GaOXvlIgjuQtiTeossE3nU8CYfkrwA9AfHe tHWY010UcqxCp+6Ddu9l/6JKdp1Q0+m0mY1iF9Qwq5NWXrjCpVNiNivDU1azSwgeCOGn nun5VYw2xEztaDrgDOUJobx1HV5fBIXSfubl+iUpjgZvFj2heeHuck8kWZWQLVbZFALa Z4I+yDFNUTm2px/P+iE/Tu/qPwOWagszkWpVYyXVfudb9jfwnawxlBOkg8LT7uw8Lvkt A3nA== X-Forwarded-Encrypted: i=1; AKwUvBzOIWoAix10rP9Z3f6q4Yf4gMQCAsbQNZSfH+hU7xeuRpIMVR03WPWwB2mtlsZdR6E6BcR1/q8iWKr++vQ=@vger.kernel.org X-Gm-Message-State: AFuF++mC4Ta71V4eB2z2q+0yd1frN46DP2dEFIGiY6kZQMyf8p2Wn7I5 +DYD1g0zm+oXmOA8QiojP50r8CoxbZ/TYyedSf35JT6UCts0rUk8gEia X-Gm-Gg: AYBFou0IzMWPvGcjYMmb9T3DspoxVh272z2OrLl2fqCpbM+2et+FMaacirPSBziUtL0 dGpeHa0BhiWgH1bMwhcPd5OBEAUCqjm87Uz3tP1R9Od7Gbak4mxJSC+04nZ0+9vz9/Rz3Pyi6WE oa5s5XO3RgOt3G432qUSqJu251hv7T1oVNWh9r3QzcOylrnCIrVjxp+erMZq7peAq/zU7sm5Mtn 3ZNf4w1Xx0P+y6Vj+gGTZEAJd6zNdAm/4DDEmYkmxCAXkHP8wM2wlWbga08BTZBuj3xrpVql52O UwoqCOowBqoCWLhD2iEaOQLmznBrGFOG1WP5A01WUQdfcs59wP95MtmzQJ1JPV6vj5fICQncMjh VfUK6SLl1LtmPifs06JKcD+LU/sPV3lc0FVX5lL1XmWLJhszHRuhLdBjpb6N1fOnuiCtEZ3rAgc j9yr0oyjRcIt/fm0o1BMLVL4j6ro5QypmUJGnlCMTgQhZjUsfox2asz1oO3oQ6TAQyzQbgKvYCT JSc106aUuYYMNMkfezA2N3wMMbaf19wAm/gEOcpsajQk+ouelaSCYUdgUPGW9ZEER3ryIzzYSMm CWh4zNJb2uZlT4L72LTPp6ZragjLfMFP9J+NgZdTxTMz1XTMKjiu0v2ShTWsry0bSPjDqsmNicb CtT9Vs10wIaaZEZV8+yv09T8CowIUKA== X-Received: by 2002:a05:6870:d307:b0:47d:a38a:6218 with SMTP id 586e51a60fabf-47de9864d36mr7458245fac.25.1789272327784; Sat, 12 Sep 2026 21:05:27 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:27 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:05 -0600 Subject: [PATCH v4 14/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-14-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 5fba3c111a4b..84e1e04d0743 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1755,8 +1755,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; @@ -1805,8 +1803,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; @@ -1835,8 +1831,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; @@ -1877,8 +1871,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; @@ -1902,8 +1894,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; @@ -1947,8 +1937,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 12:04:12 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 B983939989D for ; Sun, 13 Sep 2026 04:05:31 +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=1789272334; cv=none; b=n6LnZgr479/EU9hWVww6v8E0YdEgDrCEqcIQ2AcXpTg0ITJpeutFiitBTlPxOSZuadhq3GtPKB4wsijh4zQnjSCeNdkwcb4m2deXxj9ln9V9FPUm9L0XfeGbP/t7djxLtxM4hGHntr9RFg+thQV3WuENiTKnpfMVI5QlLXBS0JQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272334; c=relaxed/simple; bh=VjHE1JdFdVf9CJbf3YH4SKT7hC4rAP1wz6y0IHKu+vU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ryFfxuO1ettSd45Ky95U6ATGm4F5qh5gJITIiW+mHmU4lEw+dTNel8X06OkqzrnR1v/AOfvNytgWywomJ+M1rBeXtoYUx9/2PKJmRdyDZli/JgKGEqlb840ljtkHyZV5MD2EThF69pJw0wQ/EGozxwrEFTJNkpxpy0AJbp73BjA= 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=PhuCgZIf; 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="PhuCgZIf" Received: by mail-oo2-f40.google.com with SMTP id 46e09a7af769-80527255583so251258a34.1 for ; Sat, 12 Sep 2026 21:05:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272331; x=1789877131; 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=KdSItwmPertDTRkK8vqVEqMt7TRjoawR0JDQnwMenpk=; b=PhuCgZIfy3QoHTRgJEntStDefm36bnmjMfTjwcikIWyQ5FJQOvfYmr1X2sraGI9xue XOEqitkYPgH5v6naaeALZk4GUV1cdytiiQ45PP0LD98G8qnm57GEPfQhYRF8V8ApJyEB Mv5GohL+ERLS1jEOvMMYf69ra9dqIqp6d+AeSJtveJ2nyavD2EpiacguNPMIdYy/vam6 KtZYMpEvE25RBP0qDci1yogxD3Uk0j+7zldQd5sWXvtOfyk7HPdIsdMrP1nnwUI/h878 O6ZeC0iJTp90SjXKJqTSKkbbu6LxyYo3aWnncAKmwaFvy+SMI84PiliwFm/lNlEA/M0h HU+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272331; x=1789877131; 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=KdSItwmPertDTRkK8vqVEqMt7TRjoawR0JDQnwMenpk=; b=a0ei2bEKhVD5J+66UhGHHYwVJJJmpJdgh9rbWlCaO9UpA5D/C+Wce3i+90AbP8h6Q5 SmOWO59x7OCs4Eb71JoYOErjBNS0IlhCQ2z/+udjBvBeDepeAGcy8yEXCEHMHIFeZpfA qpMfK31vCMD8h8E4LlIMCYthKQ5YOAcwcxJRR3vHMBK4MUPqI47BVjd4Gjg+6c3ZvOdt BgtXUNxfi+GSlZKx6gWimaiDBdmQxYhwkku0Tjg3PKXg/kXugxf8whe4fpk53rC904BG 3H2UcmkoCWphc/DNNswwdKydkV2eF7mgQHI3EW4G2YLKwFOpjvoyPanGjQWzvxrTB4U1 d4NQ== X-Forwarded-Encrypted: i=1; AKwUvBzEd5hNlGBvxKluWtUXHTNb1C9NBpRxPskrC+IWyfP7apG/e243nkHkoDcOn859de+oqcdA0ZeijMOTPKI=@vger.kernel.org X-Gm-Message-State: AFuF++lpOIz5wqusU0NW3qjbB2DrU51kWrxI9Ac2FoR6es/AxahvftpM OwwvwwhAR/UACzk51CmMwDLiSlanwtT6S9au5nrzuQ1Yz7UmH5OyQBGV X-Gm-Gg: AYBFou1T2DtIjIsI6ayjA+BBYMx5rsy0888FhXq9JLtLw5qapj8ixRl/Z8UZPh/4sgj +5HzE3vKm4t9VguOs9lJQug7VrLYg7DSWEKp8A2inll2ugdUOHFXdJDWfHm1XBC0Cn1FMrzveap Q2LfrgPCtkPpNjgIBTgI71aPOLWj9PjhlmkA8sLjgbHYgolD2PcmW1RyP+UTiH/3jv8HP/LbJoR pPgvynyTcrJkcypXsPYaEFN8vJ2gAA+n6zntvdjWLTdRmlQexDA4hyqkH2s7Kn+lkwLb7iDabiR X1N/MaJwZn9I6qpuAIG8+1QjqpuP139RPu3s7DSyfsRHlYf9P7hR3bxJw3eH6Q/ti6RxCuQEkdw JWdwyjTd3n4czbsR2pNwdPkoXJtiimWRyqTI8bYSsq/5rfi8WP9RSVXlpmF1j22tRDrx6Ztpc6c JlfnqMGTDl325ezohb50pNeIYB0Ux64ltwoLEDn2/RMa+E3kfdDGlH7P8rN0LvzseRA/Z6SKKbV syrY1JNwFxw9qvNRtkPi8Ao265bhTltjgZio9qEHKwFDvr4/wpUY/rUut0xGB1aLdDac7/HxPSu /eqUFQxOoI4EGL+z5XU6nJpictHeAsi1oCkMXnYvtMoosmHk4MqpEDyM1WrirwcTfNsut4Z4I7i MHzlWbWL1oBNry4pUoIHa0LpYWkP3kg== X-Received: by 2002:a05:6820:61e:b0:6b7:46e9:96f5 with SMTP id 006d021491bc7-6c24e672089mr2838753eaf.37.1789272329061; Sat, 12 Sep 2026 21:05:29 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:28 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:06 -0600 Subject: [PATCH v4 15/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-15-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 | 73 +++++++++++++++++++++++++----------= ---- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 84e1e04d0743..debef3f4f0dd 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1008,35 +1008,59 @@ 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 nc= hunks) +{ + 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, 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, @@ -1225,7 +1249,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, @@ -1536,9 +1560,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *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, i), = i); + sunxi_nfc_set_user_data_len_dma(nand, nchunks); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1694,7 +1716,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 @@ -1989,7 +2011,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, if (ret) goto pio_fallback; =20 - sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len_dma(nand, ecc->steps); 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); @@ -1997,7 +2019,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, i, !i, page, user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); --=20 2.53.0 From nobody Fri Sep 25 12:04:12 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 96022399004 for ; Sun, 13 Sep 2026 04:05:31 +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=1789272334; cv=none; b=PYPWlZdGaqndNczHF4jz2KCIz/acMaiMs138tX3upjoctW5yG8J+qkehU+MwtWqWD6T/7+4OPn+Z1m+iPVbzacJJAbk+liBbWPDH0aAHDj5BuKfCRRKyWmNHdqSaqhwqcn0H4Xhac1KUQkFhDxJFrxmIMKkouoZZJYAKKZoBCB0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272334; c=relaxed/simple; bh=+b9FVk7yg1ZvvCKVqsKXTOxCwWHm82NDo3cdNKjLRZc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M7ARLW+9eYomgM8HvwxAFuaqBYF+nac9B8wtmDShTZZvA94hLTruMbqvshp14HcZQm0kXYRjuVU3szG1OXmajR0IeN0ob6frOgCy6rhuJDCbEU3feZUp4SdtXxaKZqNfVEIXn347aHHqNBqCT1xEi/BSSJD/Msz0eIjTjAj2hlw= 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=KWbQtEPq; 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="KWbQtEPq" Received: by mail-oo2-f42.google.com with SMTP id 006d021491bc7-6b1ae6b2010so738949eaf.0 for ; Sat, 12 Sep 2026 21:05:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272330; x=1789877130; 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=8EW3/f+RzpimWbfDUvAx3KSD/RKaEHodr5Jfoelq2QM=; b=KWbQtEPqkZKJ69RGJwE8w85eeV/9F469MTYj4bwXY00RTzdYlEv6v+KMA/UfkLDRbB 68dLTw9gI9sA3RoCB62/cgkZJI/mUAT1SorPGPT9hRLRzR/iAv2CfwIV9URTB1iWxGqd u5UB8gv+OrlGRJC4wKiiNd0FLRio3pJTuvKgQX72YKjF4kScoowkfUx2tH257vA+7AnB aHWv7XDrJOfAJjhxaBQMSmsanQXoXASxLROAzIcAKpNlVes6aQBGYcuCrzKsOv1NV9mn UkHl9UYpKdcFT3qVLzuK0qSBYg+qc/kmECojLFkaeT5qA2/a0mLNA5LNcC7a0vX+zPmI HdEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272330; x=1789877130; 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=8EW3/f+RzpimWbfDUvAx3KSD/RKaEHodr5Jfoelq2QM=; b=J6i6mIrEbf9KDDTCj0SNyLLW7cPbuKBVQYuFCR+Etaq2L3gCuvK78PAPmItFCwYt5O DBaZbDu39IL01ZaG+USr/yU9iXmVWytccFP78RXsCcWYQ9+83gPDwd7N+9l7jWx7brqx +KBZGytBZjs8jFHqwXvHg8WHT4kpqLNoYmNnycFagJG+zwUEJYgxPkrBuV+ScV3oukbD SqnOn1vbuS61XvGo10lrcmLljq4WV6+GHtrA6HaqKvqK6G9J58S6+uaukQ0IqalRlQEI SzPhJ9dhWpre21aYCty+amaL3BAT6BKJ9KBnJn8TjafXwuvN5GmpQGVmb2J9BF7f+pTr KEkw== X-Forwarded-Encrypted: i=1; AKwUvBzJgPQ0hbQ+jbNmBsDvY2wwjjE76JExEpnz5V7uiO5+K7pAqovg/veyrOGQ8j3jraFiDqOyXvnS7oqaJM8=@vger.kernel.org X-Gm-Message-State: AFuF++nylLmRy8WFXGfVqOHyNXadWeF/gcL1G9FsiZ5dY4poJ74HImNy dz81adOAE1dUMMZ5ALST11SAi8H5v6I8JbneIFbN89Ded9g2DtDVLHzD X-Gm-Gg: AYBFou0Sb6nFTn7Joy4fN+8+LLZBBus72vi8cam4IG9bw5Jvu7CYbLvArG19/DPahwW iCypGkdeRG6MYrCg5T/mzfdGSeDK2LnkV/fNUkUqyQ6Us13TV2hzDM5IPovbxOWPuY7UDQfCQRp XIAMaLvSI+LN3Utc46FnlCH8M4MbObbLYrYi5rOVeYfm3RAz+Pffef4WEeJqf6rrGtXa0aUgcCL gmWQ27HPB2+vsI6zRstcmArCb5d8XWdqUKatksX33Uwtyh3YA/jsUrUEBvj0tHMMLG+uQHn97Qn D6WLr82iQydVzT0PNGhV7TDrfQgTLzxEmJw+CZv72yBv0dZnRK30Uv6RrlgwBsvRKhQptwv/EDX tSMbFa5KEO/3X/5XozlMaQ4WhgXSHkkPqkpfsHpaRpoPNKkp8rb4MH/zmog651RVYAwXz80Ubl9 l2zLZc60ORJo2IpbpdciTmDBdzCTgSisDahh+zj1TM5lQNi0K+OqF0FJpdrRWsfceRVakhxRlv9 A01Vv6cbiWpPZVKlKt4fGlNze4RiQUJnzC+KJ3C6lMWjlz3qXtJ706avYGYSnClPefr0aMZw3zC +Vf7HtswoeKei+mC/qd7SBsMnAoOXVcgyUaXCpUcEUHBZ9VvAEjr4SkRfi1w/EfZxD8RDjLj/RK 9vGkCVqB0j01PCY9H+gCPhhdwFUaORkklnt+6Ni6M X-Received: by 2002:a05:6820:8187:b0:6b7:46fa:16a7 with SMTP id 006d021491bc7-6c0bd874de9mr6693573eaf.60.1789272330523; Sat, 12 Sep 2026 21:05:30 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:29 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:07 -0600 Subject: [PATCH v4 16/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-16-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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 | 100 +++++++++++++++++++++++++---------= ---- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index debef3f4f0dd..1303dca74cf9 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1150,46 +1150,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; @@ -1205,9 +1246,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, @@ -1222,7 +1261,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; @@ -1262,13 +1301,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); @@ -1276,8 +1313,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 @@ -1542,13 +1578,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; struct sunxi_nfc_ecc_status result =3D {}; + struct sunxi_nfc_ecc_snapshot snapshot; unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; bool erased_chunk_found =3D false; int ret, i; struct scatterlist sg; - u32 status, pattern_found, wait; + u32 wait; =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1589,9 +1626,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *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++) { int data_off =3D i * ecc->size; @@ -1603,8 +1638,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf int bitflips; =20 if (sunxi_nand->randomized_oob) { - sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, status, - pattern_found); + sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, &snapshot); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, page, user_data_sz); continue; @@ -1612,7 +1646,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *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. */ @@ -1641,7 +1675,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, oob_required, true, page); =20 - if (status & NFC_ECC_ERR_MSK(nfc)) { + if (snapshot.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); @@ -1649,7 +1683,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *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 ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, --=20 2.53.0 From nobody Fri Sep 25 12:04:12 2026 Received: from mail-oo1-f44.google.com (mail-oo1-f44.google.com [209.85.161.44]) (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 485E139CCEF for ; Sun, 13 Sep 2026 04:05:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272336; cv=none; b=JeR0tChJtFrRFQSO1rMbZF40Ddtz6qLyjH4zfKGwhMEo4p0yDp4xuTCA2SW1jOTYFs6FgHlutUXBl3ylmp21RkFWpoNtRjqNJqqvRcz3h+LNGkLcxIWzMO+m65AYVmWYUcM2VljO9Ex5m6yVynO6u6CEVuJkCp1yfUEQzztI+Js= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789272336; c=relaxed/simple; bh=3HfrlOISvouvOHb/zDf0DeWxK38QXA8QpUUxCtZMkLI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jf0F0pmdJOObnaWDTGKDrzR0vwLnvmcQIGICqeiDqOQ5Rh/ksSu27caJ19wNPhRl02W56z+zqD8LipNqSwkYZLtIy8xGAE6GrF5uJazBrlmkZbUPrPdYiXNHPCWjU5FhSugO5RjQg0NxPYL851mty4zIyzA1xalyGDGki0Kvf90= 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=jjzI9N9I; arc=none smtp.client-ip=209.85.161.44 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="jjzI9N9I" Received: by mail-oo1-f44.google.com with SMTP id 006d021491bc7-6aa9606ddadso1908704eaf.0 for ; Sat, 12 Sep 2026 21:05:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789272332; x=1789877132; 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=5rmncXijitRcj9RxOard0Heg+Nrz/VMzyCWVR9VWKLw=; b=jjzI9N9I2MNoXuzNEp6OMwuyBE/N5xz+WK/Vevi4SYAXnIy3Kfqi1ikuSeWh39+iiv eB03snRzbMZkJyI8pQ9mfNZTar2Mp6rNjzd2RG7/6sN5QOOgdDlGQRQJiJcLJ8J8K8LP SiILPfd2bujz95hPH0uVcISwoa0qsx1CtqMQwz5+ouPpEL1RLz+Q31nKHI4AzVB4god8 D5l97HS8Ik4UhbCqgxTGtX6IWUENe7x1YfCAP72sw8piD46GV1h7DPD56xtuJpRS+Ns1 UcYRVDrshxQAIcSTLMmG8AfwPQWL8JtxmuKpo9zLrvYVfRcYan3CHzZlM9OLDXQp5MgR lTEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789272332; x=1789877132; 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=5rmncXijitRcj9RxOard0Heg+Nrz/VMzyCWVR9VWKLw=; b=dvKoG/A4EZWR6ej9STbyieCoeczXzkyOZ9YpJDmhleHkoDyajXQ3z4wXyV7yM3XbO4 n9k5mjEp6mqRcJDKjjXtJLjvQnY6f8zJHLz+GuiwkfJZMe7NYxUfUu85oxngLRkgeNqM NH8VQEOwNlcEyEWxHayB/aC3UABTxGL/IbJUi3B5k6eKuvzKIESWee5GZt+0j+I5Labe 6YX3t78HRlA90W5aCm2FURsreZYNCRKchVNLTm3/JEMNnSJtdyU9xT71sJOg2JtmpCue 41RXGSbczNFMTiH9m3Gdgvv21sne/Tu98TzFjujZh8P3EG99+4d8SWGsM/cm3o58guxo DXMA== X-Forwarded-Encrypted: i=1; AKwUvBzCI9KbPC43z3AQuQDxeHnJMnUxLSJwPomIue/B5XvMTDIMBYHLZRbk1WQmZCGjg2jUJa7SUPIZgNHLmlw=@vger.kernel.org X-Gm-Message-State: AFuF++lFPPc+j2yaNkXNgCzLwKdGtqsSicPhOX2EqPJT3VToLVqJykrH kNjrgfGWAd8HStCEhJZapFSqZ9zSGm5PmsCyyYneOq4KrNSo4Uywdkcy X-Gm-Gg: AYBFou15lTI8Zzc6ZK+3WpCem+xD8CPv/0ZSMTwo6qQoxIERlhcVEQYSRsW/ph9EQqT r+GZHhlZ0OjBe/I/9z6VxdEUxeaNrBILO9/MzEcMDLceLHh7dgQ7NVkXUJzk17CtfDSrMkrIOGm fhVPaHGwRrnn+D5VufBUhxOr6jpLeNl6Vps1MqFYojyv/Esl9/RbP0YGZJmVC92VUNhuFfq8ofJ O5+oFPkGGNC701w+FlKf6r59aLvaA+ORFiyMxFCtOnfl80yCqIGAaRh/CZrd6tFuJKpw8/D7vRs FIYryJ6Mx0o1sDb5B2dChwlzw05wJI5tbuy4hPa0Ookkbp+sbRzf3cR4LQ1lcTHZESkKxsmQs++ ZhjrrQarlS7thz9XAta4DjLoeD/WxzIFvIYMizeG6et/XPC0qtZnoYUWkWWjVP38JafOjk8Dn8x lDTBoEZ93fEvyHcY539SaKJFmkS3lVOtAP51GrilCoRIrDNnFCUM/7CGNmISW4VXvWPI1prO0Db YD6HNAueygk9xurVU0crM/k3PohM5RuGeAQwSctgnSyPtd454La5VBnM2tCmcVH88G+LFX/OVuV yY/obRFzit7Ez0kI/HS5vkudumDJ22sP0nFPBTtbhOTSgZ/wnBgPduAURbwUoQUP6lY/MW5KFFp LxaakCV5RVxg2Yal4mH3zNFKAKC06Ng== X-Received: by 2002:a4a:ec4c:0:b0:6be:4eb3:e1c7 with SMTP id 006d021491bc7-6c0b985e1d1mr6850526eaf.14.1789272332039; Sat, 12 Sep 2026 21:05:32 -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 586e51a60fabf-47df8699647sm6011535fac.5.2026.09.12.21.05.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 21:05:31 -0700 (PDT) From: James Hilliard Date: Sat, 12 Sep 2026 22:05:08 -0600 Subject: [PATCH v4 17/17] 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: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-17-4a64bed94229@gmail.com> References: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@gmail.com> In-Reply-To: <20260912-submit-sunxi-nand-vendor-oob-layout-v1-v4-0-4a64bed94229@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, erased-page classification and the trailing-OOB read page-wide, and 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 | 270 +++++++++++++++++++++++-----------= ---- 1 file changed, 161 insertions(+), 109 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 1303dca74cf9..c43d2d268d84 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 */ @@ -946,44 +947,40 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_ch= ip *sunxi_nand, return sunxi_nand->user_data_bytes[logical_step]; } =20 -/* - * Variable-length user data is concatenated in four-byte registers. - * PIO uses hardware step zero; DMA slots follow the logical page steps. - */ -static unsigned int -sunxi_nfc_user_data_reg_index(struct sunxi_nand_chip *sunxi_nand, int hw_s= tep) +/* 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) { - unsigned int byte_offset =3D 0; + 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; =20 - for (i =3D 0; i < hw_step; i++) - byte_offset +=3D sunxi_nfc_user_data_sz(sunxi_nand, 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; + } =20 - return byte_offset / 4; + return i - first_step; } =20 +/* 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 hw_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) { - user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, hw_step)); - sunxi_nfc_user_data_to_buf(user_data, oob); - } else { - unsigned int reg_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); - unsigned int reg_off; - u8 *ptr =3D oob; - unsigned int i; - - for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { - reg_off =3D NFC_REG_USER_DATA(nfc, reg_index + 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 /* Undo hardware de-randomization for a plain on-flash BBM. */ @@ -1038,7 +1035,8 @@ static void sunxi_nfc_set_user_data_len_pio(struct su= nxi_nfc *nfc, int len) nfc->regs + NFC_REG_USER_DATA_LEN(nfc, 0)); } =20 -static void sunxi_nfc_set_user_data_len_dma(struct nand_chip *nand, int nc= hunks) +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); @@ -1054,7 +1052,7 @@ static void sunxi_nfc_set_user_data_len_dma(struct na= nd_chip *nand, int nchunks) 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, 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); @@ -1064,13 +1062,14 @@ static void sunxi_nfc_set_user_data_len_dma(struct = nand_chip *nand, int nchunks) } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, - const u8 *oob, int hw_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 /* Pre-randomize the BBM so the hardware writes it plain on flash. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && @@ -1080,18 +1079,9 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(stru= ct nand_chip *nand, oob =3D user_data; } =20 - if (!nfc->caps->reg_user_data_len) { - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(nfc, hw_step)); - } else { - unsigned int reg_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); - const u8 *ptr =3D oob; - unsigned int i; - - 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, reg_index + 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 @@ -1374,7 +1364,7 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_chi= p *sunxi_nand, struct nand_ecc_ctrl *ecc, int logical_step) { return sunxi_get_oob_offset(sunxi_nand, ecc, logical_step) + - sunxi_nfc_user_data_sz(sunxi_nand, 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, @@ -1568,36 +1558,47 @@ sunxi_nfc_hw_ecc_finish_randomized_read(struct nand= _chip *nand, u8 *buf, return result->max_bitflips; } =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, + struct sunxi_nfc_ecc_status *result, + bool *erased_chunk_found) { 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; - struct sunxi_nfc_ecc_status result =3D {}; struct sunxi_nfc_ecc_snapshot snapshot; - 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; - bool erased_chunk_found =3D false; int ret, i; struct scatterlist sg; u32 wait; =20 + if (first_step) { + ret =3D nand_change_read_column_op(nand, first_step * ecc->size, + NULL, 0, false); + 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; =20 sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_set_user_data_len_dma(nand, nchunks); + 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= ), + nfc->regs + NFC_REG_SPARE_AREA(nfc)); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1628,18 +1629,21 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf =20 sunxi_nfc_hw_ecc_read_status(nand, &snapshot); =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); + if (sunxi_nand->randomized_oob) { - sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, &snapshot); - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, + 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; } @@ -1659,44 +1663,73 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf oob, ecc->bytes + user_data_sz, false); 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) - erased_chunk_found =3D true; + *erased_chunk_found =3D true; =20 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 if (sunxi_nand->randomized_oob) - return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, - oob_required, true, page); + return 0; =20 if (snapshot.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 (!(snapshot.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); if (ret < 0) - goto err_stats; + return ret; if (ret) - erased_chunk_found =3D true; + *erased_chunk_found =3D true; } } =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 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; + bool erased_chunk_found =3D false; + 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, &result, + &erased_chunk_found); + if (ret < 0) + goto err_stats; + max_bitflips =3D max_t(unsigned int, max_bitflips, ret); + } + + 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); @@ -2029,68 +2062,87 @@ 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_set_user_data_len_dma(nand, ecc->steps); - 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_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); + 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); + 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