From patchwork Wed Sep 9 08:30:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3248 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 969151C1C0E for ; Wed, 9 Sep 2026 10:42:14 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-25744-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-25744-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 2CD6A389ED for ; Wed, 9 Sep 2026 08:32:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D771A49AA31; Wed, 9 Sep 2026 08:31:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ld196Etk" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f49.google.com (mail-ot1-f49.google.com [209.85.210.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE2074915BC for ; Wed, 9 Sep 2026 08:31:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942679; cv=none; b=LqkY3Qn1B2u8MTOplxlH4k3IYlxi92R11o+xn9Ta3WPXaXUpLHhN8JZamdDVegVfmfmVCb8/D1XDMwK5VPEcRl8/1FS6zLJI44d+g+Wz082msJUWeW2R9Xe2YH2fFAZr72xWZhqDL5tpco/Fh5fNWrObNq3sRtU8Y2nkVNwHgFw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942679; c=relaxed/simple; bh=yZNKja0Z9caXLLme/IdLs4HeW5UUaQuGdtowtZBClj8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oJqWoFIjUMOXMlTulrsZSiwAWvDS2xiZ4VwLpoWqf9tRjL1LM7ptPY5U3HYb5BUln95lkct2SZ6txER9fce6Wi4vNBc1VA7Nxt65V/0/OrAkLBGaP0mfVwONLThY+Cinnk4vg6n4uKbxY5q+a/MRc3sWkQrD9N0iN7sI8pnQe+I= 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=ld196Etk; arc=none smtp.client-ip=209.85.210.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f49.google.com with SMTP id 46e09a7af769-7f6617c7536so2429368a34.1 for ; Wed, 09 Sep 2026 01:31:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942675; x=1789547475; 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=ZVBoL4uLYSK7OhzJyk+4QlEDJCrYxUZn9Ns/nhu2ClA=; b=ld196EtkzkzlQ75veChXNEbwV5gqeg9SSChmvhBh+kvDmutXvjhctjqOBXWmd384+W lInm6aBIobYIjIA+fV2NB5AKAOdKRnQPmsM9ygyZ78OmQ3G51SLxrDPijMbrAYnvtfD5 FIGN28q1L52BHXFg9s8dHT7GZzcfhWDEqDhezfoK30uSViimJX0F27ORQEoBXTxE7f7G 1tYgwI3VMw5C0Cfy4wjt3jr5t3HsUOPOpMTJv855OYlXapsfCBPlaJLWink0HYsw3B0K tRXxS2+R1wYIPwC/DTvdawwbRdmxw+Zy9F+DnpxbjDbQfHoak0sGP9TzzDGa4DJ3loL8 OXtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942675; x=1789547475; 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=ZVBoL4uLYSK7OhzJyk+4QlEDJCrYxUZn9Ns/nhu2ClA=; b=DY+mGV8fJ/xah+cAWAz8Jo7V3FNGcNa77hxyl4RSZRtwcVmJc1L8UBrwbE9GOps3xj 0XeS9vbu+o5em1CzZfyMyZT2XuzslUqX5pv9MzFPTt7tVE6j9WZcqi/aN13lh62HJ+hQ e47AUXk2Bqa6G2XOjqlT+FgbPyplLFdfvFivByfc1LcO9fovkHoTtHLZDOEDSNRhnhPR Fu//2ND0WjB4GeMvUU9RqMyfV/fE0GeV/BhlRcP2cm5BynB2URhBMYH5HxZCmrdxYEM3 ferZxa0u7j6/VAN2Cf6l8+w6LYpxuZu6RDin0m3xDBttpc3qGZV1W1RMzI3ayuS1U+EM pKAQ== X-Forwarded-Encrypted: i=1; AKwUvBxIkNMzqZHHIsCavdmHVTQtUDMHf3VExD2X2jeLPmEz+UXirCKTdtNVhsHPhb16guBkvLQi1VrLzirS+w==@lists.linux.dev X-Gm-Message-State: AFuF++lJ/a24w7fwLmspZ3ShJIXT8kEpzYZYRXOaSgqybdRTmHeGfChf Hcm63Fw0psN2Pav2VTKuLaD+Rz4qG0jdqA7NGb/C/xMiVqmfsPZ152vd X-Gm-Gg: AYBFou10geaZ3WlNJVgYRjrXpHqIWg5T+vPIYxjd6SHE6TlMGQOx4yT0/pbRigLxogq Owcjd/XPH3hTEDf0hpAJLqKVtfd6NEpBvQGLpClDmAEbO+1I10MLNfER/ALvoWN6GQ0h/TyL5AX ClqNHb3miXJEoH4VSPdw16hdTsqvw4fXZjSWnHaCrMJMESALft90uggMSz4+Kr7/BJd9h6qxEmX NpKFMuNRUuTopFNAPyaF30DAC5YpqKwU5AE3G7gPBH8R/fcMMlnDF3C0/TccawDxYeZJZ7w8tkB 478pXNvKulrxcSwJpSwWfoerNIW83tslEhq+PEfs88W9wR8yzTWb0YPlVVS29QJ1lmg+E2cxCCF CQWzMjnka11jNxzpX7iSR0TzLqcrioC8l50+dZizBHRavd7Zmz1aK88Psy1kE0RIlJfzkxdBbYU Osgth2CxBorfSepiPX39XL5HM+d7gZYfiiD9TlL815P+5uGsniK1yUJyItlWaBFMo0e44/o89IA WgP0SBk3LImq1U2SJvDGrVTqc1xmnaCg7JN6M6bKkzHE/sbHs71v33zWwfjNzI/PScMPzFUteWa 1KS1SKsIac9ZE/97OlWsQbaDtPfujAp6XA8ZS1f4uXAa9GY1lnReDtDDeUceLhkJIiEMMIVvHJL 7owZ804KVA0WwF0Idqul9MiiIEJLKnb5b0CXcCaNr X-Received: by 2002:a05:6820:1987:b0:6ae:a950:9faa with SMTP id 006d021491bc7-6b6faee2564mr17826769eaf.10.1788942675012; Wed, 09 Sep 2026 01:31:15 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:14 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:48 -0600 Subject: [PATCH v3 15/15] mtd: rawnand: sunxi: reuse ECC status within each DMA read Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-15-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@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 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.234.253.10: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)[]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; PRECEDENCE_BULK(0.00)[]; TAGGED_RCPT(0.00)[dt]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[20]; FREEMAIL_CC(0.00)[lists.infradead.org,vger.kernel.org,lists.linux.dev,gmail.com]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; MID_RHS_MATCH_FROM(0.00)[]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,184.96.151.165:received,209.85.210.49:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; TAGGED_FROM(0.00)[bounces-25744-noreply=patchwork.local]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FREEMAIL_TO(0.00)[bootlin.com,nod.at,ti.com,kernel.org,gmail.com,sholland.org,socionext.com]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 969151C1C0E 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 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 1c1fcea69108..8710e91ffbaa 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1138,46 +1138,87 @@ struct sunxi_nfc_ecc_status { unsigned int max_bitflips; }; +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 = to_sunxi_nfc(nand->controller); + u32 pattern_found; + + pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); + snapshot->pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + if (nfc->caps->reg_pat_found == NFC_REG_ECC_ST) + snapshot->status = pattern_found; + else + snapshot->status = readl(nfc->regs + NFC_REG_ECC_ST); + snapshot->pattern_id = 0; + if (snapshot->pattern_found && + (to_sunxi_nand(nand)->randomized_oob || + (snapshot->pattern_found & ~snapshot->status))) + snapshot->pattern_id = readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + /* A new operation, including every PIO step, invalidates the count word. */ + snapshot->count_reg = ~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 = to_sunxi_nfc(nand->controller); + u32 reg = NFC_REG_ECC_ERR_CNT(nfc, hw_step); + + /* Four consecutive DMA steps share one error-counter register. */ + if (snapshot->count_reg != reg) { + snapshot->count = readl(nfc->regs + reg); + snapshot->count_reg = 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 = to_sunxi_nfc(nand->controller); u32 count; - 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 |= BIT(logical_step); - if (status & NFC_ECC_ERR(hw_step)) { + if (snapshot->status & NFC_ECC_ERR(hw_step)) { result->error_steps |= BIT(logical_step); return; } - count = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); - count = NFC_ECC_ERR_CNT(hw_step, count); + count = sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); result->corrected += count; result->max_bitflips = 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, + int hw_step, struct sunxi_nfc_ecc_snapshot *snapshot, unsigned int user_data_sz, bool *erased) { - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; - u32 tmp; *erased = false; - if (status & NFC_ECC_ERR(hw_step)) + if (snapshot->status & NFC_ECC_ERR(hw_step)) return -EBADMSG; - if (pattern_found & BIT(hw_step)) { + if (snapshot->pattern_found & BIT(hw_step)) { u8 pattern; - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step)))) { + if (unlikely(!(snapshot->pattern_id & BIT(hw_step)))) { pattern = 0x0; } else { pattern = 0xff; @@ -1193,9 +1234,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, return 0; } - tmp = 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); } static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, @@ -1210,7 +1249,7 @@ 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, logical_step); struct nand_ecc_ctrl *ecc = &nand->ecc; - u32 pattern_found; + struct sunxi_nfc_ecc_snapshot snapshot; bool bbm = !logical_step; bool erased; int ret, bitflips; @@ -1250,13 +1289,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, *cur_off = oob_off + ecc->bytes + user_data_sz; - pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); 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); @@ -1264,8 +1301,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, } bitflips = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, - 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; @@ -1530,13 +1566,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct sunxi_nfc_ecc_status result = {}; + struct sunxi_nfc_ecc_snapshot snapshot; unsigned int corrected = mtd->ecc_stats.corrected; unsigned int failed = mtd->ecc_stats.failed; unsigned int max_bitflips = 0; bool erased_chunk_found = false; int ret, i; struct scatterlist sg; - u32 status, pattern_found, wait; + u32 wait; ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1577,9 +1614,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf if (ret) return ret; - status = readl(nfc->regs + NFC_REG_ECC_ST); - pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); for (i = 0; i < nchunks; i++) { int data_off = i * ecc->size; @@ -1591,8 +1626,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf int bitflips; 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; @@ -1600,7 +1634,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf bitflips = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, - i, status, pattern_found, + i, &snapshot, user_data_sz, &erased); /* ECC errors are handled in the second loop. */ @@ -1629,7 +1663,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, oob_required, true, page); - if (status & NFC_ECC_ERR_MSK(nfc)) { + if (snapshot.status & NFC_ECC_ERR_MSK(nfc)) { for (i = 0; i < nchunks; i++) { int data_off = i * ecc->size; unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); @@ -1637,7 +1671,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf u8 *data = buf + data_off; u8 *oob = nand->oob_poi + oob_off; - if (!(status & NFC_ECC_ERR(i))) + if (!(snapshot.status & NFC_ECC_ERR(i))) continue; ret = sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob,