From patchwork Fri Oct 16 03:45:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3640 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id DBBC61C1CBB for ; Fri, 16 Oct 2026 05:48:29 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-26687-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-26687-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id BAA0B2D659 for ; Fri, 16 Oct 2026 03:46:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 353323BADBD; Fri, 16 Oct 2026 03:45:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G9yHy6kE" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f45.google.com (mail-ot1-f45.google.com [209.85.210.45]) (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 86A543AD511 for ; Fri, 16 Oct 2026 03:45:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122352; cv=none; b=ZQVslc/U3FJ2YcmNAkxTHCXxjmtCnm6yJFDVs9HFY72hGj8abhqd+Uog7CbXUmqSwJYqp2iA90Lm5tiMo6atEyPKgAgV9/nRzrZBzMz9P5fdFytSfikUZlN4SwPpdUj+XgYKqHRFd1i0V/ikvTW+iutcJp5ibWTab8K0X5+JxNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122352; c=relaxed/simple; bh=UVK7cpZsYvjLC/INqKEBYPgOs/fm62fXED+n3EHB9lc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IR9iY7Xb9D3OsuwLGwySLGcrod8WxHyaeZd/54vAJs9hVadh6x5AHvDMiDmxA7WDD/02nYHTSGkPISxHWuuwd+bQfQRnB35BqJQGyiyQ+gIZ/tqbDUTNH4XZ/A7P7pfOqGgXGT4M06AxhoVMjWv9va9kGmtAluSMx4xVaWmWPnA= 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=G9yHy6kE; arc=none smtp.client-ip=209.85.210.45 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-f45.google.com with SMTP id 46e09a7af769-8244537ab76so2725584a34.2 for ; Thu, 15 Oct 2026 20:45:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122348; x=1792727148; 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=djZlVdSi/YIckqFS7pyWE2GArCm4EkKkgRfSQpPp8jg=; b=G9yHy6kEkuARqAgigyma0b85p4Lx/Fx7nEnXgcbQ62SyneDxmPiONpkuZrdMA6P5c0 EJATBNoPjqQ4ThjiPAPqVv6bVWDKnC3zc1D8JqFix0uHef1czC9REeU4p5ctK7o1B5q6 is+8bio5s/F5KJpMUzSRHX/ZL2YVVYe1PHbv8US3Hfb4rHjlYuNLYw2v7eGEpCCzglnh dqJk4gtAzvoTzWvyaSKFxgJVxoPMEN92x+3ZD5o88TMa0PHO9/RpeZQ7czk4iZr/JN8p 7LKGA/v8HdKW+OpAlAPuATLq4Iw2IVoKLFBj4uhmkpEHyxfh3taWhEwqGSxUq9uukAT5 +LAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122348; x=1792727148; 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=djZlVdSi/YIckqFS7pyWE2GArCm4EkKkgRfSQpPp8jg=; b=oEIQTnm08wAkUtx9iD3ST3XI6yvYWAiXbd5lgCPCYXdqn9jpz+847+1Wvsbba5yIMG 2DekYRyDnnVdtW0iYPJQ+lC3nSdYuIKchWtfGj6qZ911MWJ4oY/eyystwDAKWim+OhlD TkvwlBK2mvKIdZRCb3ypqZMZBUMrBeIxtxxhjxCOFQOwDMJWshG7knkMQZf35ocHEiUP hKMrqKOiuGVtnpe5vaeZiit43JTaZB8rBciM1ySIiXqtk2gRNx5f4XWOaY/SNR3OQY+D o9A8tfY/5NTamVFMVmCQfjXuWMB8N+pEhnPnVuhyxw7RGpxNq4Lh2xdqawibdk8oP8RV XJNw== X-Forwarded-Encrypted: i=1; AKwUvBxq/+JvcioEbT2UmpqPYZbgWTAM0fjiaVW6MLmLYdsk6z/F979LV9MnBgahswEGMOMvJ9CN9t1yw9q1TQ==@lists.linux.dev X-Gm-Message-State: AFq9FYJ4VZi+OFmqx9h5laoZ7g8fYR9EiaX1BgaPkiQ6wKF2mbjs2ASP Lc1VNr7C6Wr3+B5DAsZrJdnB0+50XBHaU43JJ5VUrxsTDwW5PiM/vCQO X-Gm-Gg: AYBFou12s5NCpEh45cub27C71vt5g+/4lan4lck7pUwCHJDC3CG42oCBoybJbiHq9Jd gEiR5ws9ssxMrTVZAdw2vWv7bp2bFVHE5XspVVS2MImPwil9kyfVIW1qcrdlw9aELWRIkYVIFQG JrcXlDKLSe1qFEzFtz8aPcPOad6TqeZiwO3MNtSRJ9s/aq5Rwu/QILW5CkyEZ1emUH4kJZDmyVK yKylrxrXwYisLIyeEMZ6RgOdBj+GQXaZKLpq1P/eiebShmbQ9OVqY/ClD54cobwh//TYxXwKA3/ AnwuMFZhfBFwU6R+EGCSyqasCUBzhJQA6dvgDJG9uHBZDfSUpH5wE9cTHFreB1FSRzH+Tjbrnlo VwfDrKkWfa8g2TKi1zuC6C8C5vlF674ibGMb5WYe12TawAzkY0ceWq39IzDTAGt+tM0DpHjoz0E TnXGk3Fq1pg8YA4AxqL1O1gtqmn73itjrhIrFi27/LeWBq//Sd0ZpxOq6PTsn4N+X6kOwLIOetK O/plmsLoPkuQfN2ZJ6NrgjrA8/HMml64eNjVwpd2Q4BuXDBV9vy9oFVabgyEXJasmM0RwX3gnPA RhCBEHfKgqG9vU3xK4j5xDvYdVcU7i6bwSPKzQ+saurFfs9rCvSwJOwL3kC9m3gtNaT3DQjL4CS 78ukL4KxeabSY0ys+1KZZHQ== X-Received: by 2002:a05:6830:2693:b0:7fa:5c68:d053 with SMTP id 46e09a7af769-830993e87a2mr22826285a34.29.1792122348371; Thu, 15 Oct 2026 20:45:48 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-8429b57870fsm834402a34.0.2026.10.15.20.45.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:47 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:27 -0600 Subject: [PATCH v8 12/17] mtd: rawnand: sunxi: reuse ECC status within each transfer Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-12-8ba4881fbee8@gmail.com> References: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@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?= A completed DMA batch leaves one ECC status bitmap and one pattern bitmap for all its steps. Four consecutive steps also share a packed correction-counter register. Reading the pattern ID for every matching step and the counter word for every corrected step repeats MMIO accesses to the same completed result. Snapshot status and pattern information once per completed transfer. Reuse the status read when the controller places pattern-found bits in the same register, and read the pattern ID only when a non-error step needs it. Cache each packed counter word while consuming its steps. Keep the snapshot local to a single transfer and invalidate the cached counter before processing it. Each PIO step gets a fresh snapshot, as does each DMA batch. The ECC decisions and returned correction counts are unchanged, as is the page layout; only redundant register reads are removed. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 90 +++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 8d523dc43093..105374e93b37 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -258,6 +258,7 @@ struct sunxi_nfc_timings { }; struct sunxi_nfc_ecc_read; +struct sunxi_nfc_ecc_snapshot; /* OOB interpretation is independent of PIO/DMA command sequencing. */ struct sunxi_nfc_oob_ops { @@ -268,7 +269,7 @@ struct sunxi_nfc_oob_ops { void (*transform_bbm)(struct nand_chip *nand, int page, u8 *bbm); /* Consume one PIO step or a DMA batch; negative values are I/O errors. */ int (*read_batch)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, - u32 status, u32 pattern_found, int first_step, int nsteps); + struct sunxi_nfc_ecc_snapshot *snapshot, int first_step, int nsteps); /* Read any remaining OOB and return the maximum correction count. */ int (*finish_read)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, int *cur_off); @@ -1143,23 +1144,64 @@ struct sunxi_nfc_ecc_read { bool has_erased_chunk; }; +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 & ~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 step) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 reg = NFC_REG_ECC_ERR_CNT(nfc, 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(step, snapshot->count); +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, - int step, u32 status, u32 pattern_found, + int 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(step)) + if (snapshot->status & NFC_ECC_ERR(step)) return -EBADMSG; - if (pattern_found & BIT(step)) { + if (snapshot->pattern_found & BIT(step)) { u8 pattern; - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { + if (unlikely(!(snapshot->pattern_id & BIT(step)))) { pattern = 0x0; } else { pattern = 0xff; @@ -1175,9 +1217,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, step)); - - return NFC_ECC_ERR_CNT(step, tmp); + return sunxi_nfc_hw_ecc_read_count(nand, snapshot, step); } /* @@ -1246,7 +1286,7 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, /* Interpret one PIO step or a completed DMA batch before reusing its status. */ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, - u32 status, u32 pattern_found, + struct sunxi_nfc_ecc_snapshot *snapshot, int first_step, int nsteps) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); @@ -1269,8 +1309,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, bitflips = sunxi_nfc_hw_ecc_correct(nand, !read->dma || randomized ? data : NULL, read->oob_required ? oob : NULL, - i, status, pattern_found, - user_data_sz, &erased); + i, snapshot, user_data_sz, &erased); if (bitflips < 0) { /* Preserve PIO data before the raw erased-page check. */ if (!read->dma && !randomized) @@ -1279,7 +1318,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, } /* Both patterns are already filled; only all-ones is erased. */ - if (pattern_found & BIT(i)) { + if (snapshot->pattern_found & BIT(i)) { read->has_erased_chunk |= erased; continue; } @@ -1310,7 +1349,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, sunxi_nfc_hw_ecc_update_stats(nand, &read->max_bitflips, bitflips); } - if (!(status & NFC_ECC_ERR_MSK(nfc))) + if (!(snapshot->status & NFC_ECC_ERR_MSK(nfc))) return 0; /* Finish consuming the batch's corrected OOB before raw error rereads. */ @@ -1318,7 +1357,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, int step = first_step + i; int data_off, oob_off; - if (!(status & NFC_ECC_ERR(i))) + if (!(snapshot->status & NFC_ECC_ERR(i))) continue; data_off = step * ecc->size; @@ -1360,10 +1399,10 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; + struct sunxi_nfc_ecc_snapshot snapshot; int data_off = step * ecc->size; int oob_off = nand_to_mtd(nand)->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, step); int page = read->page; - u32 pattern_found; int ret; if (*cur_off != data_off) { @@ -1399,12 +1438,9 @@ 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); - return sunxi_nand->oob_ops->read_batch(nand, read, - readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, step, 1); + return sunxi_nand->oob_ops->read_batch(nand, read, &snapshot, step, 1); } static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, @@ -1415,10 +1451,11 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, 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; struct scatterlist sg; int page = read->page; int ret, i; - u32 status, pattern_found, wait; + u32 wait; if (first_step) { ret = sunxi_nfc_read_column(nand, page, first_step * ecc->size, @@ -1474,12 +1511,9 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, 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); - return sunxi_nand->oob_ops->read_batch(nand, read, status, pattern_found, - first_step, nchunks); + return sunxi_nand->oob_ops->read_batch(nand, read, &snapshot, first_step, nchunks); } static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf,