From patchwork Mon Sep 14 03:01:09 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3316 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114]) by mxe881.netcup.net (Postfix) with ESMTPS id 3A8281C2BD4 for ; Mon, 14 Sep 2026 05:02:47 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.105.105.114) smtp.mailfrom=linux-sunxi+bounces-25877-noreply=patchwork.local@lists.linux.dev smtp.helo=tor.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.105.105.114 as permitted sender) client-ip=172.105.105.114; envelope-from=linux-sunxi+bounces-25877-noreply=patchwork.local@lists.linux.dev; helo=tor.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by tor.lore.kernel.org (Postfix) with ESMTP id 430CE2DA02 for ; Mon, 14 Sep 2026 03:01:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E8AAE3403E7; Mon, 14 Sep 2026 03:01:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="c6FcD95I" X-Original-To: linux-sunxi@lists.linux.dev 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 82B70330659 for ; Mon, 14 Sep 2026 03:01:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354906; cv=none; b=rNPAnA8JTO4X0vrbgbWt50fa6RGJ4Q82kjl/dBNJI71kqp12I+Q8RURf/8JZvtJhS0+nFVZgZFoebdrQT2RZhmYOimDIX1XrkLZg51HWzKBNJrgl8dwnOci3WyzTSWbXtMLPFwltumx7Uw83073k7zUfz7vi+OksEYr9HhNAnTc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354906; c=relaxed/simple; bh=sEgsacOGRde9P8OKLBN0PM1Bqnp+ZYDx65EvzcaNGcA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Mm4S0JyLPmaYEiVO1TBYznE4zl8VKjzcCyuXAJ9q2U9QAidsjvmcEpm6gUz69z63G1ABoND2g3ayyoZArj4R0r/QQKYEB1W43Uq5dcy+56k4oZ98COzXDFfN9ZPuUXYxneUMw6kLM4bDNFeAk788EwXsyAYLPSJ4nNQIhQU4pX4= 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=c6FcD95I; 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 Received: by mail-oo2-f42.google.com with SMTP id 46e09a7af769-804f7045f3eso379657a34.2 for ; Sun, 13 Sep 2026 20:01:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354901; x=1789959701; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=a95pnyMUuTP3EJOQCSW0InToPnlbmRSOMBXnRGDUxFk=; b=c6FcD95Icrt0S6B+MsCZnFysZ64CuTNdtYFVR1Bu4k6Db7oouIEfJqGyfiShLnMF+H 70G/vTlD7t2KzKnauGU/qNGQqCjFYeVBMDh7EHtI6EFNM3H3r8QMwrPQFKWV869zx3WX +wLI7UQtbJ/4OQ635FhcE9tMjDoKYYJgF9JLao1+LCZrXQEL3SQK4Lg2keESBRZtiECw jbYP20nDnadWSC97kY904w3rwiO56V6j358QVjOCrYU1BHWhQ8FjK1/Myv7w2J89Ym6v G5a5xODF51F+Hgi3a6Ie2kmpXrYO4vmVh1+BOpIUtSkh0vvvL/1bld9RlBiARfA8spzJ y4iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354901; x=1789959701; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=a95pnyMUuTP3EJOQCSW0InToPnlbmRSOMBXnRGDUxFk=; b=YPuPr0s8Br/GE3+69Ij/O9on46Eef4coKyfM0Abgm2bxHnMNvGjY/oH/mIFYbPsvTy TsIFr813PnimDgdMw3j0kSndo7sIYVov4PyU/5ZXDuZJaDCuXVe1v6K+OJKPSu/J70lF IiuRaIZvOj7SmWwqA8dxVXZTEVq3SSmwEFooimGYsV6lSBCq2cVLey3lbwWiSws+rFIH ZAPZG3byfi+6V2DukrSU+iNCMsVewWE7HckvfBg556zgxLCJnURYoUFtK2wofe5VySFZ 2yBtc6s6U2ZPGN6P1IwxvyjZrI5u8+nynFsgaRXB4rthgc/g09xiEMBo0uMK3XIXJ4qA ouEg== X-Forwarded-Encrypted: i=1; AKwUvBxVzsLd9TA1ppopN631JCZGAElHbbb1dSF0ZfAhorCzg0LoOyd4L77scaJeCdgVojIeka3RvZh+KRc5pg==@lists.linux.dev X-Gm-Message-State: AFuF++n9ZItQNfOMuDIQLI4+mJKXGZYGA8ZBCBmK+8cYYpKhGuTQCqMM 1KzmDjljwJ1zKJLdnT42P28q+9CRl1UyIFaziz67CxC6Pqrt68QPngzZ X-Gm-Gg: AYBFou2p4OQAnGdQJ1p7Da9u+QmaSU02/UXOe1RKJcZZEhEmfjxu+sdF97/x7ibJKdN tyAVEDCrlRkPQ/xResxKcAQ6obBG+XGxj5QHZ+8pib156I7dbwZlHe+SC6cNnC3wCOTOHn/rAJT KwLpejvvGjGT7H91emiKKyilApRKvUFre7jsPY5fgyw58ig70eCXLr5n7UPKI//iWWvJZVqw6hg 6VPda4nd/E24fenoh8w6RtVGvSS/135Hl/0pbm1iBmVzwGjt1MMiEAqp9hcrbuGh1ZLQjW7Tnjg GOA7wm0aDLlUPnmOSWGO4BxmHMOBroc3nzubk/dgXJzGFkdv38gPjvUK+sJGD60bCpf/Z06KBYu GXaWI4KDrXf6SpkLezcj2om0Me8nLj4NqkVw/CDoIsY13NV8Julrf1EdRlL9njh656OA1qNaQ2l O+qlLxmCRsc6zmMDQezEgsxQnkQ8udKXWZihevbx1Yrn1USl3z/jJlVp0deNfT/OmvMtmRqMfop NDIsXZH757yfA6E+TnTnsdP1RE0WVEI0NdoWOXH4IKwwgTR56Pqcrea+2emI83RRNR8ztksClTK 75GGCnmPnQdRUzPqSPoWQJ1bmFxZQh9UVrGw/gvu8bjz5gnvT2ERtCDFDUAsdyCKYnOJC+Lot4/ 4R6x+FqZp+/zNYaq/p1+0HI7WznCgqQ== X-Received: by 2002:a05:6830:2a8f:b0:802:68c:1b51 with SMTP id 46e09a7af769-8089798d600mr284960a34.11.1789354901016; Sun, 13 Sep 2026 20:01:41 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.01.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:01:40 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:09 -0600 Subject: [PATCH v5 03/18] mtd: rawnand: sunxi: propagate page-setup and erased-check errors Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-3-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.105.105.114:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[21]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[tor.lore.kernel.org:rdns,tor.lore.kernel.org:helo]; TAGGED_RCPT(0.00)[dt]; FREEMAIL_CC(0.00)[lists.infradead.org,vger.kernel.org,lists.linux.dev,gmail.com]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-25877-noreply=patchwork.local]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114]; FREEMAIL_TO(0.00)[bootlin.com,nod.at,ti.com,kernel.org,gmail.com,sholland.org,socionext.com]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.105.96.0/20, country:SG]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 3A8281C2BD4 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The hardware-ECC read callbacks ignore errors from nand_read_page_op(). A failed page-setup command can leave the previous page available, so a later successful transfer can return stale data instead of the requested page. Stop before starting the PIO or DMA transfer when page setup fails. The physical rereads used to check an uncorrectable chunk for erased contents also ignore errors from nand_change_read_column_op(). A failed transfer can therefore leave stale data in the buffers used for the erased check and turn an I/O failure into an ECC result. Share the erased-chunk fallback between PIO and DMA and stop before checking the buffers when either reread fails. Preserve the existing erased-chunk test and corrected-bit accounting when both reads succeed. Before retrying a failed DMA read in PIO, restore only its corrected and failed counters so partial results are not counted twice. Leave bad-block and BBT counters alone. Route PIO page and subpage error exits through ECC disable before returning the transfer error. Fixes: 97d90da8a886 ("mtd: nand: provide several helpers to do common NAND operations") Fixes: 25f815f66a14 ("mtd: nand: force drivers to explicitly send READ/PROG commands") Cc: stable@vger.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 120 +++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 172c7c4b0ba6..d5d8d383b6d1 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1067,6 +1067,40 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } +/* + * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC + * statistics updated in either case. Negative values report transport errors. + */ +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 = &nand->ecc; + unsigned int oob_len = ecc->bytes + user_data_sz; + int ret; + + /* Check the physical representation for bitflips in erased pages. */ + if (nand->options & NAND_NEED_SCRAMBLING) { + ret = nand_change_read_column_op(nand, data_off, data, + ecc->size, false); + if (ret) + return ret; + } + + ret = nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + if (ret) + return ret; + + ret = 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 >= 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_chip *nand, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc = &nand->ecc; - int raw_mode = 0; u32 pattern_found; bool bbm = !step; bool erased; @@ -1158,25 +1191,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, return 1; 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); - nand_change_read_column_op(nand, oob_off, oob, - ecc->bytes + user_data_sz, false); - - ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, ecc->strength); - if (ret >= 0) - raw_mode = 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); @@ -1193,7 +1214,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); - return raw_mode; + return 0; } /* @@ -1260,6 +1281,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int corrected = mtd->ecc_stats.corrected; + unsigned int failed = mtd->ecc_stats.failed; unsigned int max_bitflips = 0; int ret, i, raw_mode = 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; - /* - * 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 = nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, - ecc->strength); - if (ret >= 0) + ret = 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 = corrected; + mtd->ecc_stats.failed = failed; + return ret; + } + if (ret) raw_mode = 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); } } @@ -1471,7 +1483,9 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1487,7 +1501,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, &cur_off, &max_bitflips, i, oob_required, page); if (ret < 0) - return ret; + goto out; else if (ret) raw_mode = true; } @@ -1496,9 +1510,11 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !raw_mode, page); + ret = max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); - return max_bitflips; + return ret; } 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, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; ret = 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, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1550,12 +1570,14 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, &cur_off, &max_bitflips, i, false, page); if (ret < 0) - return ret; + goto out; } + ret = max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); - return max_bitflips; + return ret; } 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 nand_chip *nand, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks); if (ret >= 0)