From patchwork Mon Sep 14 03:01:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3330 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 6E98F1C344A for ; Mon, 14 Sep 2026 05:10:00 +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-25892-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-25892-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 675DD347C1 for ; Mon, 14 Sep 2026 03:03:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 805F1367F45; Mon, 14 Sep 2026 03:02:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BEblQq1L" 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 1D40333C518 for ; Mon, 14 Sep 2026 03:02:05 +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=1789354929; cv=none; b=NHn7DRanc39DFnOei+ZVtLEEeXxI5EKnQrb9Xa1DA3rla6TeAzX+cpPTMyIOIhPeDTpl+IIlADjL8+mXrZ24mqqOgvnjm0KNqUhO5S9VJ+b0HXGwXR5Yn2tkaYq3ucr3RhRfUQXu1CjqLziDTtfEdxW38A6yFYVco/G+jFIHrlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789354929; c=relaxed/simple; bh=kb1Gsrib9J7X5Iu1bioEkSbneNLgmuqapwHKJriwhEA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ohMBNpk7sHxouU/7kJASgEcCI9cn7WBP4D+1I87puorlXX8w/2uUqlnJIo5RLhosUepzYuZM8BrImK3qCbeVJOBISRf99uZP5fY0gfe5j9f9niphPFwM4PDO2h/xi6zF7lvYH4BBm5Mpsw6AZQxT7zt4fWHI1b7+rm0armxsYw8= 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=BEblQq1L; 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-7f4f0c89e35so966587a34.2 for ; Sun, 13 Sep 2026 20:02:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789354925; x=1789959725; darn=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=gbdzTooPdY+KDhtZ/QzGrAlPMdYJpYAben39hMkDMIQ=; b=BEblQq1Lkvx+ddB+CqZ3Q478RG4ncJSGfqZ+iiDVhDWV7k4JcJRLyheyh+bSZg2dxJ xnLu1E1U3nHma2CI3uJuKwalz2ZNkjGpajWqujuj3Ffb7fdyxJ2Vi7LaznV5BwJudE3P qTLtwAywhON5Bsqlrsx0jZqs0zwblX6j57w0USCN63ATueVLBPy9bPjMNocpfMQmE8LB PxBxuo017UXfKPpA/dJkk2DlD/Lu/CraHV3XnvO4Qcwo3nkcpwpCgxeTrJ88OosztHPd +Bc1NISMne6s2g1tN1TBhZF84OZ3mrWwPgs3+/dEzHXbfyR4SfLAcVCyw5/h0P6y/gFN fnKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789354925; x=1789959725; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=gbdzTooPdY+KDhtZ/QzGrAlPMdYJpYAben39hMkDMIQ=; b=Qv6TAxO+94LowqBylOUbtKWkM5sO9JX7ac1UMJqYOL3XAU2LgBgQ9d4Tq2xiTGqwy/ ycLDPtKyyNIBhyFuLTvOyhT6F5lICSYxLF9Oae/5Onaq3bdX2WKOb5I/4VM6zoPzA9e0 j+OSeyIPUgVf5UxRfaf03ljKPv8nB4wI7KHKNti7WKcGRv8xnVTrBmbfnE67ImGMuqhd YqjKEiqbvMZqmscWv2c4WJoWaw3luChpDFjt40LXldbGj5jBaKg2gzLvKOTxFPXGvlKG pGKkGuJjjJs1XNLE44xcblaaX46ugmWUFDK9CN4Dj0HFDAkx8PZJwt/c9nhlwJI0LBau 5xIA== X-Forwarded-Encrypted: i=1; AKwUvBz4Hy9GoNDjNQnyApWoPMGY0rrG2OOhw6bdVhHR3gFymanKa4Z+zk1FtuaESBtSOPwWccSwiPuX/WksHA==@lists.linux.dev X-Gm-Message-State: AFuF++mr+2wO49wPnoGT+4JBNkN0XRf8LpO4ksorZftGrGA9L6CbZqWV ET5ae+rDx9dD+Z5jGEQOAWPlbIEOvTfS1YCUtw5n+oLELsCeOw6Y+o4e X-Gm-Gg: AYBFou0zumr4aWHQMR+JpPsHLURvnp9YA25twEV465Q+YmJJF0jfjIhGDKlxd7vly6D PHfw9pv4zEsWvN3G3TOIjICapR2RX7HsHACr8mpF+WM8Iq4vkdpMgLL1hCdUoMNS4XXKf/TKhBw iQzNrjfN3Q7Ub6wSjWpH4lgGmk8l2sI3bZ4nZC7BHlUOxdeD83I22AdERW+w6qGw1+QqtHCncjN YmpYo3VRZ5uJbYJLNwayFk1gazs0LFtUAFUNrgIKDsHGMI1j8dl02xQ6vKdGfV6Be37hANskwoE i/PLQIQXIY1I6pTs31W2debQdhCOgO0OfUoG/5122Z5fUM6Ho7BNxmg6qTT2zPoKJxK+GK5IjvR DiSM9NcvAMFU0jtvdvU4qC0xvvJ9FcmHbN/8R+Zgj5I5wM8Mlrsjhc+BSNjMRRsAqng4VbwmZ+t hjbaR0kW19wsjTBRLBXX2P0iVdWTyDNK0AdBQD9NuWPc9/q1q5R/nfp7aK5sZfdWyN++Ehk69VT tNoF5iw+CsLgRKrzVL4rqoWSgy4XwzOBXTSyOZe/y0pkWS97jWyoNP+9+TEo++qvo76f9zKfBAt cnGt+iH3llsTAvKfuBWP2cneaYqakHESri25b6pbDX9Epiblf0YNPSqjpmtSPZ/PzvzOgV7ADZA uqcaa55UMeCol5bfiKtvF1Lot/ZaKFw== X-Received: by 2002:a05:6830:719a:b0:7eb:3af8:8c09 with SMTP id 46e09a7af769-808972915a8mr274412a34.3.1789354924870; Sun, 13 Sep 2026 20:02:04 -0700 (PDT) Received: from [127.0.1.1] (184-96-157-145.hlrn.qwest.net. [184.96.157.145]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-803f60feba1sm10619014a34.13.2026.09.13.20.02.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:02:04 -0700 (PDT) From: James Hilliard Date: Sun, 13 Sep 2026 21:01:24 -0600 Subject: [PATCH v5 18/18] mtd: rawnand: sunxi: reuse ECC status within each DMA read Precedence: bulk X-Mailing-List: linux-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-18-7d711076a6f7@gmail.com> References: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> In-Reply-To: <20260913-submit-sunxi-nand-vendor-oob-layout-v1-v5-0-7d711076a6f7@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 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 | 101 +++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 2b8ed142c9bf..4af2a4f36d2e 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1149,46 +1149,87 @@ struct sunxi_nfc_ecc_status { unsigned int max_bitflips; }; +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; @@ -1204,9 +1245,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, @@ -1221,7 +1260,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; @@ -1261,13 +1300,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); @@ -1275,8 +1312,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; @@ -1541,11 +1577,12 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *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; + struct sunxi_nfc_ecc_snapshot snapshot; unsigned int reg_index = 0, user_data_sz; unsigned int max_bitflips = 0; int ret, i; struct scatterlist sg; - u32 status, pattern_found, wait; + u32 wait; if (first_step) { ret = sunxi_nfc_read_column(nand, page, first_step * ecc->size, @@ -1598,9 +1635,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *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++, reg_index += user_data_sz / 4) { int logical_step = first_step + i; @@ -1614,8 +1649,8 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *buf, user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, logical_step); if (sunxi_nand->randomized_oob) { - sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, i, status, - pattern_found); + sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, i, + &snapshot); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !logical_step, page, user_data_sz); continue; @@ -1623,7 +1658,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *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. */ @@ -1650,7 +1685,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *buf, if (sunxi_nand->randomized_oob) return 0; - if (status & NFC_ECC_ERR_MSK(nfc)) { + if (snapshot.status & NFC_ECC_ERR_MSK(nfc)) { for (i = 0; i < nchunks; i++) { int logical_step = first_step + i; int data_off = logical_step * ecc->size; @@ -1658,7 +1693,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, u8 *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; user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, logical_step);