From patchwork Sat Oct 17 19:45:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3659 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id E39831C031A for ; Sat, 17 Oct 2026 21:46:32 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26727-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26727-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 8C52738EB7 for ; Sat, 17 Oct 2026 19:46:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5FF9B48383C; Sat, 17 Oct 2026 19:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iEh29zMr" 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 5976A47DD72 for ; Sat, 17 Oct 2026 19:46:13 +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=1792266376; cv=none; b=ijvJYmcY2Mv5mTfuOOmTyQZiazRttaqeOnZgOvroPKuNbUbZdF3hO9i3gIkMbK6lIAVnBcAvskbZEo/O/Z4fRGysOC/VZ+UwCYX88lJ4xa7oj63dgCNFd119Yh3Iak9zi9eZCtTG6OD6dMqKIPJH1NH8lT9cl8nqoc+PYgeId4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266376; c=relaxed/simple; bh=Tgy/BQKxEusC0mPWdmGfYNoFGG9Ir5hPdHIGsAU1LUY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ws7VUsUtCEnXRfzVAMs3uR1Zyx+o8SCQAQi7iOhSeMICGprCy7vWk8I37/3LnvxxYaIB/06DdwdWdCtjEq5U7aB4oww6qGf5+9fBPTDC3eRKCz188i8YtnR+27RzFSIpoFYsU844baI8iscRB7ttg8K0QwK2jRMf01IgDibJOzI= 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=iEh29zMr; 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-8479f46ecd8so67433a34.0 for ; Sat, 17 Oct 2026 12:46:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266372; x=1792871172; 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=8FLK5L4m7kGeWnbYjP4uSPNLUtTL4HW4u70VBTQSqv4=; b=iEh29zMrNKMdn376cMhkQnwwOmIM71l3IAXq5JR0vLT6F8GNyEL7V/ydxYKR5ciUg5 dQ5GuLxm9o8WQ+WT8mrVLcgbUOe0j8LzbQsl8UPKLIu4MlHBy7OA/3xdBid2IWWT1TF7 cn2W6GqhKUY9E6OETop3RhUJ+YDff6XaPqdFIAdPjTV4TJQaUDhjuDRGBEBAc1YqKPLk S7vjZzYm31a7Ib6wvUsZVmAXs3KOcKwjPP7nultK9Xe8g5h/HWUKwzNo+ZsBv7Sn/edr X1FWA1TMNm72YcnNGSDEmITHDJt+65dDncIgT0W57O/0sNFKFfURg63wURUcTpt21Jug VErw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266372; x=1792871172; 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=8FLK5L4m7kGeWnbYjP4uSPNLUtTL4HW4u70VBTQSqv4=; b=TonPkrgpeD4VHRdqEHDvo/UWoz5qob0NI7eaRxpkTuawxz4Sghr0/3vkOb6psGO71G oDa8wAgdGRc4hWy0YRvZ1AP70HDTd/sNiI5f7VLihxLw5evJ1pS+z7HmTVFwemyHao0k Y/IsorH3Glc1EdOXXqC6tEEDpXRqsGkWwTqui4rcxdu0rhkHLTgG5re6WP5HZWom4c3+ 8YSqOtOE/bZ/6IvwmE8dsMyVHoVeCd1EWGYYnEpKq5NEX8gwrdF+TJV39RBvzwSmD4sa mCiJSd1Fkccd5u24wY9JilmW1gfw2+T6vPAxyxEFpIHzWEzx/Mp6ELtmLWUwE4Aj2kYj /L6g== X-Forwarded-Encrypted: i=1; AKwUvBz111U3FAq73u14rabVmM/yA5rtu2uwD4G2eBBtBF5SDCMC45fPA1VJPM6qfZVDCu3qhSxZUHKQWG2PAw==@lists.linux.dev X-Gm-Message-State: AFq9FYJoYHhvypZdAWpqyEMfXChulToNhSTiX8aJr79A0yf3jGzx6tS3 bwe6hEwrJOoM2SR7I/NL3T/ppePAkSpr5iDe0cyK/ddqbYQG4Kg6GW/e X-Gm-Gg: AYBFou3enLQGxfXODYHSvQUkyZ69QR0fGzyzqnBA1Ok//VotVMqrMcJQbh9NkGa68aN 7AROR9k2xy7FB8kqSs2YhEKz9v48j5R1yXOs/se1TQ3kskrALMdav8zXyg/sApI2O10elFUgXy0 cx2mu8tAn9abbl1jSVTGJJ7uFchcXzLKN9TwEDM3+YGGrTAhHcyQ2eHp4wiTSs+1VAtbab9scPi EF9+WdZ6G/LG4YCuJKEv9HE5ItjyMfhRVtzXELreDC/ZyFrIUhTGEk1WogazsHW+We4s16keXDR J3CDt75TSvdVhNQS6wzb6bmjtOhqKRqYseOBe6N2jqhf6RyulnfiNNBrw2nT5wmBqVNtZK97KD+ NfGYqT9zmgM8blC2XwRN65PatRpQ1UIx6KTXI+XMoKt2dV8FusJnvXYiO1bQ6Uk5jqoG1lnbuKq clDvhr0TsW00oybOy7kn6ojofCtpRwocUIVo/V3xfO3+MuOxKsMQ+IS6DrETnT0NPlwCBU6CMsJ 4FcZouhQLGB/Lp8B31Z85jKLA1XvvxGmuXxcwpoL03C2etboOIKw8+Sx/DachPQ8nvQyVVSt5vq lyMsOX+h7+xLLkCYdkuF95ghqDRgCEwctsHnlE7LIrwT5TDGmIfoNjnMnEFTJs4yk6oiVD6dCCD OcyiIVTtPenhJxl1obcFJ X-Received: by 2002:a05:6808:f8b:b0:4d6:90f3:74af with SMTP id 5614622812f47-53cd1cbc897mr2494276b6e.47.1792266372025; Sat, 17 Oct 2026 12:46:12 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:11 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:45:56 -0600 Subject: [PATCH v9 01/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-1-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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 primary ECC-transfer sequencing and DMA ownership in the transfer functions. Interpretation callbacks may issue supplementary OOB reads or raw erased-page rereads. Carry the full-page 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. Spell out the PIO and DMA OOB-read branches so their different parity reads remain visible. 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 | 554 +++++++++++++++++++++----------------- 1 file changed, 303 insertions(+), 251 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index f41feebe4257..80006d1a33d6 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -256,12 +256,38 @@ struct sunxi_nfc_timings { s32 tRHW[SUNXI_NFC_TIMING_STEPS]; }; +struct sunxi_nfc_ecc_read; + +/* OOB geometry and interpretation; callbacks may issue supplementary reads. */ +struct sunxi_nfc_oob_ops { + /* Reserve OOB bytes for nsteps before ecc->steps is initialized. */ + unsigned int (*min_user_data)(struct nand_chip *nand, int nsteps); + /* Install the user-data layout for the selected ECC geometry. */ + 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); + /* + * first_step is page-relative; status bits use transfer-local slots. + * PIO uses slot zero even when first_step is nonzero. + * Return zero on success or a negative I/O error. + */ + int (*read_batch)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, + u32 status, u32 pattern_found, int first_step, int nsteps); + /* + * Finish remaining OOB; return max bitflips or a negative I/O error. + * cur_off is an absolute NAND column, or NULL if unknown. + */ + 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 +299,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 +935,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 +974,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 +1035,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 +1083,41 @@ 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; +} + +/* Shared across a read's transfers; buf remains the full-page buffer base. */ +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 +1157,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 +1212,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. */ + if (read->dma) { + nand_change_read_column_op(nand, mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz, false); + } else { + nand_change_read_column_op(nand, mtd->writesize + oob_off, + NULL, 0, false); + 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 +1418,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 +1500,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 +1516,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 +1550,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 +1566,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 +2096,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 +2172,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 +2231,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 +2280,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 +2303,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 Sat Oct 17 19:45:57 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3658 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 066841C031A for ; Sat, 17 Oct 2026 21:46:27 +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-26728-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-26728-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 F2A1F37A80 for ; Sat, 17 Oct 2026 19:46:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4960B4848BF; Sat, 17 Oct 2026 19:46:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GwbDWKkJ" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f182.google.com (mail-oi1-f182.google.com [209.85.167.182]) (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 012F1429037 for ; Sat, 17 Oct 2026 19:46:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266377; cv=none; b=UzF0E0MwWK/uSWcvWtyl93yFQ/I04pvzprBX0JfyG/JcG+KHYEOpygu7j7JuwtT83oD5blYj8X0lZbsxFZrufmQC6crXT8kY6zlfiz3f56RYe5Ja4WGrgatXOC8RDF9SUi9v6df0NG3EyrPsX1qNQNYySWFgpHFrMBKSztbrC5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266377; c=relaxed/simple; bh=mN53hNOFiAzhWVgJjfpGtTS1jmZz/HpF/K3uG0lAfxA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gtbZsrmBQcKFJEF2gj2Vq2NSRGFZeUw59AeNVWdtRMVLmIqDpQ+HovJKTKrRTGGqZJ8hDk8ZKoDXuduqDcnZdjqCRSa+egvJjY/6CnSMw1fbwCRkLMi9GpqWmgiv6Q6VlNeL8dQT7FJ2Xlk+CBJQKaXubz97vwXM7okx7ELs/Ms= 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=GwbDWKkJ; arc=none smtp.client-ip=209.85.167.182 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-oi1-f182.google.com with SMTP id 5614622812f47-4c9859ea2ceso582854b6e.2 for ; Sat, 17 Oct 2026 12:46:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266374; x=1792871174; 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=0p7Kisx6irolstjhcUjO1VMqHlDNV2glsnd/sNiGR4E=; b=GwbDWKkJeKoNJxiZgBGhCN/xXt32p0Frlbrfb9kaJh8Mx4/3vXcQzSxhk+kymDFlA9 ++bc/ihlbW4uLDn0e8jAmSfIvkhPzg6KigTMK0SX5Z1td2y/mHb9O1erq8t+Nqq3kjKq RRnSuFeNbw81UBkEIuX2fgw3Do35vA/7H9+X4O0NRlVdJTFc1bWbUFq2nhyFtYnwRbDV fkg3e8G+xIComwPz4P8B9BlqV9uIIXIM6yqL9oO0eFDhZM6RzgmBl5IhmBxifZk8YDU5 F0HfwJ1pqumflmKRhBhbEI5Sxa+jtG69LyPg0oQCVzPiZG+xxPsVQPVtgyo1fgzKOlcT QxCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266374; x=1792871174; 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=0p7Kisx6irolstjhcUjO1VMqHlDNV2glsnd/sNiGR4E=; b=H1P45lECiThjtJECynUuSrvvO8IR/NnE8t3QikV+32jInpexnoGtjXSByZehcM9+4e C0GrOR0Zk/wVMe5CoKnt8vDjaygIg3njkSRMMnwWy4/Qu7r9lIHYUwCznq1Tu0GJznqX 0KVKymLIsp7LvIktJXn1RmD0XYI+SdoqhsOs1QH+ehGJ2RcwteD80Gjy6SB85PVhWaoO kFFkrTljLeRugs1kHCHmT+Z7iH8Mjfoai/wCYCvozkfLQtxYEWdJXARsSjf3AgBW3u37 CgqmQKHjs9g4eVgDrcFQqdUxt8hZpcJklEjI1n02YL9JhFjwyqjia2+qO7OOgQ8RsNgE KL6Q== X-Forwarded-Encrypted: i=1; AKwUvBxGAFLJldvgsEq0kMx76bfMT+Tbrih6itUHP6DU0sM264Ua2rXBBswxlxcGs7m2fCFLlzewWMkcVpsx9Q==@lists.linux.dev X-Gm-Message-State: AFq9FYLy3U/ZzuJZ3ht7IbFE2fJLT7FD8letmBuAkUAr5tSWwFK+lRF2 ztgg5dNqLy3n2FuxLbqJfFSppwJpBsdclbSlcSAGV3hWfB2FZZbeOkb2 X-Gm-Gg: AYBFou2qzYTSOyD+ZWKbgPmgrJPNU/iR9uYE2s2/6KkPicMAhiUhbxPv8JK1DkMVfv+ QUWug85YkCL1SrsWGorYv1/TTWhTmHv48NSNassrGRYl7ICUuvERAQaZmb+EiNLracSrmPKbMed I89lf6CxVb/fJpCPXxB/HUwzm28sgLU2k5tOinGvrMdXYGrfGAN22z1eBziorqTu4+bDkpnPiQj rZiQa9rXx5s3XXOsaCz34TfabfCfkjWGXgn+Se5INviUneit9wlBKaTdrRr25pGoW/sKew00BhM ylmXdefEsHhold4VrmMJLt/szPkP5TFxHo2JYmtyMoBd1ZlqnczDx4E6e/7vyAiXcBVDF7GEnFd yenrmCIj3kqGogfg2kPMLLIhgZFo+8bovR592c+Y1c/j+YgToJA016G4hg/ulPbKkcQ8twBlXt5 vijtLVSHuzBOt5h4txKKYNi7vUV7YtYi0oRGSNYC/vrIiCh+eF0KQkmYlW5iKvHw1JbRXtEGPuw zQ+MlPFDCIJIHs98urRo6If7tPlCPaq0hZ0t+e47Sl41e2h817yzSPuGpzKx+V26Lx5/G5n1fmr jaMmkNBi0TK8L4klphB3HjT5N7VffoBwOLaU1WtcjJkbIkxJeqPVBp4CBf9MkxUrJhkxnijXwXP UkuIvHkt5bnu/6Fsy/rZz X-Received: by 2002:a05:6808:30a1:b0:4f0:a3f9:9f89 with SMTP id 5614622812f47-53ccaf1dc47mr3423128b6e.18.1792266373854; Sat, 17 Oct 2026 12:46:13 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:13 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:45:57 -0600 Subject: [PATCH v9 02/18] mtd: rawnand: sunxi: reject pages exceeding the ECC step limit Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-2-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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-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)[25]; 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.167.182: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-26728-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: 066841C031A 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 has 16 ECC status slots on A10/A23 and 32 on H6/H616. Hardware-ECC setup checks the strength and available OOB space, but does not check that the page fits those slots. NAND identification can supply a larger page size, and the NAND core does not enforce this controller-specific limit. If enough OOB space is available, an unsupported geometry can pass attach and reach DMA code that indexes status and user-data registers by ECC step. H6/H616 also represent enabled data blocks with a 32-bit mask. The number of steps must fit the controller even when their user data fits the register bank. Reject excessive step counts before allocating user-data lengths or installing the hardware-ECC callbacks. Check the final step size, after strength maximization and the conversion from 512-byte to 1-KiB steps, so valid geometries retain their existing layout. This also keeps PIO fallback from accepting a page that the controller cannot handle. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Reported-by: Sashiko Closes: https://lore.kernel.org/r/sashiko-outbox-173724@kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 80006d1a33d6..bd2193d7259d 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -2230,6 +2230,11 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, ecc->bytes = ALIGN(ecc->bytes, 2); nsectors = mtd->writesize / ecc->size; + if (nsectors > nfc->caps->max_ecc_steps) { + dev_err(nfc->dev, "unsupported number of ECC steps: %d (max %u)\n", + nsectors, nfc->caps->max_ecc_steps); + return -EINVAL; + } ret = sunxi_nand->oob_ops->init_user_data(nand, nsectors); if (ret) From patchwork Sat Oct 17 19:45:58 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3660 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 0550B1C031A for ; Sat, 17 Oct 2026 21:46:53 +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-26729-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-26729-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 9C08B368B0 for ; Sat, 17 Oct 2026 19:46:33 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BAD444854F0; Sat, 17 Oct 2026 19:46:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lvIdpeHR" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f171.google.com (mail-oi1-f171.google.com [209.85.167.171]) (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 E260948424E for ; Sat, 17 Oct 2026 19:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266379; cv=none; b=Ha+y+aFcQx6pbPjnC4730d506rlDMVI+z6sN/SYKxUC8uyjrSawOmVvEVMMu9AJWhwG+VwwtRCbWcIL/5PiDoc3gUFQe1q84frGGM47iZTVN2GVcCkzg2XOER070M2Ivzt6brZ3qpP1U7eqGfVzddU4LbYNNX1eCDfivaCgWB6g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266379; c=relaxed/simple; bh=PJq0iEolMY6uVtFxaIfsS4AZnFgRVydGROpNIIiX3+g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sDT+1+FCq20kNj/dKkGmjhzm3blSUWI572w2w4YD8NK9rLDvFDfMxUy0p4UP+X+854JU42lEV2om49eLibogKAKBPwGo2N2PjIMcUWq3l0R+ijkIS9ibFwHDxid4pg74xP/4fXbu/4rcjAkRHrCFpQ/uZxvHakvvdPnRcKgZJzM= 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=lvIdpeHR; arc=none smtp.client-ip=209.85.167.171 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-oi1-f171.google.com with SMTP id 5614622812f47-53dda625f63so457725b6e.1 for ; Sat, 17 Oct 2026 12:46:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266376; x=1792871176; 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=XiS913ksGIJSVrc+zKFDmT0Cphd5sQs3qd5ybGaSzjA=; b=lvIdpeHRSKSTidZi+ZJ9tyDHL4Y8kGDuYPUm4eFeab6UmLGcyCE99Dw3BcKJ3epdfO eFvkfV2D0qpY1YaNgvQqMOODpB3Z7UcQLjj16hqyXwYvoJ9fA00TcMP2y1OfA2TFat/d U/FFeOGymhclgi+7L1SGp86Nfz/fSKxXDelSD3FxOpNldzFm9JfIqRYmVmNFNczTNUXD PndLxRbMaMCMeWvrROX35H+LPQP+KwIx+xmFvUyTNxU52ZvIhYv9ZA79/pvSAyXC59CC YjpGJjLnlGYKrLeX3AfvV86/nOUXFes6cogGhG5ErbD3uRONpY5Kc94RxfUB745MW2qh E1/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266376; x=1792871176; 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=XiS913ksGIJSVrc+zKFDmT0Cphd5sQs3qd5ybGaSzjA=; b=Y+mfziriTFKkjSlyP7+Qo7a5tvS0ZnZL+4m9SWp4mVwgKQ6BSK+eAcs3tPeRFT7FEZ tOJGS+6eJ3yNxDO/Iz1ioxIvHuVIXvH7iAC96EIOdXgJ2tYH9n/ll5jZ0lA8qArw4FCE B8/v5xlC0UFN9Mc722tN+TOMnQM9p4Iu6yy1HMej8zUYMf5X0gk8kgGUvL3QA8VNolj9 tBXdJcQqvoBm9VGE/h8yf3DLHokfm/zbe44CrrtEs0XO8uHcZR65v5fd7kCiis/qPCH4 bOHlsyQ8UjGCFrUgzMSr/poAXnnPZB3h1wRyAurr+4AcG8+oVIfsTItJl7K3G24rc5BX RbqQ== X-Forwarded-Encrypted: i=1; AKwUvBwANJlpuIiD4KB5588WZrCVUEHuSWIihfnlXZtfyZtCxUm9AkDDty41l0j/0WNduz95GQ1yPmvwuaf42g==@lists.linux.dev X-Gm-Message-State: AFq9FYIXzMu6ADRMTfpb4Ub3UzVeN7tT86HMeIVszxUzGpNnU1SBZ0TO KYnGGpBkIhCeatWM/+BkILRAPOpNh+j4BesWS3pq+VBKrj5xyiyX0c9o X-Gm-Gg: AYBFou1ynAXiVGyxMGDqVqj6I6snVCvTmG1PrS78weLTUlmiUkMmjW8+Zz1i2SFGqhg knCPwMTRanslPHqr6owC+535Qdnn71NVOnHrJCBkFrrB3oNbzX7vng03u1Igj6jhXESIDaQNbjB YP5YR2dk/0ivX343LFK3gewQToV7mXWV210DfpZm2fM8XFS/Z2jEkF1OehjGNd+JDaCLq8n38rM Zr2jg+8dhoa7YWBsaa4XBxRIlTHbq83TjBoXKeeC5LI36ovIQvZ9UXW2zRRSVAWcPMqc4bdN//h wp/cF36dIhJS4mxPIKDRLMaSkYSGAfYRfBe9ZSsIQd7zosEufqlpiDbcOX8d8yf8yKjVtZ7psba vMpLoYukj3ufTateDAfSfknzDDj+/PIEkBXrqSIZDUkPJFHmx/qBzXo2FT22667xUA7pWqhUfiC bi7eIVi91ZcrwrsA04rQEcRdNmVt8tOuCkX4LYstkemJxor8Rk/efDw/unID0kkjh3+Vwo0D3at MNXGBrUiIk7OeewBUElxZrcBiQ2jbmwOLLgNO/cV/Pb+8qV/AFv6mLkAqinzOZEebo9ttRDMnF5 G/oih7VZ9MDcNeZQNvJaMUH0C75zLzlLY/PnYoJowamIEgfSdMLuvC5ot8N8L1fgDEl6Q+w++Z7 g8qrpnJhJnAWbaCl6VRGf X-Received: by 2002:a05:6808:c20f:b0:4f7:1e2:e79d with SMTP id 5614622812f47-53ccf2f073emr2926874b6e.40.1792266375636; Sat, 17 Oct 2026 12:46:15 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:15 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:45:58 -0600 Subject: [PATCH v9 03/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-3-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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)[]; FREEMAIL_FROM(0.00)[gmail.com]; 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]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26729-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: 0550B1C031A 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 bd2193d7259d..4ff19da8b98d 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -937,45 +937,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); } /* @@ -1026,48 +1003,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, @@ -1120,11 +1075,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; @@ -1223,10 +1176,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; @@ -1238,7 +1191,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) @@ -1267,7 +1221,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); } @@ -1456,7 +1410,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, @@ -1682,6 +1637,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; @@ -1702,8 +1658,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 Sat Oct 17 19:45:59 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3661 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 CBD7C1C2254 for ; Sat, 17 Oct 2026 21:47:06 +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-26730-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-26730-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 AF3252FABA for ; Sat, 17 Oct 2026 19:46:43 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3618148F84A; Sat, 17 Oct 2026 19:46:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KyJl6bwi" 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 6EBD748FF9C for ; Sat, 17 Oct 2026 19:46:19 +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=1792266382; cv=none; b=timflIcD5IF4LUxLovA/2u46fa2hejoM0LojCeUQjtTO4hoOB3f7IVO5HJYVolqkKB9Z3N04RD//KCiWWCcj/BVeljIEecQ6tDTVTzT+peNME7gpW1lWs7Fi2RmrO7FM0G8JKOBSPt0QgfCgJZyyyP7ggnDrow1CQQPduVw9Z1A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266382; c=relaxed/simple; bh=UTEH9PIbIWwcFKs3wGw1jrXsTWb2sXQT0iEqAm4jyHg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NXtvimG8SwIKFi0qH40onbPoB/J3gXziHZaOMrQK0k7cOhvbwAaUhr08L23yMJ8guc5DU8PKIJf3R13j+OBsPlyzACgZWPxRMaCDkhOMfydCrCi/L0CKS23Ry/IePNQrKu7BZLz2AjmyoLhPcnEcpjYBFGCWg+b+XumkIblovXE= 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=KyJl6bwi; 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-8256106635eso323293a34.0 for ; Sat, 17 Oct 2026 12:46:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266378; x=1792871178; 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=AcVwsAGitc/8mDgkiqGJIxKdaOI/OCkQfgdeA86v4XE=; b=KyJl6bwiYsJIW91EEG3VboOrjPcJmDOferBfMJwdU6o081CNGvblLe5T8yTH38rmSp bYFImlvolZj+5amcP0Rdlzf8AiNXqfQk74qd1SdNqj/NRXr6xHYWHhO5EXS7lIZ8hh2m +I57HvWcek47jZt4TSe/1IJTZUlYrfl6Cqgx4hezFkL7jYocWPAtqNhlDfAzhTe78phq 3cKyGWOyr95JpeiTYXeJXhiqcsH0B1o/HfC5MlKjiqPdmpPm2MTtG8qE+SBSWzV1Fr8l aSCnQRH/VXexxAIpZpdMPgFQ+P7ihLGrxc1ldIN8F9W9BFD6zoGpDYDEchsOceBurUFT A8hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266378; x=1792871178; 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=AcVwsAGitc/8mDgkiqGJIxKdaOI/OCkQfgdeA86v4XE=; b=b2nl22qvON4VjoUwCVqXUrOxYGsX5X6Z0yGzNyVKS04Wv/9eEytqWf24RVkT4DGe4P av4/oYpQnTVwJvNGg00ErA1DMQzzjPYu8yf8qCMTAP72VgT6kx3JerRtAMBABS/LYvQV Fc2zHvWesJqsSU2tStuoy7AQHxllQYkgRK7c/0RrnC0p6iwt0hVx7PSIA7a0fjMEWErg tlxOnkodPGOIFtLTD8WBMciUzaeRTf2c/3UgjvANQl9jojk1wluJD68m1wecvFDHJ8ub 5iMuwYfh6dvsQfbS6COK1Cc7wlaNjvYQ/xp6CLLH00v/m6yGBr00WF5qXP0C/plZJlq0 imoQ== X-Forwarded-Encrypted: i=1; AKwUvBx3tXPdY3rx5i8SMVVuZPr1WbEVju9QCqgN04guIEMVvI8I6X+tnBNiSx1nOvMNSItTjFG4kFFeddblaQ==@lists.linux.dev X-Gm-Message-State: AFq9FYLYFQP8p4HRw2GnU7nCP4tE6zTzPy1u6oA66hi7UtiPz9QRmzk+ iJL1hO9KME4ONDqlL1YNUQ0v1Ktyg6nUL6AJouIffSuK7pZfoPsVLtMC X-Gm-Gg: AYBFou0ROvuO+cFWpGFivRTaPit2I99GlMSkArKXgPgutyldl4IlcKuUOMdUAPxAUuq XMwvSrNuUhluxdW6c3xNeUwNglZFKRorIBe8SqzEHTqu5xC1+50jzR+A+93jW0ZrdabgthFABDj P3my12LObR1ASz9OUjckCH/TyTojppShKvVmvBuYksBCwkrW3B2fwXdUtsQUlhLvOyCS/d59gZi AWHhw3DuCGdPtiS80uULuvNClEIPReJOUhU/Ct1uz/USnPgEXfd4KbKVFhIQJAClCYvfFJpwJaB 9Jai4iVAFwsC9SROS56+85VUMPJxkPPZ6nqcEcNJbn5Cob3PgJPYh9HcI8wW7JUaRqYt+kvgy8y Hj90CLc78O5WhuF5DEbv1A35ABqUPuAUbgh8Kgeb9A6tN/OA65SJS13wjSdo5Vd9O2SSq7UhGEO FpADQSqhbv963DybCmswKBCaUsXteMsDx+68c9vDEOTHYDgtCb3Y9OI8dEHRaJaLrDDqTQl8B9z a0HAmjzVw7B3jBLXEwKI7PeQSxPdjNKqqY3/p6wDQG/astJtLB7GFXaFbWDRXuKi2HjrGJpADLE jS7adx9tu6GC1uZYYJpFFBCmzMTlLbwBBvnLClEjPMPxyYnDF6r/NUXte1LinFYXx7jEEk6QzJs dUwXe88FMtCGK6K9CrJ66 X-Received: by 2002:a05:6808:4fca:b0:4fc:248a:de3b with SMTP id 5614622812f47-53ccaf2998dmr3273386b6e.23.1792266378042; Sat, 17 Oct 2026 12:46:18 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:16 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:45:59 -0600 Subject: [PATCH v9 04/18] mtd: rawnand: sunxi: propagate page-setup and erased-check errors Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-4-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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 4ff19da8b98d..29715d179d22 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1038,7 +1038,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, @@ -1050,10 +1053,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); @@ -1317,6 +1326,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, @@ -1324,6 +1334,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; @@ -1375,9 +1387,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, @@ -1465,7 +1487,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); @@ -1473,10 +1497,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; @@ -1489,7 +1514,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); @@ -1514,7 +1541,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); @@ -1523,10 +1552,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; @@ -1541,7 +1571,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 Sat Oct 17 19:46:00 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3662 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 C063C1C031A for ; Sat, 17 Oct 2026 21:47:18 +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-26732-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-26732-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 98C68385ED for ; Sat, 17 Oct 2026 19:46:46 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 07DA9492E23; Sat, 17 Oct 2026 19:46:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oCmpqKCA" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f177.google.com (mail-oi1-f177.google.com [209.85.167.177]) (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 4706148877F for ; Sat, 17 Oct 2026 19:46:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; cv=none; b=ObRn7tiVDAzc/fE2cMCZeduAAjvV++BdxUvZwAreKB6akTrN+EqaCI6wkGpgGj72w9QcvYTg6Qh90YnvzXQQtU34znYzgspnE+IKWJrMy5Fen/G6VuASR75cvSNLBs8OLgDpz7D8KRXz0JOW8VzJw7G2Lvy1dzNTW4ZfONUregQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; c=relaxed/simple; bh=ONUCfWg8eM4/OtI3jBJJ3OP+uv5/g7o8HsUMHh6rAVg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZWC7D1siBdyR0lZOwT5ECktcqSqBCkyBiBJnB+3GP2LkbC72vS2URSa4zVoXpg8HrBh3zx1ZgMANfIrhxVvAsPIcPNOaDcz/kufpUawIRMvSme+9jpe79LMblK3PfdvZ9nTEQbdgLeTzfcv88QLvVEcQZXr+83WVZXrO8IFEIUA= 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=oCmpqKCA; arc=none smtp.client-ip=209.85.167.177 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-oi1-f177.google.com with SMTP id 5614622812f47-4f699fe49b3so728245b6e.3 for ; Sat, 17 Oct 2026 12:46:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266380; x=1792871180; 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=S+Qvi+dU4vtXa5pndLAyH0EZ9I1y6W0niIp108EHDPk=; b=oCmpqKCAmxwSwJ8yZUC11kENVZoBlXJNXjyTWIeNk5oqPB3HfU/+NcokzxtK4tN1nK NRyupKj0G5UuuwSLqCPesK3pZs/BrwnYUrD+nqp+52/vWGr5xwy/uxfuZ/w8/QG0PPZp CLhjQK6mRma/aIaTeJs0qE2nY9iKshSsrfwdXvKW7uxvD/RMB/MpANu22eUhdwwUE/Vx ctG4qI8TBSB4YRgp2QtAgK70RLeqhcrgqKwXMOMuc2AwDS5belN6xacJf1IBIfuRKC+x PVkVBXz34bi1c3u67l38OSIkBjge1KjVpgVxuscgcSPQpPuzRit1wmvAlCbe2PwuNW2s qDHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266380; x=1792871180; 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=S+Qvi+dU4vtXa5pndLAyH0EZ9I1y6W0niIp108EHDPk=; b=uBEiZwv2jfF29vOTfC57ayKZPwov6Hs7Pp2eo8wW9hG/K/cU0JnDOZHnAv5cSuD7M3 jg2QHUd7vfRdHmfV5G7wRlmjbaE6gfmB6w2by8pxYY9f5+4CgyEEkquseE15kGNdc8cS nK3r+1WCNGE/1nQVh85newEYevMtwuqo+DGpnPQ4HxzCLm2PJtt36LTYUosbT+7zU7nh uRwXVioZsCh4FT6jtjaRz6Dkc0mrNBcKHL3AilDhUcSHv6749kyhaS90SIiw6ftCd6tZ g4vlAfmp7oBzJjeDioUOPoJRo47viGrc5Gepb8tURABlN5JLL86pqlLG4PIDdH9SpELA HRfw== X-Forwarded-Encrypted: i=1; AKwUvBy+ricOwdRtanO1b5LySMgB4AGfVvOvHtKOr29vXAJ4CmdRmcQzqAAoghyo068w6com0x9a/sFbtL2JZA==@lists.linux.dev X-Gm-Message-State: AFq9FYKZ1T3A7mmVls8bYNh30pwEQhUi9bAfyAYnhubNMK66tumxXIiJ kFAScmYm4QYbHmzSWrm5QvKa/z/rcGJs5k3uz1pj1o0eVGqvofixQ6Oo X-Gm-Gg: AYBFou1MimXDNIZm17WhEqyHPe3lAeyZXgsMtvrMIPyF7E+8fAsC3qeyke+rmJIGI2B tQnSOQstwXLbGRifMuMtq7kDtDqaRG2NsldfxHR9nRazwLaJTzjNq7+kWfZcO+rB/EIzyxPMipu oD6bkVQraOjxU2BH1Y+uQpxzOT0xbPT8K1VEp6y4ZEvvsTDteOfnCdBpg7r1k6rbFSGIJciIhxQ Wh6JCzuI5JvZzTFlJfwgSvO5D+MIiUnJGNOnJHWcm9LHHs2yVK18/0wbe1wWD8e3VziycR8TRT3 ZRRLLRY9JmHrRes44rVYJmBvlx+8RbfvGjOTzpCTwcZCWdQItT3M4hBnfdHY9qD5aEZ8ocZ2QKS 1jS9RfMzxn1ZCZtfDyVWefV3wxQYxpA5Ep75NFCr4N0gI8KfeD1ufW+hONsKJLnT987fd8ERy3/ kixArF+cXrC+gn3LK3kefwT44xR38ZeQK37z+hTVrCmw95veAohDvccuJeve4ibrGxAdIkC/JMW LrklQ1r3uQ5J2QAKYAj2rtGjoSrEUhUiizfBh7YZTt3J7h7gS2tkEH3xQp5AS1NPWRdKuZnJ0R4 xVM0kuthC8uf2nCVqMJI4eIwllG07YGjCfUdTt/r+R4AwQKtg0m0b/eImVw3BQzQylZ0gADuYhJ G4mP5adjyv4MCMSv5Hk4ZRQ== X-Received: by 2002:a05:6808:4f28:b0:4f3:e98f:fa26 with SMTP id 5614622812f47-53cd1cb5c49mr3420662b6e.58.1792266379933; Sat, 17 Oct 2026 12:46:19 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:19 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:00 -0600 Subject: [PATCH v9 05/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-5-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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?= 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") Reported-by: Sashiko Closes: https://lore.kernel.org/r/20260909085434.C8F201F00A3A@smtp.kernel.org Signed-off-by: James Hilliard Reviewed-by: Sebastian Andrzej Siewior --- drivers/mtd/nand/raw/sunxi_nand.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 29715d179d22..5b736a4a7fe9 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -401,6 +401,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 @@ -420,6 +421,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; @@ -441,18 +443,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) @@ -462,16 +466,28 @@ 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. + * An empty mask means all requested events were acknowledged. + */ + 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 { @@ -484,6 +500,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"); @@ -2664,6 +2686,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)) @@ -2672,6 +2695,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 Sat Oct 17 19:46:01 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3664 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 6B9061C031A for ; Sat, 17 Oct 2026 21:48:05 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26731-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26731-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 6DE2A3BB0B for ; Sat, 17 Oct 2026 19:46:46 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B8A0449426C; Sat, 17 Oct 2026 19:46:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eZ66kmNn" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (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 00DB6483BE1 for ; Sat, 17 Oct 2026 19:46:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; cv=none; b=em/K7/pXZfhrzoRi1NKSPJofywG9eKIJ0Mm7ircMd/ShMQyWnqfNoQT7IxlKnn5RTIbffsa/mHMb8D3hk9nJoy+aG0DYpXweAUt8EHaWxxkcQ38niXQeac1FI2/JQveKTQs3u+QtUXcCyx97OtSAjauxLXwlAVNBptpfxHRJ2ls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; c=relaxed/simple; bh=a9bbrlPbxY2D97Or1Weh83hc/hd1sg2iaNGPjE+jr64=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QaVGmxvVOKMhim3+mS9JaHKtbtNJnDgJVIBv7P5DzKYNrbsNm+FTs5taWG/Dq6HD7yyRAXwiuapuKkR+iAlLwpFa6JL9b6xTpTHewWF4IV7YCTE57itokSuoS0FQCOpZgIIU8ScLUacBz666TPJD7X1j94knInbw5J5oL6aNDxQ= 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=eZ66kmNn; arc=none smtp.client-ip=209.85.210.41 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-f41.google.com with SMTP id 46e09a7af769-824e6e6ed71so598867a34.1 for ; Sat, 17 Oct 2026 12:46:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266382; x=1792871182; 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=n9jTHHCWKanN7K8lakzXwANno/EOLzQpBktQemhjHz4=; b=eZ66kmNnRPMZqQgfMOnebyctlqKGEkg3C+OQC4FJC4UFdDr6GFLX0dbFtqlxdxv4L5 UYsbd3c6YqCGII+aS7EjVFsD4PWAJmyUzA2jMrh/hBu/tVz18tc4m5mm2uxpl1q0cO+5 +PYwTuFKOxOtrzvq7LhSKo0UMzq80d7vju61LoA1SvhEsohnuJBFT8yvhyXL2jpTlkcH WBSekGjKpyxnS9+P2AnSnStHItsPDZdTS2Ma7m5GQQzsjf7eh8irZ3Iz7+sgSVgQlCgH 1T53vh/dTUDfikNiKL3IulwRjWod3vOXf4cL1d5g456cmo9PN981hDp+pmefCoQ5U0ff GS6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266382; x=1792871182; 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=n9jTHHCWKanN7K8lakzXwANno/EOLzQpBktQemhjHz4=; b=qoK5YKrB590M+7xklPe2uAHtmt+s04CQlL3W7LPuVaK0t1TsO2jmYPkIIgnB8tqZ69 juvIXHUhG0BR1lyPJ4bUHRT4vbs3XacPqWlm3bCvYguyRKMKDNwDDNGbkd+A0QLsPlw5 DHCSdkGF+TdjWSvpSgwqCegzv77r8PI3Pkxvn+vR0Oksk/hzOZf7bQ/GJ2UDnzKmc7Tc fahWMOwVBNw5B57bR3FHX2g6FuSZRQWy4fJ1cJJm2FmcPWjIccHMT/gAxR10FqLvP78K 9TYAewzQ1+Ekta5auQOvhEkUNMNS2Yt7bLLEyFkmuKNcxVCK7uCKw0tc217uVQzqJIHd 3NPw== X-Forwarded-Encrypted: i=1; AKwUvBxH4+AGMDDTY+v0K1VJsEm5wF/o4ygM/Q0V4bnGFUeOncVyVC66f81WPtVLt/2h6KLT++hGL8ET0RqAbA==@lists.linux.dev X-Gm-Message-State: AFq9FYLWsAH1EVAFQysWz9r1o0fTnuzhhsHvh1S/E8UEw8sPNe9uxUce pAkxVdUJOkizAE3ryvzKKOTTIYgOcVpjdb/qK4GKRCpCbU8g04xF4d8m X-Gm-Gg: AYBFou1biDzEhwF/iO+qDrruvgVIyvDgfg5zeS4oN4nzHiRA8TAlldUnCUXmqyXA75r IswFGJoEBwZBhJCrCEDwHjLeQz2MIPWtknfe/1I1kt7U1v5eUIPl73nVyQqyiTjeZhsDXB6+1CE BOdKwIszjyTOeGwUGjga5qA55rFxAKrP1Lfp7c7Kpdwh6XFPfDMaYz3BavqhPpQHUlVh5q+40Y/ V/HUe0v8bXkP8QaeypGvmfyVtJr5VrdQYh4NjXDDmsWrVzjpdTz7ivg/ZuWVZs82JW3Q20J7Hdy JfFq2VJDF0vsjOJhHdmdHOI+wmQSGLhSOTPtsUpoqL+tDAP33H6PSnn6NJkzUJiUwKu+XT2UsjR HdEF3wu0g+gqSRWjY/YCYLdTLyY+4VZPn6uWt2q1AOHSb0sPYQdZF4emC/1HY9jtL29d17Vl3KU x4ivaeapMla0vjst95Mx3tkt4AhKs3phIJZjNmGNoCxhr2i6SqjtxS6KPk/xl5PTZrj0AI/gn9e P32qxDOOAlHcRHKTzpidTfLx1L2U+z7MEh+gtQInrvtQ0bFQqu8sbc7snm+26He0Fh1GHqWBUer dRnLpkq9uO/IzOQcLo12H6AxApVFEWJGduRP/w4dPm5Ivu7+/kWCFuciKSQkzwBhIcADN2dstLE 2DP06Jl0oAu5frayPykPj X-Received: by 2002:a05:6808:3086:b0:4c0:89e5:da46 with SMTP id 5614622812f47-53ccdca9f83mr2990622b6e.32.1792266381790; Sat, 17 Oct 2026 12:46:21 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:21 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:01 -0600 Subject: [PATCH v9 06/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-6-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; 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)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1:received,209.85.210.41:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; TAGGED_FROM(0.00)[bounces-26731-noreply=patchwork.local]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10:c]; MIME_TRACE(0.00)[0:+]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; 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: 6B9061C031A 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 5b736a4a7fe9..1db6ee18594a 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1614,11 +1614,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); @@ -1633,14 +1635,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); } @@ -1654,11 +1659,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); @@ -1674,10 +1681,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); } @@ -1718,7 +1728,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 Sat Oct 17 19:46:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3665 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 6B5B11C031A for ; Sat, 17 Oct 2026 21:48:29 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26733-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26733-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id B64AB3C915 for ; Sat, 17 Oct 2026 19:46:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EE7E449482D; Sat, 17 Oct 2026 19:46:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gY7ircEw" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (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 7749A49363B for ; Sat, 17 Oct 2026 19:46:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266390; cv=none; b=nuaXEG+M7mlyYrMVL8IZ6enc4f4cA4PXW4mi89HkNp0++CZxK8t98SWPxnS40BEG0tPvP+7duxVUuA2FB71wJAWW1jsR5EpPzwZtaP7bTOGEO657NrP0b6wv5O+lP8emgNKF6NezTv4STIuH35uN6EfFZYvcpaeI5pmXSJjch9I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266390; c=relaxed/simple; bh=dbYKQMzyNYaKHf5LoY3DE8dfg/ieSUwcZADEtitOIW8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gVN+jJnZf1PNDN2CqZGb7ab/HTfqa/xvszynhkg3oH+jl/YhdrNvxBZ+12SqD9KRshH+c9YjJzPq1awDjNNvSZxT23bmVnx+lL0fYLMJsPyu82vU/B+tzP5rsv69nekhXQdpTJE15P0e4MvgJ8r5x/HbWRTfeVqTdCjMl+FO1ns= 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=gY7ircEw; arc=none smtp.client-ip=209.85.210.53 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-f53.google.com with SMTP id 46e09a7af769-82380b0f55dso395362a34.1 for ; Sat, 17 Oct 2026 12:46:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266384; x=1792871184; 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=iygLDIgOD8rajawodvAmwVYRk5k/3RMou3i6AByPjMc=; b=gY7ircEw+Qeti+S4cT5fTLeV8r93LDfyxp+6YJKsOp45c7iSheo263dEYHm597Tqlu mt//peDxR/WWFNY+7zj1UnYL+wK7SNpmwB47Y2f/8mqHXsS5u4BqrjQqvLEcvt/hmYl7 H53EEapDg1nZDJJQu0iQbV5SYrwIsuGuPV3nyduiaO6BLkf0jzPXmi+GfUf5yTwsdAb/ e2PqxRgvt0RLSg6N4K9UkFKsbxX3AtUYWh1xKOE5yKXjhrFJTENBtSzmjl085w709kIn 4i4Jq7UVDFlOUgn1sFXvFbvPWuBC+vldfHBtrfeqVvENPgAYDTAuZLLJQTVPFhEYAu/x udDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266384; x=1792871184; 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=iygLDIgOD8rajawodvAmwVYRk5k/3RMou3i6AByPjMc=; b=XRpXZjGt9xFXm+0aIPQLbq1p7u6RQSo39HDBRlW99nAav8Q/4gAGCFvjaiEs0oHHLt ioQzO3Ob8smRNehCc25+whmML5RStvgQwwaT/AR7ed/72slJTJqwCv6IlOBctzjE90fQ Edu6rgmaj5olV0nqzl0Mzz5eplnHjpgCfFfPUwpUQCq7vfXCpIX2W5/F7HMZs1hBFJZn NtYkHaill18bcTSQqPucNF7Eb0vecPs/BwttiugpRZhrfpkUNXSg7vcjzGDcqPgAZp4D nGX0XgoICQw+SjAKz31+NynsZ69FU7NNByIXe4YFegSmhTMGkyLrSmPL7RPuKhP7MIfG PPGA== X-Forwarded-Encrypted: i=1; AKwUvBxKvhsCm6rSQTA7jjC64K13wLxuX6B4IvCpY/1WYNwmTV7Hc/nufU38ZU4cRPcnIzKHas2Vgnerb4sZGw==@lists.linux.dev X-Gm-Message-State: AFq9FYJAs9W2OEI9NHOZsC8iDitSbhApIEGv5CQF8a8YKXXxlUEtgEIa zOoW2CabWLTxJTJZPEbBuY/aqcNmMRj67UvvCT+9C7PY+7V19HSwUbtP X-Gm-Gg: AYBFou01caFu98ZLfp8cugon9+hPJcH9/XqpxnFdoTkgEp3GvEM1rEaxFB/QvYRt/cS eJOO7DBuY+nvTozRz52/yZYZiHVAVtdffxuqhM1dC3HGxXu+MIFphwDBPWepVthT54rbm22OIH3 vOXzTJvwzX9uI4Cp2r48d4/i0giKjPe4jrO8VyZLDxahGtK7AM2iqFtPqefLH915X5qLd/txg9A yOFi0V0wm94MduRLX3jnwmxqYqw38QusjDRb/Gz3QNm5VfZlvAjSlTByaWUqXqlA//bkzgHv5Tc +Kyk6CPTsCfbKWB5+Ow3szuB8RGXsYrTh8Nb/xEbgL8cEWYOyJD9U0hAKra2RWfXYn0YbheuHaR 4MItNYpp1T7vwm7j1nycbKlwTG55gla/Jb1SXFg+WHE9EQ+BAdYM4bkWlSK8qIxsliegofb6DRx UbK9BdlA+oTJdT+PsPtsMucyIobxrlgjLxuXmJdUHBuQ2x2eIX9Y/dXarg5j7onuLHOiTkDtgxS 8JYWTu72FpvHnNYzWQQ84AlTRCUEFXEFkKwqOpecIv/emAvKbJCdd2PaLTOLY/T44GtXntnlona aOYMaF0iP/sCcjG36+EjpjfJI6t+pJ0ylOhGVDh/KyS0dyAOTyYxnzddg4o5sVOeu5royKGgm7K 0EszZiK7f6K2RKVkGgpmkokhJQmgR1o4= X-Received: by 2002:a05:6808:ec2:b0:503:aaf8:ef12 with SMTP id 5614622812f47-53ccfbb22ecmr2554952b6e.34.1792266383632; Sat, 17 Oct 2026 12:46:23 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:23 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:02 -0600 Subject: [PATCH v9 07/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-7-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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?= 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 1db6ee18594a..22cc8998d49c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1120,7 +1120,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 Sat Oct 17 19:46:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3666 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 0D0821C031A for ; Sat, 17 Oct 2026 21:48:52 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26734-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26734-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id A2E873D4A1 for ; Sat, 17 Oct 2026 19:46:48 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 21102495037; Sat, 17 Oct 2026 19:46:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ax9a1SSI" 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 22ECD493D32 for ; Sat, 17 Oct 2026 19:46:26 +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=1792266391; cv=none; b=LlPix/Sjv2yebeAezXf2spD/53+kvK9zDngaIS46WCO30x0Zjo1jpiCjzf/Eh2UT581R9lL3e9xztfsi10pF9JFs8dKwsy+9hR5zQ35SRHwX1vgIblNVc1+TVFlgyZPcoNGPbMXmLFHU2QlQK/7JS9A8a5zTmMt/tl/Hr9Xldtk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266391; c=relaxed/simple; bh=Gr8R6NeJ/RQhMXjnXQ9SPScO5ueGFcDbXLJ+snnHayc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i0LHUWuQiQ8vIqytv1UgRo9DPRO1aP1kxe2hUgO65w6sKnbXtNyWSrw+3pNd21WcLUqLn48QH699laiSIF1sRF3TaCCUfxhuZr8rABPibN5nlkDFYbSmyF7+GhRj3mrsuV2rYnxBw7+FKh0u1HUnAPsqYQIkx6xJobnESepwwgE= 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=Ax9a1SSI; 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-84751a20d87so110967a34.3 for ; Sat, 17 Oct 2026 12:46:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266386; x=1792871186; 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=gZdHG1tGz+KtQsx+1wa5xHbH5Q5lOoI44lGCgj2AqxM=; b=Ax9a1SSI6hiDh05j+wpYYSZbpKHwcKyDiGL4ttF9F3YkyQkUhBT6CZS1JCXCNSzovs GvEbJ/7lXp0AcZDmVQbV2MjrTyLWmUWU2W8opjzPUTS03U48AcNRfpBLfjjLvRFicixV uJFB+Eyg2a9CpzB2SfGJq+1NFWezXf1K/+iYV4IKPRyH0FuNqetDvDZv9srMLesv/2uI I1jqZ+gQcoawI4DO0thpWP+fznlh6KSaxlorgTabWfJkyvp3WMO0i4BYqA6CJqUQKOhm UIuBIMDLuSQuQ5VJYKG5fD5l2phVjFISOUkavS9jywve9vErXD27N/iTOdxwYiq93dOg eUNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266386; x=1792871186; 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=gZdHG1tGz+KtQsx+1wa5xHbH5Q5lOoI44lGCgj2AqxM=; b=XH/NZnX/4hBhkfH7Jd1A4jehr55dNaIxGPt3EZPXkyKctmHt4sprY4yCBklLZWbhoa /cdxhcgSttBmiccSB7uNGlZA/t5w8xh5Orru84K54HaEfs0Ca+s14Zja9qZ6bbNOa7qK gW8AG7mZeoXovj0W2xvaoJuSaBt097b+Y4+W+xmrBdjo/3fRoOZfDOkgW2JI3l2pUYOJ TmgcoXjzCn2bZgCmerjJjUXe+Y2+htueVKrCTe9GPygOJ/BhLTpKzPM9G4Cr19KT0qpP s9W2Fu54Nljbrhga3XpRIVF/PterX6jOHRGtqEAkwyBZbV86sWStPhKoLQC2pI6yW5TC 2alw== X-Forwarded-Encrypted: i=1; AKwUvBxeFyziiSef+dbyHDQjslRtP8zzmDMqQYcm2Xwvdc/OtUPKJv1gAlqrFDsztA8diO3EbriQQxDgy82POQ==@lists.linux.dev X-Gm-Message-State: AFq9FYIAF9lIVRajauCVk4okE18I6I76FcaA3tFAxkyLO2SBujB7MnyK 0qdeSAst8yDP7yp7gcZlRPuO/ZzJv8PRthpnyZZksgm6ojf7ZMg+TWrV X-Gm-Gg: AYBFou32TaCT+peaKe3Q+zyp5dQlj/VwSYaYlE89HGlFHFSFK6dkYCm8kFa1CUkoDxH f9x4PYpCo5Oq0/F9nLLMjpQYqlQX2etmfBGhRZnV3DkNoCVZoZkiCFOA47u6c7jqo3ASg7/KP7d y6G/TPN3bzMhjbPkB8kuGuAGhYBuWFK32WfdTLTKgzhepzDmZY1Ax5mDh3q8TiLCd4SMSz7KO9z p/wk+DdYuK7snO2Rpi4eCreC54xApeq3oy9mD3I5K8fZskbOOVuEC1ktGzfkSDR4nP68ePLIYgF wUr5lobZzrx2cNnfp9Jlo+Ui5b3qW+YttF2Ca//SHKF7HwDuOWc4U4Yod8jiDgr/bLnwwqdrxkj WFGm9kiSbAaVA6hn3dajx23w1PE/KcH3BLc9Ap6R1GFFnG5PtFGMvvgpnPFduceICU20zGhbzP/ iti8f97xHeZOD5O7OtI4S0N8hWr1+fhshX2JeTvhLsow3ZYoDzs6WzdUnzFDc/GFhKrNhYq9yH8 hmk/MBrJzoH5DUKsYnCFg/1BXnlVjglujBYt7RtyzHmPHWQORvJTsktZ5qYJmVuYh+97EgMOBBo AiI4Z+NywGDMJqVq8SJh0vG7jWiW4bqostQJJy2ZCfYgwO3QuqbIsDEx0rwy4Y+uJGsV4FsDBB0 pJX9OyhMlCeRjRIFkAcTkCdIE7Yrs/QHB X-Received: by 2002:a05:6808:5392:b0:4c0:12f3:6007 with SMTP id 5614622812f47-53cc22e2b13mr2397740b6e.4.1792266385605; Sat, 17 Oct 2026 12:46:25 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:25 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:03 -0600 Subject: [PATCH v9 08/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-8-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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 22cc8998d49c..82af3ccad885 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1231,8 +1231,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 Sat Oct 17 19:46:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3667 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 926C51C2045 for ; Sat, 17 Oct 2026 21:50:00 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26735-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26735-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 80EC04087F for ; Sat, 17 Oct 2026 19:46:52 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6B9AA496D26; Sat, 17 Oct 2026 19:46:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gA0EZyfT" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) (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 C8235488229 for ; Sat, 17 Oct 2026 19:46:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266398; cv=none; b=BKVQbLnF9+ZkJg2J7L/BGNK30D6bqdlGEqrVezk0f55VGr1x96h+pBj0Fy3TMYdeXIoypiVPT4GbioCBsXs1L5rJR/XEA7j02swlseVMBFxOiRhusw4x/PfLkfDImh52lKxV0/2/IXZVChDp/ixdzbvsVc1lsc0lvDVxtBqnS28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266398; c=relaxed/simple; bh=PdQeuH/q479pNV29WIA//obFJYFHNo7YpLv2PpGSleg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HpMIiuohtKtv1MVhR6EZA+2A5O/DSNENhnSxRcoFbICR3ndD59SnGk3CbvOAf+xjtbHjaThuhik/Zm6A2mHbUS5tANVWPHqEXxDXH0Bwm+6AFhbItlkXofzX7A+DqhIDanxUPyUTZ93HduYgaF9CBAoul5iV8BsTM/vqKhlUwvc= 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=gA0EZyfT; arc=none smtp.client-ip=209.85.167.174 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-oi1-f174.google.com with SMTP id 5614622812f47-4f488ba6e90so482744b6e.3 for ; Sat, 17 Oct 2026 12:46:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266389; x=1792871189; 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=p/4qBmrvtH6EJsayupSppfu0h+5jh/KQVNPd30Ou/RE=; b=gA0EZyfToqW9Jsvnl5ShgSnQgjVmJvr28lOjhen6uiNzv7aJ5A09jTk6NSnZbvDVr1 GrsXmyqEbUW8Adp8dxDVSfTy4ehIssZHQ22J5q/TEWu46QZQz6U7TdPM4vF8VLnlnTMn dF23H/dN8LlvxV0BVF84HQcB14jAAyFlGRxC1kT8gddacO+Bcahj0YTAxRdn7xxQyHlB JFoC8CmslUkZK4jMJxucfdW4RtD+WIenGZu5FPsdnEr+aldu1DN3A5PjJD5/34cseTYf JhGny86+kvyqrTedpsyo17p1tgpohC126Y2GTTWW12GkPOJA2+hLvrxjc+COi/oxPiMj +uGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266389; x=1792871189; 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=p/4qBmrvtH6EJsayupSppfu0h+5jh/KQVNPd30Ou/RE=; b=cMrsXuloUrUVmJPGXI2bE5QYP7AVVykvoQHEN58zaKiH+lHNXC/IYeiQ7yaMXrWi1L IQP4LjmL2YMhJVu6EXNdhnkbrnvw+6zKRepL2zplg4+Rmv+bgpRBy5xPTme2f8ORJyWO 6OMbv5bCaSIA72BAxj+i0yrakEYOSEhdiCYlduzePgQzEID+Xwzn500JXf5Ppr6ocNaB jfpj2Sxly1yC23ZePp65g8NcNPKX2257nkDzclaTVDiBDRJo3ULmzmA24TW68gaGiS7h TgLegT/8sYz2dnxr3eJwXngYtyX9zILCeVoYP8p6Iq7mobiBTnO1M7Oq0D9NVtfJuiiU lq2Q== X-Forwarded-Encrypted: i=1; AKwUvBzN8Yzxnm9ACPwXoG8MrktzYQWCBy9EIEXV62/21rRDeBFRY3kDKY9gaQFCCjL41ewWQyHeHx/QW0jdxA==@lists.linux.dev X-Gm-Message-State: AFq9FYI4j5OpCT48+7pZAx0SsAnUemevjutLd8gCCqPjVGpvW94zmxf8 z804RGcNtvlSSg4lDZ9nfdTp7PxKpzRfc24/tJdS/w0TJ3603dgX1wCU X-Gm-Gg: AYBFou2F1k9Ay+A0o3Il0dNLG+KOWoA5C/J33bjaAOlT+VXcE2M8JzMxzUJ1ZOn+Ery H/YHjVRdD5OWDPAKhXyTV4KIq6sV6Y9DLoctsAqFxC6EGpwI60FkPQ4gkuX9y6ydl5zkaeEN6LH KOgM+Lzs3YEoKgA1+b/CHZIYjN7PauzCfnfMJ1Lf6Sw4d+UuUUl0PPCMKgUFg1xRLZA2+vAm1x0 lff4eylMrcVpwYUdTf5GlGEhaHol2xNqm3f1wCsKJsG1xi4AtNEW8+OazJjEndAA/MW+d6U/6V+ teWzcHuiNu/UFCnudoM1kYDig4hNMfRRj4SFqrFKx3f7NJmR2Nk24ARfdf3cLqhlUPkiWr/5TPz dvrJg9uoY1Gay5E7IUBJW0X265kyCqUyXnzURBcX5tf64Im72CiZQ94RWLoZp63DStM2JIwQauc +t4LJv+TBe9YK9q0+oJJ5BIRR3ecZ5qWzEuKvC2kgHXqbt0YiEZ+8NQrZYOlEpJeQsB/CLV1auL A8LuoM5i9GzwpsilImnDf3y9t63UWBy1xS7Bb4qFUsY1eu2ics2K05MhKMyOxfPSBOqaa9uv+4f kcxcc3buYcn6ZTdXjv0G1fIDyjvgu2Orx3uzWihVs88tQYzlGXIXkc+oJ7K3RmvbXu8lqkvY9kk 8hBXLuwLB8OG2OWwNdoe4 X-Received: by 2002:a05:6808:c115:b0:53a:8c5:d7d7 with SMTP id 5614622812f47-53cd209d1damr2708997b6e.58.1792266389388; Sat, 17 Oct 2026 12:46:29 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:26 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:04 -0600 Subject: [PATCH v9 09/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-9-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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 | 174 +++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 82af3ccad885..b79a20158cd4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -681,7 +681,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); @@ -697,7 +697,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; @@ -709,17 +709,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); @@ -735,7 +737,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); @@ -749,10 +751,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 */ @@ -902,23 +906,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) @@ -1169,31 +1181,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. */ @@ -1243,14 +1263,22 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ if (read->dma) { - nand_change_read_column_op(nand, mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, false); + ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz, + false); + if (ret) + return ret; } else { - nand_change_read_column_op(nand, mtd->writesize + oob_off, - NULL, 0, false); - sunxi_nfc_randomizer_read_buf(nand, oob, - ecc->bytes + user_data_sz, - true, read->page); + ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, + NULL, 0, false); + if (ret) + return ret; + + 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, @@ -1290,9 +1318,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; } @@ -1311,13 +1344,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) @@ -1440,13 +1481,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) @@ -1472,27 +1521,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, @@ -1640,8 +1697,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); @@ -1766,10 +1823,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 Sat Oct 17 19:46:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3663 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 7C5E71C031A for ; Sat, 17 Oct 2026 21:47:52 +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-26736-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-26736-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 68B5639875 for ; Sat, 17 Oct 2026 19:46:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3C0E949502B; Sat, 17 Oct 2026 19:46:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q/+TLI6Z" 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 2DEBD495AD1 for ; Sat, 17 Oct 2026 19:46:35 +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=1792266400; cv=none; b=jcasZH7ELVapIr2MX7xYGwdPmy5GW4iNFrkQoSxjxHAmUJPB0EBqtC+lO9dp3CESdmFilV/7uS7Ri0gr/fM+sNJ1lIVRatn1l2URq13EB+s82pe1yXWmdWNOvjzbiaoewqSXuGJKety08GK62yNhVGpncSYgC6FTd5DFKOgKqEM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266400; c=relaxed/simple; bh=m1ZuakMOOcoJ2UTtQA9uEqk1ka8SS9czOwQlxYyqTGQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eUVVHXHvpXdf7fV/XZJ/rvI8VAgrGauGhLpYOjhWXGj0hRlPIfFo3nZthDbO7ibicoXbZpvR+eQJPEYW3/a7zw2jNXpdPFf6K8Olx+FgGM7wmE0rs2V8FXMtbYwmL3dJizaktoZmCwOxTpsdqunpQwNVx4EUZZ5kLahjfAU5CXw= 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=Q/+TLI6Z; 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-6deb848ddd7so678950eaf.0 for ; Sat, 17 Oct 2026 12:46:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266395; x=1792871195; 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=ggIlYqb11US26O5sA+ImWPEli5zTJui5OSrJsvz0LFw=; b=Q/+TLI6Z6vTjuZFNh6jl8t1wkOW9gPvIchMI0jtgt8OzBIuoSlG0YybJxcOtkWxx/B 3BitDku3DAhdKMZvBreKnMPWZ8/IGGvA/MKoQnkauf3JhPc8LrXuJiHxzp+D8dP8kOJM cfHOPpO1uHJUIdA1HW1oQHXnfJyqxMdDxwhDCpKLrM3kpP4ie1KpDrrEVl/9vQGj7rz0 k4FQCB3bVwnv7Vjo0PlsVSJ6r1SsQtBA8Ps2qt0oihHurooEQNln5W6BcoFeroTUGQZ6 x3yllWtML1d31s68oMi+PmFjS0bVOPeaGKlK9lmNPl15ORPWfApGin26eXN5B5iEPyZr dNOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266395; x=1792871195; 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=ggIlYqb11US26O5sA+ImWPEli5zTJui5OSrJsvz0LFw=; b=NyEfZeth0Z7QLy2/kZFxnMD394c+0mBFo6Cg+XZ32wWTMpEqmYhgCLUZoqmOEZO1+Q oNvr8wdEoRKP8SCPufioEO5vdjnaNQezTipKZJoTkG45/Zigp2y8ylyONsJiG1xsxEkh PKWD221jbjfqbrpmD4rRRhFmnvM6iUwLHrw41mBy2Hx71hCPB4O5NoeabHPPv+r0FVrO d0FaOAbpgxJvaBo62lpPBC0+GJqX4XNDPjnjPVSsNfvHjVkrwiKv5FWuz9bmV7Dn7942 08zqT5MG4blch+LgniEoxyYnHaTaDdcSM0wcVvNI/5kTJj7F51Y2cCwrQz+G04Ro2h1e GxeA== X-Forwarded-Encrypted: i=1; AKwUvBzPaFe9ZNJ/GvpqXSSeoBxEfPL+hLUfWEeFAsUvj9OHKSxVxQNK7rAZXyd5LfcN6GVWqS2Gmmj7mh54Tw==@lists.linux.dev X-Gm-Message-State: AFq9FYJZSLTLeD1fxTSmYyE+xnH5xJGygQaxDvF9wKBng1XeufouUK6g 7iJLBZnIxyNfZ2tTuNv2ZQM3OB02fZutq2Rfa6Dm8Wg4AQ3PtOPBX1j4 X-Gm-Gg: AYBFou0EwIDOkHAC5fOZ5CQOI/uea7mVjNFPdw6kYpNpQdzWPhyrXv4ETrt1rJCaZuv APlzHLcobgY8nTQiDsbD2YDn0ekcMPsaMlio6GLevGfaPPu5ffevcqkf3aUBrI6KFv58hJunc/0 GM5hvapGhI4vsCvZmWhvrPOTWEL+sA0DtcDa70k/47wHINVVAxZIBFezZnZZnwY+djlKxHQIqv+ JhXuiHv3Z1pF21+7X8ygHsQLdi3CjsTKUbAqeLAEBlZt8ED96NXY2aq7GT42fNNcQpZSH1eX4kK 8CT9roqb9GwYGAaHCF3MnCriLTE3TGqBE1QknfKLVNBOVZ4pWLfFFNZ0QXLl/ddMQpzCaTL1i1Y BSdo/h9RjFf3CPhwpMMvR37zY1QQO4sIuLckDEHJ2LmuCZsdq+WJs55tpCkxhfKjYd9s4ne+YsK Oyqet/VKYHO56nTgg2mFVM5fQlovazpGZHc/NqLy7QVLhcE2hQx1v1K5sAKQORrV6VPHmlVKdTf Z539gRtepeFfDL/RY51WwyIIo17qwByeRLRsafLRP/Fm8AGh1zUqKg2AghpNJ+66Uxlfu1+YoVg rxgpAHTlcKMVXdS4FBJwExqq9p8MlPhZpNgB5fgXnzS0wiUeo3EcCtrRLEYtOEWsOcpkZ415FFS 8ka/k++YW6zIO1el2aJ8N X-Received: by 2002:a05:6808:238a:b0:4c3:9892:96c3 with SMTP id 5614622812f47-53ccb300dfamr2614650b6e.22.1792266394712; Sat, 17 Oct 2026 12:46: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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:31 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:05 -0600 Subject: [PATCH v9 10/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-10-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1:received,209.85.161.45: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-26736-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: 7C5E71C031A 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 b79a20158cd4..f00f9a8ff66b 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1848,15 +1848,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 Sat Oct 17 19:46:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3668 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 83DE51C2045 for ; Sat, 17 Oct 2026 21:50:40 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26737-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26737-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id F0EDD42DD0 for ; Sat, 17 Oct 2026 19:46:54 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 28F8248F84A; Sat, 17 Oct 2026 19:46:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="L2f4F2va" 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 99AFA4963CA for ; Sat, 17 Oct 2026 19:46:38 +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=1792266404; cv=none; b=qWOYPQSXMW30s7rDFGdfZdCfElYnRQDcPMlFC1ASDLQKFELD3K23I1zBdQKp7jAMDSaNSbLP9os7eMrOoy6hbAkkZY9iqGPKe0N2xppUd5K2W3lxmgMvOJUw2cUWMl647OOGN7HoOoCOUuIjIJWqXFeuRccj1LZFsOk3L8KL9aE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266404; c=relaxed/simple; bh=lCv2gYemwbI1mKURr3K14d4/Nb3rNKPrtxXImPwhdBI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ESn6S5XguG5gduNLqZiVCC1jxYLLMs4QCEB+Ius0GpIAZ8TM9/puG2yKAURGX0miHRIDGTR6s7MHdGmz6XQqsH6blO8gCqLZH5dQ9zCzUb+yB2TeTKH1y7uzZohNedwmO+TnWezk8DVIwBG/iBrMHckqPGv07abJlIzPZJ/K2Mc= 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=L2f4F2va; 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-8451a619da7so568254a34.1 for ; Sat, 17 Oct 2026 12:46:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266397; x=1792871197; 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=mTIpJDfoSvJa9mNPyvSlvbjoEPEDMGD1iYdf7xNBtEM=; b=L2f4F2vaOmzWR1Uwd5vTutGzS6YlAHyUzC1b+ZGbiOVITqaeYFgceqMibLHcj/QgxV QFubIRMSwrwy/HUyXEp7qL/pemHFtOhzrHz0hgIdyqEivd3YiHT9xxEFu4EK2SZQdQuR I3ft6pt4KMOUJDUbwTO2D7O4Lpflgk3YFCJStth+8gdPTQZLMCFyE5xFYJPYZHMNaw3J jGJjipU5oqyRIkru7ehwL5anUzrgZbF2gX3hbduT4ogfSEQOalP6rsWhTT7BUxhonSHI 3AQIevf3L52EqqXHjskrZXbms45qJLtVs1IUQEV8wvWrhpwWHv8FRVF5h83DjMZLFXOQ 6yZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266397; x=1792871197; 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=mTIpJDfoSvJa9mNPyvSlvbjoEPEDMGD1iYdf7xNBtEM=; b=rXpWouNwhSGxSsuxkIixs3ZZ2W1Z4mR1kzONYlS3SKDzeXk6ZKdcCGTZWYOMFTmTTC VLyyPWrebwqWVEJWrx5zd0iRVjTcBULfoshIVM6DF/7+T9liIkboLQ6oAc23UGnR9mhF Pv9W5EG2p+lKFeldlQ7a9TJP9NuB4wx5MhkKuYH+bUQpWO8hln7AfIeFTTk4dygihyeB znQgiaEVrgtsBwGGCe40Fycp/bGHPjXhquRNCujm+oNYpBfEb1thiQWpSd0QcI0MpYcS VaNipPzlOCyfLDRlxXUHGYAtx5ROpnvwBJ61qOdePuol3V/LX7lq1Uo4QJP9syC2scxB VEag== X-Forwarded-Encrypted: i=1; AKwUvByoGKQBvcI6ic2BJGzNVGTG2kdSqZia6hFWMndMBZYsT2noQj+xMx+OAlXpUl4LPvqgDIZEL/fdgJX2eA==@lists.linux.dev X-Gm-Message-State: AFq9FYI9TtbHdo793TS/6xKVHQ86Ef0tnC6HrWod1qMZyQtlkJXO+hlX hU4vJL4TrvhEI1/ro+N4B6Sfu66jMCSuaoBmi04slAiGsLltu9zLcHhh X-Gm-Gg: AYBFou24e5xYkEx6Yfy1+DBrCrCzU1FwW5KLeGI9lDNIV4yeF5doo1takPalWChMui+ +a8llu44A2at06RJPL5DrDMgVKOGNZttUFLF8ThnL5KgbrbDOMata+ukilamuERtviPnNEiIFS+ 1LuTN8qyyOZ9EOCwvLgPER8T4lcWLbgCgpa1iFchFjuNCc1CW4/Kza2uhwswEkudfIK27w/jd6d VVh3ch6yXGl0uIbS9ZseUeae8l08JEnAJBR+lvrbkscY4lniHsDnbSgam1EKhPrSNXiaDBIbw68 Q2im6dO50uvfy6p6SPbND18SMvjM1kDNlkv8sNeuo93ZixwJorx1kteERTVEZyajyPeECwYh4C7 pdBgcieIooWHQNTDMMctKr4rI4ygtaIAzx7AbCuRYlJgbrWL+XeG7TGTFPfw6hVsKI3BKCwW3EX 09q/+g5A/ieAL/fOpqb9RdGhTCaW7no77vz/K929jGCxcMyFnUxl3pOwdMiBPLGiFrZ41yVTUyA fcuMcZ5AXImdx0FoG5pV+fm7T/0Mg== X-Received: by 2002:a05:6808:6b89:b0:4b3:7549:d3c0 with SMTP id 5614622812f47-53cd20aaa38mr2724743b6e.18.1792266397145; Sat, 17 Oct 2026 12:46:37 -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 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:36 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:06 -0600 Subject: [PATCH v9 11/18] 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: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-11-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@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-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.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; 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)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; RCPT_COUNT_TWELVE(0.00)[25]; FORGED_SENDER_MAILLIST(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]; FROM_HAS_DN(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; TO_DN_SOME(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1: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-26737-noreply=patchwork.local]; MID_RHS_MATCH_FROM(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from] X-Rspamd-Queue-Id: 83DE51C2045 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. Reported-by: Sashiko Closes: https://lore.kernel.org/r/20260913041642.E28F81F000FF@smtp.kernel.org Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 40 ++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index f00f9a8ff66b..ab9ff470062a 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1072,6 +1072,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. @@ -1080,7 +1090,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; @@ -1088,13 +1098,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; @@ -1196,8 +1205,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; } @@ -1263,14 +1272,14 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ if (read->dma) { - ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, - false); + ret = sunxi_nfc_read_column(nand, read->page, + mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz); if (ret) return ret; } else { - ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, - NULL, 0, false); + ret = sunxi_nfc_read_column(nand, read->page, + mtd->writesize + oob_off, NULL, 0); if (ret) return ret; @@ -1305,7 +1314,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) @@ -1345,7 +1354,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; } @@ -1355,7 +1364,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; } @@ -2333,7 +2342,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 Sat Oct 17 19:53:01 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3670 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 4972F1C2254 for ; Sat, 17 Oct 2026 21:53:36 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26738-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26738-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 2071D3933F for ; Sat, 17 Oct 2026 19:53:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D9F9B47A88E; Sat, 17 Oct 2026 19:53:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aDwbqF5A" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (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 CE348248F72 for ; Sat, 17 Oct 2026 19:53:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266795; cv=none; b=kT5WOEHxkLJYX34068UIuQpVIyYWClyaCMb0dRhYk5UHry1fXMMjcLOxkl7Iy/hygKHUYROUx2zLTujQ/Z4ybIRAR3n9yQp4dOhJRGWhhGTDbmHk+3Wkav4jc2Jegqq5Ubq7Eicpk0PweKWq0YRggisXKpVqYNHDZFqsUAGNeSw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266795; c=relaxed/simple; bh=GV2IeXg9Zq5O8ipbm51muo9ULIjiv+n4/kbqUlzqrm0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Erh3aMtPC5UkHU055MFMYxnihEzrRDFrZH4BSVqfRc371xgkTLFczGlCEkpJES3Sh9NxWBchuPmtnkRUyI5XCoeQHXoWRxA0rmiZdCXR/Rb+Ps/Xuiicc/UZ46F2uVgEz/Pt2zIHomVym6EeRDXI/hCPbxlLRwT9BPmtfXz7kc4= 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=aDwbqF5A; arc=none smtp.client-ip=209.85.210.53 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-f53.google.com with SMTP id 46e09a7af769-845f3fa7f38so219509a34.3 for ; Sat, 17 Oct 2026 12:53:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266792; x=1792871592; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=4P4PvF1h4nH9aNU08hyrkF4dkUmnUPpBIVg5VJpyCM8=; b=aDwbqF5AmBzvlOeVJQvO9QS6OQzdXP0QO/icjMn/59ngGYoBxNa38DCCw5oGhsbNFK JYTS6CWk4wQQ1hIVfBCoxhIGCxs7i4AuhcQawcZGSrko9q65ASMbHDL4MjfYa7svZbRt wJHlSAks9l9T7+hbSbGMNlRsxJHL9BvIa5+HDCoARwOTG5SyqXh/advMWcsQgCyeSmJz s7vK2bvoEzPzE0UvuNryOmeDWiodocjdh/DCMlywVpOuTOupPw/8AznppngFQMFz7xt4 t8K9ke9LFHOttfIz43S6OfDL9S4GXMVKC6XH9hmkG11Athzev8VBlKKb+1gIP8Gi88g4 k+vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266792; x=1792871592; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=4P4PvF1h4nH9aNU08hyrkF4dkUmnUPpBIVg5VJpyCM8=; b=c02hO/hoE/jYbKGyfIi51mGPA1Gl1n290rRMYmeDPielPNCBE1CWKn8pO7MXukQ4cI /Hw7KuAVZcemaJaRrfrv518sm5GYt4lA469kKdpgqikcQ/KKsplXscT6AVQ3WQv7rxhl XXyj/w2KxvXySTpTyoOiOv98SAd0JKwu63UhAicFKOladakrYwZMuoQGOCWjdtRENjcu UnA/DNj2kE6laBiCFuuuIQxjRNHx2DhdIfJ/HpVW/bslJlZWBg0uGJbUcjCBFwvVYuyP 72CRkByUWB+M1NQR3N8hcqZ65gJ6ssqpnrf5pONL2T5CPZ5bAeMvgCyNSaXTVsqNGbm/ U/ng== X-Forwarded-Encrypted: i=1; AKwUvBw/zewuq/D2HHtXuAiw0vO6OBvJqulXHhMIjwb2KRa+V0j7DEeKlBRUg95nGkuK7vhTT7yxEmIbZhu5Cw==@lists.linux.dev X-Gm-Message-State: AFq9FYJc0UqAvr9Ngqcqrv1jKxDLu/MTGJt6y2wxDGIh4TIwQW92muJF 3qzSa2Z8QY6tWnbyT03q+y5ysFEzwC1Ob7IxhygYb5K+V0KIM6CNieVz X-Gm-Gg: AYBFou01FAmjws+XcMnpVeHXd/2g5Yp366IT78hDOqXEpdvtcNuzZrB6x3CkSRG87n5 LPe6l2WIk2VV3RkTYAt1PxAPLW/57AHImFCgWMFchpF6q2PEumvqn+x8oCTI7UEcM6bXvlUbFhW kU5x381tlY9iFwO/+t7TqPXhMWnJtgubcttpLsanVOKX/Xm6KSjQXahLi62rwmb/jWvQAW59SNJ tVj7dlQkMbjJbqT08f65yjDv4nnb4Li+0o9KwEiKMvh2QXi+QsHz6peu5+oLJnZiAi3k26wOYzt VQ+/ik40Qk9WGGK0JUWEPZc+fftAt4S1MpZlgWZPmlVO57WMpa1hYtGSn3l9e044dqqOlUZUJzN QCcoevbOkpiyk1i8ze0QwJclcmMpUe8fhOyjhAtErmqI85n82zgIvCkHgiWwUI+X1L8GA2uAXMa lT8PQpT8fetmqagJFWXczCTSOA8d5od/ipj9WrpIfAxR+GRs7Gr6E3oEb7Fm0oaVqXNnMkupJfe bKIP17Jyfq0j+v0taf08M6Ivl6aj5d8U5LKlLw6uTiiyOMAOCQyBT3YBbYVqwsBm1F4lDg5si1v nJALfg5y5NoEdaNqNg7ZNrcwjrK6xreyMphjxEgoQeKHkeE1AGYCdXi7bbvTP1Uu5UtfXmzKbXA Aefe4/nvnCXRoHWBL/W5d5ZVfuGZDteo7OqkUl/FRIfln X-Received: by 2002:a05:6830:83b4:b0:7fa:5c68:d050 with SMTP id 46e09a7af769-845009804d7mr3324399a34.26.1792266791655; Sat, 17 Oct 2026 12:53:11 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-842a6e12dfasm4829795a34.24.2026.10.17.12.53.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:10 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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, Sashiko Subject: [PATCH v9 12/18] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank Date: Sat, 17 Oct 2026 13:53:01 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-12-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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") Reported-by: Sashiko Closes: https://lore.kernel.org/r/20260909085138.9A98A1F00A3D@smtp.kernel.org Closes: https://lore.kernel.org/r/20260914031929.2E7091F000FF@smtp.kernel.org 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 ab9ff470062a..69e92fe21040 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 */ @@ -969,7 +970,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) @@ -1394,30 +1424,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; @@ -1425,7 +1457,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); @@ -1457,10 +1494,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) @@ -1766,71 +1825,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 Sat Oct 17 19:53:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3669 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 5CF3D1C2254 for ; Sat, 17 Oct 2026 21:53:25 +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-26739-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-26739-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 032BF2B8A5 for ; Sat, 17 Oct 2026 19:53:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9F48D3E3166; Sat, 17 Oct 2026 19:53:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PtI6gqhe" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.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 D481646F484 for ; Sat, 17 Oct 2026 19:53:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266797; cv=none; b=RIF2kRnhX9jZ2jTsXcmjfw6I3ZLN9PoBlze24U5KIKwaYfY0LTw61fY3MQcxEIkXXI9TArw93k7jPv04oKoNF5Z/n6b3MVCmycTxjLwMNyiA9LrhwYxn+5+24D5BQsOSt+YRAjBleHJrebTbHgvvCahANmFDvrIJeX7xKx9nd54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266797; c=relaxed/simple; bh=y/k0+Vyv7GMZjSS1jO8ajLO2qrk157wIklTWriY/pDc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=umAHIdFyCdku0EKBMvFR32RIFkNQsT92tvUEfxwB+SlmxXQ/w+5QZ2WBrIHsUyfxFoUPZ5tR85b+MpmV/P2Ho5bZbhZyO9GL0nai8FNvg9x1qGFAEsQ7BB1xmeqSPfLq5aIM6OtdoaNp6QGUvF2ceULKvJ+VaqTZEyHLMJ8PjBA= 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=PtI6gqhe; arc=none smtp.client-ip=209.85.161.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-oo1-f52.google.com with SMTP id 006d021491bc7-6f5a0893610so693690eaf.1 for ; Sat, 17 Oct 2026 12:53:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266795; x=1792871595; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=Nf9wESnWB/+K14vmtalekHavvufaIUlDxawFx43Br50=; b=PtI6gqhee3t4bQ09PO/oPA77lBYOqCCN1c3sIdQ1nrdKmX1/B1uUzDGpPodm6kASb/ qIoj5s8FCd+XR2rEtS6KPzkGl7AfB2kBOkgA4daiVa6Mg2XNjRIjtYXFKVyGTRPz+hf9 3Y2yu5fzE5MCXhhW5TkTsWwQm4ucwhAg9BqDZ0hJJXmYlQ0D3DxtGA0pbGoIJ0rco/Bu pJnJaS0JwDJAMrla9e9sfD5W5/R2levzf3IEMvzqIL1yR2PJRI7efH1/CJzOXdj2ykqE weWfWd+YAlDxtLXEIeDblvwUMhbTlGV8FaBVityIRX90u9zElotvfjGAG8l249d02at6 xf+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266795; x=1792871595; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Nf9wESnWB/+K14vmtalekHavvufaIUlDxawFx43Br50=; b=p0gd2R6W8uJGpdjVu2lNkYhYs9ZWuY0xTD/vupsKoUMwM7rEjrcft6HFf23xz/MUGG DQZr8OlaDxl71kJTXMSv3vW5hcLjMibxCKqZlp5A0WZsL8ni8O30jH2Q3FAKcrZnxMT6 GsVKvBDUSQszflD+WpFAaHXRPXqM+klLAdxnfVITR6ep2u9s20QFwvzJp4LcSWD/m/5y bGK4Ua/UW+pgHU76C6lKLo0+UrPxU9ILc/sd05jZ8bGZxEOVu/aZTPQNZD3amXRgYGFz H83zEyj0HBFJmu3A8dPuvzLdraHpvXZlfHSI+DxcmqigG1HiAjWbEB7LU+4hJYGyRd3n kCTA== X-Forwarded-Encrypted: i=1; AKwUvBzExCgBUC2ZEXb9oCA/pu8L6ssk1/7yjB9PZRAto472XBf7LJP7wWTEiHFGCE1yq2BHa+RAR9nFmkM7xQ==@lists.linux.dev X-Gm-Message-State: AFq9FYKuYULblV4xpdLorCra4Y8qsdQT5JUDgTLyewDGkJm9Mr0MF8Bs E1wwkDzGHDAnZRGg/OANyIhw8vt9osZ9/Wf0UU6YHQhOFBRzwoEyLand X-Gm-Gg: AYBFou2W7gKpPAhGiQ7vOCiCPaIIv4rl5GF4ZcyClM9t+47ExAzodKaEeSTQB+Kqtz8 RAE1eUtzXgLhsWPFpzQHfu5UHeGl2oPWgLlllXKJlSk2fzfsVIogEnG5jig1d9F5+sXf9SXj/hl 6E4zjuNS9SHFzciSKayTSL5egcxgyrlVAFieG/MEOK0xQ5OI5VKRyyuQCmQniHuiZvHbcJwHjxT uxTYfys+oZ8DoBdnrTg8gJhtWtWwmUJ36qtXrXekF5sdtxgq+YyYwd+dJmrQlLV+GX11Kf8c8yd rWwFbwnPGKTwKBKtQN36UCZ7jQJSxnTaDdz3Z3Jnu8h1a4KmvpXBZVUi5OWHIKTjeF2543C9pee Ma/KVVQPV2DeuP9mNqq38O+xy5O2L63gMD1pi8P2hYqeHmz5KvqdZK1emLgoIu70zUWgrH5SUd7 XizalN5+889/t2OH8WvlSLvK5TymOfgKK3K7sd6kfMUc3pYe4usLsfLnwfWCqh1hJ6w/GrY/8n1 NA1f9lNTcd4ZLHZk43fwwJm9o9hpAKjO2+7qHZJF0ZN/r4VVijuPwy2hGLEnDkbnddYyXqMO5AX 5OMnLwrMbCXt4YfBryZEBIKcSmYyf061iD/ZM9uCYeOXE1mDE9wDnhJO8YGCKt2zqKRaS/TeM18 JaYH8X9xsA16En62lgZ+35+NUCrRO18iq0Q8CevtpcPw= X-Received: by 2002:a05:6820:1693:b0:6f7:b0e0:63c7 with SMTP id 006d021491bc7-70356495839mr2211954eaf.35.1792266794730; Sat, 17 Oct 2026 12:53:14 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-842a6e12dfasm4829795a34.24.2026.10.17.12.53.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:12 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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 Subject: [PATCH v9 13/18] mtd: rawnand: sunxi: reuse ECC status within each transfer Date: Sat, 17 Oct 2026 13:53:02 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-13-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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. Use a cached accessor so a reader can request pattern IDs without knowing whether the initial snapshot already fetched them. 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. Consume lazily read fields before starting another ECC transfer; each PIO step and DMA batch gets a fresh snapshot. 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 | 108 ++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 28 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 69e92fe21040..a12ec60c63b4 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 geometry and interpretation; callbacks may issue supplementary reads. */ struct sunxi_nfc_oob_ops { @@ -273,7 +274,7 @@ struct sunxi_nfc_oob_ops { * Return zero on success or a negative I/O error. */ 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); /* * Finish remaining OOB; return max bitflips or a negative I/O error. * cur_off is an absolute NAND column, or NULL if unknown. @@ -1155,23 +1156,82 @@ struct sunxi_nfc_ecc_read { bool has_erased_chunk; }; +/* + * Transfer-local ECC result cache. Pattern IDs and correction counts may be + * read lazily, so finish consuming them before the next ECC transfer. + */ +struct sunxi_nfc_ecc_snapshot { + u32 status; + u32 pattern_found; + u32 pattern_id; + u32 count_reg; + u32 count; + bool pattern_id_valid; +}; + +static void sunxi_nfc_hw_ecc_read_pattern_id(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + /* Zero is a valid pattern ID, so track whether it has been read. */ + if (snapshot->pattern_id_valid) + return; + + snapshot->pattern_id = readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + snapshot->pattern_id_valid = true; +} + +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_valid = false; + if (snapshot->pattern_found & ~snapshot->status) + sunxi_nfc_hw_ecc_read_pattern_id(nand, snapshot); + /* 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; @@ -1187,9 +1247,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); } /* @@ -1258,7 +1316,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); @@ -1281,8 +1339,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) @@ -1291,7 +1348,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; } @@ -1327,7 +1384,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. */ @@ -1335,7 +1392,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; @@ -1377,10 +1434,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) { @@ -1416,12 +1473,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, @@ -1432,10 +1486,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, @@ -1491,12 +1546,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 Sat Oct 17 19:53:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3671 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id B104A1C2254 for ; Sat, 17 Oct 2026 21:53:59 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26740-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26740-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id A5B123B2A3 for ; Sat, 17 Oct 2026 19:53:20 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 85DAE3C8C62; Sat, 17 Oct 2026 19:53:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m3O0w4EA" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f49.google.com (mail-oo1-f49.google.com [209.85.161.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 E0C193F9278 for ; Sat, 17 Oct 2026 19:53:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266800; cv=none; b=pdvYwUDJYL+QncI8eWVovYQhnwmNAtIdrJswuSePo02lwll9FV3wzcWf2kYkx5YpiYvzZGL44XZg5V6Fm8NfcuNVcAmgAGXm/KfqIlQDUFPY67G0GedPZpHxOr4lFjdEjHbR7ypaNLkuo2w97UdKcY4iTSU7Tfi+xIW8WmQTJ78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266800; c=relaxed/simple; bh=53QYWE27UsXxj+fYmOb0Pfq2oxCp5h+os5EvQeG7UFs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IMoPwPwSTALjE4yyM1FCeBWtuJjSOBJIsftV2/xDgEYibXdmGO/tjwKPF598gp1AAUT3/XjnzstCer3cIbVIswm8f+PS448gkxhKWWc//He3H8Bv80YF4oIJ34Wuh6Zy1L99Fo974XYg0J/UuhV9Nv9IZy0/A/faXJxrfm01/Jg= 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=m3O0w4EA; arc=none smtp.client-ip=209.85.161.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-oo1-f49.google.com with SMTP id 006d021491bc7-6de1ca1b05aso763878eaf.0 for ; Sat, 17 Oct 2026 12:53:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266798; x=1792871598; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=SAeoEq6yHDKt64XU8PioOz0s2+K/90/TohU+qG8Q+p0=; b=m3O0w4EAHmUMTbd3M2gRfgiZ1bcMYEfgFqq0CKa7wNXm8sBSMaQlXu1TmlbdyaY0er j1DKo+G+S1dtaBUg93cBl43jRlfrJsFX3UWmUA6yr1xQHII20hUOvAZ/fbhpF/DUlBPw DKQ+jn9AHyCUJmmnMR/cQAb9zYJ6y6HTqw8QlIS3TaVY4DIs8Lf7DXvIAO9LxpEb+W5E /+KRBXglaXStbK2e3k9AEY1OUffvNZyzerOwYaTgghd+MLRZ4Q5nyz/rjWB/MjqeBEEz 0Q0RSbPtAJi52JuL7x64yMJLx8b0pmSZdn2aF/3e+zoJP+4HU2RQ4r6OsiUhA2KlIaqL NT8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266798; x=1792871598; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SAeoEq6yHDKt64XU8PioOz0s2+K/90/TohU+qG8Q+p0=; b=krXJzIxVsZBO6zSYTK75YlPiaje7+FX6e+YYdrP4MqtoJ6zZ0VTQdVwZgD5CDazVJO fVPkBKdcB//EIoDnITNKgEMOc0DmHsqTmf0pEOK1ZKbeL9XNqMs55Dy+R2K/THZNyzL8 MsOaLqI9Has01k/WmLEqHQGqWDaeRuOAs19z0zoUG4id8U5dBfmWLgGMOzAXeK0lhtso FGlzuJdkJMynNeRxqTIEkxZCPIyBzKIvL4pbTTACnRljw8dDDqdX2cgr91wLQ5DbFzvX uJ1knI6kOo2Gyx9Hes23eLwjEy6PONdsHN7jNc3DCiZRbcQl68B7ktmxtmq9IeWE6Xv7 ag0A== X-Forwarded-Encrypted: i=1; AKwUvByPZo/KmjFdhnT6umHTPoAEK4n6Kq8LB0+zaBVvrGgC3kUaWtS5BrghxuBB+p4h2g1J+mZbd8X/Y3FvyQ==@lists.linux.dev X-Gm-Message-State: AFq9FYKKUqXROO05SIVZxDv5DXFDEhUHGzqrVmxk5znI4yRW8RZZ+g70 Hl/P/sqzTiUitg2y500Hz/jMu6uNO+2bDMt99SPe3VrMH7vwWzu/EXWl X-Gm-Gg: AYBFou1TkRWAePEoV2HYuVKIzxIM0kdwgTIcrN5mSqhLV8MxTj81uDarpvtJH02KjEq DzarjS5GLlWO3nJvh+v0Aell5kYgStsOsBi6WS8amI1mkFSB5Bhkl0jkowb8hj+nqn02ZzuChve hxNcF7jvSXe5NQiWaTERoKB5DB6ORbwluU7ZUDn945VevyluMjeuCexkF3hX0VeinKFfGGPi6c/ cujLLM4CPLFuzXDm2BlINsYKO27Skyfe6HmFybCDzcDfpCV+THq3peqFgSnEqB6+1TJ6TfS//w8 zBosjJoCwFsSRR0QKlQXEJBTiLgqvXQOYxFCl8UTA8Zbq01sqiJgIT+04wZ2h3w5MfZXD2Yd31r eFe+kHLlW+zXXkLtlyGy1e0UJXbO/jxTmfRvQQn45u7AIl25p5MnQEy7F4XVmDuo890dVjS1P9m /yJ46r4XBe94oYPFjI7yKJKvH5ckuCxGPNjqJx+yZ/jXlJzbnkMOL74FITDF6OSP2hKym7t7WQc EED/5jG8Nujj9AZGyt79zwxDWQNhGppxLeGBUjIyd6+CfYpx3ko3efiW+kK0PmVD7x/nVNHoVWe TyjOCtD7EPUhS4sXQSPYs9WrsVfLpTm8u2Wc3WzqHgVk/xxGBAI2jiuIAibxH8ih/bzHuaZaEbQ dT9Fgk9aA3pqKL93D15qEOOMW4lmVWtlAzvOnRuM5Onn5jcaB8qibnQ== X-Received: by 2002:a05:6820:c2c7:20b0:700:da68:7396 with SMTP id 006d021491bc7-70357791d36mr1496668eaf.67.1792266797756; Sat, 17 Oct 2026 12:53:17 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-842a6e12dfasm4829795a34.24.2026.10.17.12.53.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:15 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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 Subject: [PATCH v9 14/18] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB Date: Sat, 17 Oct 2026 13:53:03 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-14-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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?= 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 a12ec60c63b4..993e2efcee04 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1655,7 +1655,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 Sat Oct 17 19:53:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3673 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id AA9771C2254 for ; Sat, 17 Oct 2026 21:54:25 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26741-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26741-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 4106F340AD for ; Sat, 17 Oct 2026 19:53:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id DC96E42048E; Sat, 17 Oct 2026 19:53:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nSzZdMBp" 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 8757C2F7EE9 for ; Sat, 17 Oct 2026 19:53:37 +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=1792266818; cv=none; b=sw07tl9tFEufWOW/aMSSXk9WkejFiB6+cLtbUv88QklIOFPdCqOjN6THRgLB89EjedqeHXhgBXay72KhqSgl88TNS317s3hyHkizbOU044BU5BHjIvXnRTrg4excDW61FSQ4sBNFSXLhOIbfGn1e8Q8yInuiwaBzvb+gz4IIM0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266818; c=relaxed/simple; bh=xZ0mPLMCwDzY8Ny6l4vz2klxVY5qj+EkWBSLeSH6W5k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tdU6Akmn4CoGNZ/8+d/32fpGdDzhP0TkzhFvOMSPJGgeIOQAOqsBy6z74MiZEQ/0lAKuIM0GFDcC5mf2oyEipeF4vJaXWL6+KXi0Az5KFA8WoYVrMF80by2/d53U+vn8Nim1RdoBkYHMtuzsEIrJb9KPI0XZE0d9gaH1/KaoY40= 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=nSzZdMBp; 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-845f3fa7f38so219574a34.3 for ; Sat, 17 Oct 2026 12:53:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266816; x=1792871616; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=xcmdGAknSlSB095s7l2UZ1pCIYoSMNB0vG29+Hnkm4I=; b=nSzZdMBp2mHe3UuWU5zklJn/+kjTMJajRCeiB9QVK+YiRFlYHEViSR1oNmYKBBIjYp erV5fv54N9ocEEYm+slTCL3D8SDHmAWq6vyZzh5gIi6FggRmkoOCe375EcVcLVyDaPqf NhDk7wLBZtog7apr8dj3tsYZnWjRL+Z9Caay12eXt4RWOWgLtFvvCwCVgouPeUrtMKJt r5B1/8nnw3S7NBY6M8o3bT3fk6JSI/6tW7mWjT1D59OT+Nm3dx18hL6awi8m/YndPp7L HQXnJdOlKzPXl6xgxEEr70e3sNbnJ81K4RfK/QHRNvM/Ea3+Gg6YBrcyWQNDbFxE5HsG hzEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266816; x=1792871616; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=xcmdGAknSlSB095s7l2UZ1pCIYoSMNB0vG29+Hnkm4I=; b=jibJ/Kjjt9boT9xcx1cUiXefnttHBIHhbNOfih33CljrPfooUR1WZtM3j6KI44LG5H O7MuJgqkSnBMCoRGMgr9TXmF267iQ1kv4ksAk40TAmOgOSdxYWGQjAEz0yHh/6sfIjpY aJTD50k4ZBlmp5UAGiWF/MociGP3emsFzPP8TOnX9i4nomsiCQP5lYYiCoA8y3SX6FFs I+pgZ103IULfN+UFC5eq3BYA0bybN1ghQr/1mcgqdkN7C0SZ28oogFv88uq3LiJUHASN R2zd/d6HxIas3Ktw8a6sUwL/g2FJBlQAyuHb7yviEcE62ay339mAYcxiNq4+T1HK/iZi lZpw== X-Forwarded-Encrypted: i=1; AKwUvBwseWgtuPT1nb6F4Morf3pYIgOyle5SiAPsxeAjRJyTFChdI2QmC0hFf+8XDa67rUXqgsPXGCKTclVaVA==@lists.linux.dev X-Gm-Message-State: AFq9FYL1ZX26aSuEJqsfhfPWRHMZ4/oU6TY7s1+r//nW/J0tP8SzO2xh /iGNeaTrWOEkzBj2JLRGPu/Ho8Y6wEgmuBAoB7Z0WyjwKGvzDZYx7pRp X-Gm-Gg: AYBFou34hE3RxsCKuYlWRfD48Pr8DMjJoBfWqnw05V9DLSVzLOd1OGTTtlO8qq4EDoq Ne4rLx7ZBosh4Tpw4Wm86K3k6zbASRS6wHslVfLPYcTGnSN/YZXkpvbRNq5dkeMF9v/aj6rxpkf 1KVAGlvfh8O+SSmCt2aRvBi0K2PCfSbazELNFyG3d8/ZmVoeg1ihn5j2KPzfZP0eG3xhaYBL+rl 101hLYl+x7N887QbUbVCwo4iyLdBjuHaC1C4VEIDR+slGeotPLe+6p9rDuaf6wW7vTJ25dDvGJl 5J7pdxf/Fdyj0jHg+Q/FQFdFFyGH2Qkofn1lPqjk3Zd/eqNG0O/uUqtdikkCAYBhz/NoRwaBxSd gG32hUUwxBEPJeEA6J2Y7rTz/eLMc2/7ns1Ryq/SGY2JYtnO72cIMlnGaH7Z4xvfNw7mfmx0++4 IfSHS9rYbjuv0wBlcXDRXFtqZWFFJ1jQd5re3OmAyFIBcNZaZ+f5pMz24tC69xy272GPW4b75wB bvRHg40knDbaMS5suDcwRe5p1wOlJI7aUeMqIASUVb9vd67fLy5xcxUaYh2EMjObf6g0Zwgs2oG 40qCOkw+sITn/zKIKiTe4dyymvXNmpDCzy1rO4cuW8yRoUv7Eu4w0I79PCc57BXET9z61Gymmxe NjR7e1IACjtkz9kLyw+OImK+/lnykIWKs5Nk/6JyWOkzSeF9vPZ5cXw== X-Received: by 2002:a05:6830:4129:b0:83c:2a05:c65d with SMTP id 46e09a7af769-844ff4249d6mr3801148a34.18.1792266816507; Sat, 17 Oct 2026 12:53:36 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-845b9e280dbsm2212064a34.19.2026.10.17.12.53.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:35 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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 Subject: [PATCH v9 15/18] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands Date: Sat, 17 Oct 2026 13:53:04 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-15-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 993e2efcee04..45172175d4e6 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1685,8 +1685,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; @@ -1712,8 +1710,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; @@ -1739,8 +1735,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; @@ -1769,8 +1763,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; @@ -1794,8 +1786,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; @@ -1839,8 +1829,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 Sat Oct 17 19:53:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3674 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 6B5781C2254 for ; Sat, 17 Oct 2026 21:54:45 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26742-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26742-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 757CC3C3AA for ; Sat, 17 Oct 2026 19:53:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 52EC9481AA5; Sat, 17 Oct 2026 19:53:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="paxq1rzl" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (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 98EDC46F484 for ; Sat, 17 Oct 2026 19:53:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266822; cv=none; b=ML8C0ELvL53/Im3qfnqbG478z1DX3/8UGcMDyXaKtuhfF15vDXK3BHXrdIuoi4qHjQeYU9MZWtrsQycCWca2rjctWcHTfIUc4VP78Ljv1YlmJSuT/J5mGIBa8SMoKmzJPcQrHn/dC6Q69VOEOXgqtDQm+j7TAp6nk/+x47d8QcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266822; c=relaxed/simple; bh=Nd/PTAsUmsfvFKiGUyB1xYo/rMCCfj6VytCfy4wTcFk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JyMQgFTHgVtu2rmYeJRUK1HTcoAwNvuGj5x0eg+WMOIuhpJNKbkXQYvVj11jBllwSl2/LZ9iLsYGKJ4PKyBfiXjIozlIdxdpK9W/iA5YBgFWYogT6rJL1fsXNg1D9F5VrQ6drn/ZLEA7tFqhDNre5ZGwjo6023Tsee2OxA96v2s= 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=paxq1rzl; arc=none smtp.client-ip=209.85.210.44 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-f44.google.com with SMTP id 46e09a7af769-7f48c750afcso489251a34.0 for ; Sat, 17 Oct 2026 12:53:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266819; x=1792871619; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=1FyhwdcLvc7Hi0cJi3ietTvT1uU5sBD8ynqEwPpQzmw=; b=paxq1rzlegbmNeFryaZe+z4BDy60XZMrsqz5zZmPV0ZnSiw7AxtOxDx7K5LCAgTfh+ LmILd1XwHQTXIFbspd6ce8Bmecnip/FO0RnDp+ic9sCsRo7VhAjMcKty1ZCTW0W4eR/t px0y5ik/tTLWEpkST5uGbIsKhANperLmZzEs3uCLs+lZwKI18FfVZfdgJPhSzr9ETrU2 +PnG+2sJO6t9rsSAs8M7BlGnJafjNzrMc7x4A7Xy5m8aC28Fh6U6UHdScn6Ml+JnKDDg XxXUVxuzHQIvlXrL2CHKba6sg3DYd5eGKf99uTEFG5BW2Jh8nuOWtrJkICgAtgwKYS8j 9sPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266819; x=1792871619; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=1FyhwdcLvc7Hi0cJi3ietTvT1uU5sBD8ynqEwPpQzmw=; b=ky7ej3yDtUrg6vKMW8hpgtYjiHL4TE8hnJ0l8mbw23ybQFupcB75SCiqoCcmN4wsrl WnT6RFnsSBxuF3kY/VT/LLSiEcg0wie3fMXaRLpEOCvJjGdNQe+Xu/FA3MPrOsw/MB+z zzRaAFyumIWbzR3GdYnU8Wbd8Y1mPqBZLA62lXBzlL59v7c5UZ9fh2jI0O2W5/pkvdEA Yvs0qaIrHR4oQ7zQF5mJgvi4v6SshbH5FtrGTULplhN9iIFiw9ZZCz2bfdE9UKdy0rC4 9XM9sfGNDhUabU+OPIfT5c+K+UOqCk2jsO3FDWFcFMQLWGX/f5u5IrHt+vfQyxH06Ajv 9hRQ== X-Forwarded-Encrypted: i=1; AKwUvBxwMmKX4wPZRrbNKRqWegyK2kGENmRIXYfC9l9f5IpqluuxNB3RMryT5izIXFf3+p2xqZ+ti8ShWk3eDQ==@lists.linux.dev X-Gm-Message-State: AFq9FYJe+DyjQKvLPH/rcptG/pw7zcZ0vC4mLquQGB3WG63R/ApGWN/b cljgTIMgJo/ZVxunbMdHvsflMku5/kvau19SzcwnyxO4OdQcIobN5qps X-Gm-Gg: AYBFou2VO+RnhYm449hjFyNZwQ7hOhWBpl770Jd96X+lvHZE840L9WbY8umK4q4se7I GY7WlUOeB7XhjwSzUbzSEh+8uxXhn0ZgU1TQgJfg5V/8JlOY5ytaYaDqJR4+xl/fpYSxzg215AW /SFQXqi8KZVnU1JqU0L3spZtk6BFy8MM3/HozRZBq3vannF+t5k1ITcGWKdrYvSxEwLMv6S/eKJ pzJXzNiDxy2f1kD5ChaAaqkm9orVo3MuAA3eU+k8sRCbtEwVuY6APiMhKuVpSiGzSWA1JjUxBz7 EOTexZhuT1JKyyDJ0NYE6wKabw7/cTLskbvSdafIt0lr4YPt1hcWp69Jhr8a4y95IHYlQc5rfOG zexQH3GHMJqq+7vxS5Ix6SZFiQYhfPHsKVHpjxq02+4rOTMGoCYnX0OUWMw8a4ok30zhN8LKlAU CE3yA9GpaOycRswW4146Y8wvHHhwmyWh35b+gF7MpZvrcWSfPVhBU1+RmWTvI6FnXGUyB8dWzXW 7T9mvJT05zoi5weZlWr2Xysm0TkW0rxqr8KYZASbUZ8Jn5e+IeCir20v2ufpqa2miU+7vnx98ac BUFc5ZGD4c2A2h8V9tdq2Ppb5uLijCez5eEXMYf2x9Wkv6oQUoNJ0XYubGuue0nGwFQ/HIRCKDv 7b9cwWb47gOxCd8qqInixGtb0Yw2v0p9TRueoa0yU/Hc= X-Received: by 2002:a05:6830:67f4:b0:81d:c548:292f with SMTP id 46e09a7af769-844fe7827e1mr3438567a34.12.1792266819518; Sat, 17 Oct 2026 12:53:39 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-845b9e280dbsm2212064a34.19.2026.10.17.12.53.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:37 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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 Subject: [PATCH v9 16/18] mtd: rawnand: sunxi: reduce user-data length register accesses Date: Sat, 17 Oct 2026 13:53:05 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-16-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; FROM_HAS_DN(0.00)[]; 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)[gmail.com,kernel.org,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; MID_RHS_MATCH_FROM(0.00)[]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received,209.85.210.44:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; TAGGED_FROM(0.00)[bounces-26742-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:172.234.224.0/19, country:SG]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 6B5781C2254 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 45172175d4e6..a20886991975 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 + \ @@ -1036,35 +1036,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, @@ -1460,7 +1485,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, @@ -1489,7 +1514,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) { @@ -1510,10 +1535,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), @@ -1623,7 +1645,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); @@ -1890,7 +1912,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); @@ -1898,7 +1920,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 Sat Oct 17 19:53:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3675 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 0414D1C2254 for ; Sat, 17 Oct 2026 21:55:08 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-26743-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-26743-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 8B84D3CFE4 for ; Sat, 17 Oct 2026 19:53:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9165947F762; Sat, 17 Oct 2026 19:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ECebXROB" 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 68ECE48383C for ; Sat, 17 Oct 2026 19:53:44 +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=1792266826; cv=none; b=Rb7xPasHpTjj7jt2CNJsV4JKC4QEG2u7HRxL3lKAEpR21cFbv/y+ZQLeSMHJKMfAbWemeVGKGsw4Kldcz98tFxExc7ESAD4FL0HwVqojqBEbWrvKcg9dxC2VV30tNkcVS4xLpTtstUsx/D51j9inwgAL6P7PYXJK7LTj+tQ15AU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266826; c=relaxed/simple; bh=A1STkpE9307vxyyhV24//arWM0j0kn3Imh1Mn5JF96w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MkO+ynDXKhuP/iTzVW5k9UrKXV2Y//q/mPVlgFKBcGiRPYikD7gxkT7Wtuq3pA0zstdIvVBMdTcdFGMExAGBz3Ksfqzl0kAhI3YgfzpyDRxAZ9G+FvpWLcUMQca6m0282d5hgnRMYDS7AFFVy0bzBE9YCYwqUNTHoArX4oQWom0= 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=ECebXROB; 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-84751a20d87so112353a34.3 for ; Sat, 17 Oct 2026 12:53:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266823; x=1792871623; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=ECebXROBa+4KIRYxiaunrFY3u5ogsQr7U3ahOK0Ml/jLYZDDG1Dsnx/Z/qhIj+9pFE OdkhfzF+gYL9lvvYQbOKRvA8empAa3++93JjBLWnHrtB5Iu3b4aipXIcbsk6UiLVb+Hm tV8ULHeQ96Kzvlx/mt06mKqlI4y5eV+YighiEQX1iT8k+wZlajmvJHXrFM7Vo4PeQXzh nkkm27iJxu3vrDG8uJnWBOTgJ/JO8xV6EMoYxyEue5KtwYbpujsEu9U6KO5TznjBXIov EBnJf83JFFzSeXk/7i0MiTHvEVKnssegfcbT1Q6jcRWliul9ww37ERCx5ZLqIJVZJyJR 7zRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266823; x=1792871623; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=Z4hPCGqSHVxGawWA4e6GpSrQUvlS4V7jNgIoMggTW0o+vd/L+dDjeVoNKuytED4GYG OnklH37d+LRgMrqA6p0DR277CxDDBM6ZpLdrTFc3WZRFNMnaCESCe/1VHjr6+T4n3n3v o8YdSPCwawCqke1PmyS1gT9YK7QuI7HE/EhuTqT86hJZWxgRkyjFBpYwL3syF7Li8E4I EWVcTYrHOtvCeUbzOnuelMIzhxtjWYZuADJPwC5OKHVavpR1DQE6Fl892JqRq14WdZuw z3a3ydssZAlTzQK+5u2864RV4DnSSPDX4outM4kLoIcSa0+mpeakc2fbTlbqD2iOI9mr PC0Q== X-Forwarded-Encrypted: i=1; AKwUvByUAu5RL5cO+BVJSSjD+y8rUt1SVfuZNxWhZZoPWf4UuhS8V9PBl81m7GS6pa2BldyJm5GRd2HLzDnx/w==@lists.linux.dev X-Gm-Message-State: AFq9FYIxqj3KmMv84BxVP8N4EDlGnhJJb+Y2KLkZcVjBanua2LR/iUvE z/xn1WsJtypwQ6roCrFRQtDgSAwUV2sT9SjGrjZ64W1a+Ek2vSlx8v0x X-Gm-Gg: AYBFou3HXrysEv8arYAus6kXi2MTCeXL4O/zXYp7I0m3jSEh4YDOyQFDQCrKwSNWK8k Gy+/smCoRbDFz+y3Bi/6whZsEs4ixQaxvyZuVpwGvA7aSM+PO5f8F4oFJKFWRCh0x5Du9ed2wAG 6FqCJueZTEY8Fmy8SJtWA9bH1F+VGO8MTCay+IMs70HQdIGIg2PX+yaPhhXFdA8O9vkgDEIncBy IlvQG1OCwT26b8c1LBlkmkO++CpypuqsNm9AzMWBQjci0PekYUJ2wKsL6Krf3hjqS9mC76EA4Io sRJ3hMqw8Czwv0PAxFm1rIvE+HWfPf6GzpwHLa2EW+UK6kmsizyiZRutJ3d3ZYzfEItedzFytI2 NTGwFNmYQwIDazIX8jZTCb5ZHRKLxpz02lSnMIVNyGDvVi304Z+OmTYGHB6aPFpcLJeSo1ENPin WWcDDfkTqUMV2JzYAo076+29VdggvoO+7iLslcXv3/j9y4ILnemyM4tedLZ2g4CGYbZAKJtOAgl 8lbBTZrh5tSNpzCEej19xAVCURjtWvHKcvd+BuO5RmGIwF3NcFRSYBc/haAebHujl3tv1F2BQND 0oqwRiecXyGzTg/WhJBCOhz6U/fFgPj9aLlIR9GsVdkQbY51BrPSW39D2OPQsKiS8wT2rQpgVyn JuDwCkzD0Zr2JU3kI5vVZKMTJkOvEZg8GED68O4X12JU= X-Received: by 2002:a05:6830:4389:b0:806:3072:240c with SMTP id 46e09a7af769-84501cf7377mr3819310a34.29.1792266823279; Sat, 17 Oct 2026 12:53:43 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-845b9e280dbsm2212064a34.19.2026.10.17.12.53.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:53:41 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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, Conor Dooley Subject: [PATCH v9 17/18] dt-bindings: mtd: sunxi: Add randomized OOB flag Date: Sat, 17 Oct 2026 13:53:06 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-17-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; 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)[25]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[gmail.com,kernel.org,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org,microchip.com]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,microchip.com:email]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[174.29.1.49:received,100.90.174.1:received,209.85.210.46:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26743-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: 0414D1C2254 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 Sat Oct 17 19:53:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3672 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 0D5C31C2254 for ; Sat, 17 Oct 2026 21:54: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-26744-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-26744-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 65ADB3466F for ; Sat, 17 Oct 2026 19:54:06 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 338603C81BE; Sat, 17 Oct 2026 19:54:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mlZ+jd4v" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f44.google.com (mail-oo1-f44.google.com [209.85.161.44]) (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 140FB248F72 for ; Sat, 17 Oct 2026 19:54:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266846; cv=none; b=EWOKMZhlMePtiKwA5wJ8HxAA1xOIHz4OEHPQR2HykkYBqrrPqqV68++WLcuUviYFE2T6fA+Rx186vMiE5MKvGe4PG8ler7/d+0ctFYPAIdVsW77GduS75PeFtR42GwviEyZTZ6lUPceTYSAqoxo7UGkfIerru24iJ3yn6I8ecfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266846; c=relaxed/simple; bh=K8P9jyhQysqyBit1YPvdwfMq1Q+3lb3jRay5pMQQRCE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fC3WTfK0tlemioKav4RKwSg/zZcWnofsF4i/a9zHdEBTHnPiszGVH2lDsTI1EvK2lrqaspqxwpyyfgiNgYO8PEDn2uPfFQtcq4QhkOlF0m98mEk8HU9jPl/uqJLrMV9P99qQs6tdL899qSLc20dGScfCRPrwbArk5oA4N2G+/Pc= 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=mlZ+jd4v; arc=none smtp.client-ip=209.85.161.44 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-f44.google.com with SMTP id 006d021491bc7-6c8f6a53fabso1953352eaf.1 for ; Sat, 17 Oct 2026 12:54:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266842; x=1792871642; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=InuSVqxPfUCmyhULsrPo5BS+GpwfEUb58pXMQyuM1sQ=; b=mlZ+jd4vDYF8oNJKzp1B+DV5rao5E1bsXSCY45GpVjVFuYUuQDDW3+mDeHdpAzfozM TS0QJuxdKkRoExMqAroMRekc6N7jHNk+U3iQB0jz8f6lCrn1tC/6adVvuLNvJIqb4UEI IkdizxL5ouxpsZeoXSfAqkALqewxDbu79RRo5DNNoC0kwo1JSRVqs/nfKq0PJqnLBmSr p3/EKNcHe5OzYlG2GVFZeO7hBqyWmaD795BhagaIic3Er1nMxmzgj69Z8q8HBEIXe6ck ZeGnSW5Hwtc4iHsvNc2JAxzrjoFzkOreKPcRwaCrt7qWTeQXBGOeInzrOvn1t7lqrtq2 tMOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266842; x=1792871642; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=InuSVqxPfUCmyhULsrPo5BS+GpwfEUb58pXMQyuM1sQ=; b=RG+BtlKkis0YzB8wXBFuvby+mIyQDUCmguIVScuVLRehQsjATf8lzewSpu3JEaF/KD mUbMgSabAo1o/z/GuZFdF/1tnA2VMcYenwMyEa2sRgMlGhGusNkdB1u66r2ifN7r/yQJ VgJENH3lS0Kb/d0nFBhNPX3ZFJNTHPN1XGWzADSK4QpWIKrc3PRC/nWpIM454R99JJ/l Xjb6edpvmVZqve1l52vNk+AsQqqJTNIq8D+WXloqofly6W/UUhRNDB/f7tpPRrVlKFL5 txnw451EhekfFw9v+HJnJQsvuXZ+ewxXHaXvi3BTW0J/8dL5nMqFYy2OskoJ4znukf/F GxhA== X-Forwarded-Encrypted: i=1; AKwUvBxqkOwxh9DpOfjfp+e+85HiaiwO2Lqt2McvmTtuS4fTXMTHtvW6GAAfUa/hN4Lce8/ISeMUVdR9LPppCw==@lists.linux.dev X-Gm-Message-State: AFq9FYLDT2MUfsVVWWZWpDz57yWr+AQm5AlswqB9R/JUHd3IRPRe9Cbv R+wGFg0fZSW4R/JdfTJUxugZxseC2/50d91TAzcnMNQJlWAfCImAqe8L X-Gm-Gg: AYBFou395eN9Jx8pr7wsVhM4vzdG9nMv/nOSDzmF3wwjzwBYHlPvM/QpU6rF5oJS0Rq Jx/GhCajCHFNsa/eY4UzU41dXRZfCRhfmZS4a4yie8XpbXw3Y6bWj0twcbjXBJbYQIMhVvPF9+r GQbetbZSUOlyasaNSNGcsqYl1tw6uUmuitj9ChHvHGQlqQWGqy8QEX4pad2og/MbRteGPiWArhh xXwRfGCjFi9ESnLePMvt1DZi85LBqVZh9Ac15/Ujw8s9ldz+mbCt3CLo90UvUriFp9aFVAumIOE uq742eF+gSqzuh266BW8w0sxMb9Qj8WoStxdR21TCjLP5Xd0B5Z688baCxD++EFesZhkgHZErJv d534VnKPCzSawkOaC69Yi987JoQjWs+Ovs0c+wGEF/A88k7DNMoxZIdRMAlfLKl1r9ZIKs7Yc41 gCYyLLC2AaJQ0KTobOZc8keal1EWMFuN7FSNDHemqyvYcNRFyqYgXJgPy1Xy8HUVHuULsKlbLUB g3lQ+tlvclJHxTuyJ5n4FMAZq+VdXhKvxj8pzJtfR3X7k9UI8C+bvEX3fSMfyILBE+5+3jxKoP+ kVhcgUHgDSKwy23o5IZJG54aoUVEOygxzwr+HNRA+ALH22rVI/UYtaP5XcFxNqnHCeoI7ikTX6F GhOkRhiPajaz1B1OZeb8gKdTqYpEOjeEvdP1balXkQw== X-Received: by 2002:a05:6820:1a08:b0:6de:16c8:d8f with SMTP id 006d021491bc7-7035639b864mr1771244eaf.34.1792266841868; Sat, 17 Oct 2026 12:54:01 -0700 (PDT) Received: from james-x399.tailafd1a.ts.net (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-701900722d9sm4107119eaf.10.2026.10.17.12.53.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:54:00 -0700 (PDT) From: James Hilliard To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: James Hilliard , 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 Subject: [PATCH v9 18/18] mtd: rawnand: sunxi: support the Allwinner randomized OOB format Date: Sat, 17 Oct 2026 13:53:07 -0600 Message-ID: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-18-5af9a1be16ef@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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)[gmail.com,kernel.org,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.161.44: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-26744-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: 0D5C31C2254 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. For a two-step page, eight user-data bytes precede both steps' parity, instead of four bytes before each step's parity. This is the stored format, not the controller's user-data capacity: increasing the reservation would move parity and prevent decoding existing pages. 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. This tolerates one non-0xff byte among bytes one through nine, but never the marker byte. These are byte-based format rules, not a count of erased-page bitflips against the ECC strength. Replacing them with the generic test would change which pages are accepted as erased. 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 | 331 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index a20886991975..f1c28a3d49b7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -357,6 +357,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; @@ -385,6 +387,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); }; /** @@ -1171,8 +1174,16 @@ 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; +}; + /* Shared across a read's transfers; buf remains the full-page buffer base. */ struct sunxi_nfc_ecc_read { + struct sunxi_nfc_allwinner_oob_status allwinner_oob; u8 *buf; int page; unsigned int max_bitflips; @@ -2377,6 +2388,298 @@ 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. */ +/* Firmware metadata limit, not the controller's user-data register capacity. */ +#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; + + /* Keep the marker byte erased; tolerate one other non-0xff byte. */ + 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; + + /* Page classification also needs pattern IDs for steps with ECC errors. */ + if (snapshot->pattern_found) + sunxi_nfc_hw_ecc_read_pattern_id(nand, snapshot); + + 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. + * This prefix fixes the parity offsets on firmware-written pages. + */ + 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) @@ -2513,6 +2816,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); @@ -2538,6 +2863,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; @@ -3035,6 +3363,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 = { @@ -3058,6 +3387,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 = { @@ -3084,6 +3414,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[] = {