From patchwork Fri Oct 16 03:45:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3633 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 8C9DD1C1CBB for ; Fri, 16 Oct 2026 05:46:15 +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-26676-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-26676-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 EF5F43D627 for ; Fri, 16 Oct 2026 03:45:35 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D12C12931D1; Fri, 16 Oct 2026 03:45:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pgtKXnnV" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (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 80FB727AC31 for ; Fri, 16 Oct 2026 03:45:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122331; cv=none; b=Vs7XIzns4sFbDkl3ZRN/BqhIOtlASoWV/1wOwxLFNB5wev+yI9m/f/iR7vSBOhTXECDLwMHn41tdW2elfV+SQOmjGkbBMuUQuNjBdxogC/NgwiijrH+f7XL+0E31FcIKM+grD5yjI+YbPaKFrrTInhAshzRq3SodHeVcFqj1kAY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122331; c=relaxed/simple; bh=a8ql8pZvfkQJaeQ7cy57dwhSEFwwh0JZjOipei5GbpY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qqFdFVXKDlQYQjjqyFYpdeWMY0eVmr2bG2toqqITaMPJTACsq53mCpMcj0yQbL7rb9emi+BewKbZqGPBjcYt8N4MCcpvqGoIgX6GnKbmVTuPpADlJEcLt+YMwdEbScTtW+aQQPWuFF9at1s3l3cU9H3RiVs+rgPKzDdhfz19y/Y= 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=pgtKXnnV; arc=none smtp.client-ip=209.85.210.52 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-f52.google.com with SMTP id 46e09a7af769-8244537ab76so2725508a34.2 for ; Thu, 15 Oct 2026 20:45:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122327; x=1792727127; 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=E3QlrVAtVf/XpX+ZsmjMjSLBH4hnwCKgBumw+s30nkM=; b=pgtKXnnVBgcEIrZjH6vXPwhufMXrRQufV3MLa7fPe7jJPnLEtzHzlNIF2mIaAExySP CcSbhJGHDCAUyHB+8qRtnzX06LtIlX60qXhplkQlE/BJFQM3dTGGPxk0UgAI3jsG+dSG lkXexNu60i2ks8A8bbVJ8HKYTq9lT8W+96FQ3bCbhTAwiFazjdhMQC/Ke1rs6jD8f+9v WueO8IGJcxL1NY1TJrrrawE9L1mUfxIe1oS1lbhnmLiqrIbnv/aOTag0rCXCHh5bsQYY nRZGvSMGgN5qUCWX6gujUOwCnzxS/Jwu144wLyG4N7vWjb3uIsIM2Pod+i6AyS0RgFyf ENsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122327; x=1792727127; 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=E3QlrVAtVf/XpX+ZsmjMjSLBH4hnwCKgBumw+s30nkM=; b=dxX5rCptuKZOy4iW53moBLP6Io+CRydCHaRsayIAD9RMUHc3ZdOR/IkIXbdjmMuVlB c/ueaMk2Q8VEGna8JDkoN2MvJ8KeKWciNvWmNR3T3jI5RCOQZzfelOD33ciUwnDCg5Hz BQpPrUCuaq53p0gR474KbQ+BpXgUPwAMRyDOS+LaxF2F0tasVC4asxGaQm3Kalcc6Xna W81UktSQGdaEMg0FTQFNI2jTbkfSs+yB/vrzJUna2rOnIIbXrVD/mbMSZVFmEYQZ4S86 5fxABUjGFJjZz6f3Q0XCC9HbMg5scYGbO2i17G9MvfpX6mvw4j89wv0qE9LZlSAvorS7 O7Ew== X-Forwarded-Encrypted: i=1; AKwUvBzSmyRw8KEB+q8LuomMz0DFX8gCpD7wZ3ClsTqC22cAxMQE2R+qiV2vZlWYVSQ4wSeSZ2DDPJ4+huHnvw==@lists.linux.dev X-Gm-Message-State: AFq9FYJLb4ykDrHXagjrq76uG4ywbVlBPIUbTQS1RFmFmia6wIV4mwEq CRyo9XJkyqztHTXjwur8efKUrJg7yCKDauJ57aygEnaHYSUHNcEYti3A X-Gm-Gg: AYBFou2TtvgTaf7dMYNmvD1vsO28HkTHvOooBDtSqbqwKIfBT8DFvXhB0siz/NnnmBx 5uwi35GTpSBJvx7YxvW69RaKKzS8m+N/xRUv4Tr+hZzY757fTcyjUxG72HYsk5LNJq3gdxuiXg/ r1gETBjvfLIpl3+VzW8rdhAzwuPo32jVkGHe4TwbqY6by/VhcxyhZFT3IR6CvhBza+tMNawKAAb W8ROUpQ/nS2wnBCfP//IVxdKxYB2t4PLgKICxR5Mew3f4t+JfLQTDly7+Fpb+iBQdRr4nJS9aa+ EOZAzNyyQ/MdohUFZ/LUqoTVkv0apxXgvoiW3q2CILfP6snGGYz9gS1vxt9xCeQX++SMRqQxbI6 F4lkRnvU+/3JjtewBWBc50zKi0GLOM61OCM0/ofMbubObNg8MTBH5VI1euaZYth3WkjxekQOpRF hXGiaa+vxtCaMgpbmpDf39ksAbiGtm49W0IJCxN+yfVE24avp5RG9km0EO8JsFA9/7mvgXPNIjP iGcNJt0NdZG2VksDu5jULjLkkeVCdx4C82LORQZPul82sDi2Tlgt+Aem/OI7QPKQVBfOg4ERv6J hCoqXDJ8qvjPMKWKskbiMmZGYty+fyG900Gcym9dKpw7IukpTsNKFNNMrrN7k2hYYNs83J0WnYc xyHP2rHtA1P5PVdF7cuKJmzw= X-Received: by 2002:a05:6830:3698:b0:81b:bfb5:26cb with SMTP id 46e09a7af769-8309093be73mr18566604a34.3.1792122327199; Thu, 15 Oct 2026 20:45:27 -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.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:26 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:16 -0600 Subject: [PATCH v8 01/17] mtd: rawnand: sunxi: centralize OOB handling 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-1-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?= PIO and DMA interpret the same hardware-ECC results, retrieve protected OOB bytes and check unreadable chunks for erased data in separate paths. Keeping that policy in both transfer paths makes fixes easy to apply to one path but miss in the other. Share the processing through per-chip OOB operations selected at attach. A read callback consumes one PIO step or a completed DMA batch. A finish callback handles the OOB tail and returns the largest correction count. Keep command sequencing, DMA ownership and randomizer control in the transfer functions; carry the buffer, page, correction count and whether any chunk was erased in a per-read context. Move user-data reservation and layout setup behind the same operations. The existing plain and scrambled-with-plain-BBM modes share geometry and read handling. Only the scrambled mode transforms the first two user bytes to compensate hardware randomization and keep the on-flash marker plain. Preserve fixed and variable user-data allocation, including the older controllers' extra two-byte reservation when maximizing ECC strength. This preserves the existing register accesses, transfer ordering, OOB length selection, error handling and ECC accounting. In particular, retain DMA's two passes: consume corrected OOB before raw erased-page rereads. PIO keeps its current parity representation and physical reread behavior. OOB-length fixes, read-error handling and register-read caching are separate changes. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 545 ++++++++++++++++++++------------------ 1 file changed, 294 insertions(+), 251 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index f41feebe4257..27d6ae635e9c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -256,12 +256,30 @@ struct sunxi_nfc_timings { s32 tRHW[SUNXI_NFC_TIMING_STEPS]; }; +struct sunxi_nfc_ecc_read; + +/* OOB interpretation is independent of PIO/DMA command sequencing. */ +struct sunxi_nfc_oob_ops { + /* Reserve user data before maximizing ECC strength, then set its layout. */ + unsigned int (*min_user_data)(struct nand_chip *nand, int nsteps); + int (*init_user_data)(struct nand_chip *nand, int nsteps); + /* Optional symmetric conversion of the on-flash bad-block marker. */ + 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); + /* 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); +}; + /** * struct sunxi_nand_chip - stores NAND chip device related information * * @node: used to store NAND chips into a list * @nand: base NAND chip structure * @ecc: ECC controller structure + * @oob_ops: OOB geometry and ECC-result interpretation * @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 @@ -273,6 +291,7 @@ struct sunxi_nand_chip { struct list_head node; struct nand_chip nand; struct sunxi_nand_hw_ecc ecc; + const struct sunxi_nfc_oob_ops *oob_ops; unsigned long clk_rate; u32 timing_cfg; u32 timing_ctl; @@ -908,6 +927,7 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) return sunxi_nand->user_data_bytes[step]; } +/* PIO uses register zero; DMA concatenates user data within each transfer. */ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, int step, bool bbm, int page, unsigned int user_data_sz) @@ -946,8 +966,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, } /* De-randomize the Bad Block Marker. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_randomize_bbm(nand, page, oob); + if (bbm && sunxi_nand->oob_ops->transform_bbm) + sunxi_nand->oob_ops->transform_bbm(nand, page, oob); } /* @@ -1007,9 +1027,9 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] = {}; /* Randomize the Bad Block Marker. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { + if (bbm && sunxi_nand->oob_ops->transform_bbm) { memcpy(user_data, oob, user_data_sz); - sunxi_nfc_randomize_bbm(nand, page, user_data); + sunxi_nand->oob_ops->transform_bbm(nand, page, user_data); oob = user_data; } @@ -1055,6 +1075,40 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } +/* Return whether the chunk is erased, and account for its ECC result. */ +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) + nand_change_read_column_op(nand, data_off, data, ecc->size, false); + + nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + + 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; +} + +struct sunxi_nfc_ecc_read { + u8 *buf; + int page; + unsigned int max_bitflips; + bool oob_required; + bool dma; + bool has_erased_chunk; +}; + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, int step, u32 status, u32 pattern_found, bool *erased) @@ -1094,98 +1148,6 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, return NFC_ECC_ERR_CNT(step, tmp); } -static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, - u8 *data, int data_off, - u8 *oob, int oob_off, - int *cur_off, - unsigned int *max_bitflips, - int step, bool oob_required, int page) -{ - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - 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; - int ret; - /* From the controller point of view, we are at step 0 */ - const int nfc_step = 0; - - if (*cur_off != data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); - - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); - - if (data_off + ecc->size != oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); - - ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); - if (ret) - return ret; - - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); - sunxi_nfc_randomizer_config(nand, page, false); - sunxi_nfc_randomizer_enable(nand); - writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, - nfc->regs + NFC_REG_CMD); - - ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); - sunxi_nfc_randomizer_disable(nand); - if (ret) - return ret; - - *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); - - ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, &erased); - if (erased) - 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 - 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; - } else { - memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); - - 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); - - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, - bbm, page, user_data_sz); - } - } - - sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); - - return raw_mode; -} - /* * Returns the offset of the OOB for each step. * (it includes the user data before the ECC data.) @@ -1241,18 +1203,166 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, *cur_off = mtd->oobsize + mtd->writesize; } -static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf, - int oob_required, int page, - int nchunks) +/* 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, + int first_step, int nsteps) { - bool randomized = nand->options & NAND_NEED_SCRAMBLING; struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(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; - unsigned int max_bitflips = 0; - int ret, i, raw_mode = 0; + bool randomized = nand->options & NAND_NEED_SCRAMBLING; + unsigned int user_data_sz; + int i, ret; + + for (i = 0; i < nsteps; i++) { + int step = first_step + i; + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + u8 *data = read->buf + step * ecc->size; + u8 *oob = nand->oob_poi + oob_off; + bool erased; + int bitflips; + + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + bitflips = sunxi_nfc_hw_ecc_correct(nand, + !read->dma || randomized ? data : NULL, + read->oob_required ? oob : NULL, + i, status, pattern_found, &erased); + if (bitflips < 0) { + /* Preserve PIO data before the raw erased-page check. */ + if (!read->dma && !randomized) + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + continue; + } + + if (erased) { + read->has_erased_chunk = true; + continue; + } + + if (!read->dma) + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + + if (read->oob_required) { + /* Keep the existing PIO and DMA representations of parity. */ + nand_change_read_column_op(nand, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0, + false); + + if (!read->dma) { + sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, read->page); + } + + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !step, + read->page, user_data_sz); + } + + sunxi_nfc_hw_ecc_update_stats(nand, &read->max_bitflips, bitflips); + } + + if (!(status & NFC_ECC_ERR_MSK(nfc))) + return 0; + + /* Finish consuming the batch's corrected OOB before raw error rereads. */ + for (i = 0; i < nsteps; i++) { + int step = first_step + i; + int data_off, oob_off; + + if (!(status & NFC_ECC_ERR(i))) + continue; + + data_off = step * ecc->size; + oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + ret = sunxi_nfc_hw_ecc_read_error(nand, read->buf + data_off, data_off, + nand->oob_poi + oob_off, + mtd->writesize + oob_off, user_data_sz, + &read->max_bitflips); + if (ret < 0) + return ret; + if (ret) + read->has_erased_chunk = true; + } + + return 0; +} + +static int sunxi_nfc_oob_finish_read(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, int *cur_off) +{ + if (read->oob_required) + sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, + !read->has_erased_chunk, read->page); + + return read->max_bitflips; +} + +static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + int step, int *cur_off) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(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; + 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) + nand_change_read_column_op(nand, data_off, NULL, 0, false); + + sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + + if (data_off + ecc->size != oob_off) + nand_change_read_column_op(nand, oob_off, NULL, 0, false); + + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); + if (ret) + return ret; + + sunxi_nfc_set_user_data_len(nfc, user_data_sz, 0); + sunxi_nfc_randomizer_config(nand, page, false); + sunxi_nfc_randomizer_enable(nand); + writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, + nfc->regs + NFC_REG_CMD); + + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); + sunxi_nfc_randomizer_disable(nand); + if (ret) + return ret; + + *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); + + return sunxi_nand->oob_ops->read_batch(nand, read, + readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found, step, 1); +} + +static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, + int oob_required, int page, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + struct sunxi_nfc_ecc_read read = { + .buf = buf, + .page = page, + .oob_required = oob_required, + .dma = true, + }; struct scatterlist sg; + int ret, i; u32 status, pattern_found, wait; ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); @@ -1299,83 +1409,12 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf 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); + ret = sunxi_nand->oob_ops->read_batch(nand, &read, status, pattern_found, + 0, nchunks); + if (ret) + return ret; - 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); - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - bool erased; - - ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, - oob_required ? oob : NULL, - i, status, pattern_found, - &erased); - - /* ECC errors are handled in the second loop. */ - if (ret < 0) - continue; - - 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); - - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, - page, user_data_sz); - } - - if (erased) - raw_mode = 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); - } - - if (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); - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - - 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) - raw_mode = 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); - } - } - - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, - page); - - return max_bitflips; + return sunxi_nand->oob_ops->finish_read(nand, &read, NULL); } static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1452,11 +1491,13 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; - unsigned int max_bitflips = 0; + struct sunxi_nfc_ecc_read read = { + .buf = buf, + .page = page, + .oob_required = oob_required, + }; int ret, i, cur_off = 0; - bool raw_mode = false; sunxi_nfc_select_chip(nand, nand->cur_cs); @@ -1466,28 +1507,15 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, sunxi_nfc_reset_user_data_len(nfc); for (i = 0; i < ecc->steps; i++) { - int data_off = i * ecc->size; - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - - ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, - oob_off + mtd->writesize, - &cur_off, &max_bitflips, - i, oob_required, page); + ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) return ret; - else if (ret) - raw_mode = true; } - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); - + ret = sunxi_nand->oob_ops->finish_read(nand, &read, &cur_off); 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, @@ -1513,11 +1541,12 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, u8 *bufpoi, int page) { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; + struct sunxi_nfc_ecc_read read = { + .buf = bufpoi, + .page = page, + }; int ret, i, cur_off = 0; - unsigned int max_bitflips = 0; sunxi_nfc_select_chip(nand, nand->cur_cs); @@ -1528,23 +1557,15 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, sunxi_nfc_reset_user_data_len(nfc); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { - int data_off = i * ecc->size; - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = bufpoi + data_off; - u8 *oob = nand->oob_poi + oob_off; - - ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, - oob, - oob_off + mtd->writesize, - &cur_off, &max_bitflips, i, - false, page); + ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) return ret; } + ret = read.max_bitflips; sunxi_nfc_hw_ecc_disable(nand); - return max_bitflips; + return ret; } static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, @@ -2066,6 +2087,58 @@ static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t oobsize return 0; } +static unsigned int sunxi_nfc_oob_min_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + unsigned int size = 0; + int i; + + /* Variable lengths reserve the first word, which contains the BBM. */ + if (nfc->caps->reg_user_data_len) + return USER_DATA_SZ; + + for (i = 0; i < nsteps; i++) + size += sunxi_nfc_user_data_sz(sunxi_nand, i); + + /* Preserve the older platforms' extra BBM reservation and ECC strength. */ + if (nfc->caps->legacy_max_strength) + size += 2; + + return size; +} + +static int sunxi_nfc_oob_init_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!nfc->caps->reg_user_data_len) + return 0; + + /* Prioritize ECC strength, then use the remaining space for user data. */ + return sunxi_nfc_maximize_user_data(nand, nand_to_mtd(nand)->oobsize, + nand->ecc.bytes, nsteps); +} + +/* + * Both modes use the same layout and ECC policy. Scrambled transfers also + * compensate the first two user bytes to keep the on-flash BBM unmodified. + */ +static const struct sunxi_nfc_oob_ops sunxi_nfc_plain_oob_ops = { + .min_user_data = sunxi_nfc_oob_min_user_data, + .init_user_data = sunxi_nfc_oob_init_user_data, + .read_batch = sunxi_nfc_oob_read_batch, + .finish_read = sunxi_nfc_oob_finish_read, +}; + +static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = { + .min_user_data = sunxi_nfc_oob_min_user_data, + .init_user_data = sunxi_nfc_oob_init_user_data, + .transform_bbm = sunxi_nfc_randomize_bbm, + .read_batch = sunxi_nfc_oob_read_batch, + .finish_read = sunxi_nfc_oob_finish_read, +}; + static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) @@ -2090,33 +2163,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, ecc->size = 1024; nsectors = mtd->writesize / ecc->size; - if (!nfc->caps->reg_user_data_len) { - /* - * If there's a fixed user data length, subtract it before - * computing the max ECC strength - */ - - for (i = 0; i < nsectors; i++) - total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); - - /* - * The 2 BBM bytes should not be removed from the grand total, - * because they are part of the USER_DATA_SZ. - * But we can't modify that for older platform since it may - * result in a stronger ECC at the end, and break the - * compatibility. - */ - if (nfc->caps->legacy_max_strength) - bytes -= 2; - - bytes -= total_user_data_sz; - } else { - /* - * User-data lengths are encoded in four-byte units. Reserve - * the first word because it contains the two BBM bytes. - */ - bytes -= USER_DATA_SZ; - } + bytes -= sunxi_nand->oob_ops->min_user_data(nand, nsectors); /* * Once all user data has been subtracted, the rest can be used @@ -2175,20 +2222,12 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, nsectors = mtd->writesize / ecc->size; - /* - * The rationale for variable data length is to prioritize maximum ECC - * strength, and then use the remaining space for user data. - */ - if (nfc->caps->reg_user_data_len) { - ret = sunxi_nfc_maximize_user_data(nand, mtd->oobsize, - ecc->bytes, nsectors); - if (ret) - return ret; - } + ret = sunxi_nand->oob_ops->init_user_data(nand, nsectors); + if (ret) + return ret; - if (total_user_data_sz == 0) - for (i = 0; i < nsectors; i++) - total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); + for (i = 0; i < nsectors; i++) + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); if (mtd->oobsize < (ecc->bytes * nsectors + total_user_data_sz)) return -EINVAL; @@ -2232,6 +2271,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, static int sunxi_nand_attach_chip(struct nand_chip *nand) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); const struct nand_ecc_props *requirements = nanddev_get_ecc_requirements(&nand->base); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -2254,6 +2294,9 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) if (!ecc->size || !ecc->strength) return -EINVAL; + sunxi_nand->oob_ops = nand->options & NAND_NEED_SCRAMBLING ? + &sunxi_nfc_scrambled_plain_bbm_oob_ops : &sunxi_nfc_plain_oob_ops; + switch (ecc->engine_type) { case NAND_ECC_ENGINE_TYPE_ON_HOST: ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np); From patchwork Fri Oct 16 03:45:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3631 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 9A7401C1CBB for ; Fri, 16 Oct 2026 05:45:42 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26677-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26677-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 36D2C6060D6 for ; Fri, 16 Oct 2026 03:45:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AAF8538B131; Fri, 16 Oct 2026 03:45:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JQ1u7Fpu" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (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 2D806383326 for ; Fri, 16 Oct 2026 03:45:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122332; cv=none; b=qyldlWAiLO240+wrhuffMmd1k0GLgGxZkY8MoERAtqYt86wNDWWbsQdwaF8ypRsGglfazEydrrx+OYc2fbSBa5/XLz8/grNspkZ+WaftkyPy+M7JVNLU8jxs4QIND6pMLE0kcv0U23zioAeruL8yj9kPKu5j6ClNSzpKGWk2kIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122332; c=relaxed/simple; bh=3GQZX5iNGkz0/Zep2FfFJdRYaRxOFK4ZULPjzOeOBBo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tAEM2qLW7hes/mg0D18wS/Fo3UPbuhS7jmBXTZfnGyM2/nLaqldoc/oug86ViY8IhzBlkweRIp0w0aJiZ4jzBXqoLNKt7a4NwS+aCpz9JBTYaB7QUFSir7L7AQC3ot7Z2K3QXLLaLoIdcOZ23oX0efrpkpyMF3reUAqNJILnSWE= 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=JQ1u7Fpu; arc=none smtp.client-ip=209.85.210.46 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-f46.google.com with SMTP id 46e09a7af769-833e671ee9fso4328491a34.0 for ; Thu, 15 Oct 2026 20:45:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122329; x=1792727129; 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=EDQOoNR8PIvzHZhKm/btQU1LikxfvBk4c4i5XkHFMOI=; b=JQ1u7Fpu44jQ5J/fuyRPeJfScjh3pyDt9XNtnohz7lV8vI05qhGGw7zo3Wiya6W/WK FVM8hDtxzRx7y6XsuZHu1/TXifKNnLxs+lEcGD1yW6rRtnaMDGtsacuGNbFndrXMndaD gRlmm7ZadrddUBBhP6q3iLAHebn/VEyNjHaZqKaey0IYYzm6lQPHA3Jgxp2pgHEWK/LU sLodSMHPB6hmBZVvYd9pxPaCwzl/QFKDaIRMLQ3wdetDJHxGRza5f4Tl0yj8KUkdrk8E JncE4Zx/G7mJwVOzP2OHxI7KTzUW5XG/yeWXMZtyOJKeMkdo7TtlPvf2+8ffqBhoJ75S kA6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122329; x=1792727129; 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=EDQOoNR8PIvzHZhKm/btQU1LikxfvBk4c4i5XkHFMOI=; b=tlBn3OK/o4nu00xZAxeLNwwMgNmA8b7CaansKMt09ZiIWHQ4gxPPRZx928vkavOBZ8 EOS+Q058AxMCszK0hVrnPae4QRd6foR/oPy+pNHkSP6Y3RtPD2Ox9E6EXCv58vWVwLDt iwmKdkRnB+fWth/qfqDNit4B16vSjxP4dPcPdY3BryyzmzQ+oAdw6Mion33DUxYbrZi8 YqxSQ2p5m0BIyIuxtq1hDDVSXvTizI4Sg3UdNOvlu9279zBWEaXbcLYVQ5jsCjgXIIcl 8X1WAb9MCrSBjKZ0kkjRb515mEpsc5miAb4eVmDZaT1iaenSzuZzEFZWd21iIWl6jL0T yrAA== X-Forwarded-Encrypted: i=1; AKwUvBzEeBoKeQ+4H9qcBgrFwTf39BO4DPOTYTfyO8qDCOxzD+heeQYjq7UXf3FjuGu6szVbHcJvPhcgrjqU6Q==@lists.linux.dev X-Gm-Message-State: AFq9FYIYHIwlUCW7GBj9iaFGg6ZggdWkuez+oDFAHJl0e5bbrcZDrEBr JYE2VPFY1URElH63A4XUfwdnBzZGwo9PJrp6oaK2gkESqnQKRcOpQHbM X-Gm-Gg: AYBFou0x3GCPUnpC6ED4T07Nn8Vej5EkUKRyMxQCSsQzsxGO+JgAHA0Jo74ivAJA3Fe G8kfAh5HOR6vYx0d9CKRRiN/oSlimrDloDiUgg+dgeGsLdyaEN/qufhNK+YaemHA1/2siCjR23B MyFXMFfmDjfTIlE0jgcO4ElzrF5LEAM020laQ7mrM+J1nP+EfWJ5zRYI6/HcKUqf57ZbBLSvmKm /q0ecwKF++hPzTAohWvrGCXBdUAddZCr4l4XbrYTmZwNHSzlJppl5YNJT+KX2bc/z5Ilm7J/UZf xl4hP71WNTD08d72bmyhffJBs+EbyPJeTCDaQe1aVlIB0CyT6/U9FdlHb1sCtrJXBwMII1SMFNt dHjyT91PjjFooApyZdAd5++nbAGBHyKii4aCB2SWQ7knPY2y+T4CIj8Koyqm9tpWb86CSkvWefX eVU83x/B0v13X2p3j0+kM/mRsGo7mA/vqKCAMPi0+j4LyzEt/WEgPutJf4KR6cClUiSk6C3YBZP TKLdaKsDiFnl7qeH5mMZ/H+NI6pmFtMhlBnI6xkuS96WF0nepHyecq4jm2ppWHFZ51hU7edfnSc Zx7nkcHIeDpavH4adO59+UllILTTY3GwMz+TDI9UKPRidayvEz35SrAy56i/dAHe04QYNzHdAxO jihIzCqjIdlgg1YnjVzx5pA== X-Received: by 2002:a05:6830:368b:b0:81c:a6c8:8a65 with SMTP id 46e09a7af769-8309758aae9mr19094737a34.25.1792122328983; Thu, 15 Oct 2026 20:45:28 -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.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:28 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:17 -0600 Subject: [PATCH v8 02/17] mtd: rawnand: sunxi: use the logical step's OOB length in PIO 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-2-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.232.135.74:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[dt]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; PRECEDENCE_BULK(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; FROM_HAS_DN(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74]; TO_DN_SOME(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1:received,209.85.210.46:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26677-noreply=patchwork.local]; MID_RHS_MATCH_FROM(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.232.135.74:from] X-Rspamd-Queue-Id: 9A7401C1CBB 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?= PIO transfers each logical ECC step through hardware slot zero. On H6/H616, user-data lengths can differ between logical steps: step zero can have 32 bytes while a later step has only 16 or none. sunxi_nfc_hw_ecc_correct() uses the hardware slot to select that length when filling pattern data. A pattern detected in a later PIO step can therefore overwrite the following OOB region with step zero's longer length. The protected-OOB write helper makes the same mistake when loading slot zero, reading bytes beyond the current step's user data. Pass the logical step's user-data length explicitly to both helpers. Separate that length from the user-data register offset: PIO always starts at register zero, while DMA advances by each preceding step's length in four-byte words. Update both DMA callers with the helper contract so variable-length steps continue to use the same registers. Fixed four-byte layouts and the on-flash geometry are unchanged. The mismatched logical and hardware indices were found by code inspection while consolidating the PIO and DMA OOB paths. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 106 ++++++++++++-------------------------- 1 file changed, 32 insertions(+), 74 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 27d6ae635e9c..c2e97b8656f7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -929,45 +929,22 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) /* PIO uses register zero; DMA concatenates user data within each transfer. */ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, - int step, bool bbm, int page, + unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) { - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + const struct sunxi_nfc_oob_ops *ops = to_sunxi_nand(nand)->oob_ops; struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); u32 user_data; + unsigned int i; - if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, 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 = 0; - unsigned int reg_off; - u8 *ptr = oob; - unsigned int i; - - for (i = 0; i < step; i++) - user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /= 4; - for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { - reg_off = NFC_REG_USER_DATA(nfc, user_data_off + i); - user_data = readl(nfc->regs + reg_off); - sunxi_nfc_user_data_to_buf(user_data, ptr); - } + for (i = 0; i < user_data_sz / 4; i++) { + user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); + sunxi_nfc_user_data_to_buf(user_data, oob + i * 4); } - /* De-randomize the Bad Block Marker. */ - if (bbm && sunxi_nand->oob_ops->transform_bbm) - sunxi_nand->oob_ops->transform_bbm(nand, page, oob); + /* Undo hardware de-randomization of the plain on-flash BBM. */ + if (bbm && ops->transform_bbm) + ops->transform_bbm(nand, page, oob); } /* @@ -1018,48 +995,26 @@ static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, } static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, - const u8 *oob, int step, - bool bbm, int page) + const u8 *oob, unsigned int reg_index, + bool bbm, int page, + unsigned int user_data_sz) { + const struct sunxi_nfc_oob_ops *ops = to_sunxi_nand(nand)->oob_ops; struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] = {}; + unsigned int i; - /* Randomize the Bad Block Marker. */ - if (bbm && sunxi_nand->oob_ops->transform_bbm) { + /* Compensate hardware randomization so the BBM stays plain on flash. */ + if (bbm && ops->transform_bbm) { memcpy(user_data, oob, user_data_sz); - sunxi_nand->oob_ops->transform_bbm(nand, page, user_data); + ops->transform_bbm(nand, page, user_data); oob = user_data; } - 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)); - } 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 = 0; - const u8 *ptr = oob; - unsigned int i; - - for (i = 0; i < step; i++) - user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /= 4; - for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { - writel(sunxi_nfc_buf_to_user_data(ptr), - nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); - } + for (i = 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)); } - } static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -1111,11 +1066,9 @@ struct sunxi_nfc_ecc_read { 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 = to_sunxi_nfc(nand->controller); - 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; u32 tmp; @@ -1214,10 +1167,10 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; bool randomized = nand->options & NAND_NEED_SCRAMBLING; - unsigned int user_data_sz; + unsigned int reg_index = 0, user_data_sz; int i, ret; - for (i = 0; i < nsteps; i++) { + for (i = 0; i < nsteps; i++, reg_index += user_data_sz / 4) { int step = first_step + i; int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); u8 *data = read->buf + step * ecc->size; @@ -1229,7 +1182,8 @@ 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, &erased); + i, status, pattern_found, + user_data_sz, &erased); if (bitflips < 0) { /* Preserve PIO data before the raw erased-page check. */ if (!read->dma && !randomized) @@ -1258,7 +1212,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, true, read->page); } - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !step, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, read->page, user_data_sz); } @@ -1447,7 +1401,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *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); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, @@ -1673,6 +1628,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct scatterlist sg; + unsigned int reg_index = 0; u32 wait; int ret, i; @@ -1693,8 +1649,10 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *oob = nand->oob_poi + oob_off; - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, + user_data_sz); sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); + reg_index += user_data_sz / 4; } nand_prog_page_begin_op(nand, page, 0, NULL, 0); From patchwork Fri Oct 16 03:45:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3632 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 640691C1CBB for ; Fri, 16 Oct 2026 05:45:51 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26678-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26678-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id A3C8E6061F1 for ; Fri, 16 Oct 2026 03:45:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id ADF9B37E5D0; Fri, 16 Oct 2026 03:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="acH64NKi" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f45.google.com (mail-oo1-f45.google.com [209.85.161.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 5FFF1346A18 for ; Fri, 16 Oct 2026 03:45:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122334; cv=none; b=WAexiX68xEqLRzX81c1DxbPBdAp69CvfbKrUsysgykgefV3Ozbw9PsiYaKtZXhSmDLsSUVtErWQ4BUwTyXmLUb+7801S+jA/zKpFGan9BHJZSAQi5Y7Qr8631MCbkRUx9v0369HT41xCcwqzTrFgbtnY4vzbwnV2lb2/PMmBNew= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122334; c=relaxed/simple; bh=5swNrnjhpqGxZeyGDlWe9TNZCEAsFDPalqzTOJ3Aefg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cNbiaFaVi6AI2duwqmcj7aLvQDiCdMludEgVpXtKHZ+0JYwmdLcw0TRanLtPpg4+hGYDq+wSxSkL9OvSAx4bBQ3D3LiiiZ7pbZFnIJSIDowsmnNgZVKZJBsyjCu6ZtJcyUGA74shm10WmPCL0AssTVt8ATFo5zt6JdyE2cUlvDM= 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=acH64NKi; arc=none smtp.client-ip=209.85.161.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-oo1-f45.google.com with SMTP id 006d021491bc7-6b19e291cc6so5523559eaf.2 for ; Thu, 15 Oct 2026 20:45:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122331; x=1792727131; 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=hlWVFZs9qMdbAGtAdGz2zNdnsjoirOAt+ztYuqFoEV4=; b=acH64NKiyGVn/ffUblXF4m6JX8cwlQ/OYY/knan+tu/jZZdRuIR1JlPN7lZ8gyEems Qbfh91W/u0m89whCkA+FOIS4rk0lIF8z+NlCYrjG3ulRrwkTnM2vNGMCJ/zq9xbOCrTI on7TUXdHE2DD8jGF6OguLArP/57xY0tAQLvlqwhRuAhWQw6IWm6KomLrSOtksMxBIhMs i0A+37WMx0kObpHke8M2hQfFkL/eN/lirWuIcPhgxl3DDf0UvfetkQgXmXYXo16JcKsN AfKXZ0CjSzs+lr/qTLyH6yc+PWVknsxFriq4alRDvbyzkAIEb0Y1rFxYoTnGfWvEPhwa hDkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122331; x=1792727131; 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=hlWVFZs9qMdbAGtAdGz2zNdnsjoirOAt+ztYuqFoEV4=; b=Uc1RpmB5qQnj4rXoZZc5P1HZAPBQBHyB8sBkrWUAngBhHKLpOAWbikXWTAkPkawkpJ 4jMI8Z4DGW4Pa7FADk0c3HvD+P4Iia1EJag+Mscx6aunOiRxk8StKT97uhPLgIxgSL9H 3jA0ZVjNV+gMgiF5XPEDOIBaqhyCl6xYb+xDR3Bvl/TuIOX40zWSRRkRRnbEnaYAEEHF w+Na3MYZWS2rlVHsZMjYj39AH5JjQetg/VhaBlj+hHS7PQyaY9aERY6sOW8nP8itIBch P0CUhMmuq5yPazWE3VuwaWQ0UwTRYPo1IVAxZQiPOBR3yhw+w7HocJikKKk0c/IxK4Ya iXqQ== X-Forwarded-Encrypted: i=1; AKwUvByT8LddxzDHyIR7r7cUpFv52cm6JZ0Xw0jGSMgPVsz8ON5632ToPcAratlSbOLUj8F7whbBGwRHrUC1NQ==@lists.linux.dev X-Gm-Message-State: AFq9FYJ5i6gDEgvmPlIMKZVSScrTMagXqeMjrHToU0laOl8lr4GWGyAP 4ujD9vdXh8KysuNxqD6XvRjALAf9ruIhZioLkbCBOpD5sX5F5gQBO09I X-Gm-Gg: AYBFou0Oq9vuKc4N7g4hw2Cm1kvussFAesV/GdRp9XWzPybNnvugi343ZVrskCqfVfj mOtcLW4Oz7A1d54kMcHus/YfEoVIirEzxwIPs3Cs6XzOsvrepQ6EKaCcelfNH+5VKCc1yGAlXd+ uPjYlShOlm1w6h9C2grysHdHHV7NIn4GH622s85JxtuaXyW8E0epqBMiB7zAJ1vzB1QjGP3+UzM 4dVzZ7Y3QiOfLplL4FTx+q1cXNU6052WfnRMKVbVji6u14vAHCr2sKI+r3AIKm4wCuW2pF22XYt 54bnmeaES/tFleEqhCXjMEPFxSh+gtE+azyqIPQNwCroI9yRn+gc0Sk1OhIRqpfbO44GPh0ZW9t 6ZIkTfM2YCU1NGppT0PQVjgqgL3r9k/aoLptxjk0na12WgrjSDJ5j1aaYTOGd1SzdtK9u+8+9IT syD9HDEpeOfyszgBIFZEltkGrxsA1+CYmBq6l71H+j1bOeqTyMXG/bftq0DyDkQsRm3w5AmC6bZ W+I6O7MsMgQ4Mm1s5JZNvhAVSBHU7gNpiv3/8Iwa0iDrujzgMM9QVFSJkFFUTMyNWV+Papz9vX7 e8mMf2BRXrEE89gG/qQB7wZbM/9d9Myq0zEkMtg4doqVRQiKlnECsI4ysHPgBdKZUDa+i7JuxVy QTLKuFtVRF16JCkwvvkfCVw== X-Received: by 2002:a05:6820:1503:b0:6d7:cd0c:752a with SMTP id 006d021491bc7-6ef0faaa6f2mr17901293eaf.54.1792122331029; Thu, 15 Oct 2026 20:45:31 -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.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:30 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:18 -0600 Subject: [PATCH v8 03/17] 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: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-3-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?= The ECC read callbacks ignore nand_read_page_op() failures. A command or ready timeout can therefore leave the requested page unselected, yet the driver continues with data transfers and can report success for stale data. Return the setup error before starting PIO or DMA. After an ECC error, the driver rereads the physical data and OOB with randomization disabled to distinguish an erased chunk from corrupt data. Those rereads can also fail. Do not pass stale buffers to nand_check_erased_ecc_chunk() or count a transport failure as an ECC result: return the reread error instead. Successful erased checks retain their existing statistics and correction-count behavior. Route PIO read errors through ECC disable. DMA has already released its transfer resources before interpreting the results, and its caller retries a failed read in PIO. Restore the corrected/failed counters from before that DMA attempt so earlier steps are not counted again by the retry; leave bad-block counters unchanged. These unchecked returns were found by inspecting the read callbacks and their NAND-operation helpers. 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 | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index c2e97b8656f7..6c0d3e2d2be2 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1030,7 +1030,10 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } -/* Return whether the chunk is erased, and account for its ECC result. */ +/* + * 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, @@ -1042,10 +1045,16 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, int ret; /* Check the physical representation for bitflips in erased pages. */ - if (nand->options & NAND_NEED_SCRAMBLING) - nand_change_read_column_op(nand, data_off, data, ecc->size, false); + if (nand->options & NAND_NEED_SCRAMBLING) { + ret = nand_change_read_column_op(nand, data_off, data, + ecc->size, false); + if (ret) + return ret; + } - nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + 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); @@ -1308,6 +1317,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(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_read read = { .buf = buf, @@ -1315,6 +1325,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, .oob_required = oob_required, .dma = true, }; + unsigned int corrected = mtd->ecc_stats.corrected; + unsigned int failed = mtd->ecc_stats.failed; struct scatterlist sg; int ret, i; u32 status, pattern_found, wait; @@ -1366,9 +1378,19 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, ret = sunxi_nand->oob_ops->read_batch(nand, &read, status, pattern_found, 0, nchunks); if (ret) - return ret; + goto err_stats; + + ret = sunxi_nand->oob_ops->finish_read(nand, &read, NULL); + if (ret < 0) + goto err_stats; + + return ret; - return sunxi_nand->oob_ops->finish_read(nand, &read, NULL); +err_stats: + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected = corrected; + mtd->ecc_stats.failed = failed; + return ret; } static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1456,7 +1478,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); @@ -1464,10 +1488,11 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, for (i = 0; i < ecc->steps; i++) { ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) - return ret; + goto out; } ret = sunxi_nand->oob_ops->finish_read(nand, &read, &cur_off); +out: sunxi_nfc_hw_ecc_disable(nand); return ret; @@ -1480,7 +1505,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); @@ -1505,7 +1532,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); @@ -1514,10 +1543,11 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) - return ret; + goto out; } ret = read.max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); return ret; @@ -1532,7 +1562,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) From patchwork Fri Oct 16 03:45:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3634 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 7A0541C2044 for ; Fri, 16 Oct 2026 05:46:20 +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-26679-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-26679-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 7B3F92944B for ; Fri, 16 Oct 2026 03:45:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8EAB92931D1; Fri, 16 Oct 2026 03:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kNDeZj4W" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (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 353EF39B4AF for ; Fri, 16 Oct 2026 03:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122336; cv=none; b=MGCYGxfwj+KajF4mhvu17xRhwrszhuDN7LxEvejxMP/j2o3yOkDfEJ7GVwXjppnAUJ03BVQPycPfrv+jC4OPvJ7EICsXjxdYBeTfmiDErY9gjNijiKnwQdvmZ09Y/EOsuHMBv3yfyWpuE+tqj0GgClNg4XzqJaRk60ctbESUpcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122336; c=relaxed/simple; bh=rEuLYDr43bv01Uvpdc+7lvdWEzGSSi8n2u7CVCX1ggM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cMa6ba74z10UGA2mpiUDPeVt1IHrG6Y2agni+NOe3N2kgirLZhul9UXiXPP6r+CudnfGh8FF29bUhXRjN2OFqpR1io8bDdD/K9MBqyMFegukGZex6TyMHuoKFiGeWN/XJD1arrGcMztk/XtkgbPAzXsYE5ovTT20GXh2K9FLL00= 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=kNDeZj4W; arc=none smtp.client-ip=209.85.210.42 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-f42.google.com with SMTP id 46e09a7af769-823e4047037so4571154a34.2 for ; Thu, 15 Oct 2026 20:45:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122333; x=1792727133; 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=piZMAcnvcZQBNALlEjasAqt9FGU3IFC9Bc/Ax/PGx1o=; b=kNDeZj4W86sVQky2jPxnJPGFzgx48LJyzOKK6lbJWJqnNPpRb689ttpDHJNDDoh0B2 JJn0pt1DG3QdH0JHZTTHpzuIhWRy84VVF/1rBKuXQ9iOYoL9iffE2waLNN3eN82YB8yc TjrnoGgmxKj5NM3Vd7HvqXC9xQRHNLBeGy4VpLZQnRv/IubfRBFdscANvt7zyngTJdU4 FYLo0YT3spnUnaFvkIDjUkPQsdy0z+8ijCbfDQds0l466GLGfgSBvijC+PfpV7cjVjAR eF3NswwXFeAjmKiUviZi4I8CyLxGF96XLZw+zLq9OQXTrhUzHFFX3lKCmccg+4wTZ2As XoJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122333; x=1792727133; 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=piZMAcnvcZQBNALlEjasAqt9FGU3IFC9Bc/Ax/PGx1o=; b=pmOFQC8XjhpVSua0B2ZTYdLwGqdUNwNsRJY8mt9i8VFYyGquBGMgdMM9YPVd+4yAA4 7qbI6cgqmGZozRTseclmyRBY9cnvHb4KJDvtMKe50hKhmFBHcuU6n6/AeFvrBl+WUIJC IPC1ztqGpjlMy2U7I2pXbBhXTEGMhw4GjIC2f3+QuBWIvSg14E2hNRlVVw4Sv5zleS3A uXsXQ4COm156TBNmZ/p58LvrBUzUMUX5bZKc8blK5uoYDBnt948ELyT9uPw9JWUJxTpA Qh22De1nfCC8M20LfkVAXhL3wI0RRZ862NE2PzIZ8JGFqls+OhUgMIsRjNaNt+VK5uEo 1k9A== X-Forwarded-Encrypted: i=1; AKwUvBxwlKhNOiPpXUo40x9KDqO9MGuFrNRywckuClaNSvFufBIDjcWutREPOcD1srN8jILFts+UPTCt62T/QQ==@lists.linux.dev X-Gm-Message-State: AFq9FYIf689jieMNG0WRAjfa0OdIZeAOYWU//T+uDxSEV1d993JVi60Q xnanA+D0fC5cWrJJzeTR6cApFIjiKAGLTFVGJNZ59OcLHRNFIdVP82fy X-Gm-Gg: AYBFou2TUV2T1naOzLFQRiZ4OwpIIfBIaxXiidozL3wnMSzq4z2pxD9u97x1APUkDd+ Yce1n6NBhSo9laMP/yhIyVy9jsNhIW3Z3cu/SZYFamuGCynDM5k4k77AmuPiTfDMsqdAKZmqmHb WMhpkdvNwAznPuQ8qDIT6AwrNXM/DqPREVyyyCsn6w9YO3H45ZG8wjsedSxoi4a6G87P8fjzUcR /Fhn7iBKiaEx8fhp3wcN4zKd2rHEPNaK92z52Q0uZvVNdQTe/Ey5l8rVP+Ou1BSyzOm2xuPq/f9 RTYVd+BNPQhn7DqWHmqQEJbi45h9IUzNtVqmErigj591LkIbi/hBXxkabfONwTZbzfnpOxWOuyC VjwJMclNwmO1Wpt6R3HCvvxmmIeWjR/8XvzIX5nS3Cheu2Greflp01nEApV2AazSGlf5bFMptRa CagTg8TM3y9LLKPlmw6/7aThOTlPxaM7H86ytxRJN+SFxrOQuZJC5vrSXGO7lWVGpavgw4WzMV5 CEhg97Gd6Dn/yoIc7QbJ2xG5AvseN/2Fw025XDOh59Eri7mLIGz8qdPwf+ur6s8irxuXw98Ayfb dtuM40rZ3dm4/G+fpYes+iQ4Xu3JFPsBqZaXSO71oIB6ptIy3aNvpJBHbXmGG2kj1qLS75yPQzg OigQ+v5ImY+smjk8XhUy/EpNGHDxepKUd X-Received: by 2002:a05:6830:270d:b0:80c:d34f:5f63 with SMTP id 46e09a7af769-8309814be28mr19957456a34.28.1792122332994; Thu, 15 Oct 2026 20:45:32 -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.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:32 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:19 -0600 Subject: [PATCH v8 04/17] mtd: rawnand: sunxi: drain interrupts before reusing the completion 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-4-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received,209.85.210.42:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[104.64.211.4:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26679-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 7A0541C2044 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 controller uses one completion for successive interrupt-driven waits. Some transfers wait for both command completion and DMA completion. The handler acknowledges each event and masks it, leaving any outstanding event enabled; it calls complete() when all requested events have arrived. sunxi_nfc_interrupt() currently calls complete() before updating those registers. A successful waiter can wake on another CPU and start the next operation before the old handler acknowledges status or rewrites the mask. Move complete() after those updates so waking the waiter cannot precede the handler's last controller access. A timeout also needs to exclude an unfinished handler. With PREEMPT_RT, the flags-zero IRQ request is forced threaded. Near the timeout boundary, that thread can be preempted after reading status and enable bits while the waiter times out, clears the device mask and rearms the next wait. The saved snapshot can then restore an obsolete remaining-event mask or, if it satisfies the old wait, complete the new wait. Masking the device does not invalidate the running handler's local values. Repeating init_completion() can also reset its waitqueue lock during complete(). This lifetime problem was identified by code inspection during review. Initialize the completion once in probe and use reinit_completion() for each wait. On timeout, call disable_irq() before clearing controller state so existing handling finishes and no new handler can enter during cleanup. The hardware may have finished before the delayed handler runs, or the handler may complete the wait while disable_irq() drains it. Recheck status against the remaining enabled events before clearing either register. Events already acknowledged by the handler no longer appear in that mask; if none remain, the wait has completed. This also handles command and DMA events arriving separately without requiring an already acknowledged status bit to be set again. Then mask and acknowledge the events, read back the mask to flush those writes, and re-enable the IRQ line even if the recheck changed the timeout to success. Keep partial-event handling in the IRQ handler and leave polling and controller/DMA abort handling unchanged. This keeps additional synchronization on the timeout path, without a driver lock in every interrupt and wait. The caller can sleep, this IRQ is not registered as shared, and the handler does not acquire the controller mutex held by the caller. The tradeoff is unbounded cleanup latency and no priority inheritance: a starved IRQ thread can prevent timeout cleanup from returning and block other operations on the controller. This is a handler-lifetime boundary, not an RT recovery-latency guarantee. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6c0d3e2d2be2..f7ddd4116bf4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -393,6 +393,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 @@ -412,6 +413,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; @@ -433,18 +435,20 @@ static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id) if (!(ien & st)) return IRQ_NONE; - if ((ien & st) == 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); + if ((ien & st) == ien) + complete(&nfc->complete); + return IRQ_HANDLED; } static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, bool use_polling, unsigned int timeout_ms) { + bool irq_disabled = false; int ret; if (events & ~NFC_INT_MASK) @@ -454,16 +458,25 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, timeout_ms = NFC_DEFAULT_TIMEOUT_MS; if (!use_polling) { - init_completion(&nfc->complete); + reinit_completion(&nfc->complete); writel(events, nfc->regs + NFC_REG_INT); ret = wait_for_completion_timeout(&nfc->complete, msecs_to_jiffies(timeout_ms)); - if (!ret) - ret = -ETIMEDOUT; - else + if (!ret) { + u32 pending, status; + + /* Drain the handler before it can restore an old IRQ mask. */ + disable_irq(nfc->irq); + irq_disabled = true; + /* The handler removes acknowledged events from the mask. */ + pending = readl(nfc->regs + NFC_REG_INT) & events; + status = readl(nfc->regs + NFC_REG_ST); + ret = (status & pending) == pending ? 0 : -ETIMEDOUT; + } else { ret = 0; + } writel(0, nfc->regs + NFC_REG_INT); } else { @@ -476,6 +489,12 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); + if (irq_disabled) { + /* 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"); @@ -2650,6 +2669,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev) nfc->dev = dev; nand_controller_init(&nfc->controller); INIT_LIST_HEAD(&nfc->chips); + init_completion(&nfc->complete); nfc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(nfc->regs)) @@ -2658,6 +2678,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; + nfc->irq = irq; nfc->caps = of_device_get_match_data(dev); if (!nfc->caps) From patchwork Fri Oct 16 03:45:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3635 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 0FDC21C1CBB for ; Fri, 16 Oct 2026 05:46:34 +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-26680-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-26680-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 0C42D2A4A2 for ; Fri, 16 Oct 2026 03:45:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1283C3AB48F; Fri, 16 Oct 2026 03:45:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z+EYXWQy" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) (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 03D4839F168 for ; Fri, 16 Oct 2026 03:45:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122337; cv=none; b=K1Uullqka/If7sPMwpnftQi9nwgyt9RQJkl6xLbmjSZN8GTjIcxd47W76qB3EY6QtJQsfCs3o4NWfyXYEtCblgyKCEOPPHZRmv6qAuVF//Yd2GQAyOmINwxms67fua8mQFruIjNL76OnX+tDIGaFPaCtlYM3RbF8ZAjWLfdk/mY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122337; c=relaxed/simple; bh=QP1mT8TLRuJ9xSIvxqSG9BInMHYpQcC5zhAAnQdC80g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AsfNUmeAAc3ZNxLpFngS+UsQVk8GqMfk4woesaaqTNeL0XaGHMVFqIzcgkWFy3RY7DthGEewwiwR6K+oJfezkp3v/RdOLaKqf0CRt+BqlSf/gtYJxTwuSWNWMVV9aQBobB1FK0VcJpj/4xnOKRucZWzwwOMI+iOTE64xuKtAEAo= 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=Z+EYXWQy; arc=none smtp.client-ip=209.85.210.48 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-f48.google.com with SMTP id 46e09a7af769-823545ce223so2086374a34.2 for ; Thu, 15 Oct 2026 20:45:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122335; x=1792727135; 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=9xu2UIC5iJfecJVYRm44JjAaDQ7zuRMhXFx3hC1cl90=; b=Z+EYXWQy/hoXFteAWmiHxKgwLbFgtCdCWNPF8Y7oKWoI6EWPOuuHO4ySSSZ4WV46OK ITc1DZ3WLySMh1uVvC/XVT8skXxTnZD2m2uPOVllBUTWo9CAcCKu9dyJprPVyOlI0Seb JYnNdnFyaf3u9tn2022LwJoYeE2P4VcaRo6ibiwBGuv5LjbMfxC0ilPcMUyEfRV1XXKv Es1/C9xTTtcVsLtvTPjCUNQ2/X9U4LcDDR9/1Vg9ndJehiVUzeTGUDdKu5UJe6NbssWO K3Tx/2dX7c6vku1HJi2d4hOxm4tya8NI0p/MqVtZUdjbeCjitPKwRyh5UDaWIc/c0hCy lQvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122335; x=1792727135; 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=9xu2UIC5iJfecJVYRm44JjAaDQ7zuRMhXFx3hC1cl90=; b=1aj0Qo2XsKSK4s551hK47n07S569KQlGl0vaUEGTZ1l6jhaKPVnB3gcXzfLjoeMJLE KdV+ojNsZYDxNoxK7XG3mgTvhFlL8Wpaa2M++FMWDVI1/TnhZOUA/taiCUDm9Qy7I/OC 9aYgcj/Qeve+NBVY92A9EqTowRm7BvgDOJf4jnjsTrO8fyilI2KiOi7yOtQofbpG50YL 6FX4eheLOXzONeN9WHIvk8ibddUIsr2NxUBYGDIvarIReD6QVEpjdP+G9o3+FZUJjg/o waGm1DmFHHDLrBvnMioShdgDJjCQEBLXj+orfQOaxOxk6lLkPaSpCmeAj80Yg+V/3yHR rC6w== X-Forwarded-Encrypted: i=1; AKwUvBzFDuyKc3bR+tUqcTRAsWhckRpPN3DJYpkV+2OBj0YrSFoW0EJ345+mVnVVxJP/IAGAhbUwj+N7FIktTg==@lists.linux.dev X-Gm-Message-State: AFq9FYLF42kBT7PpIfxhVdOZ/THb95OlFCyN+I1VaNSXb1msrzcje9R1 rPLlZQqESz8YVL9o1HrYc+kGelrMEdlTqhus+la/7w3zcKbTlGKQwD// X-Gm-Gg: AYBFou06XblyZhi+GSdb9GPgGBQB+6jIZWO1nJnhG/OK8VID8EC1dfT7BDnd82YsHfr AuO3r+qe4ikxO4PeTuwh/GuVXOnMfKXH9CKFXAvqrTmkJKEzEQW82uKkAgEBF5h74506jqYh+/4 Jyq7wYaWEK1/8V0Tk5ZOSNpgaF8s6UvCmQQa76T5gMygDLm+nyleICCnn3+9Nw06BfbuCzcwpug UScAdfazHQoLTV+L7v0cUDkr4snbpGbUgr6PZiPCc/FbdMfiYHrc2k9EHMHOSMY9T+in/+83iUo ksnqNTC5M2127EmzIDYddpzY+9oGMQtarnbwJJ/BLxXGzatdPXCkyxhYAleAqYHyF5IKmCbIvZw Ewn771LNg0o0X+l8ZmzpHf8dNx7iy518JByN4r4ItVU28U+uSvTBRjen4EmaJl6HOOggjCibomA j53t+x0DXcoJpAhIACBos50uja/QTt4cNDgCav6U/2N1farrzp5USzBH6c/lr9EgFmDZ8bEddpg O3lPJsuWp2naww4roklpBgUJs7jGosI3Q+dDH5jvEgkHrwk9p64QsUwtFUjAcQOnHGzNMG/Xmnl KKPeEgUTOWQov0ANv4pT1TVQuIkElShpPximJknkO9TEC9vDg1fM1v9qNo2OL22bZWyNtjbnSjd j4Bj3uOVjk+QrIB+nNnKBxg== X-Received: by 2002:a05:6830:4394:b0:81b:9d18:75e with SMTP id 46e09a7af769-83090e15541mr22707196a34.4.1792122334840; Thu, 15 Oct 2026 20:45:34 -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.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:34 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:20 -0600 Subject: [PATCH v8 05/17] mtd: rawnand: sunxi: stop failed program operations and disable ECC 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-5-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; MID_RHS_MATCH_FROM(0.00)[]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,209.85.210.48:received,174.29.1.49:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[104.64.211.4:from]; TAGGED_FROM(0.00)[bounces-26680-noreply=patchwork.local]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 0FDC21C1CBB 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 page program has three stages: send the setup command and address, transfer the data with ECC, then send PAGEPROG to commit it and check the NAND status. The PIO page/subpage and DMA page writers ignore the return from nand_prog_page_begin_op(). A FIFO or command-completion timeout can therefore be followed by data transfers and PAGEPROG, with a later success hiding the original setup failure. Check setup before enabling ECC or transferring data. DMA preparation occurs before setup and may already have queued a descriptor and mapped the buffer, so use its existing abort and cleanup helpers before returning that error. The PIO writers also return directly when a chunk reports failure, leaving ECC enabled for the next controller operation. Route those exits through ECC disable, preserve the reported error and skip program-end. Keep the successful setup/transfer/confirm sequence unchanged; this patch does not add a new controller-reset or NAND-abort policy. 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 f7ddd4116bf4..d71b980ababb 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1602,11 +1602,13 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; - int ret, i, cur_off = 0; + int ret = 0, i, cur_off = 0; sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1621,14 +1623,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; } if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, &cur_off, page); +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; return nand_prog_page_end_op(nand); } @@ -1642,11 +1647,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; - int ret, i, cur_off = 0; + int ret = 0, i, cur_off = 0; sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1662,10 +1669,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand, oob_off + mtd->writesize, &cur_off, i, page); if (ret) - return ret; + goto out; } +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; return nand_prog_page_end_op(nand); } @@ -1706,7 +1716,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, reg_index += user_data_sz / 4; } - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret = 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_enable(nand); sunxi_nfc_randomizer_config(nand, page, false); From patchwork Fri Oct 16 03:45:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3639 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 01E041C288E for ; Fri, 16 Oct 2026 05:47:51 +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-26681-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-26681-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 4B6BB40C27 for ; Fri, 16 Oct 2026 03:46:03 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F27203B27F9; Fri, 16 Oct 2026 03:45:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ma4A8ijT" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.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 A8D7B38B131 for ; Fri, 16 Oct 2026 03:45:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122340; cv=none; b=LPuarIdj2ugvpedLLO28Hzj5qKyUCO2+IaB7OsXvHTQC71Xo5FeWwwUJLVNfY/AiLFiFzBK93uhMBpqJSe2UwrCDg++nQCFw9JXJKhvBbpcdoN/TGDHN6fr9rXzgH6ICZhWT8ACq0loDoZNFeM6j90GRw+BAMTRSToQGU2hmauM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122340; c=relaxed/simple; bh=HeEn7ZBI4PAW/iteNQhqHA4zXunmr3jV3/OD3Rh6OA4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p8SHAPLecImgpmucc7ngVPprnmtWHo5XEzyn3VJp/8cwYgj1UiSOYTI/6GHvwpw+SG3TnA1UwY7IqCSchI90ettt4dknLhdrYO0gtreMNyfOe2odw7V3A0+JT+AUxlWxfg/jw7/Zlz657BuRYSMQhFL+7jmHREax1LGvFNu5caI= 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=ma4A8ijT; arc=none smtp.client-ip=209.85.210.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 Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-823e4047037so4571187a34.2 for ; Thu, 15 Oct 2026 20:45:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122337; x=1792727137; 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=mbxk8jsiAzvQZpmw8X3BW7J7DhacWFvl1KbYwBAc0jg=; b=ma4A8ijTZIlhygedjQHcnkgWZ2qGokOU5BwZeGrJncfyFW8qyJz2AG65DvqxCoJsrX vmdirW6FRyLQVAC8MifKxpWeCNFMQgQqQW+42HkvDmb7f68PzK6D3aE09NLozZb3k5Pq VqZwEoBLnizk6ytinfyyxPMUjRD7tZQhOwlfyfR7nGePVGTlAMNcVw9YXauWiwayFhPE 1jjBdVP8ERpWmvY3chELnN3YgRrrjFaUwtdatriMWU3lhIjsYAsZwCcCtZXKgdn4ZQN7 6u/mBqLlI6N6/cCOTbgcf69Cwo+KslZFndfLbubuSybW1kzWbYdp3g7LQZI77O0jeJCj tWEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122337; x=1792727137; 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=mbxk8jsiAzvQZpmw8X3BW7J7DhacWFvl1KbYwBAc0jg=; b=l3c4h3RcnyZ5a1wG6LPfFEq/J5tbouDsOh8We3xzN8yrobE9WhDEZDBxLN/XOBaCQp ulCDaKPJzY9z8sY0Dvyd/8Pz0RWk7n6wTNv/DSiZbXvLyITnHPIT7pra49ZyQnN8l/1i cewXqKHsyRlBsVbJhPWYtGBKTrr/2DFizim3/iX8VGPpuEeKM46xtQ7XIh5w04eg4Csn mTMpdd5ffyRmkgtuqRQtjs0jr2fkTEOozeqKSo/PzMP6jwZkGrEYkeIgB6viphMXV9MN eDE5fPnE7+4HR1Jzw0qaxaSpgxMO3+tJqgi5q5SBlwAmwzNT183zSrKTD5RKsmqOachP epZA== X-Forwarded-Encrypted: i=1; AKwUvBwZnOEgrkXDSQblAjeSXThUdm4qFVZ39h5vUjAr7B9v4kk6WQnpsGqiIZLsJpkziCk+sWRbegZkFXfsgg==@lists.linux.dev X-Gm-Message-State: AFq9FYLcrNNz4SzSe7wNRwSR43Vl2iI9nT0f2HJsBDjhMV4Pebh63mhw 8dcl9OIX5/duwoo4Mj5Jg8ffyQ0yweKN1+q+CByQhaDQO/LCwhyqIyteWnS4ILNQ X-Gm-Gg: AYBFou0yBa+10aLbnG1Y7bTwnUot/FGjBRJfbugzbrrgihw/xOrDwdk062mj8dE7W8o 5ZqCYUNcbIr9opbxtSSILjovSrqB/rq196rmefviibn5R+kjlrWaRQpQjClFQpLsk0YNOOuzwp4 SLXf/rjeStthizdli9h4wbLo5RijkKLWz11eSk7udFXLw3FJWcJD3ZV7WakYpbtoCQ83FanGiVH ySlXZJNW6O79v3NVmK+SJdB03hVJSy4jbtSPzWTbW+quHbnDSSc5kMjdR91NWSYWhBWp0+LGG/0 +XYLF7sCWc8KSlWXfKVYDPWDZ9FWc3N2UFmlAJjfZxd1G20eGe4S+2+BJJCdgVU4bemBps+tyi3 LyQJKfqpKga7QQVr8+N6dnGtkNIJWgPlYrXlLB72JckX7qRG7LZk+oPf0br0WiYG8wqKpV8maj4 c80NbG9CvtRGgxOnoEH+AjJ0ZWLhJJDaN1uloO3N9Z2BFk+Fl/z5lQcdSdM5f7X5mHC1NbPw3vk LwpXh6tqFKGaziHGiHoJDmNUT91T/9D14CaF1IL6+3nCkcXhVLV/BpstKkOb8gHCaN1qny/RInp S5a/VKzpGTttRYbXLsrZ+b3op252bVTfntQIOZNjjb01cA0daEVQG/3UcQ/w9tK30VgOgjXL08O NH8wDNLhsyhDPMrx6aIcxjw== X-Received: by 2002:a05:6830:6a14:b0:81b:ac9a:5681 with SMTP id 46e09a7af769-8309814bd65mr21830521a34.29.1792122336679; Thu, 15 Oct 2026 20:45:36 -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.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:36 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:21 -0600 Subject: [PATCH v8 06/17] mtd: rawnand: sunxi: select the pattern ID for the current ECC step 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-6-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-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)[]; FROM_HAS_DN(0.00)[]; PRECEDENCE_BULK(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCPT_COUNT_TWELVE(0.00)[24]; TAGGED_RCPT(0.00)[dt]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; DBL_BLOCKED_OPENRESOLVER(0.00)[tor.lore.kernel.org:rdns,tor.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.105.96.0/20, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.105.105.114:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26681-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 01E041C288E 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?= ECC exception mode recognizes physical all-zero and all-ones data blocks. For each hardware ECC step, a pattern-found bit says whether this happened and the corresponding pattern-ID bit distinguishes zero from 0xff. The correction helper checks the current step's pattern-found bit but always reads pattern-ID bit zero. PIO processes one step at a time in hardware slot zero, so it is unaffected. DMA processes several steps at once. For example, if step one is all 0xff but pattern-ID bit zero is clear, the helper treats step one as all zero. On scrambled DMA reads it fills that step's main data with zeros and reports success. Requested OOB is also filled using the wrong pattern. Conversely, a zero step can be classified as erased when bit zero is set. Test BIT(step) in the pattern-ID register, matching the error and pattern-found bits already selected for that hardware step. Fixes: 614049a8d904 ("mtd: nand: sunxi: add support for DMA assisted operations") 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 d71b980ababb..661ced4e07de 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1108,7 +1108,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, if (pattern_found & BIT(step)) { u8 pattern; - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1))) { + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { pattern = 0x0; } else { pattern = 0xff; From patchwork Fri Oct 16 03:45:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3637 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 E30441C2044 for ; Fri, 16 Oct 2026 05:47:01 +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-26682-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-26682-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 0AEDF2B221 for ; Fri, 16 Oct 2026 03:46:06 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4085C39A06A; Fri, 16 Oct 2026 03:45:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qeOsXU1e" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.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 CCF9C3B14A4 for ; Fri, 16 Oct 2026 03:45:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122342; cv=none; b=oLshG+CWTs1YCdcwurDEfk2D4zlc2zJMFg9B+jG1lj0B5Th2pCwlcYtp5X4z2ajAKgFsINQtMf4xv0iKN7dCTtfAQWPownFRPVWj/IvTx1P1EwbUavRfBIDd6rG/+DD61mdeQJrI0pr5gjEFajIMRbG/n8irnTG7JKc9MFau4go= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122342; c=relaxed/simple; bh=H5TfgRr2Bv5tbABipMunxtVTh9+p1lSGxQCm++Vk00I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TZZh7RoqQf4Nj7nHCU9Urqab/LYFpJqrtSb2ceItItmTS0itMp1+iglxUFNHTyKML9sOdp3Ao5mr142Cy15wa9f+ibB72/C1hMTZnO4jwVngWTTLDD21Mr1Smm3wRu1M2qMTwzKl6AQzVQt7dLwM6C97mWhgNsgN53lQOiLl5dk= 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=qeOsXU1e; arc=none smtp.client-ip=209.85.210.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 Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-8241a56cd70so3923479a34.3 for ; Thu, 15 Oct 2026 20:45:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122339; x=1792727139; 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=b+uyWszwAFvFc8JbK1nSE8GaRzk3E1Kb/gXy0IKu03o=; b=qeOsXU1eJDEYBy5tDXm0y5PlG+CY3MG9GoXxylyVe74nEkml8ZQNPlT23n3iZSnCFj ND4cyxZkkY0SzPL8LVbSa6+2u5fFaDOfCj/ofNj5tXq6BrtRCdTJK9A+sAjOrJtAX7Bu XLJyRY7NhuemNhwqe0AJMwkaublHQznQk1sSM+6dn67esCyvxjOvMR64Exak/d4ly9q4 Ca2eIpA/XuhcuiNrpJFe9bJVT9OXuoxpEwvfFTqGIwLGqpOkEIwAMUb43k+b1FkT58vO b+g63ZmrGxT+apTE8ytgaiqxweA8YVQBAzHxyPEIB+DlKNqQQevCJrnzXocjjTjEdAv2 AA+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122339; x=1792727139; 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=b+uyWszwAFvFc8JbK1nSE8GaRzk3E1Kb/gXy0IKu03o=; b=E3E1lvxvLOPPhov/3IAxlFETsahD9wi867F/Dog9g+8/ZHWI+erSc9ez3m/bBygnbL 7zdvr69klJ5su1iQKnjOg6OTTgtPFibucnObmece44b2bUlHxXDuj5WB10s43KaecSOp +kusOf1mH/9TNlF6G9E46N4Aa9sXZbdASWH+Fw4X2XDQl7sxH/CgNGbnZVsaDjnv/SZR kjOohYstzKjPOwJSAADix8DU/IYJNb2vI124RE6Nc4Uq9wsAEvfRaB7uuhhHNdA/igxw oCjsi5mZpqTRAzQrC7XotWC7gPgYT1ZM7yvjp93xRvI6T6yPn1o5YtWq8Q75Pmv+ijgM 9lAg== X-Forwarded-Encrypted: i=1; AKwUvBwraqwBvbAkcj/ZfkAudREubkO4LukQENQWJsZ9fjcJftUSPqvhWk1QuuwpxosODUZoeDc8tuEnaX+CMQ==@lists.linux.dev X-Gm-Message-State: AFq9FYK0ax4AKejvyF8jwNoIzk1JxU2i97nM4ocnT1ilCL0wiUnQGTH4 rJbCi5bbe9h+S9LhnlziU+8jsb8ZXP15yrrACe7s03ZCnXLfnuWF4AxI X-Gm-Gg: AYBFou07PKrB1CE/WNHB7vcrE+x5F8mY4mG/g7TCqR++BR39xpAzsIck8RdTXM2KfAb YwFrH5RWVRX3w0IbfX5Fti+ZPLCer+ckpd6OYWSwUAGuIt7B5SSLZen+iPmN9ZgIKaOCFpOFkp2 rxuyqxzpU4i7wWopm3vL/jShco02MBUTHgxad7XYStM5fEbENjZR4XVgtU5Er+vGKHfv0dM6wBe fbO2a/RIbUFngwstheEeXZYURb9bDBXTKCFSPML6/LRyUvMOpsUrCHmoSTJdt/LIt3JsR+0hCRl 7EbVjz+RqGX0nX3YZdfJirWXtORmN7QELZ2cBGmb0uii4a+yVMsVTb0BkHO98OM6P0TPLkyZMW/ d4WVSDkPTXma9LOmlPHWujFOcJI0HOSJrFruI8RWs4B0E5YxBz/h6p7bdkn9zvC+TZ4sjxD6eif NWyGYxEOMsuCUz7UpF5FLROZ3REYezXcqT3lUUZv2QjCJN0159VlkkFmTM8JwNpsoVEyEpgOMSz 15UKUX7DWSgAQJFz6jvejlF7k3AlxxvM2Pfgk4noqYg5u/dOvpCq7s8PQyXb/7Mwf3t4mx7KY2j d1ecEEMQlfRUw2aFVyg3Rt77RnhCakF2OeYERLLnsDwjs39a2iCefDE1uyLxWaLf6Fqer8Ny6EX sOOp5bMf2NoLlRnCcqlN2m2ZRyzRv/L/fpw== X-Received: by 2002:a05:6830:82b9:b0:822:27d6:c281 with SMTP id 46e09a7af769-83094f728ebmr20703536a34.8.1792122338629; Thu, 15 Oct 2026 20:45:38 -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.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:38 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:22 -0600 Subject: [PATCH v8 07/17] mtd: rawnand: sunxi: preserve synthesized zero-pattern data and OOB 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-7-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 , Sashiko 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?= ECC exception mode recognizes physical all-zero and all-ones chunks. sunxi_nfc_hw_ecc_correct() fills their data and requested OOB buffers with the detected pattern, but sets its erased flag only for all-ones chunks. The caller skips normal buffer retrieval only when that flag is set. For an all-zero chunk, PIO therefore overwrites the synthesized zeros with SRAM contents. With scrambling enabled, those contents are descrambled data rather than the physical zero pattern, yet the read reports success. Requested OOB is also reloaded after synthesis, in both PIO and DMA. After checking for ECC errors, skip buffer retrieval for either detected pattern. Keep the erased flag separate: only all-ones chunks may set the page's has_erased_chunk state, which controls randomization when reading the trailing OOB. Preserve that state if an earlier chunk was erased. ECC-error steps still take the existing raw reread and erased-page check. Fixes: cc6822fb756b ("mtd: nand: sunxi: move some ECC related operations to their own functions") Reported-by: Sashiko Closes: https://lore.kernel.org/r/sashiko-outbox-172123@kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 661ced4e07de..a244d2158d76 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1219,8 +1219,9 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, continue; } - if (erased) { - read->has_erased_chunk = true; + /* Both patterns are already filled; only all-ones is erased. */ + if (pattern_found & BIT(i)) { + read->has_erased_chunk |= erased; continue; } From patchwork Fri Oct 16 03:45:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3638 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 C70DD1C288F for ; Fri, 16 Oct 2026 05:47:08 +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-26683-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-26683-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 8C7D72B73C for ; Fri, 16 Oct 2026 03:46:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EDA7D3B4E80; Fri, 16 Oct 2026 03:45:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jZNRSDV3" 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 E25803B3C12 for ; Fri, 16 Oct 2026 03:45:41 +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=1792122343; cv=none; b=ZinhuBf4c97BquondIHQgjSyO0uxywpejB8OdZPeyGZekqub3Ky0bIbUEy6rxHg0Z80Xjq4OMrA4vcBo3lDeISznBvoxqXgIA2zvXx8PgV64frRy7/DQgF8rlL50NBR7zhrOJUeWYGkf371Rx1X/s3kXEbsPtx7CiVYUvheBFR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122343; c=relaxed/simple; bh=KL2itoqI1FRgl/wkdyzI6omghofE7iWi1HQCV9M7LQ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WN2ze7JaCA6rQrySnejI9DBraGe1Csdgd6CdyrIvntRd7zefJoCf85GBp+IBEGkK73le0tysmJk9D3NJ4ehAZn5Cdv2aSmnJ7qsLCA2dA6hr1S1P2Z5VWR0VzAEzQUY3ebrj1zuA0gtOgZDF9mm3mzrsCUo9++TTJc0fPNS3FAw= 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=jZNRSDV3; 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-823e4047037so4571215a34.2 for ; Thu, 15 Oct 2026 20:45:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122341; x=1792727141; 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=jq/NuCCaL8gKhO+mvfil1XtSoT7M57C6sxsBn3oDvGc=; b=jZNRSDV37T+JTWbL3DxHXPXq5G5lXGjZezMRZDrvS3wO3iKzBJ1dUKInAd9qHwAo12 yKHo/I4GjB24y0NP2+pa0y9r0twJ2KptgXSzJe7vRr07dSlmgHh3Tp64P83F4l5ESluD dxl1blW8Ad3F0YOVfGR4YfOi97IcU/dcqib/CR11CGjI1rLFQHx0askA4yr3mvdgr0i4 pSmTBVcynllHLPp7FD8NCMYfZdNcG0vSCfKNzSIzdrSpP8NefJgJSQn9ot/vwHa62WVx MK6uZwGdBpAisI7hXuRFEtXOa4HGui06wBM7qrRdirVXwYOa/qIjB1COzOhYPvvMqvWv xGaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122341; x=1792727141; 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=jq/NuCCaL8gKhO+mvfil1XtSoT7M57C6sxsBn3oDvGc=; b=qeMlFMU2Jjldiy6vKtIFlvUASF22wII1PGFtACglp0/pRUll/xIjsChBbwg5dUXtTC OttXslh8FZ2xd/PP7zr7lVUsH3eFLqo2X44inz1obcVVyfBnmFvLs5IMIFWZu8dyTS1+ /84vQvk/VrgY+BGpiJg83sGU5oy5NbQCSVLHZVPpX8bc9jDr9kQZjFpMVwawKYIYR7WX bPkbMMADKyXNpley7+//rfUU1Ezsbu7Hhb8lnqrCWWQK++q1GgGtbxHfrp04D53NnpDo HPMTaP9ZJyENzR1tY7MrzSQZ66Iw4h0H/J0Zny843se2XMO2FCmqAr2zqGoAXCRCi2RM r8Rg== X-Forwarded-Encrypted: i=1; AKwUvBxTyWJJZmYr8NgkTOUJYFInQ2tNEsee/WQ+6fTgG7zfPvOXgeJfQiJ4zZnA5QlOhrEFSezehJcEZSIJEA==@lists.linux.dev X-Gm-Message-State: AFq9FYLHuKIVuV2qYBVAviTBN1Ztxv94aUyZSZHCBa/98VzMWL3qvJuU bFKSQzE5acknHoitHrOLXClIL2pB1ROaIje6Ucxef815PEKsbTHQi4Py X-Gm-Gg: AYBFou3dIUu3QCdK1/IXMl1XDMKvGzazRSUSnfNypMq5fvBj76Vkm5Gn25AkIYMN0Pk C/HhJPwMAirTxHCMdu40wliaraKSRnquG5/eXHCKnylQ9q0mIH49qRDPfkYE8RnC1dyWOIUGICL iT3WMcjr3zaO5WvZk7cJ+V18wLsgceoWK4lh0aaAq6SIrYMEWAuhtZWPj25l39zfha16Ct1a+YO +Lhe/AJuBkUoJ14MqDAnE1cgkM5XnrM+U2/PkMr77KwHaCqqxRkOMY1R1TnUEn5z3YrIiNlJJXp 3XJ8qIU5uti8VDlylsZP7yak7cfhTuoucs/yzrrNpncT+3exqUTE9ImUSbt4E8ycZJY78bWtUv6 sCNp67LfEnMnWXFhNbmcX/7DDu1uqI1KQrnalPB0dCzEkuPY6dkFcpLjS1QckR4enR47HwkioCR cY4jZI4pE/HBDTj6ur7HFdg7xEU98J9K16/FsBog17B77pqyLFeMKOwn+A7vacnnDB1Xj4lBq9U 1nD4nhJSCdKX5IeeCIjIE3gP8UWEx9D+Pk1seK3xagDLTFk3NBO3tYw/U46Fa0WzJt8cxZiDksK REaoPjJXPwUYnr1iNa0OOqkm6biTu7V5W9kKOQmgl+I181rZ13vs0Cl7BJZoGk15p3AihR7jd8W I1JkJfyefG/97FpbSw/O6PQ== X-Received: by 2002:a05:6830:2b23:b0:7dc:dbe4:3f21 with SMTP id 46e09a7af769-83090e20c67mr20939261a34.1.1792122340590; Thu, 15 Oct 2026 20:45:40 -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.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:40 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:23 -0600 Subject: [PATCH v8 08/17] mtd: rawnand: sunxi: propagate buffer and column transfer errors 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-8-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?= sunxi_nfc_read_buf() and sunxi_nfc_write_buf() move data through controller SRAM, waiting for FIFO space and transfer completion. On timeout they stop their loop but return void, so their callers cannot distinguish a complete transfer from a partial one. The hardware-ECC paths also ignore some NAND column-change errors, including extra-OOB transfers performed after DMA. Reads can thus succeed with incomplete data or bytes from the wrong column; writes can issue PAGEPROG after failing to transfer all the intended bytes. Return the transfer status through the randomizer and OOB helpers to the page callbacks. A read with a NULL destination still fills controller SRAM for ECC and must report errors even though it does not copy to memory. Disable the randomizer after either transfer outcome, and use the page callbacks' error exits to disable ECC and skip program-end. Update a tracked OOB column only after the requested transfer succeeds. Keep transport status separate from the maximum corrected-bit count: zero from a successful OOB read must not erase a positive correction result. If an OOB read after DMA fails, restore that attempt's corrected/failed counters before the caller retries the page in PIO. Leave successful command sequences and the returned 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 | 170 +++++++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index a244d2158d76..fcb017f048db 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -670,7 +670,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs) writel(ctl, nfc->regs + NFC_REG_CTL); } -static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) +static int sunxi_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); @@ -686,7 +686,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; writel(cnt, nfc->regs + NFC_REG_CNT); tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; @@ -698,17 +698,19 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; if (buf) memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, cnt); offs += cnt; } + + return 0; } -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 = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); @@ -724,7 +726,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; writel(cnt, nfc->regs + NFC_REG_CNT); memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); @@ -738,10 +740,12 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; offs += cnt; } + + return 0; } /* These seed values have been extracted from Allwinner's BSP */ @@ -891,23 +895,31 @@ static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm) bbm[1] ^= sunxi_nfc_randomizer_step(state, 8); } -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 = sunxi_nfc_write_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } -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 = sunxi_nfc_read_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand) @@ -1157,31 +1169,39 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, sunxi_nfc_user_data_sz(sunxi_nand, step); } -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 = to_sunxi_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; + int ret; if (len <= 0) - return; + return 0; - if (!cur_off || *cur_off != (offset + mtd->writesize)) - nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + if (!cur_off || *cur_off != (offset + mtd->writesize)) { + ret = nand_change_read_column_op(nand, mtd->writesize + offset, + NULL, 0, false); + if (ret) + return ret; + } if (!randomize) - sunxi_nfc_read_buf(nand, oob + offset, len); + ret = sunxi_nfc_read_buf(nand, oob + offset, len); else - sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, - false, page); + ret = sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, + false, page); + if (ret) + return ret; if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; + + return 0; } /* Interpret one PIO step or a completed DMA batch before reusing its status. */ @@ -1230,15 +1250,19 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ - nand_change_read_column_op(nand, mtd->writesize + oob_off, - read->dma ? oob : NULL, - read->dma ? ecc->bytes + user_data_sz : 0, - false); + ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0, + false); + if (ret) + return ret; if (!read->dma) { - sunxi_nfc_randomizer_read_buf(nand, oob, - ecc->bytes + user_data_sz, - true, read->page); + ret = sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, read->page); + if (ret) + return ret; } sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, @@ -1278,9 +1302,14 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, static int sunxi_nfc_oob_finish_read(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, int *cur_off) { - if (read->oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, - !read->has_erased_chunk, read->page); + int ret; + + if (read->oob_required) { + ret = sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, + !read->has_erased_chunk, read->page); + if (ret) + return ret; + } return read->max_bitflips; } @@ -1299,13 +1328,21 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, u32 pattern_found; int ret; - if (*cur_off != data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (*cur_off != data_off) { + ret = nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + ret = sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + if (ret) + return ret; - if (data_off + ecc->size != oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size != oob_off) { + ret = nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1428,13 +1465,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 = 0; - if (data_off != *cur_off) - nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (data_off != *cur_off) { + ret = nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + ret = sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + if (ret) + return ret; - if (data_off + ecc->size != oob_off) - nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size != oob_off) { + ret = nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1460,27 +1505,35 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, return 0; } -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 = nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; + int ret; if (len <= 0) - return; + return 0; - if (!cur_off || *cur_off != offset) - nand_change_write_column_op(nand, offset + mtd->writesize, - NULL, 0, false); + if (!cur_off || *cur_off != offset) { + ret = nand_change_write_column_op(nand, offset + mtd->writesize, + NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + ret = sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + if (ret) + return ret; if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; + + return 0; } static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, @@ -1628,8 +1681,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand, } if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - &cur_off, page); + ret = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + &cur_off, page); out: sunxi_nfc_hw_ecc_disable(nand); @@ -1754,10 +1807,13 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, if (ret) return ret; - 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 = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + NULL, page); + if (ret) + return ret; + } return nand_prog_page_end_op(nand); From patchwork Fri Oct 16 03:45: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: 3636 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id E63A81C1CBB for ; Fri, 16 Oct 2026 05:46:44 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26684-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26684-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 53E406076DB for ; Fri, 16 Oct 2026 03:46:13 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4E2AC3B2FFB; Fri, 16 Oct 2026 03:45:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IIOQbFdP" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f48.google.com (mail-oo1-f48.google.com [209.85.161.48]) (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 AA2753B42CB for ; Fri, 16 Oct 2026 03:45:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122345; cv=none; b=VkQd2TMoCOdYfgdvKKuN7HMk5M9r7dWqCbGy9yy/SJEG5+r7AESpey48Hhi7hkk8/UTDhS8IdrLm5AaAxaVytNPkrPse0ymo73dF+E1BWT2VX76iL490lWxBiIexffP3vPZl63ecQQc4+y8oQr4KcZhexBEXoArWc7Q+X/E1hiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122345; c=relaxed/simple; bh=L/2f/9mfvoIW49CSofbEAEVCbPChwciqXDpasHFoGaA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TrBKaWFlPvH+hzeeOgve7CYpjXbR5bFCqF87jbdamHfbNWMpY2yrSHSyNmT0wQQscJ+YEuBPP/I/iPfUTRBiXFE+TaifESBbZ/GRrOylWZ2LCfOaMijVx3VGuBR4YX7COAyi9ruqziLvVsmuPT9193qts+LAsEXYQX5ftYTyeec= 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=IIOQbFdP; arc=none smtp.client-ip=209.85.161.48 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-oo1-f48.google.com with SMTP id 006d021491bc7-6dd7070699eso1929672eaf.3 for ; Thu, 15 Oct 2026 20:45:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122342; x=1792727142; 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=CSHtLPHY+Puvgtw6ujh03ffVT/c3YjQWJScgGpszE50=; b=IIOQbFdPPiBp5+ZmI4Uj+oi0zda+r+AAMIRlOH9qInWs5idpbIc9Za9i/pWg2VctiG FyHHkO9ndzQL+f7VgC5Tc7YSePDGd3Sj0DIJYULLJ5Ag2GDDUc5o0qHxWyp4NrNwZcwS 1gFirkLuDIDYb2CxNSr083+060Z+zHn9Kg2wcPsUdFmgFbMMKGcjoGqO9FWZTyPYrAA7 p3AKaGgeWvBeWTwo+aHzxt29+TPREDVyMTzvo0VXIr7ZJZK/Mz9ZSo2yIoyqVvk1TwnD 44O7UEPON2E9thSYVrp22sQlgRKJI74kN7uk3gxMSPlW4qKKCiYkQRoeXBJZC1ChvdVw blYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122342; x=1792727142; 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=CSHtLPHY+Puvgtw6ujh03ffVT/c3YjQWJScgGpszE50=; b=a0NUpdX/KKQtQ6phcR9FmC2YuxV9MzihvpkhANuGMWGmtQKNPxrCCKaHHfAbqTpKHF 3JA9VSt979mujjkBo7cgRb2ObF2ko7fXGrpTuPNMMOzft28JYNKYM7wyOJaWQEtSNWDu qDJBMQUFiAVvAjDTetBsGdEyAXNUZ/3sIgK/7bAtwEd4TTRRr3IZqvT9Y4G6u1rQFgC4 gEVoTTsAYcvNeWDSA/FAlvrz96E9eokDU96IbZBGmAahcvmhaYFQ9JU6bOELyubEanLk AltfOdN/dA7bNQ1Tnf/qzzeKpIQl5sLgbBA4kMRT7F7juQfn0+q86mDQyGrFhMFLRq3j k3sQ== X-Forwarded-Encrypted: i=1; AKwUvBzIGrBO/c5j43zkWE4xhsNcgQa4J0akudSY+Xadx7eJsDOGBvCrdF6MLsSKjgoMCUbRxGUU+UgHRWEJiA==@lists.linux.dev X-Gm-Message-State: AFq9FYK5VYm6DJtf1Ad/fWrSDOE6UrmEfkVPjcATk8rayZ8KFT/xHhA7 FjiwnWKqqD/RPmUvYXFd1V01Q+ytWd2bdfLEuAHfVGlP3kfpZFTnOzny X-Gm-Gg: AYBFou3fKm6DzWLhR+O8Ttdk47C9vLUB1YuB9yxyA8vTQTekC11ZvjB+AgYs4x/L98e H3YUoE2uy4cMtjPC38VeEH+OaAEQglVl1B1GS75yV9Pkj5UjayuVN5Wp4YdX7KgN1Vtf/yGiFm5 eXzTrIvWPx5dao6YGw9GhPdWJkqsIvwuwfOQ9fhZCaUW7St6IFXJV7hDuCHUuu426KxBJtbguog AVFDbinLcocXSxbJ7m4rnXZCxbvyHiiy9Z3RKwiZ9JTRjtaR1NwJdgEq4Htpp/5rYYWqZ8Pa1sP D6ena90P/wJ7RB5Y+EZxV+d+64ogWOtfLfnLLRkd5uWcmlaqqrmdSsTIYvIzqfICF1RquDy8aQ/ V3UX3aeXFSvfujJVFqzBb75BQnRCc29wmODEQrGTMRrd7ss0kWmNivGuXCKHRb4k9ql7jwXChkK tOJ6WJUZHDhtpKzfxfysP+HHEbvqlfvonvNLOw3BJajiXhhDaUuwVYDyEx7wgkVDsgS9gsDtP3s qm+YLiSRHIDDxess3uE+uFV8VJVGN9JpZQlfEoFY46Ne1c/NwT9XG1b9UrcegjB0SPiKUcKzAf1 QRSFJHrBEQDq3m66zMMm/v4aEkelp6FMxtrsGNTgiL2I2zSRTPwBrjqli7O3gxuWAUppOB1fYo+ fuMWPd4ZcWu423KWfdajVmhYC8DLunRG+ X-Received: by 2002:a05:6820:4c14:b0:6c8:fb02:527e with SMTP id 006d021491bc7-6ef102aa365mr15532787eaf.39.1792122342481; Thu, 15 Oct 2026 20:45:42 -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.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:41 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:24 -0600 Subject: [PATCH v8 09/17] mtd: rawnand: sunxi: avoid a second program confirm for OOB writes 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-9-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.232.135.74: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)[]; PRECEDENCE_BULK(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCPT_COUNT_TWELVE(0.00)[24]; TAGGED_RCPT(0.00)[dt]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received,209.85.161.48:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.232.135.74:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26684-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: E63A81C1CBB 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 OOB writer fills the main-data buffer with 0xff and calls the selected page writer to program it together with the requested OOB. Both the PIO and DMA page writers already finish with nand_prog_page_end_op(), which sends PAGEPROG, waits and checks NAND status. The OOB wrapper then calls that helper again, sending a second program confirm without another setup or data transfer. A failure of that extra command is returned even though the actual write has already succeeded. Return the page writer's result directly. It remains responsible for the single program confirm and status check, including on the bad-block-marker write path. Raw OOB writes use separate callbacks and are unchanged. 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 fcb017f048db..9f03ba22b4b7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1832,15 +1832,10 @@ static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page) { struct mtd_info *mtd = nand_to_mtd(nand); u8 *buf = nand_get_data_buf(nand); - int ret; memset(buf, 0xff, mtd->writesize); - ret = nand->ecc.write_page(nand, buf, 1, page); - if (ret) - return ret; - /* Send command to program the OOB data */ - return nand_prog_page_end_op(nand); + return nand->ecc.write_page(nand, buf, 1, page); } static const struct sunxi_nfc_timings sun4i_a10_nfc_timings = { From patchwork Fri Oct 16 03:45:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3642 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 DD1C31C288F for ; Fri, 16 Oct 2026 05:49:08 +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-26685-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-26685-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 9F2CD3D9A1 for ; Fri, 16 Oct 2026 03:46:20 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 64BBF3911B5; Fri, 16 Oct 2026 03:45:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R6mBbqrA" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.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 920E03B637F for ; Fri, 16 Oct 2026 03:45:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122347; cv=none; b=aUW5pnMpMaLcKaKvM1dZGdGw4pdcblcBIqOQC1oXwk6YXrvzrENdG4D1/I0MQQkbgGwV3+vp50IkoSDelXwqCw6GOmFAQf59/HXzSa7f6AwverDJO5GQjKVc9PUoSYjvTVACs6YApKPUieeXQn+O6trEpGp4uHCs2FhylmJ6yaM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122347; c=relaxed/simple; bh=44SdB/unSRPSVYBoHP4dv/wWCcEp8Mtv+c+krHUUX5E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jMSxV269GbEiHa2MBkCqDX43l3fe+PamoPMsqFKJ+LRk2bhPQ7jL2dbqnHtGloq3t0Dm/JV3oh7fgoELbcak+lMiaf62o1Du8/WMhIRjI6WtI2Hp+HEyxyh22n8vf67lJxQ5yrpt3cSlEDDbvtNoNqDDCpgsMLEnz4sGSeh3KGo= 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=R6mBbqrA; arc=none smtp.client-ip=209.85.210.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 Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-823545ce223so2086436a34.2 for ; Thu, 15 Oct 2026 20:45:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122344; x=1792727144; 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=5/V8rc4CjnNbzKk1bJzDBVlS/8f2AkkYVi/FGYi/KHc=; b=R6mBbqrA+ki/phn+ERLRF1M14VxiAhblKWLkGnDk6hjCU0Kzu6UduF32xbDtk4IHn+ zWjqolJyevnR6Q2opgpMQZqDnAeswrhg9SwLR42B4eHuXQgP5WQcu26gunZHf5a/GwlZ o98YXLqkyjnLC0Zv4LBoiALTKIiSBDnltvbLKXRLI0WqgLq3GB0ZPHlq7Cga7BedPWgo Jp6PIR8JXSBygGjTAnKMf1aMvW1qolRv/9TVwA+yZxztdKeT/wBqSDL4eWu23OBUvMOk VLQI1GGTp45vokQgFpQfXTkAOpDXVvMe/cYDmBEOZWkVOTinOnFEHwxTujnCZ2TdWqS4 763Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122344; x=1792727144; 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=5/V8rc4CjnNbzKk1bJzDBVlS/8f2AkkYVi/FGYi/KHc=; b=XN8mGgkP2RUJ8sq9mhgCoZpDCaBYPgglqOsyBMEMHqsmhz7Bkfk1ipkl/ePeRKk9nD cGYf3B+584egSoiyTnwZiHPeRIBaRa5ZAvZdufcx3zl1kXA5jsLIttGBhqf5WTgGVedj hSnUA3uMP2+OXz3z9gOYIVX4unvJ3dZ5IzaRzNsqvDZGtdJFTdPl1G+WvBxXF/ds+YLi n367bx4EFL0TuY1qBF7zKjqM6M1MfGGYwvq+qijwZUtv9xlLKokI93ZljFGj/+YC4paC agdRhobU6VHMdMnHQihgzIjXEjkTJyEEqN+NePKBg8eSoyQR/0EfAm1FN8zv3hz0Q5TV FsBA== X-Forwarded-Encrypted: i=1; AKwUvBwb9N0dAdmnL94Aw+7i6Cgw90liMes/7NPKtqRwuj6KP34acrRRSGcEYeHIwgPzVbjOKj40Xiws18CYMA==@lists.linux.dev X-Gm-Message-State: AFq9FYImtnS5JpatdpIfU8VJ7S98DlEfiOHLxTXlow1uGeHyxZGKJQvh ypcTMu2bQKP+o02yKrhnas9LZdT8PyH2y3CTU9WwjI9njVccg468ZYas X-Gm-Gg: AYBFou0Azo+txSE7Oh3ZJVcTveFIMd2rfoeSLi+oafi5VMlZc4bZhKwgkSdnZtVjzSp nPsYtVK7u7FIHSIQFEDfwYbi2WxC/pF4WDI2n0bX56kbUqiEJBAsHOGogOlnX8To8YHR80akRGs NtHG0Yx7ptq4s/kJoKcm4TbI8Gb8Mvbr+WFUQnu7YQhTmBGLWV7jgJnF36Snlt5l89uOvLl3Pje S7s95LSRH2cCUHl8jlCulu5D9rUqVPwkquEGICHS2IJTrMw6wTgKWSTxllRhzjxmcjVOCG+Ee2I D/65kQLA1qsqs0ELX0yPJW0kz+hNPXH2nkQIaPochf+nO9YwCSKrac1+mOYBzbjNV/slsNZXDJ3 VdYikFcrZRlOTnrLZgEqwdFFRfSN3IRwu60nOHelfDqlFpSLgY5lsZekrXS01atLMWI85T7rhsY T7oHH8zh9mA+4l4h7eeGclyWxubIcxhMH4jCZv2U3KIVSmsIkQhQm9OEf/mM+ZcwXJLP0PJwxl7 4BLvUpJQEl1OAQVU9Wona2j5D9yNM2vt6dgTBDr+Q0x602vVLBw8jX3aaQidlpLUaoyDYk2ojvl EErt5FRUzUgD4dQsQ8NvYZHEhkywWFnpApSD9SbwcvbsbExFjtsGqmi6DChoeVzAmZdPy+/EeJ4 iO4o9duMjPK3FVTluoV+Jjg== X-Received: by 2002:a05:6830:6816:b0:7fa:ac4f:79d with SMTP id 46e09a7af769-83097c62d97mr22209672a34.25.1792122344353; Thu, 15 Oct 2026 20:45:44 -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.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:43 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:25 -0600 Subject: [PATCH v8 10/17] mtd: rawnand: sunxi: use page reads to reposition small-page NAND 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-10-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.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]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[tor.lore.kernel.org:rdns,tor.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.105.96.0/20, country:SG]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received,209.85.210.50:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.105.105.114:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26685-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: DD1C31C288F 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 reader moves between main data and OOB, and rereads raw bytes when checking a possibly erased ECC step. It uses nand_change_read_column_op(), which sends large-page random-output commands and rejects NAND pages of 512 bytes or less. For a small-page geometry accepted by hardware-ECC setup, these reads therefore fail when they need to reposition, rather than using the small-page read commands. Add a read-column helper that uses nand_read_page_op() on small pages. The core selects READ0, READ1 or READOOB for the requested column and sends the row address again. Pass the page number through the erased-check path as well, and preserve errors from the resulting operation. Keep the existing random-column operation for larger pages. Select PIO for small pages even when DMA is available: the DMA PAGE_OP sequencer uses large-page random-column commands internally. This corrects read-side repositioning only; the write-column helper still rejects small pages. Software-ECC and raw callbacks are unchanged. This is a command-path correction found by inspection, not a claim that ordinary 512+16 NAND becomes supported. The existing controller-ECC limits still apply: it needs 512-byte ECC support and at least 28 parity bytes plus four user-data bytes, so 512+16 remains rejected. No small-page hardware validation is claimed. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 9f03ba22b4b7..34c1c5037b11 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1061,6 +1061,16 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } +static int sunxi_nfc_read_column(struct nand_chip *nand, int page, + unsigned int column, void *buf, unsigned int len) +{ + /* Small-page NAND needs a new READ0/READ1/READOOB and the page address. */ + if (nand_to_mtd(nand)->writesize <= 512) + return nand_read_page_op(nand, page, column, buf, len); + + return nand_change_read_column_op(nand, column, buf, len, false); +} + /* * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC * statistics updated in either case. Negative values report transport errors. @@ -1069,7 +1079,7 @@ 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) + unsigned int *max_bitflips, int page) { struct nand_ecc_ctrl *ecc = &nand->ecc; unsigned int oob_len = ecc->bytes + user_data_sz; @@ -1077,13 +1087,12 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, /* 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); + ret = sunxi_nfc_read_column(nand, page, data_off, data, ecc->size); if (ret) return ret; } - ret = nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + ret = sunxi_nfc_read_column(nand, page, oob_off, oob, oob_len); if (ret) return ret; @@ -1184,8 +1193,8 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, return 0; if (!cur_off || *cur_off != (offset + mtd->writesize)) { - ret = nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + ret = sunxi_nfc_read_column(nand, page, mtd->writesize + offset, + NULL, 0); if (ret) return ret; } @@ -1250,10 +1259,9 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ - ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, - read->dma ? oob : NULL, - read->dma ? ecc->bytes + user_data_sz : 0, - false); + ret = sunxi_nfc_read_column(nand, read->page, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0); if (ret) return ret; @@ -1289,7 +1297,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, ret = sunxi_nfc_hw_ecc_read_error(nand, read->buf + data_off, data_off, nand->oob_poi + oob_off, mtd->writesize + oob_off, user_data_sz, - &read->max_bitflips); + &read->max_bitflips, read->page); if (ret < 0) return ret; if (ret) @@ -1329,7 +1337,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, int ret; if (*cur_off != data_off) { - ret = nand_change_read_column_op(nand, data_off, NULL, 0, false); + ret = sunxi_nfc_read_column(nand, page, data_off, NULL, 0); if (ret) return ret; } @@ -1339,7 +1347,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, return ret; if (data_off + ecc->size != oob_off) { - ret = nand_change_read_column_op(nand, oob_off, NULL, 0, false); + ret = sunxi_nfc_read_column(nand, page, oob_off, NULL, 0); if (ret) return ret; } @@ -2312,7 +2320,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, ecc->write_oob = sunxi_nfc_hw_ecc_write_oob; mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops); - if (nfc->dmac || nfc->use_mdma) { + /* The DMA page sequencer uses large-page random-column commands. */ + if (mtd->writesize > 512 && (nfc->dmac || nfc->use_mdma)) { ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma; ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma; ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma; From patchwork Fri Oct 16 03:45:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3644 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 CECD71C1CBB for ; Fri, 16 Oct 2026 05:49:50 +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-26686-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-26686-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 29F5344091 for ; Fri, 16 Oct 2026 03:46:30 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E018C39792A; Fri, 16 Oct 2026 03:45:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZhyKiVBH" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (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 93A703B8BDA for ; Fri, 16 Oct 2026 03:45:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122349; cv=none; b=TzZr717ACk+2mqo6Uq4Wf5kuddC6iq94+jwOl/09bbaGLS44fTRYEnUEuIMkBgSYgVaajeZT3tl5AfMK88e9yt1SPXiPXDHURQnZbKfce2r5Js2AdCJDnGzYFs4vcCg/dSuRhoUVd3KeDzXzbSJ/KwFoLtsS0pDp2GCPGUpkwYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122349; c=relaxed/simple; bh=7IlRb7p3+mxoJYiFONd9hyYYAjrV4/WLWy/JUlReLeA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IeNmpWC+b1w2UsbUdJUAs9uXu/JDY6tYgMmz5o/V21mwEdGD7ll+eSU0XH6AtZT+wz3ONMp5dUiS37H5IL5mE6CC76SM+hSY4UKkv8fuzPBGNtFqD3iY5Z64H6qGOsXivXuwi8HV4Fdb74DdlWmtxL9rJpVO0aNRwnZ1XBjfZB4= 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=ZhyKiVBH; arc=none smtp.client-ip=209.85.210.46 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-f46.google.com with SMTP id 46e09a7af769-82478760557so2035352a34.3 for ; Thu, 15 Oct 2026 20:45:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122346; x=1792727146; 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=mIhYiFHKevI+TgLh8D6/Es11X0vbpNIS3dQbtC4YQf8=; b=ZhyKiVBHmEGJQciSC4TGXSxMdELm8qNMdYKjKSMKuH3KXKoShWJJhK6fmdgsSxWPFD 9pCITqNX4B7voKj1Lx1Yua+ijmmn/Nhtnk9950m7Ixjs2mLr02Gk3kW5DXMi01m1xC87 IDTLvCVXcBG4edS5+Fl/T+bBwgbNdFyyEZlJZY9H+OK+ZFPCblkCVZF2PFnc9wms4gWV xzBVWSSnMC2VtnaN4b5S9RnTupHFo0b3LDvcM1ZlDSO8GFDyAwyu3zGiF4BaQoaLglNq MMxX4pA44EB4j/XRKpLD9L/8PzE6fSlEMN/3Hp/nHUaSkaNwb1rEPOmz6tb1eAff1hNa UaaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122346; x=1792727146; 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=mIhYiFHKevI+TgLh8D6/Es11X0vbpNIS3dQbtC4YQf8=; b=v2W8syotu9XDlIRJrf5SmT1liJCZwss5TY6JcNEBqGo9bDqLzjKrrN4oUABrO5gxab ZzQBcZUeRW2zWXFOG+C6NslyQX9f6W+7m/v0nFhtyafvNsGVXVdgab1W9ye+DLBUvOt0 6PMt9bNfaxlhWdDC84LJQOoQovPV4UddpbMm8Dsut9IB6pM3Mb3r3FbpECtmLj3zCV63 iBWNpMokGay8ceh+gdK/zBTD2ZCpEQ6fJqFYrj996sR4afo5bo6SMW6Ni8FsGXTe4bu9 veKhPDBi0lY43KC2RgB5NImkkuNK0VF17/9KqNYCA0sP1rk3P4Olw8Fx4Xg28g8v7/pe HG0A== X-Forwarded-Encrypted: i=1; AKwUvBzB/IxlT4nxoFt089IV9dWJYGJDP1ypFbRs2vwRiJnROnhVdTA9wAZIn5r5yFDmdHHbpn4eYYFvgS5wIw==@lists.linux.dev X-Gm-Message-State: AFq9FYJxE8Y6Wg8AyYtVs1t7s5w6xtQ/PRcKBU21fC44Uk2PnydVGNeB lIReTeFMzVedDm1aP/YVuWgm2MKl2Y1/Ufn4A81F4qJTU/XLGUaiN6K6 X-Gm-Gg: AYBFou1ugHP0/YG1JkGc7farTcFvu/XouI3c5MLGP9Epf0enhjvirre0YX5x0AVmt7y WaylpS1w89UvzcjWWOB2UQw/By4FC5qyyz1gY8Tt1BKZ1X53NOIqGjlQSA4+GU1imi6xMnZ9LAm KMfB39xXANPo8G57pEMATIEJU2YT5DnCBWzWKZXCynLHgFx5cqeT+TbqtyBX6R+0tRYJNoXb3/m EVxpBm73o1IoGLMBJXrYZRJ0cw9Qp3JZKtiqMo/Q/ZAJzFOeLh6js+X7Lw/QrFhtSxWCaRWOc9u 0CQi1k3Oxtzf/qX1hSF2WTw8SWXOU/Uxt5CNjIKqlyTvnVGutdIWeumr4TuWtmxrXswrAN+O94D ri9LIvTqTGwMlSXCgKfFREVvIV6fLuDXoAkJlinrjfALXMZ4+rggqdzLqm48kG261SFa2DXE6dS fFh65qdRk0gTTS0SyVuSoL+YcL4bOz09VAzau3xJEnt4/tCv0shonbriAxS2Nc/KJwDdvU9C5ql Xlzpn6r87MI9qhtErbLoYLGXk71hqnakTLvDIzC0hvCuPwBglK8OZracWY2WGJ9qiGBIWM4DUOm jlVDm+1lB43XXEgil5LXVt0xpJKBRbChsLbFabEIikRocNMGSLRf4pCyQD2N124Mupz++WsbpGb DrHBOE0vIj3zCDcAJq79D/g== X-Received: by 2002:a05:6830:44a3:b0:806:e047:cd6e with SMTP id 46e09a7af769-83094e783b4mr18588745a34.8.1792122346290; Thu, 15 Oct 2026 20:45:46 -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.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:45 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:26 -0600 Subject: [PATCH v8 11/17] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank 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-11-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?= H6/H616 store ECC-protected OOB metadata, called user data, in 32 four-byte registers. The fields for successive ECC steps are concatenated in that 128-byte bank. However, the existing allocator fills the OOB space left after parity, allowing up to 32 user-data bytes per step without limiting the page total. A whole-page DMA transfer can exceed the bank. For example, 16 KiB main data plus 1280 OOB bytes with BCH40/1024 leaves 160 user-data bytes; with 1664 OOB bytes it allocates 512. Register accesses then extend beyond the user-data bank. PIO can handle these layouts because it reuses register zero for each step. Capping the page's allocation would instead move parity offsets on flash and break compatibility with pages written through PIO. Split DMA transfers without changing that allocation or the logical main-data and OOB offsets. Fill the first batch up to the 128-byte limit. Transfer each remaining step in a separate batch, using hardware slot and user-data register zero after explicitly selecting its main column and spare-area base. PAGE_OP generates later main-data columns from hardware slot numbers, not relative to the selected initial column. A multi-slot batch starting partway through a page would therefore revisit an earlier column. Single-slot later batches avoid those generated column changes. Pages that already fit keep one DMA batch. Program length fields from the batch's logical starting step, and consume its protected OOB and ECC status before reusing the registers. Keep erased state, correction counts and trailing OOB handling page-wide. On a failed DMA read, discard all partial statistics before the existing PIO retry. Use one page-read setup or program-begin for the whole page, and send program-end only after every batch and any trailing OOB succeed. A write may fall back to PIO only if DMA preparation fails before its first batch; never retry a write after part of the page has been transferred. Raw access and the OOB layout reported to MTD remain unchanged. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 202 ++++++++++++++++++++++++++------------ 1 file changed, 139 insertions(+), 63 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 34c1c5037b11..8d523dc43093 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 */ @@ -958,7 +959,36 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) return sunxi_nand->user_data_bytes[step]; } -/* PIO uses register zero; DMA concatenates user data within each transfer. */ +/* 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) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + unsigned int user_data_sz = 0; + int i; + + if (!nfc->caps->reg_user_data_len) + return end_step - first_step; + + /* + * PAGE_OP generates main-data columns from hardware slot zero, not + * from the initial column. Use only slot zero after the first batch, + * so the explicit column change selects each remaining logical step. + */ + if (first_step) + return 1; + + for (i = first_step; i < end_step; i++) { + user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); + if (user_data_sz > NFC_H6_USER_DATA_REGS * sizeof(u32)) + break; + } + + return i - first_step; +} + +/* 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, unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) @@ -1377,30 +1407,32 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, pattern_found, step, 1); } -static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, - int oob_required, int page, int nchunks) +static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + int first_step, int nchunks) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(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_read read = { - .buf = buf, - .page = page, - .oob_required = oob_required, - .dma = true, - }; - unsigned int corrected = mtd->ecc_stats.corrected; - unsigned int failed = mtd->ecc_stats.failed; struct scatterlist sg; + int page = read->page; int ret, i; u32 status, pattern_found, wait; + if (first_step) { + ret = sunxi_nfc_read_column(nand, page, first_step * ecc->size, + NULL, 0); + if (ret) + return ret; + } + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) return ret; - ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, + ret = sunxi_nfc_dma_op_prepare(nfc, read->buf + first_step * ecc->size, + ecc->size, nchunks, DMA_FROM_DEVICE, &sg); if (ret) return ret; @@ -1408,7 +1440,12 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, sunxi_nfc_hw_ecc_enable(nand); sunxi_nfc_reset_user_data_len(nfc); for (i = 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(nfc, + sunxi_nfc_user_data_sz(sunxi_nand, first_step + i), i); + /* 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); @@ -1440,10 +1477,32 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, 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); - ret = sunxi_nand->oob_ops->read_batch(nand, &read, status, pattern_found, - 0, nchunks); - if (ret) - goto err_stats; + + return sunxi_nand->oob_ops->read_batch(nand, read, status, pattern_found, + first_step, nchunks); +} + +static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, + int oob_required, int page, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct mtd_info *mtd = nand_to_mtd(nand); + struct sunxi_nfc_ecc_read read = { + .buf = buf, + .page = page, + .oob_required = oob_required, + .dma = true, + }; + unsigned int corrected = mtd->ecc_stats.corrected; + unsigned int failed = mtd->ecc_stats.failed; + int first_step, batch_steps, ret; + + for (first_step = 0; first_step < nchunks; first_step += batch_steps) { + batch_steps = sunxi_nfc_dma_batch_steps(nand, first_step, nchunks); + ret = sunxi_nfc_hw_ecc_read_batch_dma(nand, &read, first_step, batch_steps); + if (ret) + goto err_stats; + } ret = sunxi_nand->oob_ops->finish_read(nand, &read, NULL); if (ret < 0) @@ -1749,71 +1808,88 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct scatterlist sg; - unsigned int reg_index = 0; u32 wait; - int ret, i; + int first_step, batch_steps, ret, i; sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); - if (ret) - return ret; + for (first_step = 0; first_step < ecc->steps; first_step += batch_steps) { + unsigned int reg_index = 0; - ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, - DMA_TO_DEVICE, &sg); - if (ret) - goto pio_fallback; + batch_steps = sunxi_nfc_dma_batch_steps(nand, first_step, ecc->steps); + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); + if (ret) + return ret; - sunxi_nfc_reset_user_data_len(nfc); - for (i = 0; i < ecc->steps; i++) { - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - const u8 *oob = nand->oob_poi + oob_off; + ret = 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; + } - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, - user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); - reg_index += user_data_sz / 4; - } + sunxi_nfc_reset_user_data_len(nfc); + for (i = first_step; i < first_step + batch_steps; i++) { + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); + const u8 *oob = nand->oob_poi + oob_off; - ret = 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); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, i - first_step); + reg_index += user_data_sz / 4; + } - sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_randomizer_config(nand, page, false); - sunxi_nfc_randomizer_enable(nand); + if (first_step) + ret = nand_change_write_column_op(nand, first_step * ecc->size, + NULL, 0, false); + else + ret = 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; + } - 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_step), + 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); - wait = NFC_CMD_INT_FLAG; + writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG, + nfc->regs + NFC_REG_WCMD_SET); - if (nfc->use_mdma) - wait |= NFC_DMA_INT_FLAG; - else - dma_async_issue_pending(nfc->dmac); + wait = NFC_CMD_INT_FLAG; - writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | - NFC_DATA_TRANS | NFC_ACCESS_DIR, - nfc->regs + NFC_REG_CMD); + if (nfc->use_mdma) + wait |= NFC_DMA_INT_FLAG; + else + dma_async_issue_pending(nfc->dmac); - ret = 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); - sunxi_nfc_randomizer_disable(nand); - sunxi_nfc_hw_ecc_disable(nand); + ret = sunxi_nfc_wait_events(nfc, wait, false, 0); + if (ret) + sunxi_nfc_dma_op_abort(nfc); - sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + sunxi_nfc_randomizer_disable(nand); + sunxi_nfc_hw_ecc_disable(nand); - if (ret) - return ret; + sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg); + + if (ret) + return ret; + } if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) { /* TODO: use DMA to transfer extra OOB bytes ? */ 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, From patchwork Fri Oct 16 03:45:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3645 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 994FA1C1CBB for ; Fri, 16 Oct 2026 05:50:32 +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-26688-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-26688-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 5C31646081 for ; Fri, 16 Oct 2026 03:46:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F23B63AAF4C; 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="q1rEV7O1" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (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 4D3053BBA03 for ; Fri, 16 Oct 2026 03:45:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122352; cv=none; b=LvgMyMKL3H6GmKpsMyutnPqZBkkFwZ27Grx4Dg/bj9wjWSZVe2Shbco4N5izvCPi7g7vvDjEUtcmM3hiq79X7CDiHXa3hIrcK7R0uUYC8Rm+wPf4tUiMQuxMie0pCFZSghpkhT0X+1Xi/iXd8q2Innae2vVCrCjvIqKQN+l1ww0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122352; c=relaxed/simple; bh=8gBZUPMs/8ybH7J2DLSL0LxVyDkr8YFuS4UrXkubECQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jxXIpbFJ0GFBFEo5FrpETWzHQrUXpsC5TSK79uSpQO3ZfnAUf57fihJfrVfW4q7pog10WPc7hpKa8zMw3ko/7q774Z99IN/BpyP6QU7ep1GiIyGu4ZNqxkzgG0pWWqiEBoff5OLa1dSPDJElPSsqEjV/7jo8CiI94BRDcL46Ito= 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=q1rEV7O1; arc=none smtp.client-ip=209.85.210.42 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-f42.google.com with SMTP id 46e09a7af769-82478760557so2035368a34.3 for ; Thu, 15 Oct 2026 20:45:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122350; x=1792727150; 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=2rczNXeActkyUZxhNs2zIIuhfq4VixMAxBK569RVDfs=; b=q1rEV7O18FTX1+tmSMSsXMF4Z+oe63gjeMUJNnyq3pK3dOMpjmCRDUvs1DGQA4jyb4 yjjQuNapGEhPQPoDYjHvlQ11pILFOdw7vRcBn+vieu0BSMYcwPurhZpglCeaFv+vysPz oiIlc/Bda53wm96aL++zmlxguUS4y4r93qhLHUVDZHfTx8aVGcwbRsq0xIzmNhOApH0p Wtn/Q6IYBFTCaMuUzlOI/bQqXHz7LRoMVg0JZmrhsn9Yyp1fhdTIfTkwxnhIA4QBSQV9 NYDz4MF/fY3VjMlTaG9vTyeroW2rop1L5xvRgJOvZWceM/yYxhKUW1MXMkabJDlgc3Nb 3R/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122350; x=1792727150; 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=2rczNXeActkyUZxhNs2zIIuhfq4VixMAxBK569RVDfs=; b=Q8oREaylQCvoQeki5VcgC6rKFIfLOWiGtqXj9moYviL5CBXm+mDVjfwDHUCXJcAPeU vwHSjkyWC4zIOEET4vs7l/YBzxqWL0Sciw8Yu/i6wk0Ykv5Hha9UMmjNyS02ElBOkuKL /NcohaaFLMdrON3MFeXZl2Nvzd9u7LC7jE5R4wmvf80IZKBTo55ZILRVUHGUCUp3IGZh OsRCS3+RsXJ8sydEJvRmCRNKtTS8e4p4NrfUMlvJ4ri3NQ/+bogvAAtIFeTknPXpKEEO 1DFZ3jIjCfTQLKBenluqOztWkkhdlshM4idZ1Pc6jW1xB3e36p1MJIfxKfEfKV3AbIoc Bx6w== X-Forwarded-Encrypted: i=1; AKwUvBzKsCt8IlpnfUm0t/geUrh5VwnFfoqqYQNKtVxpNawC4mQWFj/drNkhviHKGBjFj0bTi5e2tMk4PIpbfQ==@lists.linux.dev X-Gm-Message-State: AFq9FYJcx3y0xDvxBLoI/r9d5cg8lt52BbYept3mcGx/R611LdN1BIN7 WySFoaukGGBbaY/nyhBkvheK6QX3aVofqM+vQlmMT+CopyH6DyajYdHop381yp+P X-Gm-Gg: AYBFou0CkUBEc5kiBwnGrEpAh5qMAwAzCfURKpW8EqRh0H5M/kq1kOjqFxhilMQDB47 SkUPI0zu3x36djAEJ6pzozBtxi/81pgRiunc2+hyY/+H9beE5u1JYrgHghHfwgdm7YlSpWolR5P VMIsmZ2R5cG8cJT61F/VQ48w/CWuk5p/sMRtiDPPQOL7bncNMFuFtmd8H2dsLDnKk21DALNA84q Mv9aN9+P4Rss2D9dA085U1CqLKszYVe5ON4xn0aK+qUw8z22iW89QCgjnlKSouRaCWqnIhReWis 7Rm6Lfuur02ChnXoEo6uJvkjtxyn6sAuGM7mwQUPIq/yYVLbCv+YJLN7bvltm2y7cRSFi3mShBM a+esG8N8FsAUdtYkAkVv0gfCjS7T2Zn/Ece42smU2R6qQjocNTSFDcQ+/eRRl//DE9NwpTUQTnx RRGPKxh+27A/JtYJRj+RiiTNLwakcTUm7Sn8RrVWXI09YuV/uJZzPdRdzyvL1JYlTv2oIL6OI5q voIsZd37vpHFovHGlHWxbO6eYWg3iVhNVe2Q2+x5K3FFEDnrZlDBWFEWeaKsIbgvlAmiRPr1/Z8 BS8TUyP7lgFvmR6P1jw2pCEo8E/SWSU/QsyGIDf3xGibyoPl4okNUS8m/d+CsU1EvlN/kcIs0E/ IiSbrV1niOeP2N/h98Na/Uw== X-Received: by 2002:a05:6830:640d:b0:804:ca33:4aff with SMTP id 46e09a7af769-83094e783f6mr19887903a34.9.1792122350229; Thu, 15 Oct 2026 20:45:50 -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.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:49 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:28 -0600 Subject: [PATCH v8 13/17] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB 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-13-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.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]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[tor.lore.kernel.org:rdns,tor.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.105.96.0/20, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,209.85.210.42:received,100.90.174.1:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.105.105.114:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26688-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 994FA1C1CBB 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?= Extra OOB is the spare-area tail after the last ECC step's protected user data and parity. The PIO write loop tracks cur_off as an absolute NAND column, starting at zero in the main-data area. The extra-OOB helper instead compares it with an offset relative to the OOB start. It therefore requests a column change even when the last step has already reached the tail. Add mtd->writesize to the comparison, as the read helper already does. The comparison and the column-change command then refer to the same byte. Keep the command when the cursor differs or is unknown, including the DMA path, which passes no cursor. No transferred data or OOB layout changes. 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 105374e93b37..dfb2a64c6b50 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1620,7 +1620,7 @@ static int sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, if (len <= 0) return 0; - if (!cur_off || *cur_off != offset) { + if (!cur_off || *cur_off != (offset + mtd->writesize)) { ret = nand_change_write_column_op(nand, offset + mtd->writesize, NULL, 0, false); if (ret) From patchwork Fri Oct 16 03:45:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3646 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 0931B1C1CBB for ; Fri, 16 Oct 2026 05:51:11 +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-26689-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-26689-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 4DF9A3EC40 for ; Fri, 16 Oct 2026 03:46:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EB7653955EC; Fri, 16 Oct 2026 03:45:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jmygGpa9" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.47]) (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 430B33BCD26 for ; Fri, 16 Oct 2026 03:45:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122355; cv=none; b=fm2dZxHJIFQYCbFMvveatBxADqT/GIyDvdpPcQXzKJ52x7MOY45yXeNv9y2SpYqqDXuWjxIKb5N0vMLadgSbvcgBYKSp9sTRYbB5EB3oJAmMp1ENh4VV9bobvn2kQMYj8Rd2hoocbP+8kNeymrLxtYzTMLtIKjf1IezhoDY5n78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122355; c=relaxed/simple; bh=yG1at5m5QJbhW+ecohWXOpUrfbsO1PE/mD8DPJcdLP0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bo3rNGc2YNh+nkLjJElheqR3RuiYM98RbxNkkZtjKUk+0d+MSCwOBQOh4FL2Uyp8pldDAcz+TfXnZWdpx2xHNRuLwESbicT5CPvY0Pm6nLsFkByq1FmKaem0MdSKCDL5dyELilLjgFxCSrDbR/GEDOCBvOTjL/jCFP1Ll6BpKLM= 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=jmygGpa9; arc=none smtp.client-ip=209.85.210.47 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-f47.google.com with SMTP id 46e09a7af769-8198a3a54d7so687037a34.1 for ; Thu, 15 Oct 2026 20:45:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122352; x=1792727152; 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=VzQcb2tw5a4i/pk86YXUJlRkyNKtc4irBMv9ftSpeS8=; b=jmygGpa9ZSkRkiiMg+XpiPbFtT5Ota/rQHbh9tcsKz9/1846kdjGm2vzxaUglQ3qbz VRxg6sKo/oas3O9ckZZSIRNY8Ffo+poydTYt/9gRqyDgZ5HknS8CwpWlBjSKY2cZlUa1 W6x072UvOddfwfwCgLz79NO4Rm93bIOtSmm8wW2egFWbt+Gy7Ll7RWPYjWWnmnVJD0x9 jXzUsJl7v2Z2IrR3CltHHtbUasRKHteLpgM3W49EtjCTs5E/1w58kWreWbdWwriblRKc hEgdCJChbC1rNzWAbbKZikdSzOfrbmp0J3GvCmAC9zvSrGUNDAvXK0FkmYESOHUGiQnF ui/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122352; x=1792727152; 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=VzQcb2tw5a4i/pk86YXUJlRkyNKtc4irBMv9ftSpeS8=; b=lhhCh/2aDvCehwBoQEuqqGd0/uHWBvOTjTaaUigsus0XaENcrRQr3pdpUqRn1ZQDmT Rmqzlxxd240F4MPiV5LOOJW4/UZ4RFL9JDav4XZMtvazXkj7rNDuqSPctvRxYDbycju9 dlUuxWABPJo/9jlK2ai6vMfqCLZVxWmIeQSDM8H/dewcA5ZI+Nqgm1oN11TMSWTxDpuN OeiisO3xpLVXXfNSu4IpvB/Xw5Pxy4lAY85Lo36TEoMIQSJchEt1ILx69tVnmlXk7WkN Jd6+ISWm7r45SD9p4HgH4QiFrll205UwBXA8VF1lI0NkNqOJij8sriImlP8FJhVNFKW+ +70w== X-Forwarded-Encrypted: i=1; AKwUvBx/IwaQE66rdJIPWI5dj/tzEL1SQlvbCu7W4oWDwhpzGga7L5JFDbd73QEu3GYtqgC08Qssn9DIX0zKZQ==@lists.linux.dev X-Gm-Message-State: AFq9FYK4fQx2iVSAn2hG60aWi3E21gUfFLXu9Sg+WszUwV/Y1M7nedGX EuPEDJ1RhoLETRqiqmGv+ZeII3frB4r/ty8uV6yk40ycXoALsdvYVdks X-Gm-Gg: AYBFou0wqXkC27Am9NZ9E9vEVva7iJ+mqhKpdl7Wp0/sPl9uG0J985QrtmbxCbzlJXW xlVwic+Nrn1w4dq73QCEDFDP0WBm9jUsudWo4X7zzEGY6a3jz1EUOzxAU1jQu73eacxNOi/YExr ZDsBtNhRpXTfyMMuE/UvcVnB+tKxCpItL/X2yMtt+hToL2hZM5B/M1mJ3t5W9Yxsm6RX1zd1wXv 8dBwiRdProS+LYbjk1oYpOqijWBf8ifEDZoGNiLbyBjeH+Uut2f3xbx1xUVcSMvEFMpcpNAzPZ2 +ZblUbaPrQHPPgi2DvwT/PnN8ibtGGSzXPgEBl8vAORSq0+HS95JMMR5BfvOrw7By9t1lLvt/yP pxuo4CMckTi1PzK5RqD46pBYOfBYmiSE7zBwTpeDunS6kjiJLL/1FaaXuAyBvw8moGUT15eyeXQ 4p5Ajq4ENVXdib8F/uyaWGXb9arvYfDJA0rJxC1C9T0B8Jclteq5IieBxAifnzzyMVpfFSauUhT FZxwKsVfCqd0ziOHaud/TVgwBmo+jTKEOaLDoez0BgpIvS3phbmgiOdQlDNexonVmW3WgbE8G3Y 13CSYpJWDbioX3i2Z+QsDXfvKjAfSiSzjZHhUJnqFm0Bg8ZF/Qzyjs4IH0/d/AhIzVr00fVcIyq OpFJbo30ofmOh2pgpmy4tDA== X-Received: by 2002:a9d:6241:0:b0:843:39a0:7a8e with SMTP id 46e09a7af769-84339a08521mr158641a34.21.1792122352163; Thu, 15 Oct 2026 20:45:52 -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.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:51 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:29 -0600 Subject: [PATCH v8 14/17] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands 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-14-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?= sunxi_nfc_select_chip() programs chip selection, timing and the spare-area base. The page-read callbacks and PIO page/subpage writers call it directly, then immediately call nand_read_page_op() or nand_prog_page_begin_op(). Those helpers dispatch through sunxi_nfc_exec_op(), which performs the same selection before executing the command. No controller access between the two selections needs the first one. Remove the duplicate calls from those callbacks. Keep selection in the DMA writer: it accesses registers and prepares DMA before program-begin, so it cannot rely on the later exec_op() call. This removes redundant setup only; selection still runs for each executed operation, with no new cached state to invalidate after resets or chip switches. 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 dfb2a64c6b50..2a9fe89b1ba5 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1650,8 +1650,6 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, }; int ret, i, cur_off = 0; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1677,8 +1675,6 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, { int ret; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1704,8 +1700,6 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, }; int ret, i, cur_off = 0; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1734,8 +1728,6 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); int ret; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1759,8 +1751,6 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand, struct nand_ecc_ctrl *ecc = &nand->ecc; int ret = 0, i, cur_off = 0; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1804,8 +1794,6 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand, struct nand_ecc_ctrl *ecc = &nand->ecc; int ret = 0, i, cur_off = 0; - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret = nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; From patchwork Fri Oct 16 03:45:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3643 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 E614E1C2044 for ; Fri, 16 Oct 2026 05:49:21 +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-26690-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-26690-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 344F12752E for ; Fri, 16 Oct 2026 03:46:58 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9FFC73C1F46; Fri, 16 Oct 2026 03:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kpu2qcJ7" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (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 3C4E93BED71 for ; Fri, 16 Oct 2026 03:45:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122357; cv=none; b=epb9hNPs4sFcb+qJ5vIqVdKePtBQSi9QtzERclId3dgohtbW1/RlvgAQETlnuT+IhDy5NFZjeGsMmq47aKoDC103cXlvHwbw26dsyrAgxxBRgTivn6fbP+s7NtTKbcVPB8+8TgaFmo9/f1bPA8wJsJjsb0vrTgWP3BCo6pXgCVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122357; c=relaxed/simple; bh=3PLYNRG+R1vcn+zst5EafJtg8zZpSNmVtMEe2/zmAwI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E8j4Hrn97+ihIiQWCUYzDQVwM1s7gZTXWxgkp9WY7j2Gbc3Xf6gUmHiAHf30FIEZswn2Naf1ZEA0dM9KFZGV+oKj5C1SIzpSVMxl3/CPS2lB/q3FtYkW8MIe5r5QewJH6DXUTX++WcWPjfVs8UmxOBY2EnYDYC578ksidguLAKk= 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=kpu2qcJ7; arc=none smtp.client-ip=209.85.210.51 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-f51.google.com with SMTP id 46e09a7af769-83bbcfba0ffso2130316a34.0 for ; Thu, 15 Oct 2026 20:45:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122354; x=1792727154; 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=zAN0y/NlYSkso/Y1xGAc/UgZ/A9idw6Kq1nSbL1jYtY=; b=kpu2qcJ7zs3G//7gHhLd9Z84/CCgQ7Nrl0gWxMttbqmPAl60iqHjMv7OWca7sR+mLr aG7YbmFUeQaKwpN+YhiniXYetFnpZ1hV/ZoKRgCgczIRJM+rtpVaayUDDH95bclCvKND gBvakgDe4vVfoC9XkCVsbKxIwVPCh0zBAEhqkV17AfL9M2g3frtB79tkczZabzPpFfoj 32vR4Fkme+MCqruDOvjCFfGERUI2uj727QXmdhvCRNkeBLwUJNGZH0udGcDbn/ItuOuF e2yfrjVeSFgXIX1PZhgXDa5CK4bUlrzUrsatrWohQelhYdPzjF1pGkt+JYwTEt5KGAU1 gAjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122354; x=1792727154; 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=zAN0y/NlYSkso/Y1xGAc/UgZ/A9idw6Kq1nSbL1jYtY=; b=q1LO7tHrGJvDU9JJ66K/Dri0kd27FEGSr2owXvvrYz0Xo0WqfiDNCqW1mLZ4nYAx2h 0+7o/PrDFY8gFXtVZP/x0+X/jlY8GplxrxC+NZMLFY7aH86SxjsuVAzEvkdmn/BRiKOl r1GChCeI5fA5zGO0Rj3NKrGhtrcB7ptz+Upad7DkEYtMkQs0qgDQmq2C3lkNPa5eCOVR cUm2/XfZtTJxMBfejxGN2iO4maKBJ4T1x3HHt4qtL63muEtCtR0uxW0eB7yyCRJjAOB2 xLpuUw2/ZeJbgFkurYDuZKFvTuoIC1Fwh/tGaZzX6SbMzUEUfqJQhYKzs9pvF0uK8lOe bguQ== X-Forwarded-Encrypted: i=1; AKwUvByj34w0ETzCeGiDj0qIXwT8C1JCyWUgD3oHcVzgdey0gUMP/yGdDafwk2SfOdDCXl/ipHV040rNNMc69w==@lists.linux.dev X-Gm-Message-State: AFq9FYJr+nwH7MGF6eo3kU67336XpSJ6Bsm+nMXIQX+aRhGlkACQ42bF QnO0RYCSEPSSAq4J1frfB9pWGwwQtsqW/vMbym/Pe5wKXlWfuPh/3qN/ X-Gm-Gg: AYBFou3jI5cEEaEqilGyJ3KkLYdwqxD8EULv7Rcb0BRZkTBF+e65WL7seUDBqGCnI9H KViE3njg6TIr+9AVsiNPiODFdrHYy/qhtvMV3XuY0wAUCyyCnolVf1fxdR5LLW4IUrHxJiJ6TTA 21FjrZvVnmo5KR0F8B8jxa1pyCJwUUrKgl3fk4U8j8tjCg2azStbYbBXt9dqHnEXS4FuOe1+xnq 8dOEuSi6+tUi25KP8bCVBf3Uz9gKZA8iV+F0X9L87L8r1OZo+XbIg2ywp7JSxXBjmk2yxlxUUnZ na57cRgTNqujJnWbJ1sjRnT+/Wlz7YSCvGx5tEXnPwbEOmB8CvjITqAdK/baKVUd96TXysCkYcW IWt1XDPNcoDYoSC8IfWoU7hmNDQVEzoaPC+KMeI13STGxG5YzkOCC/5EUlhI0NRi91ezIYJW0D/ YsqK2VriP7u9sJaU5WWzdg4aF8C3sLLJF+pm+LoYgsz9O+2RMVm1DSnZGcyu9kgYuVuyDTyvFaN 97fRv3M733HyBNpZtJuXtB/QrQfF/iG8CZTzGIXym0R9ety71a0E67YLqBCtevixGahGWlSqG9i wlCxZP1DAVrRYSANV7ib1SattRdUA3WLbVXRjpJ42NWYm6iMy0xFE1iQo7tVsiPW3FPno5yGAwm DiQpp4xsTov3ijFqTXKF2S+dNnBUtzHgR X-Received: by 2002:a05:6830:4c0a:b0:80a:b8da:2792 with SMTP id 46e09a7af769-83094e783camr22214084a34.6.1792122354047; Thu, 15 Oct 2026 20:45:54 -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.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:53 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:30 -0600 Subject: [PATCH v8 15/17] mtd: rawnand: sunxi: reduce user-data length register accesses 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-15-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?= H6/H616 pack eight ECC steps' user-data length codes into each 32-bit register. DMA currently clears all these registers, then read-modify-writes one field per step, repeatedly accessing the same words. Code zero means no user data; the other codes select lengths from the controller's table. Build each packed value in memory and write it once per DMA batch, including zeros for unused slots. Take each length from the batch's logical step but encode it in the corresponding batch-local hardware slot. Rewrite every register on each batch rather than caching values across resets or changes of chip. Share the encoding with a PIO setter. PIO always uses hardware slot zero, and its page callbacks clear all length registers before the chunk loop. It can therefore write the slot-zero code directly, without a read-modify-write. Keep the page-level clearing so unused slots are also cleared after a DMA-to-PIO fallback. Older controllers without length registers remain unaffected, and the chosen lengths and on-flash layout do not change. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 79 +++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 2a9fe89b1ba5..56594bb41193 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -57,7 +57,7 @@ #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 */ +/* Each USER_DATA_LEN register holds eight 4-bit ECC-step user-data length codes. */ #define NFC_REG_USER_DATA_LEN_CAPACITY 8 #define NFC_REG_USER_DATA_LEN(nfc, step) \ (nfc->caps->reg_user_data_len + \ @@ -1025,35 +1025,60 @@ static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc) writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i)); } -static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int step) +static int sunxi_nfc_user_data_len_code(struct sunxi_nfc *nfc, int len) { - bool found = false; - u32 val; int i; + for (i = 0; i < nfc->caps->nuser_data_tab; i++) { + if (len == 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; - for (i = 0; i < nfc->caps->nuser_data_tab; i++) { - if (len == nfc->caps->user_data_len_tab[i]) { - found = true; - break; - } - } - - if (!found) { - dev_warn(nfc->dev, - "Unsupported length for user data reg: %d\n", len); + code = sunxi_nfc_user_data_len_code(nfc, len); + if (code < 0) return; - } - val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, 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 first_step, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + int first, step, len, code; + u32 val; + + if (!nfc->caps->reg_user_data_len) + return; - val &= ~NFC_USER_DATA_LEN_MSK(step); - val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + /* Write each packed register once, including zeroes for unused slots. */ + for (first = 0; first < nfc->caps->max_ecc_steps; + first += NFC_REG_USER_DATA_LEN_CAPACITY) { + val = 0; + for (step = first; step < nchunks && + step < first + NFC_REG_USER_DATA_LEN_CAPACITY; step++) { + len = sunxi_nfc_user_data_sz(sunxi_nand, first_step + step); + code = sunxi_nfc_user_data_len_code(nfc, len); + if (code >= 0) + val |= field_prep(NFC_USER_DATA_LEN_MSK(step), code); + } + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, first)); + } } static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, @@ -1425,7 +1450,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, if (ret) return ret; - sunxi_nfc_set_user_data_len(nfc, user_data_sz, 0); + 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, @@ -1454,7 +1479,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, struct sunxi_nfc_ecc_snapshot snapshot; struct scatterlist sg; int page = read->page; - int ret, i; + int ret; u32 wait; if (first_step) { @@ -1475,10 +1500,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, return ret; sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_reset_user_data_len(nfc); - for (i = 0; i < nchunks; i++) - sunxi_nfc_set_user_data_len(nfc, - sunxi_nfc_user_data_sz(sunxi_nand, first_step + i), i); + 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), @@ -1588,7 +1610,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *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_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page, user_data_sz); @@ -1855,7 +1877,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, goto pio_fallback; } - sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len_dma(nand, first_step, batch_steps); for (i = first_step; i < first_step + batch_steps; i++) { unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); @@ -1863,7 +1885,6 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i - first_step); reg_index += user_data_sz / 4; } From patchwork Fri Oct 16 03:45:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3647 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 5DA621C1CBB for ; Fri, 16 Oct 2026 05:51:39 +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-26691-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-26691-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 A81A04778A for ; Fri, 16 Oct 2026 03:47:05 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 39B822F8EA3; Fri, 16 Oct 2026 03:45:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IY47efxw" 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 268EF3C141F for ; Fri, 16 Oct 2026 03:45:57 +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=1792122359; cv=none; b=VwUhpbyMOODZOldsMJpj6Lb9e740MvXjRF8mbscFdEClNwRMbtmNYSBFOiU5nXiW6TSWh99k4J6j+o5wWuOPlxDKL4VM2oxVaIBNeEUMtIj1wmszvFxhFVm4WAgZ9nUQ/ETBK4/FA2KUhnCcOSgNdhGaZFoU1dCy5i2gXWA5CGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122359; c=relaxed/simple; bh=A1STkpE9307vxyyhV24//arWM0j0kn3Imh1Mn5JF96w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gqfIwGv/bFr6E1c3iKlWJvLnh4AQbRXoqf10ZOxVyOcF/8WUgN2ksF3HNcNpm6CeQf9ePIp/V1Eh/wKP2dW05rJmJ2iy6IxNChBFyNwEog3k6TzfZvV1k1HqlUKoOX/Ke26u6oAc3pRTHgzdx3PLpBnczkcwxCmoJok6Hm9oNko= 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=IY47efxw; 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-823545ce223so2086521a34.2 for ; Thu, 15 Oct 2026 20:45:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122356; x=1792727156; 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=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=IY47efxw6C8gpgDCpgFccRWBDTQlMNr38cfMAT6BruIjwUAyXvzkZBe42Y+VLmkL1c fg3GKq1EExtmxqmk8Z8fBcEkTfhCfwDqYra+HSappc4pLyT6+G3zT9HLNhyoqI2JQwNv UCklANqMvk/bzS53wxGhWBKzIM/FUFhwNku5tcc7lIUaBuSR5ielUTUXFV4a5HUWUOrR UOOoSNTUUx9SI/yZHLqe5xhEcet5qrjhhFdvo7IQlXv0Kifmu2dCj2ZuwaKYLyuZDYEX Q0xbBeuGdmjnx1kh3fcRDrOtfpW36pK76pjkOwzoAhbP5mwvsauF7xkLGRL0DeBLUajc Zvzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122356; x=1792727156; 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=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=mRk5pLo8KO/diyr4hhs6uo+3Nhwx0gyVU38wH+uIrcc5kLrMUWx9Z3KeoHzvqylf0c LFlel5soFq+yxkWcnopy+VkKCE+ZDB59yrDVQxNVUJyoGpGtF0JSNaneJcwgqGY/j7mr y4Xhz8HTHAlgQoV/3k3yUNNqjDxucP9b26gzhYM4OsjB0OJmeASLpD0oBGmuF0PrNg/q JvI0KSTEHKbwASJrF23IEkNWiBxi6ne4M0OsIZSndXdnThNKULDGIBkvknMVJtnceI3v HpxDoF+IdHfPhGJqlNhjjEwVuh2X0RmpL6hZ9XxWEteI+igoaWLaUfsgLmAy43vqfyfx QXOg== X-Forwarded-Encrypted: i=1; AKwUvBz138nRWMOxqUgWD63Tw61y3LiAulQZK4W43YBlp5cjKROyc1X7pwtwLNbORejB9nVTZtGv6BIWoVGhrw==@lists.linux.dev X-Gm-Message-State: AFq9FYJAlVtAOtEnXb4xwWYQnaOEfelQucdaHVX88rji78ENVZV8oZt7 Zy67yEIoqCW8p+kC14r7vvZZY3qgpUKW7qz6dRrJYYoJm6XWnz3xv2I/ X-Gm-Gg: AYBFou0Nxu8BMKEoemQ3mGfeIavppYlUkhRUGO5SsF9CgFJUT5xQaRsYgMJ3lbk6QR9 TukYmVIFp/6Rz9LXVTB2tHXKBN+TcqAZJ8StHyf7ZQZC5j8Dmvh7UQQvMnLi//Xp0gc9EcAL1qL DozFZeAf6oEFdUv4jrQ8v8Vpn+hK2nJyZKel8F9K2/Ng9FG8LnVD19cd44gVTrKe4Fk1pueFPnY CAYRyHOH8A0Ryr9tgT7+O9fyMwThgKEYxaDBmpqU2+uAm9jaFwlf1YUGAsgqXTD0BTcaofTYn/w cQ77puyXjfujvOhGSWEpiUIQc8xQgEIbnymjT9bu3UbTDszVEkpfFByrOpjJ6e/GCWl0wMJoLx0 prVAsTvVN4T7VVNeht4KoBCDM/4o/ad8NNOaHo0ZRVQTmjFIygj3mq+EpiURPXpc/OOsYTQRFvt 8v6zPryv+LEFxNxCiuBYWvoi4+68vktY0zR+NVSluE2uXizWEnlWPGhRLc1rJaDY9y2WvF2mKZS JGjEWj7GdbuWp6PFmPCAx5rv8PuHzmgEG1J4fJmSsLHOw6qm5zdahpTxVZ1iNtieO3Q5s03KB9X DlOpjOYPSM6tVO3G2bmeJpdxPad6yniT4gQxAa8SpJMHjgZ5drLeFZtaiMG3zVXEArViFmJEUKH z3oVM/uREqPm6vqRYxGz3Dg== X-Received: by 2002:a05:6830:43a0:b0:81c:4784:a5e2 with SMTP id 46e09a7af769-83094e738d8mr20216845a34.6.1792122356017; Thu, 15 Oct 2026 20:45:56 -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.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:55 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:31 -0600 Subject: [PATCH v8 16/17] dt-bindings: mtd: sunxi: Add randomized OOB flag 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-16-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 , Conor Dooley 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?= Allwinner NAND firmware writes the bad-block marker as part of the controller's randomizer stream. The mainline driver compensates those two bytes so that the physical marker instead remains plain, even when the rest of the page is scrambled. On H6/H616, the firmware also places a fixed amount of ECC-protected user data before the first parity region, whereas mainline distributes available OOB space among the ECC steps. Add an opt-in property selecting that firmware page format for the configured controller hardware-ECC geometry. It identifies how existing flash contents must be interpreted, rather than changing the format of all NAND attached to a controller compatible. Without it, retain the mainline marker representation and protected-OOB placement. The property applies to normal ECC transfers. Raw operations still bypass ECC and randomization and expose physical main and OOB bytes, including the physical randomized marker. Acked-by: Conor Dooley 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 + 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 remains + in its data stream instead of being compensated to stay plain on + flash, and protected user data uses the controller-specific placement + expected by the firmware. + unevaluatedProperties: false required: From patchwork Fri Oct 16 03:45:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3641 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id B0BF31C1CBB for ; Fri, 16 Oct 2026 05:48:47 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26692-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26692-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 32D0F6080DA for ; Fri, 16 Oct 2026 03:47:31 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 33EA63B27D3; Fri, 16 Oct 2026 03:46:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="o3RBZG21" X-Original-To: linux-sunxi@lists.linux.dev 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 482723C417E for ; Fri, 16 Oct 2026 03:45:59 +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=1792122362; cv=none; b=OycNj6wbi3dyYy9aO+pB3KICjNXMQeKEu2F4/RYSJJ1bY34hPkvZEybQ/egWbSC82WEqbWxvgmgtDSKj4cSbEJHVBWx4WeAHk6bwZeE/GFbKHpG9uKTn/vYUb19eCQGrWF7hJnx4i9vX7p8wd/56BJHHPmtwfJBfpVrv2G922DM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122362; c=relaxed/simple; bh=pp/7egmqL+3cGtYqJnr9xv+dPjdJAkMPSG5BNPLG7Zg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z5qbL/xCL6jj/wAzCNnONAmHfHN6C/emkDdkrExEwJoCaW6AIQsSRoBEFno/tuhmKRK0Du06+Wm4+G0SuhbdvrgCeV/Zv4Hs0KSKtPBCpDaltOsh02qJXVATX5SIa8KYLJrtyV+POagjNWZjyCF4euDsuaJZgH/2GG4K7/E9Rc4= 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=o3RBZG21; 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 Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-82478760557so2035429a34.3 for ; Thu, 15 Oct 2026 20:45:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122358; x=1792727158; 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=QbSWlHvRSkwrntnAwnz2EiQPWPQUyhRA77LwoZKqBYc=; b=o3RBZG21oygWV8U8ljbVKynneLLpMhyqTnueXxqQehcTe43aaNHKsdz80rdxMhamfQ Zdkg1EGInSdFplla6FXzmOPk1ovUkNgmJemA2qnLjEbyoRCnK64pqMdo53aLRAyte4TN /nk5wuNSHoemJS3eXWX/z6X6WCC9jWwPpKIPVG1gDhh/T3eEj5HboBs3wPAiYpowST9C qA3IVtJI5K0TzMXc+xlbaVhdn0RYIYOcSatGSqmOVg/x/wsOpIBxU9Srg5jhnzQlTy8U npVZ/mI8pMb20i92hCSNw/OxWWbjfzIE28N32hBDT3j/UiYV+OZe2C/G2RrFzP8nHQwG Xa1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122358; x=1792727158; 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=QbSWlHvRSkwrntnAwnz2EiQPWPQUyhRA77LwoZKqBYc=; b=K0Uj4ijjofcvvbUKC1CJUuIrgCTq/rBU3ncfbgYURyzglGYWboNTQJEvQ0zvWd24aC tzRh+HukW05A0aAlO+DMSdlu5/ZoQU+w8rPuNRpgRgR3F351z2wQJRYqUa9uqi+w8+Jb fW/jD4WZ9jborayFqa183T+f1/R8ocwDGkPqvTGFJLaaqhY0osbA8WhcXVsixWcn9rs0 fC1SO50fYfmp9Hga+cYc8tymuhsty9h0L20b8JRhj09bf1Svq0NxrO7MJsqZLt0bHPXO ERa4Ud4dtePLPvOM6w0rMjHtB1UOZCT5M7CrdmIUfAc8DXspaDzaQVpJ7tOpzrdi3AHM Fz1A== X-Forwarded-Encrypted: i=1; AKwUvBzaGo2xEWBuqqOmXAQNuIm+ULicAGwtLIdu4+5wQjLEOm5qymJRa170m9fOIMb4WskcLGgJAjh2jYy1Wg==@lists.linux.dev X-Gm-Message-State: AFq9FYJrW5lcI5ti14lFGr3kAmHBf5Om4tdIkqjnkLx3/Kc2N5IpOGWv PZZPRJkb6b64ZDdnKmKcM88u3hqCox7wzkRLTFP5TrVD1DGBaO6n2TT8 X-Gm-Gg: AYBFou1TaFi1jsVTnbE/gdr4pnE4ki1JFRszDZDIuM5/xkHYpqwSuK8wFaPC9XpY6Jv R8b/ZBiPu+fUBWrxTEEtkALpq9edl5EpfNI0NxsXPcYlOT2JRANqxCr1huhJKY1Pzq7AXp540iE dSO/06IsnTGaPIYf2k34VjHxCuq2zi8dEmzWLC92a8AX6ltKyyFABa3QNZOZpwxfa2fdi6GAVoG ZMulzWNdmFIG2NOWEovU3z7/9R/JUMapV/0+HuIW70ysQEPBy61LOGSjaSJcT+g73nXzq3wQCEM xgGxEQZHAWNa9JMdZL0nKwZoryLvYXtENDPiw6+48zUZXWB01sAuUr8JSrBWLlzi2w/akON/1Qp oyvjdUDIxcII4+JSNyTAaepwqXBh/IiPUjL5AAsnX4Gpvs0kg3dAriS9B+2U9dKM02x2A4kWrSg /9pTfhiaMy6MZ3w8a9LmbDPfLUSx4Lth708Z46Ba01CqtqhImowLr7lIEw4IQXwAH9Xib6LIKlj aIql52IHevyXUvSUBl1klsl8baGfBi0obh3b2Xx42WNp6nd8TZrgF/hDtD73bXrVz0qSyg7ypnZ 764VGmmYuDGdyu/k1uhRJMwAo0Dq0xzH9V3ggJnP1jT7X9Awu3a1CIiyFs3MiYss2FKXT0oYydX sCxqrPr+AohYzHvpl0QQ6cw== X-Received: by 2002:a05:6830:6d45:b0:806:3072:240c with SMTP id 46e09a7af769-8309815e745mr20040213a34.29.1792122357925; Thu, 15 Oct 2026 20:45:57 -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.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:57 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:32 -0600 Subject: [PATCH v8 17/17] mtd: rawnand: sunxi: support the Allwinner randomized OOB format 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-17-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.232.135.74: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)[]; PRECEDENCE_BULK(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCPT_COUNT_TWELVE(0.00)[24]; TAGGED_RCPT(0.00)[dt]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1:received,209.85.210.54:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.232.135.74:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26692-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: B0BF31C1CBB 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?= Normal hardware-ECC reads also decode protected OOB, including the bad-block marker and metadata used in bad-block-table scans. Allwinner firmware leaves the marker in the randomizer stream, but the existing driver compensates it to keep a plain physical marker. On H6/H616, firmware also packs protected user data before the first parity region rather than maximizing its allocation across the page. Those mismatches prevent normal ECC reads from interpreting firmware-formatted pages and their markers. Honor allwinner,randomized-oob through a separate operations table selected by an opt-in attach helper. Enable scrambling for normal controller-ECC transfers and omit marker compensation. Reject software or disabled ECC, and reject a step larger than the page before the core can fall back to software ECC. Without the property, keep the existing operations and geometry, including the plain marker on otherwise scrambled NAND. For H6/H616, reserve four user-data bytes per ECC step, capped at 16 bytes per page, and put the entire reservation in step zero. Later steps have only parity. Apply the same reservation when maximizing ECC strength so strength selection and actual layout agree. Older controllers retain their fixed four-byte user-data field per step. An erased page physically contains 0xff, which the randomizer turns into non-0xff decoded bytes. Select the Allwinner firmware's controller-specific erased-page predicate instead of the generic bit-count check. Apply it to ECC-decoded protected bytes re-encoded with the OOB randomizer stream. This is not a raw reread: bytes corrected by ECC retain their corrected values. Older controllers require eight exact 0xff bytes, with a four-byte shortcut at block page zero and pages 127 modulo 128 for 1 KiB steps. The H6-generation predicate requires byte zero and at least nine of ten bytes to be 0xff. ECC exception mode can suppress errors for uniform physical data. Include pattern-found steps in classification even without an ECC-error bit, and ignore their correction counters. Keep decoded bytes until the page-wide decision: an all-zero physical page takes precedence over the spare check and returns zeroed data/OOB with ECC failures; an accepted erased page returns all 0xff. Other failures retain decoded main and protected OOB so bad-block and table scans can still inspect the marker or signature. Read complete pages for subpage requests because these checks classify a whole page. Collect status during each PIO step or DMA batch, and defer statistics until requested OOB reads succeed. Read unprotected OOB only when requested, combining adjacent parity/tail ranges without crossing protected user data. Preserve each step's randomizer phase and the existing PIO/DMA representation of parity. Raw callbacks remain unchanged. All format policy is in the new callbacks and attach helper. Apart from the opt-in dispatch, existing functions are unchanged: geometry allocation, marker compensation, status collection and PIO/DMA transfer sequencing continue to serve the existing operations tables as before. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 332 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 56594bb41193..0e2ff1c59120 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -349,6 +349,8 @@ 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: Allwinner randomized-OOB erased-page check on + * re-encoded protected OOB bytes */ struct sunxi_nfc_caps { bool has_mdma; @@ -377,6 +379,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); }; /** @@ -1160,7 +1163,15 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, return ret >= 0; } +struct sunxi_nfc_allwinner_oob_status { + u32 error_steps; + u32 zero_steps; + unsigned int corrected; + unsigned int max_bitflips; +}; + struct sunxi_nfc_ecc_read { + struct sunxi_nfc_allwinner_oob_status allwinner_oob; u8 *buf; int page; unsigned int max_bitflips; @@ -2342,6 +2353,299 @@ static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = { .finish_read = sunxi_nfc_oob_finish_read, }; +/* Allwinner randomized-OOB format, selected only by allwinner,randomized-oob. */ +#define SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ 16 + +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len) +{ + while (len--) { + *buf++ ^= state; + state = sunxi_nfc_randomizer_step(state, 8); + } +} + +static void +sunxi_nfc_allwinner_oob_record_status(struct nand_chip *nand, + struct sunxi_nfc_allwinner_oob_status *result, + int logical_step, int hw_step, + struct sunxi_nfc_ecc_snapshot *snapshot) +{ + u32 count; + + if ((snapshot->pattern_found & BIT(hw_step)) && + !(snapshot->pattern_id & BIT(hw_step))) + result->zero_steps |= BIT(logical_step); + + /* + * Exception mode can suppress the ECC error for a physical pattern. + * Classify these steps with the Allwinner randomized-OOB page check too, + * and do not use their correction counters. Keep their decoded data until + * then. + */ + if ((snapshot->status & NFC_ECC_ERR(hw_step)) || + (snapshot->pattern_found & BIT(hw_step))) { + result->error_steps |= BIT(logical_step); + return; + } + + count = sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); + result->corrected += count; + result->max_bitflips = max(result->max_bitflips, count); +} + +static bool sun4i_a10_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + unsigned int block_page = page % mtd_div_by_ws(mtd->erasesize, mtd); + + /* + * Older Allwinner firmware recognizes 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 == 1024 && + (!block_page || block_page % 128 == 127) && + !memchr_inv(spare, 0xff, USER_DATA_SZ)) + return true; + + return !memchr_inv(spare, 0xff, 8); +} + +static bool sun50i_h6_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + unsigned int erased = 0; + int i; + + /* Byte zero and at least nine of ten bytes must be 0xff. */ + for (i = 0; i < 10; i++) + erased += spare[i] == 0xff; + + return spare[0] == 0xff && erased >= 9; +} + +static bool sunxi_nfc_allwinner_oob_spare_is_erased(struct nand_chip *nand, + int page) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + u16 state = sunxi_nfc_randomizer_state(nand, page, true); + u8 spare[10]; + unsigned int len, pos = 0; + int i, off; + + /* + * Re-encode ECC-decoded protected OOB for the firmware's spare check. + * This is not a raw reread: ECC-corrected bytes stay corrected. Each + * 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 = 0; i < ecc->steps && pos < sizeof(spare); i++) { + len = min_t(unsigned int, sunxi_nfc_user_data_sz(sunxi_nand, i), + sizeof(spare) - pos); + off = 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 += len; + } + + return nfc->caps->spare_is_erased(nand, spare, page); +} + +static int sunxi_nfc_allwinner_oob_read_unprotected(struct nand_chip *nand, + bool dma, int page) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int len, off; + u16 state; + int ret, i; + + for (i = 0; i < ecc->steps; i++) { + off = sunxi_get_ecc_offset(sunxi_nand, ecc, i); + len = 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 += ecc->bytes; + i++; + } + if (i + 1 == ecc->steps) + len = mtd->oobsize - off; + + ret = sunxi_nfc_read_column(nand, page, mtd->writesize + off, + nand->oob_poi + off, len); + if (ret) + return ret; + } + + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + for (i = 0; i < ecc->steps; i++) { + len = sunxi_nfc_user_data_sz(sunxi_nand, i); + off = sunxi_get_ecc_offset(sunxi_nand, ecc, i); + state = sunxi_nfc_randomizer_state(nand, page, true); + state = sunxi_nfc_randomizer_step(state, len * 8 + 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, + ecc->bytes); + } + } + + off = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); + len = mtd->oobsize - off; + if (len) { + /* The unprotected tail uses the page seed and its 15-bit advance. */ + state = sunxi_nfc_randomizer_state(nand, page, false); + state = sunxi_nfc_randomizer_step(state, 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, len); + } + + return 0; +} + +static int sunxi_nfc_allwinner_oob_read_batch(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + struct sunxi_nfc_ecc_snapshot *snapshot, + int first_step, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int reg_index = 0, user_data_sz; + int i; + + /* + * The normal snapshot skips pattern IDs when every pattern has an + * ECC error. Allwinner randomized-OOB page classification needs those IDs + * as well. + */ + if (snapshot->pattern_found && + !(snapshot->pattern_found & ~snapshot->status)) + snapshot->pattern_id = readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + + for (i = 0; i < nsteps; i++, reg_index += user_data_sz / 4) { + int step = first_step + i; + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + u8 *oob = nand->oob_poi + oob_off; + + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + sunxi_nfc_allwinner_oob_record_status(nand, &read->allwinner_oob, + step, i, snapshot); + if (!read->dma) + memcpy_fromio(read->buf + step * ecc->size, + nfc->regs + NFC_RAM0_BASE, ecc->size); + /* Page classification needs protected OOB even for data-only reads. */ + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, + read->page, user_data_sz); + } + + return 0; +} + +static int sunxi_nfc_allwinner_oob_finish_read(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + int *cur_off) +{ + struct sunxi_nfc_allwinner_oob_status *result = &read->allwinner_oob; + u8 *buf = read->buf; + bool oob_required = read->oob_required; + bool dma = read->dma; + int page = read->page; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; + int ret; + + /* + * Allwinner firmware treats an all-zero physical page as bad, even without + * ECC errors. This takes precedence over the spare-byte heuristic. + */ + if (result->zero_steps == GENMASK(ecc->steps - 1, 0)) { + memset(buf, 0, mtd->writesize); + memset(nand->oob_poi, 0, mtd->oobsize); + mtd->ecc_stats.failed += ecc->steps; + return 0; + } + + if (result->error_steps && sunxi_nfc_allwinner_oob_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 = sunxi_nfc_allwinner_oob_read_unprotected(nand, dma, page); + if (ret) + return ret; + } + + mtd->ecc_stats.corrected += result->corrected; + mtd->ecc_stats.failed += hweight32(result->error_steps); + + return result->max_bitflips; +} + +static int sunxi_nfc_allwinner_oob_read_subpage(struct nand_chip *nand, + u32 data_offs, u32 readlen, + u8 *buf, int page) +{ + return nand->ecc.read_page(nand, buf, false, page); +} + +static unsigned int sunxi_nfc_h6_allwinner_oob_user_data_sz(int nsectors) +{ + return min(nsectors * USER_DATA_SZ, + SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ); +} + +static unsigned int sunxi_nfc_allwinner_oob_min_user_data(struct nand_chip *nand, + int nsteps) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!nfc->caps->reg_user_data_len) + return sunxi_nfc_oob_min_user_data(nand, nsteps); + + return sunxi_nfc_h6_allwinner_oob_user_data_sz(nsteps); +} + +static int sunxi_nfc_allwinner_oob_init_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + /* Do not let the core fall back to software ECC for this format. */ + if (nsteps <= 0) + return -EINVAL; + + if (!nfc->caps->reg_user_data_len) + return 0; + + sunxi_nand->user_data_bytes = devm_kzalloc(nfc->dev, nsteps, GFP_KERNEL); + if (!sunxi_nand->user_data_bytes) + return -ENOMEM; + + /* H6/H616 pack all protected user data before step-zero parity. */ + sunxi_nand->user_data_bytes[0] = sunxi_nfc_h6_allwinner_oob_user_data_sz(nsteps); + return 0; +} + +static const struct sunxi_nfc_oob_ops sunxi_nfc_allwinner_oob_ops = { + .min_user_data = sunxi_nfc_allwinner_oob_min_user_data, + .init_user_data = sunxi_nfc_allwinner_oob_init_user_data, + .read_batch = sunxi_nfc_allwinner_oob_read_batch, + .finish_read = sunxi_nfc_allwinner_oob_finish_read, +}; + static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) @@ -2473,6 +2777,28 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, return 0; } +static int sunxi_nfc_allwinner_oob_attach_chip(struct nand_chip *nand, + struct device_node *np) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + int ret; + + if (nand->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) + return dev_err_probe(nfc->dev, -EINVAL, + "Allwinner OOB format requires controller ECC\n"); + + sunxi_nand->oob_ops = &sunxi_nfc_allwinner_oob_ops; + nand->options |= NAND_NEED_SCRAMBLING | NAND_NO_SUBPAGE_WRITE; + ret = sunxi_nand_hw_ecc_ctrl_init(nand, &nand->ecc, np); + if (ret) + return ret; + + /* This format's spare and all-zero checks classify the whole page. */ + nand->ecc.read_subpage = sunxi_nfc_allwinner_oob_read_subpage; + return 0; +} + static int sunxi_nand_attach_chip(struct nand_chip *nand) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); @@ -2498,6 +2824,9 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) if (!ecc->size || !ecc->strength) return -EINVAL; + if (of_property_read_bool(np, "allwinner,randomized-oob")) + return sunxi_nfc_allwinner_oob_attach_chip(nand, np); + sunxi_nand->oob_ops = nand->options & NAND_NEED_SCRAMBLING ? &sunxi_nfc_scrambled_plain_bbm_oob_ops : &sunxi_nfc_plain_oob_ops; @@ -2995,6 +3324,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = { .max_ecc_steps = 16, .sram_size = 1024, .timings = &sun4i_a10_nfc_timings, + .spare_is_erased = sun4i_a10_nfc_spare_is_erased, }; static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = { @@ -3018,6 +3348,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = { .max_ecc_steps = 16, .sram_size = 1024, .timings = &sun4i_a10_nfc_timings, + .spare_is_erased = sun4i_a10_nfc_spare_is_erased, }; static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = { @@ -3044,6 +3375,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = { .max_ecc_steps = 32, .sram_size = 8192, .timings = &sun50i_h616_nfc_timings, + .spare_is_erased = sun50i_h6_nfc_spare_is_erased, }; static const struct of_device_id sunxi_nfc_ids[] = {