From patchwork Thu Oct 15 01:33:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3614 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 ABF2A1C618D for ; Thu, 15 Oct 2026 03:34: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-26649-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-26649-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 6F4513A47B for ; Thu, 15 Oct 2026 01:34:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 281A833970F; Thu, 15 Oct 2026 01:34:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="e4kyLTis" 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 00129336EC9 for ; Thu, 15 Oct 2026 01:34:12 +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=1792028056; cv=none; b=hpsKbXoPkQIVs9Fr+k8zj05gLvuF0Tw8zdS2GbQpnKAk0c6xzRlzrx8JEiWsVs99Up0olgH41X9n0uwDJBTQd0myr6bMSjzAI2xvupOGLdbEIU0drfhM5paqsp5EzgSRKU3hfOnBJtXuVNzXzAp9iraHs26510ighi+fp/IIaII= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028056; c=relaxed/simple; bh=a8ql8pZvfkQJaeQ7cy57dwhSEFwwh0JZjOipei5GbpY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OA604kQSgLWdEizGi2A1EybkDPLVqMrjbBNTQUhYaeREizrFw3MsiA/zJL0ybToXFGity8xUB0QQwOVzQrJ0A26rDC1qqLGJbj8JKguSgupyTw3R7WosZfd+a3LeZAF4JIF7xulTxjcGBOEkvpEB6oI5xYv+EX1uphAMZ0PKUX8= 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=e4kyLTis; 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-4f488ba6e90so2108390b6e.3 for ; Wed, 14 Oct 2026 18:34:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028052; x=1792632852; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=E3QlrVAtVf/XpX+ZsmjMjSLBH4hnwCKgBumw+s30nkM=; b=e4kyLTishfC/qHocSiLCBXc87V2sjA/qazZ1lmDus4GLCugECko6ue+NOAO/ERBV1x X75rfngxC9L1RGSN7TRzCnFsratpt49d+Vz6bcL4jJSu/PHIcCV9jC11K55gARBuBP47 qT8VaAlrTnyiVxJrT6vk5vhL0JHYGwRwmrqcgpUa/SFFqrylK/OE5Hoq0xkUz8LyAh7j GTOLph6WwybT44PWOVuOOEZC0PZdIpLWNgq1xiTz9/R8sHbueghRXZImBAnP8JzJuamf 0jN7UYXkqaWrKa95X3mZqc/eZ7x4/Nijn6W0R28MmIkfPA6UMvj01/rV+qRULkptw8H7 PNQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028052; x=1792632852; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=E3QlrVAtVf/XpX+ZsmjMjSLBH4hnwCKgBumw+s30nkM=; b=huFNcvseh3QCxzqEH2hKwOFiYVmQWo1AEMPcge4+9Dyud4vsRn+a9hVZFFvcS9EetY ihzA0xWuYeVZ6gzN313Jgls+GB/bLs0Kp6xIj7o8Sz3XEqPM5d8ccykCgTokF79bspx3 aTf1AW4KniNkcXWue2tgd/mjXxztQmws9pDu/L0mQh6B2KDqMdqmqh62IHSUfCpQxTuF TOEpzXvtrh52SVG08N/07UyKmTqDfhO3e12MhzuadNQkfu5T4ZnA5nlPwoL0cdKqsrA6 LUBIje9W81SAcxorZu4K5jLMTc2V8FOGCQWqzxdis4XfvInYOlia7aLJVOwOE3Q9u2qC 7HIw== X-Forwarded-Encrypted: i=1; AKwUvBy8ZP1txua5iAxVpSgu9NCowM5bal6dF+edaortrJNQnHLaFUqWf25UxGrXuzlRZZzvKk93uuO9ptEELA==@lists.linux.dev X-Gm-Message-State: AFq9FYKhY8/RXNeb1oidvgMvllxRsbR1Pbk+iEdMUe7dc0qIY7/yKsMP LNKWLNXZQCHK8Z3JHq9HHkBGyYfAePGHXQG0Bdf2iTOxDYhLXPoVEksX X-Gm-Gg: AYBFou34GzxVJaLU0Yz2Kk6mYwieIXdbKpn9olggHwiVtJcbIaOJ99x2HYQd1k1Kn/i ULJKbwdzEBo/6nwyk8VzZ5kyvmZNnsb8rTKHEn6nzEZxkqZfnLiphG7oUg3b3Xt9wi8lC09xZ/C 5zpW0gTZiRyUqbv+lhZkp1KQ2IQzLKhIqVjBr/u1UhurJBiZpE4CaDR4vpUit0BEGDfHz+kYqms 4jijPxfftHeCRn5q/qyRC6yMXpbCQGGSOZCO9I3eR0uVzQAnloP2Aash9RkT9ebyFThu8bAE0CD MIl0jTkKUY/+RECp+rj0xInpFahmBtbSQBILnQkGVeFlzk2zXHOUPf31bS2heLmzqzQ3cTq8roG NaiuwkDySYSK7bv/wMskuOXP1rxiDGHVQCz3HYLts117khVW9iEEFqUX6sdsyE7EDp+QopnP6tm dyNjGb8FZzXODIxQ8afldGbfnsZY4Edu7o3oxIcdH9bepIXsi/a6q+s9i6l7OZ0qaCpd7qQUc9+ NdRxyVppQ1PokCLFknUNQwr28Mk+UQLuoT2YqiGP0Z9rJFN5HgMDz4Y3/1QvYqZ8d/zH4UXC/16 YqdPloJ+Vj/WDPFohg3G8bRVu42utHT1Odbr3fNrvZs+X8HdJKVrzPJMP/uUidlfmk9+dtEh3JR +Bt5Gn+zhUl/dZ/ij+tRojA== X-Received: by 2002:a05:6808:c1f3:b0:4f4:b5ba:a236 with SMTP id 5614622812f47-50c4e68002amr16797862b6e.10.1792028051591; Wed, 14 Oct 2026 18:34:11 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:10 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:48 -0600 Subject: [PATCH v7 01/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-1-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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.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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FROM_HAS_DN(0.00)[]; PRECEDENCE_BULK(0.00)[]; TAGGED_RCPT(0.00)[dt]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-26649-noreply=patchwork.local]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,209.85.167.177:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: ABF2A1C618D X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= PIO and DMA interpret the same hardware-ECC results, retrieve protected OOB bytes and check unreadable chunks for erased data in separate paths. Keeping that policy in both transfer paths makes fixes easy to apply to one path but miss in the other. Share the processing through per-chip OOB operations selected at attach. A read callback consumes one PIO step or a completed DMA batch. A finish callback handles the OOB tail and returns the largest correction count. Keep command sequencing, DMA ownership and randomizer control in the transfer functions; carry the buffer, page, correction count and whether any chunk was erased in a per-read context. Move user-data reservation and layout setup behind the same operations. The existing plain and scrambled-with-plain-BBM modes share geometry and read handling. Only the scrambled mode transforms the first two user bytes to compensate hardware randomization and keep the on-flash marker plain. Preserve fixed and variable user-data allocation, including the older controllers' extra two-byte reservation when maximizing ECC strength. This preserves the existing register accesses, transfer ordering, OOB length selection, error handling and ECC accounting. In particular, retain DMA's two passes: consume corrected OOB before raw erased-page rereads. PIO keeps its current parity representation and physical reread behavior. OOB-length fixes, read-error handling and register-read caching are separate changes. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 545 ++++++++++++++++++++------------------ 1 file changed, 294 insertions(+), 251 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index f41feebe4257..27d6ae635e9c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -256,12 +256,30 @@ struct sunxi_nfc_timings { s32 tRHW[SUNXI_NFC_TIMING_STEPS]; }; +struct sunxi_nfc_ecc_read; + +/* OOB interpretation is independent of PIO/DMA command sequencing. */ +struct sunxi_nfc_oob_ops { + /* Reserve user data before maximizing ECC strength, then set its layout. */ + unsigned int (*min_user_data)(struct nand_chip *nand, int nsteps); + int (*init_user_data)(struct nand_chip *nand, int nsteps); + /* Optional symmetric conversion of the on-flash bad-block marker. */ + void (*transform_bbm)(struct nand_chip *nand, int page, u8 *bbm); + /* Consume one PIO step or a DMA batch; negative values are I/O errors. */ + int (*read_batch)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, + u32 status, u32 pattern_found, int first_step, int nsteps); + /* Read any remaining OOB and return the maximum correction count. */ + int (*finish_read)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, + int *cur_off); +}; + /** * struct sunxi_nand_chip - stores NAND chip device related information * * @node: used to store NAND chips into a list * @nand: base NAND chip structure * @ecc: ECC controller structure + * @oob_ops: OOB geometry and ECC-result interpretation * @clk_rate: clk_rate required for this NAND chip * @timing_cfg: TIMING_CFG register value for this NAND chip * @timing_ctl: TIMING_CTL register value for this NAND chip @@ -273,6 +291,7 @@ struct sunxi_nand_chip { struct list_head node; struct nand_chip nand; struct sunxi_nand_hw_ecc ecc; + const struct sunxi_nfc_oob_ops *oob_ops; unsigned long clk_rate; u32 timing_cfg; u32 timing_ctl; @@ -908,6 +927,7 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) return sunxi_nand->user_data_bytes[step]; } +/* PIO uses register zero; DMA concatenates user data within each transfer. */ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, int step, bool bbm, int page, unsigned int user_data_sz) @@ -946,8 +966,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, } /* De-randomize the Bad Block Marker. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_randomize_bbm(nand, page, oob); + if (bbm && sunxi_nand->oob_ops->transform_bbm) + sunxi_nand->oob_ops->transform_bbm(nand, page, oob); } /* @@ -1007,9 +1027,9 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] = {}; /* Randomize the Bad Block Marker. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { + if (bbm && sunxi_nand->oob_ops->transform_bbm) { memcpy(user_data, oob, user_data_sz); - sunxi_nfc_randomize_bbm(nand, page, user_data); + sunxi_nand->oob_ops->transform_bbm(nand, page, user_data); oob = user_data; } @@ -1055,6 +1075,40 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } +/* Return whether the chunk is erased, and account for its ECC result. */ +static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, + u8 *data, int data_off, + u8 *oob, int oob_off, + unsigned int user_data_sz, + unsigned int *max_bitflips) +{ + struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int oob_len = ecc->bytes + user_data_sz; + int ret; + + /* Check the physical representation for bitflips in erased pages. */ + if (nand->options & NAND_NEED_SCRAMBLING) + nand_change_read_column_op(nand, data_off, data, ecc->size, false); + + nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + + ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, oob_len, NULL, 0, + ecc->strength); + + sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); + + return ret >= 0; +} + +struct sunxi_nfc_ecc_read { + u8 *buf; + int page; + unsigned int max_bitflips; + bool oob_required; + bool dma; + bool has_erased_chunk; +}; + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, int step, u32 status, u32 pattern_found, bool *erased) @@ -1094,98 +1148,6 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, return NFC_ECC_ERR_CNT(step, tmp); } -static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, - u8 *data, int data_off, - u8 *oob, int oob_off, - int *cur_off, - unsigned int *max_bitflips, - int step, bool oob_required, int page) -{ - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); - struct nand_ecc_ctrl *ecc = &nand->ecc; - int raw_mode = 0; - u32 pattern_found; - bool bbm = !step; - bool erased; - int ret; - /* From the controller point of view, we are at step 0 */ - const int nfc_step = 0; - - if (*cur_off != data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); - - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); - - if (data_off + ecc->size != oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); - - ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); - if (ret) - return ret; - - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); - sunxi_nfc_randomizer_config(nand, page, false); - sunxi_nfc_randomizer_enable(nand); - writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, - nfc->regs + NFC_REG_CMD); - - ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); - sunxi_nfc_randomizer_disable(nand); - if (ret) - return ret; - - *cur_off = oob_off + ecc->bytes + user_data_sz; - - pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); - - ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, &erased); - if (erased) - return 1; - - if (ret < 0) { - /* - * Re-read the data with the randomizer disabled to identify - * bitflips in erased pages. - */ - if (nand->options & NAND_NEED_SCRAMBLING) - nand_change_read_column_op(nand, data_off, data, - ecc->size, false); - else - memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, - ecc->size); - - nand_change_read_column_op(nand, oob_off, oob, - ecc->bytes + user_data_sz, false); - - ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, ecc->strength); - if (ret >= 0) - raw_mode = 1; - } else { - memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); - - if (oob_required) { - nand_change_read_column_op(nand, oob_off, NULL, 0, - false); - sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + user_data_sz, - true, page); - - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, - bbm, page, user_data_sz); - } - } - - sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); - - return raw_mode; -} - /* * Returns the offset of the OOB for each step. * (it includes the user data before the ECC data.) @@ -1241,18 +1203,166 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, *cur_off = mtd->oobsize + mtd->writesize; } -static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf, - int oob_required, int page, - int nchunks) +/* Interpret one PIO step or a completed DMA batch before reusing its status. */ +static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + u32 status, u32 pattern_found, + int first_step, int nsteps) { - bool randomized = nand->options & NAND_NEED_SCRAMBLING; struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; - unsigned int max_bitflips = 0; - int ret, i, raw_mode = 0; + bool randomized = nand->options & NAND_NEED_SCRAMBLING; + unsigned int user_data_sz; + int i, ret; + + for (i = 0; i < nsteps; i++) { + int step = first_step + i; + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + u8 *data = read->buf + step * ecc->size; + u8 *oob = nand->oob_poi + oob_off; + bool erased; + int bitflips; + + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + bitflips = sunxi_nfc_hw_ecc_correct(nand, + !read->dma || randomized ? data : NULL, + read->oob_required ? oob : NULL, + i, status, pattern_found, &erased); + if (bitflips < 0) { + /* Preserve PIO data before the raw erased-page check. */ + if (!read->dma && !randomized) + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + continue; + } + + if (erased) { + read->has_erased_chunk = true; + continue; + } + + if (!read->dma) + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + + if (read->oob_required) { + /* Keep the existing PIO and DMA representations of parity. */ + nand_change_read_column_op(nand, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0, + false); + + if (!read->dma) { + sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, read->page); + } + + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !step, + read->page, user_data_sz); + } + + sunxi_nfc_hw_ecc_update_stats(nand, &read->max_bitflips, bitflips); + } + + if (!(status & NFC_ECC_ERR_MSK(nfc))) + return 0; + + /* Finish consuming the batch's corrected OOB before raw error rereads. */ + for (i = 0; i < nsteps; i++) { + int step = first_step + i; + int data_off, oob_off; + + if (!(status & NFC_ECC_ERR(i))) + continue; + + data_off = step * ecc->size; + oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + ret = sunxi_nfc_hw_ecc_read_error(nand, read->buf + data_off, data_off, + nand->oob_poi + oob_off, + mtd->writesize + oob_off, user_data_sz, + &read->max_bitflips); + if (ret < 0) + return ret; + if (ret) + read->has_erased_chunk = true; + } + + return 0; +} + +static int sunxi_nfc_oob_finish_read(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, int *cur_off) +{ + if (read->oob_required) + sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, + !read->has_erased_chunk, read->page); + + return read->max_bitflips; +} + +static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + int step, int *cur_off) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + int data_off = step * ecc->size; + int oob_off = nand_to_mtd(nand)->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, step); + int page = read->page; + u32 pattern_found; + int ret; + + if (*cur_off != data_off) + nand_change_read_column_op(nand, data_off, NULL, 0, false); + + sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + + if (data_off + ecc->size != oob_off) + nand_change_read_column_op(nand, oob_off, NULL, 0, false); + + ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); + if (ret) + return ret; + + sunxi_nfc_set_user_data_len(nfc, user_data_sz, 0); + sunxi_nfc_randomizer_config(nand, page, false); + sunxi_nfc_randomizer_enable(nand); + writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, + nfc->regs + NFC_REG_CMD); + + ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0); + sunxi_nfc_randomizer_disable(nand); + if (ret) + return ret; + + *cur_off = oob_off + ecc->bytes + user_data_sz; + + pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); + pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + + return sunxi_nand->oob_ops->read_batch(nand, read, + readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found, step, 1); +} + +static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, + int oob_required, int page, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + struct sunxi_nfc_ecc_read read = { + .buf = buf, + .page = page, + .oob_required = oob_required, + .dma = true, + }; struct scatterlist sg; + int ret, i; u32 status, pattern_found, wait; ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); @@ -1299,83 +1409,12 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf status = readl(nfc->regs + NFC_REG_ECC_ST); pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + ret = sunxi_nand->oob_ops->read_batch(nand, &read, status, pattern_found, + 0, nchunks); + if (ret) + return ret; - for (i = 0; i < nchunks; i++) { - int data_off = i * ecc->size; - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - bool erased; - - ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, - oob_required ? oob : NULL, - i, status, pattern_found, - &erased); - - /* ECC errors are handled in the second loop. */ - if (ret < 0) - continue; - - if (oob_required && !erased) { - /* TODO: use DMA to retrieve OOB */ - nand_change_read_column_op(nand, - mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, false); - - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, - page, user_data_sz); - } - - if (erased) - raw_mode = 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); - } - - if (status & NFC_ECC_ERR_MSK(nfc)) { - for (i = 0; i < nchunks; i++) { - int data_off = i * ecc->size; - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - - if (!(status & NFC_ECC_ERR(i))) - continue; - - /* - * Re-read the data with the randomizer disabled to - * identify bitflips in erased pages. - * TODO: use DMA to read page in raw mode - */ - if (randomized) - nand_change_read_column_op(nand, data_off, - data, ecc->size, - false); - - /* TODO: use DMA to retrieve OOB */ - nand_change_read_column_op(nand, - mtd->writesize + oob_off, - oob, ecc->bytes + user_data_sz, false); - - ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, - ecc->strength); - if (ret >= 0) - raw_mode = 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); - } - } - - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, - page); - - return max_bitflips; + return sunxi_nand->oob_ops->finish_read(nand, &read, NULL); } static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1452,11 +1491,13 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; - unsigned int max_bitflips = 0; + struct sunxi_nfc_ecc_read read = { + .buf = buf, + .page = page, + .oob_required = oob_required, + }; int ret, i, cur_off = 0; - bool raw_mode = false; sunxi_nfc_select_chip(nand, nand->cur_cs); @@ -1466,28 +1507,15 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, sunxi_nfc_reset_user_data_len(nfc); for (i = 0; i < ecc->steps; i++) { - int data_off = i * ecc->size; - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = buf + data_off; - u8 *oob = nand->oob_poi + oob_off; - - ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, - oob_off + mtd->writesize, - &cur_off, &max_bitflips, - i, oob_required, page); + ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) return ret; - else if (ret) - raw_mode = true; } - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); - + ret = sunxi_nand->oob_ops->finish_read(nand, &read, &cur_off); sunxi_nfc_hw_ecc_disable(nand); - return max_bitflips; + return ret; } static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, @@ -1513,11 +1541,12 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, u8 *bufpoi, int page) { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; + struct sunxi_nfc_ecc_read read = { + .buf = bufpoi, + .page = page, + }; int ret, i, cur_off = 0; - unsigned int max_bitflips = 0; sunxi_nfc_select_chip(nand, nand->cur_cs); @@ -1528,23 +1557,15 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, sunxi_nfc_reset_user_data_len(nfc); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { - int data_off = i * ecc->size; - int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); - u8 *data = bufpoi + data_off; - u8 *oob = nand->oob_poi + oob_off; - - ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, - oob, - oob_off + mtd->writesize, - &cur_off, &max_bitflips, i, - false, page); + ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) return ret; } + ret = read.max_bitflips; sunxi_nfc_hw_ecc_disable(nand); - return max_bitflips; + return ret; } static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, @@ -2066,6 +2087,58 @@ static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t oobsize return 0; } +static unsigned int sunxi_nfc_oob_min_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + unsigned int size = 0; + int i; + + /* Variable lengths reserve the first word, which contains the BBM. */ + if (nfc->caps->reg_user_data_len) + return USER_DATA_SZ; + + for (i = 0; i < nsteps; i++) + size += sunxi_nfc_user_data_sz(sunxi_nand, i); + + /* Preserve the older platforms' extra BBM reservation and ECC strength. */ + if (nfc->caps->legacy_max_strength) + size += 2; + + return size; +} + +static int sunxi_nfc_oob_init_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!nfc->caps->reg_user_data_len) + return 0; + + /* Prioritize ECC strength, then use the remaining space for user data. */ + return sunxi_nfc_maximize_user_data(nand, nand_to_mtd(nand)->oobsize, + nand->ecc.bytes, nsteps); +} + +/* + * Both modes use the same layout and ECC policy. Scrambled transfers also + * compensate the first two user bytes to keep the on-flash BBM unmodified. + */ +static const struct sunxi_nfc_oob_ops sunxi_nfc_plain_oob_ops = { + .min_user_data = sunxi_nfc_oob_min_user_data, + .init_user_data = sunxi_nfc_oob_init_user_data, + .read_batch = sunxi_nfc_oob_read_batch, + .finish_read = sunxi_nfc_oob_finish_read, +}; + +static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = { + .min_user_data = sunxi_nfc_oob_min_user_data, + .init_user_data = sunxi_nfc_oob_init_user_data, + .transform_bbm = sunxi_nfc_randomize_bbm, + .read_batch = sunxi_nfc_oob_read_batch, + .finish_read = sunxi_nfc_oob_finish_read, +}; + static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) @@ -2090,33 +2163,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, ecc->size = 1024; nsectors = mtd->writesize / ecc->size; - if (!nfc->caps->reg_user_data_len) { - /* - * If there's a fixed user data length, subtract it before - * computing the max ECC strength - */ - - for (i = 0; i < nsectors; i++) - total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); - - /* - * The 2 BBM bytes should not be removed from the grand total, - * because they are part of the USER_DATA_SZ. - * But we can't modify that for older platform since it may - * result in a stronger ECC at the end, and break the - * compatibility. - */ - if (nfc->caps->legacy_max_strength) - bytes -= 2; - - bytes -= total_user_data_sz; - } else { - /* - * User-data lengths are encoded in four-byte units. Reserve - * the first word because it contains the two BBM bytes. - */ - bytes -= USER_DATA_SZ; - } + bytes -= sunxi_nand->oob_ops->min_user_data(nand, nsectors); /* * Once all user data has been subtracted, the rest can be used @@ -2175,20 +2222,12 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, nsectors = mtd->writesize / ecc->size; - /* - * The rationale for variable data length is to prioritize maximum ECC - * strength, and then use the remaining space for user data. - */ - if (nfc->caps->reg_user_data_len) { - ret = sunxi_nfc_maximize_user_data(nand, mtd->oobsize, - ecc->bytes, nsectors); - if (ret) - return ret; - } + ret = sunxi_nand->oob_ops->init_user_data(nand, nsectors); + if (ret) + return ret; - if (total_user_data_sz == 0) - for (i = 0; i < nsectors; i++) - total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); + for (i = 0; i < nsectors; i++) + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); if (mtd->oobsize < (ecc->bytes * nsectors + total_user_data_sz)) return -EINVAL; @@ -2232,6 +2271,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, static int sunxi_nand_attach_chip(struct nand_chip *nand) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); const struct nand_ecc_props *requirements = nanddev_get_ecc_requirements(&nand->base); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -2254,6 +2294,9 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) if (!ecc->size || !ecc->strength) return -EINVAL; + sunxi_nand->oob_ops = nand->options & NAND_NEED_SCRAMBLING ? + &sunxi_nfc_scrambled_plain_bbm_oob_ops : &sunxi_nfc_plain_oob_ops; + switch (ecc->engine_type) { case NAND_ECC_ENGINE_TYPE_ON_HOST: ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np); From patchwork Thu Oct 15 01:33:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3616 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 E01331C618D for ; Thu, 15 Oct 2026 03:34:50 +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-26650-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-26650-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 16F973ACC0 for ; Thu, 15 Oct 2026 01:34:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C9BC333C194; Thu, 15 Oct 2026 01:34:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fO6j4AZH" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12818244694 for ; Thu, 15 Oct 2026 01:34:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028057; cv=none; b=N+h7DQOViSvx4KjVE+ZV1OcBGsW9+o+A+1NS3G6YwFssZL1uVtZwPnrAg0ohMDgQPc0TyZ5PdkOXAsYqn7YHavNPUjLhHIeoArtsrYnnO9YIm4P77nbATt2azaS4Af34SRgTOruDVOJ7i/zAFRX0HOg+i8j2s7h1vOTjmmzMD1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028057; c=relaxed/simple; bh=3GQZX5iNGkz0/Zep2FfFJdRYaRxOFK4ZULPjzOeOBBo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=D/dqusstH+3WSF8AJIwMgVlAgMa5wYgUKq8Q08fqmmo8T2NXlZ96sPV/S/U6c9muB0KNBb2nA8L3dfPjsRGBfQTKnJzhKN/+qFZco/LHQmJQ4ZuPoN/UyFyQLc8/Avzd4dUbL1d+UeHE627flUeLqIUwj6DJZmR5GjkzZEC6EwY= 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=fO6j4AZH; arc=none smtp.client-ip=209.85.160.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-49e13495e5cso4846098fac.0 for ; Wed, 14 Oct 2026 18:34:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028054; x=1792632854; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=EDQOoNR8PIvzHZhKm/btQU1LikxfvBk4c4i5XkHFMOI=; b=fO6j4AZHmhMGGKcHEmi77fBo4zHZyac7d7C/vxBWkLogkzmfoAZKMVpsA89VjY8ZD0 kIs4m+kk4oWsmjdgjn5YYPm6Y7hAR/316P0qZkRqbOPpLFiom7F+EqixHi7Cu9x0pHZx e+PspAu0b5zyCMDCkUhxrGr+TQWVpJR4WNOSAJ0Da/iE0OMgQyXNQrqFMhBKbqvhTYd8 7VtDfWbAOwEIlAVMEEMNPkZyMOPwoxgeZOsiMJGKyezitiZCmJZKSF3Wxro6PIXJTOPD 9nhRBzyW6TFOaofxu9uPXw/DIlGvZgvq03lmPzmo5siYsETxH25EMvYo7vc/Xlk6KYGJ lkFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028054; x=1792632854; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=EDQOoNR8PIvzHZhKm/btQU1LikxfvBk4c4i5XkHFMOI=; b=NtutZ+/+kvtCiY1Uo0OPWgHqGHkMZ5Zz4T27pmAQc3aYZs1GJZkppZhvz9vPVDju54 vYRWH+qH0oaDts9OE7Bz1z8q9JzEtQFyfKTaHo7CjOW8QhBbA5WdcEIA1Gzh9BAaCel5 se0KbVfOVzR0xE6A5kc0FN5DeXcvN1wv19EWloS2TtxsUVaBbUqbV8cdCSg9dzkHk7mG WdQt1/9U+LxQiRNiO7HE659kgvldSIJa0UNgNKdfWA53hzyncK3G24cK5yYDac3Mjx4i 0NMFw+bj9cF4JDyI5nv/3Xoy3jPDg2mMiCarHthPsdFY6Ffd7ByeMk/vW5zTGQtJkZ1B vjdA== X-Forwarded-Encrypted: i=1; AKwUvBxIwc1vgUfSfEGAMnciS8H/5dfDOpJ3wPidUsctQH6/neFzKhhdAWVSuaD3H/s6SZFL9SsP21jgbmLWYw==@lists.linux.dev X-Gm-Message-State: AFq9FYLazHnIcWMycCjYP3icBF1jHo/3IGcjZOPYMhYL4iLDmsQ9jKkp 43XGv0HfdVLeAZe9NLbdCu3ofmSV8Hfl2ltsCIX9eY7/hWm2TJu+GVYv X-Gm-Gg: AYBFou2GeZc5l14e2LEUPG5lk3hcE89xPlpc73ExdKeLZ+Nz5teKa3s67VrmZ1OTque yI2Bl0a7f5GNXDNzFrC4DA5Vq7XgMnFX8XyftOE+J6/7MJVDlozzRPhJ3Me40wxlvRTw0XfWjel E8cw1zLXvcZmNG5kuEygbyQMl7qBta5+xJnwUfTNT+9yBYyKwd4UwS9Lhed5Gz7yI8OxP6tKS0i ZGcK6Ufj7If/MmXiV3H2oK/Mco0i4jdq91w+Blk9wA1b1Fh9/3hf3Mns54XTBLETinrsmWU3cfk zQ6W3CYKITppZruq5S5+x45l/W10j7vdBS3mTlIv9l34AOk1t319yE2C6opaVcNb0WOlxKlD0+Z H/g2HPfW/kFzXL+WSj3vBF2y5+qrOwCUl/Ng9exirr780G57aIYYTmUIzd+m2R3XOL1JRoaRfKJ 1tqJbKQ+qKZotNv+M+h3arDzs0tt/Qe30sEb8B+oaJmMVY+R1zPb03iopv97trvVv4eZFUUwSxV 3qfFnak3WG7IaMVGeHR9p+TBfakwCmYXKwpaiEchvflyRUfTUzhHw8aCYmDTBWmLKKh8Of3p5kl QHApZeSCPP2+kDAweCJRGnJFG+a98rkV1Z03ToEBAf39lhS7e5bL3TzJP45kmwuNDjI2alNezPk aUJDRAU1J9pPLx6+hh75E X-Received: by 2002:a05:6871:c8e4:b0:49e:cbe:9968 with SMTP id 586e51a60fabf-4a2a4a5d4f8mr12119173fac.28.1792028053759; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:13 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:49 -0600 Subject: [PATCH v7 02/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-2-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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.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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FROM_HAS_DN(0.00)[]; PRECEDENCE_BULK(0.00)[]; TAGGED_RCPT(0.00)[dt]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-26650-noreply=patchwork.local]; 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,209.85.160.43:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: E01331C618D X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= PIO transfers each logical ECC step through hardware slot zero. On H6/H616, user-data lengths can differ between logical steps: step zero can have 32 bytes while a later step has only 16 or none. sunxi_nfc_hw_ecc_correct() uses the hardware slot to select that length when filling pattern data. A pattern detected in a later PIO step can therefore overwrite the following OOB region with step zero's longer length. The protected-OOB write helper makes the same mistake when loading slot zero, reading bytes beyond the current step's user data. Pass the logical step's user-data length explicitly to both helpers. Separate that length from the user-data register offset: PIO always starts at register zero, while DMA advances by each preceding step's length in four-byte words. Update both DMA callers with the helper contract so variable-length steps continue to use the same registers. Fixed four-byte layouts and the on-flash geometry are unchanged. The mismatched logical and hardware indices were found by code inspection while consolidating the PIO and DMA OOB paths. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 106 ++++++++++++-------------------------- 1 file changed, 32 insertions(+), 74 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 27d6ae635e9c..c2e97b8656f7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -929,45 +929,22 @@ static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) /* PIO uses register zero; DMA concatenates user data within each transfer. */ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, - int step, bool bbm, int page, + unsigned int reg_index, bool bbm, int page, unsigned int user_data_sz) { - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + const struct sunxi_nfc_oob_ops *ops = to_sunxi_nand(nand)->oob_ops; struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); u32 user_data; + unsigned int i; - if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); - sunxi_nfc_user_data_to_buf(user_data, oob); - } else { - /* - * For H6 NAND controller, the user data for all steps is - * contained in 32 user data registers, but not at a specific - * offset for each step, they are just concatenated. - */ - unsigned int user_data_off = 0; - unsigned int reg_off; - u8 *ptr = oob; - unsigned int i; - - for (i = 0; i < step; i++) - user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /= 4; - for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { - reg_off = NFC_REG_USER_DATA(nfc, user_data_off + i); - user_data = readl(nfc->regs + reg_off); - sunxi_nfc_user_data_to_buf(user_data, ptr); - } + for (i = 0; i < user_data_sz / 4; i++) { + user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); + sunxi_nfc_user_data_to_buf(user_data, oob + i * 4); } - /* De-randomize the Bad Block Marker. */ - if (bbm && sunxi_nand->oob_ops->transform_bbm) - sunxi_nand->oob_ops->transform_bbm(nand, page, oob); + /* Undo hardware de-randomization of the plain on-flash BBM. */ + if (bbm && ops->transform_bbm) + ops->transform_bbm(nand, page, oob); } /* @@ -1018,48 +995,26 @@ static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, } static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, - const u8 *oob, int step, - bool bbm, int page) + const u8 *oob, unsigned int reg_index, + bool bbm, int page, + unsigned int user_data_sz) { + const struct sunxi_nfc_oob_ops *ops = to_sunxi_nand(nand)->oob_ops; struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] = {}; + unsigned int i; - /* Randomize the Bad Block Marker. */ - if (bbm && sunxi_nand->oob_ops->transform_bbm) { + /* Compensate hardware randomization so the BBM stays plain on flash. */ + if (bbm && ops->transform_bbm) { memcpy(user_data, oob, user_data_sz); - sunxi_nand->oob_ops->transform_bbm(nand, page, user_data); + ops->transform_bbm(nand, page, user_data); oob = user_data; } - if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(nfc, step)); - } else { - /* - * For H6 NAND controller, the user data for all steps is - * contained in 32 user data registers, but not at a specific - * offset for each step, they are just concatenated. - */ - unsigned int user_data_off = 0; - const u8 *ptr = oob; - unsigned int i; - - for (i = 0; i < step; i++) - user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /= 4; - for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { - writel(sunxi_nfc_buf_to_user_data(ptr), - nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); - } + for (i = 0; i < user_data_sz / 4; i++) { + writel(sunxi_nfc_buf_to_user_data(oob + i * 4), + nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); } - } static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -1111,11 +1066,9 @@ struct sunxi_nfc_ecc_read { static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, int step, u32 status, u32 pattern_found, - bool *erased) + unsigned int user_data_sz, bool *erased) { struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); - unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc = &nand->ecc; u32 tmp; @@ -1214,10 +1167,10 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; bool randomized = nand->options & NAND_NEED_SCRAMBLING; - unsigned int user_data_sz; + unsigned int reg_index = 0, user_data_sz; int i, ret; - for (i = 0; i < nsteps; i++) { + for (i = 0; i < nsteps; i++, reg_index += user_data_sz / 4) { int step = first_step + i; int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); u8 *data = read->buf + step * ecc->size; @@ -1229,7 +1182,8 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, bitflips = sunxi_nfc_hw_ecc_correct(nand, !read->dma || randomized ? data : NULL, read->oob_required ? oob : NULL, - i, status, pattern_found, &erased); + i, status, pattern_found, + user_data_sz, &erased); if (bitflips < 0) { /* Preserve PIO data before the raw erased-page check. */ if (!read->dma && !randomized) @@ -1258,7 +1212,7 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, true, read->page); } - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !step, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, read->page, user_data_sz); } @@ -1447,7 +1401,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page, + user_data_sz); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, @@ -1673,6 +1628,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct scatterlist sg; + unsigned int reg_index = 0; u32 wait; int ret, i; @@ -1693,8 +1649,10 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *oob = nand->oob_poi + oob_off; - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, + user_data_sz); sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); + reg_index += user_data_sz / 4; } nand_prog_page_begin_op(nand, page, 0, NULL, 0); From patchwork Thu Oct 15 01:33:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3617 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 50D1F1C2272 for ; Thu, 15 Oct 2026 03:35:03 +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-26651-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-26651-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 74E3D3B3BE for ; Thu, 15 Oct 2026 01:34:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3D56333F8AD; Thu, 15 Oct 2026 01:34:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WmSYQ08i" 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 0DDF833F58D for ; Thu, 15 Oct 2026 01:34:16 +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=1792028059; cv=none; b=I1WfWoZEQpZDVHdNmo7rV9iidW+gzzrmNbUxGbpxQXDJ6wnGE63FdaNSiIWCLHt9r3UM30/5gB/9dBtOaUg63s6RnSrfUQLvYtSDfCdEVkYzUGPBuNhz0wdhBYbJ/Zf6iaqAqw2+2T9G9b5QmyiLaUr2YX+E9J7x1xKjRBb3cHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028059; c=relaxed/simple; bh=5swNrnjhpqGxZeyGDlWe9TNZCEAsFDPalqzTOJ3Aefg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hsa/BKAIjRZj3esfhMZtvAx4fkMiaKNdUZeV4Ky7QDYoLf6c2E9/J/jndc6qTAGLCGtl5IlOSji/SduJIpLkDqEwJPeGwmmOTOQsvT4BpRi74l+RK6YuNfX9h8hn7cElonE3I0lfWknsTDAfr2xrPlO0Xty1qbUGkF2c7kgtN7k= 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=WmSYQ08i; 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-4b21f71613fso3041909b6e.2 for ; Wed, 14 Oct 2026 18:34:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028056; x=1792632856; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=hlWVFZs9qMdbAGtAdGz2zNdnsjoirOAt+ztYuqFoEV4=; b=WmSYQ08iY2tvForWvkX21Eb7gSjWGWzxtHfHpIX+u3sG+81+seMWESPPoDUrTKUIED 9zdC4FR+A36vGkOD90lAg7EXfksWLiaWvOx3eBK5V0gTUoWFbjEUHbHSULS8ba069d42 0fvSXqNDcx/oaweVGrqk5j0dIPnB47402lCXRFz9PfvR50Tbtl//O3eizwdE9mgkSSsa Hs6Vc3navssuDigo7ljETVjGzZS2qnS1V5Ck2nfpmMsvUAoThb+IWKrwuu5nrXmrVYYY wDLS5nOvlHNkF0+4blUrC/7mEH12TcuiQQOWYv9OSFhUg06nmt3wnRD8PZob+PxsXcMH VjgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028056; x=1792632856; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=hlWVFZs9qMdbAGtAdGz2zNdnsjoirOAt+ztYuqFoEV4=; b=GEFSsxl2mJNlslFhJQtqI5WDKVxMpfPDep33mlMKsv9CVXeLcSdBICVvWdZXuR2WAD b2gUfDGypfyZE/zA2dXRVoplNBY2SycqkGGEbDY74x5nKf65jwJN111+TUyCZHvnV6hh AIO37ggvsMtPscqWP2FMJytoZRLZEXlFzju9MspLMNwY7ORzaWVhi1e+YtYfZnzBvHAk jdMg84d8eaW+OxW1H0yJ8+s+b759QZSoH4X+qLiM/WjdwojpLo0meMIRnCNR1bESpWmt 8OIv2eh+PnpSviptBClVpOrKIURn0F7I4yYTOKYKQCccUUK7IyAw7wptWfN34E4ev2gs d8sQ== X-Forwarded-Encrypted: i=1; AKwUvBwOWfohoKcLEc0qS4Cdi3zNjD5UAlD16jhh8tt094MwM90AqIBet/Cz5iipgXrcvZB8zT/7HFcJyHt/Gg==@lists.linux.dev X-Gm-Message-State: AFq9FYJpXhdK6HjOKndzlQUAilLFE+OYZQEXVlTdTkAedAsm0JlgUDF/ 2r5+SThERTFfpJMmN/8pLanAAvcRqabv7RHQmI/dKslIrWljMmH2x5p+ X-Gm-Gg: AYBFou1m5IYMzgY6FGeBZ7PMSJXt5ELiVBqO+m02B2JgWpIE8+Z6dRWMn1rWpEOtxNy ybVwV+TDhWzAUKWt3Bd7q0czS9kMtsrBT/HtSaoixtbj0GyjnZgwBhxkGwl0gqrnB3zqj12EM9/ a9LQdpQU5MRtDI70ILb9AEAMxkO+iFM5ewwqBIyUqyCbwfIetfhi/VWMKej8+iLCm8MDa6/5vfW 9kkZeOlI73FTZsRS/Fyci7fMr6n7dvoaWjcjDeRESDTH/UdVZzzRhoPXY72N0gRYqp4Cvp+FHlV 5xvfIN/VYREmroiaC06C/wJYSDlWKQgLopXgHnqOLe4ftTQtPSf8PCJMWt/pwTUF36ZoYYsjSHA UiI3cX77kT8doQ0k4cyNfumBIPCMTa0jxmIr5O0t5H8W/O6Klcng0b3MhrsT8IUywDOlUJ5BevA iim6HNy8SMJQV/P50GgMRzeM+h5YCEc/tEUQmsgOSuCuqP8Ss4LcNb3Ca+C+hK+hhTGp/wlCAZD RfprdkK+JbJX8S/OzMbUDgcSnnG/vsNUJMsy02EJxJpn5eUWERVYU2s50m3UVw33JgXVjsWIJiS lGiRVK3Id1nZO1HbVlQXZ1VJAVIrCSFuLJDjY/H12+oeKEnkmj7rOv1/kDgGgT1ndqd6M372R04 N/KTRFo9OtEPm3YF6+ZVa X-Received: by 2002:a05:6808:251a:b0:4cb:818f:d56e with SMTP id 5614622812f47-50c4c7a2fbdmr18782064b6e.22.1792028055832; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:15 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:50 -0600 Subject: [PATCH v7 03/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-3-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; 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)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[209.85.167.177:received,100.90.174.1:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26651-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 50D1F1C2272 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The ECC read callbacks ignore nand_read_page_op() failures. A command or ready timeout can therefore leave the requested page unselected, yet the driver continues with data transfers and can report success for stale data. Return the setup error before starting PIO or DMA. After an ECC error, the driver rereads the physical data and OOB with randomization disabled to distinguish an erased chunk from corrupt data. Those rereads can also fail. Do not pass stale buffers to nand_check_erased_ecc_chunk() or count a transport failure as an ECC result: return the reread error instead. Successful erased checks retain their existing statistics and correction-count behavior. Route PIO read errors through ECC disable. DMA has already released its transfer resources before interpreting the results, and its caller retries a failed read in PIO. Restore the corrected/failed counters from before that DMA attempt so earlier steps are not counted again by the retry; leave bad-block counters unchanged. These unchecked returns were found by inspecting the read callbacks and their NAND-operation helpers. Fixes: 97d90da8a886 ("mtd: nand: provide several helpers to do common NAND operations") Fixes: 25f815f66a14 ("mtd: nand: force drivers to explicitly send READ/PROG commands") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index c2e97b8656f7..6c0d3e2d2be2 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1030,7 +1030,10 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, } } -/* Return whether the chunk is erased, and account for its ECC result. */ +/* + * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC + * statistics updated in either case. Negative values report transport errors. + */ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, u8 *data, int data_off, u8 *oob, int oob_off, @@ -1042,10 +1045,16 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, int ret; /* Check the physical representation for bitflips in erased pages. */ - if (nand->options & NAND_NEED_SCRAMBLING) - nand_change_read_column_op(nand, data_off, data, ecc->size, false); + if (nand->options & NAND_NEED_SCRAMBLING) { + ret = nand_change_read_column_op(nand, data_off, data, + ecc->size, false); + if (ret) + return ret; + } - nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + ret = nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + if (ret) + return ret; ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, oob_len, NULL, 0, ecc->strength); @@ -1308,6 +1317,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; struct sunxi_nfc_ecc_read read = { .buf = buf, @@ -1315,6 +1325,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, .oob_required = oob_required, .dma = true, }; + unsigned int corrected = mtd->ecc_stats.corrected; + unsigned int failed = mtd->ecc_stats.failed; struct scatterlist sg; int ret, i; u32 status, pattern_found, wait; @@ -1366,9 +1378,19 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, u8 *buf, ret = sunxi_nand->oob_ops->read_batch(nand, &read, status, pattern_found, 0, nchunks); if (ret) - return ret; + goto err_stats; + + ret = sunxi_nand->oob_ops->finish_read(nand, &read, NULL); + if (ret < 0) + goto err_stats; + + return ret; - return sunxi_nand->oob_ops->finish_read(nand, &read, NULL); +err_stats: + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected = corrected; + mtd->ecc_stats.failed = failed; + return ret; } static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1456,7 +1478,9 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1464,10 +1488,11 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, for (i = 0; i < ecc->steps; i++) { ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) - return ret; + goto out; } ret = sunxi_nand->oob_ops->finish_read(nand, &read, &cur_off); +out: sunxi_nfc_hw_ecc_disable(nand); return ret; @@ -1480,7 +1505,9 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page, nand->ecc.steps); @@ -1505,7 +1532,9 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; sunxi_nfc_hw_ecc_enable(nand); @@ -1514,10 +1543,11 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand, i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { ret = sunxi_nfc_hw_ecc_read_chunk(nand, &read, i, &cur_off); if (ret < 0) - return ret; + goto out; } ret = read.max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); return ret; @@ -1532,7 +1562,9 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, sunxi_nfc_select_chip(nand, nand->cur_cs); - nand_read_page_op(nand, page, 0, NULL, 0); + ret = nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks); if (ret >= 0) From patchwork Thu Oct 15 01:33:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3619 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 ED64B1C2272 for ; Thu, 15 Oct 2026 03:35: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-26652-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-26652-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 155E73C7D8 for ; Thu, 15 Oct 2026 01:34:21 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C5D9233D506; Thu, 15 Oct 2026 01:34:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nyHSqz8N" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f54.google.com (mail-oo1-f54.google.com [209.85.161.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E67CF33C19E for ; Thu, 15 Oct 2026 01:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028060; cv=none; b=EiatG5vK8ncHM01Wl7bsKLhIAx4JbxynLJxVDGRUkROQC4PcrWGVuGX9WP16zlmkjB56O7XkhKkb+f+U+iDD3u5k23kdg03GrB/6Y7PWwz6AtDqSQcFwC/eCD91zh5nRjFeqC3zeM+BVpEsKxf6T2w41F9+RSnnRrOIy8ZJyKs0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028060; c=relaxed/simple; bh=eu782ZILQEt1gvhW41qEkk/lHnvXY0oqpsX4MnquLe0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TUumAbyCYGUHKridEbajkWaorgYpwVa90MOxcacd8X3RpzOaOA3Q0fAyHU8U2rolNcA2OQjz3duCxfkpqqnn7TXVWmyJzYZx2e7a5xtnbyVjD7n6hAQdteTmslgPudIZ38/7quYQ8U5s/VQqKNo6RJVNJ8iEJtB3QAVAfiHySjc= 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=nyHSqz8N; arc=none smtp.client-ip=209.85.161.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo1-f54.google.com with SMTP id 006d021491bc7-6c8f6a53fabso5890261eaf.1 for ; Wed, 14 Oct 2026 18:34:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028058; x=1792632858; 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=UnbuymXcTtfKlGuvgEcxzPNrCMdjSx6DCt9Jhk4Q3PI=; b=nyHSqz8N/yhPGnBRTDowE3ZCGIzc55pTd0ZH8uJPMgeocpxTSrhRm9/jrDJxV8b2iq Mk6OcnrnE0oOLg8jsxRJh9DdCTLiP0d1e4V/vQVF9Jeps5XPjEGzr57jMQd+dHpiYXlw hg6WuaELD4Cg1Jw0atoTuFS8r7n1Po8Bmu8QwTXYSQqnQZe1zy25ByV0FhuQXuWf2Q0U 91xXC9cGkcRlBZ/MJGn5A32GrYyEFSg3KhmTm1V6rbuctixG7u4wbw6yZGcxymF1DETL ZXn/j0cI/UHQZ9IKM7TYivConiDB3RJ/r2011vHMu5nnVrY5+QuQC4YZnnYC5/1SBcPJ RQMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028058; x=1792632858; 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=UnbuymXcTtfKlGuvgEcxzPNrCMdjSx6DCt9Jhk4Q3PI=; b=pBdxOMe7rxfGuYtt6x3tUOVQJw4Z8a3uUJeUMYhse2trbglwBOl8CGSJxaP8i1edY/ hjlM/mRdGELfpM27B7XJdK0er7BLx+XNwErbCImw9dFlUuZIPi+dx5ejfrhIyq1t64Ch 5EaDmgojO+StCZs9LOKkTaFgKlCN+ZB1n4rY3zZ9o+AJ9gFxLBii5Fv/tqPe3kQ0HN2o yQhzB7SEcJibD2Fdd5rG/8eVAup8b7nE4CN3O5N32zjxjUQO2qNxguC8q9AyH5Hn3N0j DbgepKjJkJluRosQer+/kiNnUf95MExYD5992CMMeFcn36xBo772Qod6/nLOmS3hAD/w xYGw== X-Forwarded-Encrypted: i=1; AKwUvBxCNiOjlttlRfgUFvpXIo4A+H5bbL8nHeled6HfiMLQusz/u3AVt1IKHx+6y78xtapUPD20bV0wLruEIw==@lists.linux.dev X-Gm-Message-State: AFq9FYJp0372NRPFbiccRVseUWNvWne4L+kjcPA7k820pjqcJr6vdnyO Cs5Ag+Tf0sjPRUOvfJkyWbh1ROEgj7Z8kIfVwAz1NX6JCj7Wjdmh9CJA X-Gm-Gg: AYBFou1Mv/RyZpLx5AN9UHyp3tDYV41MPlp0Pt/8ZkHMn6vx+upFC6isjb5aVZfexhk NfjjBSNp20MpZlw+UTkdhiXIOYKbkosIN5uWlxiJjL+778fHrVtsZxD3hi/sUEC/HdwfxbCpCT4 Y+/Bl22Cxopnzw9VR7W3rPtiJbetD6NqGWCIOslMa78mwXnJNPlkaVlxraWVFFuTBFiEg9LVWt4 6Oo/wnuOKP0CYsQ1+tjLAzf6L41QITvxjwybP8wfS1oPD5WTMAHgXf618zHjbKL2QrE40GgfEW5 BfUJ6/fzfUN/bXLsii6j03RwLoivcxuzsp6L5Em2wBcpIDNddwF8jMODXDjFZ9PmA4fp7dFzytZ gZF81YXKdVrWnp8XTmyNv2XYfRsdP3qMp4pIUtr2eT9xnMpD6LPLgKSTcClG1EikENeDLljQzXv K9d/eM8Czyg+HntcZstmTm1wwufwvuXj+JFQZH+75UaRhxi3//Q08r1WtJS6u8AW+kAXqeVaNNb /ZdzmzKGd3IG2gGXIN/9lQ8xot0sNtRjGPn9zi2iT9zvy30I+8KEKJw0spoIsJBJfznedsxNE/g n2XY9sI9+b2XIC3E/WV4J6LG78ezu/EHCfkiqKEqZFl2f/QMe9gB28ImXXBH8Ryx6KyBCV1NaP4 JoxQ3gN6rX9kTt14r7UpE X-Received: by 2002:a05:6820:5056:b0:6f5:a844:b12 with SMTP id 006d021491bc7-6f5a84410admr7628975eaf.57.1792028057776; Wed, 14 Oct 2026 18:34:17 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:17 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:51 -0600 Subject: [PATCH v7 04/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-4-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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 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. Then mask and acknowledge the events, read back the mask to flush those writes, and re-enable the IRQ line. Keep partial-event handling in the IRQ handler and leave polling and controller/DMA abort handling unchanged. This keeps additional synchronization on the timeout path, without a driver lock in every interrupt and wait. The caller can sleep, this IRQ is not registered as shared, and the handler does not acquire the controller mutex held by the caller. The tradeoff is unbounded cleanup latency and no priority inheritance: a starved IRQ thread can prevent timeout cleanup from returning and block other operations on the controller. This is a handler-lifetime boundary, not an RT recovery-latency guarantee. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6c0d3e2d2be2..bc38330c0e36 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -393,6 +393,7 @@ struct sunxi_nfc_caps { * @chips: a list containing all the NAND chips attached to this NAND * controller * @complete: a completion object used to wait for NAND controller events + * @irq: NAND controller interrupt * @dmac: the DMA channel attached to the NAND controller * @use_mdma: use an internal MBUS DMA backend * @mdma_desc: H6-style MBUS DMA descriptor @@ -412,6 +413,7 @@ struct sunxi_nfc { unsigned long clk_rate; struct list_head chips; struct completion complete; + int irq; struct dma_chan *dmac; bool use_mdma; struct sunxi_nfc_mdma_desc *mdma_desc; @@ -433,12 +435,13 @@ 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; } @@ -454,16 +457,19 @@ 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) + if (!ret) { + /* Drain the handler before it can restore an old IRQ mask. */ + disable_irq(nfc->irq); ret = -ETIMEDOUT; - else + } else { ret = 0; + } writel(0, nfc->regs + NFC_REG_INT); } else { @@ -476,6 +482,12 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); + if (!use_polling && ret) { + /* Flush the mask and acknowledgment before re-enabling the IRQ. */ + readl(nfc->regs + NFC_REG_INT); + enable_irq(nfc->irq); + } + if (ret) dev_err(nfc->dev, "wait interrupt timedout\n"); @@ -2650,6 +2662,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev) nfc->dev = dev; nand_controller_init(&nfc->controller); INIT_LIST_HEAD(&nfc->chips); + init_completion(&nfc->complete); nfc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(nfc->regs)) @@ -2658,6 +2671,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 Thu Oct 15 01:33:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3615 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 D3FD31C2272 for ; Thu, 15 Oct 2026 03:34:45 +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-26653-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-26653-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 8781D3734C for ; Thu, 15 Oct 2026 01:34:26 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C011531B101; Thu, 15 Oct 2026 01:34:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oytNhFrN" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f47.google.com (mail-oo1-f47.google.com [209.85.161.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3098433C194 for ; Thu, 15 Oct 2026 01:34:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028065; cv=none; b=Kae0BqGAw7tPax8bSsikh1SFW2L06/Hwdube0IBREI4dHgrc3Fs8mavgXFI/mULPPOyq12xZDT27p0qvq9cbNA1dKMYiw1NnZm2zzGpRD2Wy0oT0gOODG89e7tfrtWQbD96nKztEbinkmTV8nWnT3ZGFxUCL+y7AjTwtDF871vM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028065; c=relaxed/simple; bh=JonTCMkfo5CDzyNZ0Z71f8IamWNK7BpOBHaurYUB32M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PdMk+YJX60DhKgiIZZONDxC7oKNEHogmj+FBHlr6M0X/HzuecGc8CShL8CdLukHj2ZE7smWXxMYfSh1v9jRV0S5r8Xduw06RpHqEJpPSl5PxxSqXwEHMQGB0Dfwd9jBM1+Ajqj5UG4NpNfTzzjT1n4h8Wn8RmGHvbKXrKDX29Jc= 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=oytNhFrN; arc=none smtp.client-ip=209.85.161.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo1-f47.google.com with SMTP id 006d021491bc7-6d7e06dbcccso2888462eaf.3 for ; Wed, 14 Oct 2026 18:34:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028060; x=1792632860; 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=GyWvw8mLllrKH86kVSbt9VISfrTspBfEjHuwdH6ZSfA=; b=oytNhFrNQGMH9xG+n/+iamK5aD747UkHh0j6/roG6fTxvZKduSttSMPlD67TZXBThM Qk/q2F6bAo6CZAMrQQlvJBgEs+1m+X7HqYRs6Sm7wMO0uEHzp6PdHLAKYEomee0RiqC3 GsHCzDa39M2RBvrqyS5Evs3lk3AAKD/dIBwbPFCQwDzlwYWCw1QHJXVRi3TrDfGVNZ/Y VEZF2CMNetfoW62Wyo73YVLifhob8Fw33XgYZEGeE2us8sO+BeAJtXeFxzRvnuTz206W 5Eahl2Pw8RZdx1JxWZsfOdbok7j8k456d7A38wEklp7M9qvYn6HlmK2/XGkQa5FmhGDL 1hFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028060; x=1792632860; 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=GyWvw8mLllrKH86kVSbt9VISfrTspBfEjHuwdH6ZSfA=; b=fX6JVwgvvYQ9uUw/F6z4OqhKhI9hXB27wgPV1V2TfvaAF3nE501z3sW6UvQKOMArO1 b9g659A/tvnuWYmb2RKqlJznDlGHbG7Hu19mrsiDwdOZiKwZIsUAMwoaF/u1LknsZu5I fS10RWopt1aWc/QmhaophOZXUcM/++P7KzLwRGvuhGwtZqmMq6TgbNvQlkq7tH6EhtEY GnW0kqOhc/HYbX8Lm0k/3MriYQO9HIE38yFsx/PDIkj79ZB56UGAd1L16JuYNIEyaMoW lg8hPSKGr+OfuEAlJSsUFCcy1KSyDFA/JL6HW6T0GbZLwCkB3EsCe8eMpNBKw32Ipssy bRMQ== X-Forwarded-Encrypted: i=1; AKwUvBw6x5k3vfH8kNJnBwgazJJBJ/etcIX9NvIUJBZCKlabORbk0IJTrkW6NfJhPc5XJL2AhCtouhPyi8rKPg==@lists.linux.dev X-Gm-Message-State: AFq9FYKU8q5R5pt5F/tBmpmab0KpludCuqZbdvz7me7l0Go3iaxUINVu QHhSzvcVIme79VISocsxuOKhabiNXQW9HXV4ONnvIorGihdW5niXyIRc X-Gm-Gg: AYBFou1F+upIL3p3LoNFWwbiqkNnKJlaH7130RuEa//SlAp9ToJBCJOYFJaaLFkg5dS om9LhM6BoXTMhzenAnHgzUGhsZAq8h4HbWipY+I/MNlx6wKl4aKEBIJGfIZk6la8F5kWn+Oy6pA 273juKZL1cl1KRCC57mwM4iQ8IJNHZ6MuWd0bWrlITIDRSUGLOuNWVjeuF3nhL5OZLzIYg1VpDt wVfdlor1kQmbG/yyo11R94MGGFt6NrGhFmMbby+lrIwpyEvQKLfk5ihHC1YxHcah96SL2w3p59Y W4gnCC29WYuwlBk4tNIb7VORTuurPXMLXFzAweyPcyoFDCeeVexyRRnxVOdO56QkgPpYEMavN3G Ptr14XaejEer4/i9RVyOg/cbZQkIcMPZz13rXutj9tyIFfINBN+2vPTeoyjZiZwVqfKuEcLHfwn t/fC/6/fEFiscbkt/3X1P6nRsB41WdxpQb7xz4clkUl/JITgApHMTgdkc5Nchyjf6fxL/G43qy6 ehor+srtab139tVxHmn//ZRdfzxw7xzBAX0N9VZjl6Rfw7KhVuS44BC8og4+ANUW5g9o0eiSMlG 81W6L4o8K/qs1KSIMq8aF+TRG/7Z1HkOSeLGj93aT9mYYylfIlH3iL3TcRBmmHUuILuZ8/D4Z6D K6g5pwJSELC39Xbc5Atws X-Received: by 2002:a05:6820:4d07:b0:6cd:3fdc:6001 with SMTP id 006d021491bc7-6ef115523a1mr12486639eaf.82.1792028059992; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:19 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:52 -0600 Subject: [PATCH v7 05/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-5-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114:c]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,209.85.161.47:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26653-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: D3FD31C2272 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 bc38330c0e36..57df88099206 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1595,11 +1595,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); @@ -1614,14 +1616,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); } @@ -1635,11 +1640,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); @@ -1655,10 +1662,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); } @@ -1699,7 +1709,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 Thu Oct 15 01:33:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3622 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 BFC281C2272 for ; Thu, 15 Oct 2026 03:36:44 +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-26655-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-26655-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 D08F13E7FB for ; Thu, 15 Oct 2026 01:34:27 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5090733F8D4; Thu, 15 Oct 2026 01:34:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ngjjsKZf" 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 2B799272E6D for ; Thu, 15 Oct 2026 01:34:22 +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=1792028067; cv=none; b=OhTtkVeP01GvZYFEuIOYmu6lI/vX/EMQdh4BC91iMPTIrBUwROGhNGoaSg77HwwsEKc4O1sn2ADI2QPbRgGAZ8wraTZyc+o33oZ7SKEdYSG+khJtlJX0p8csThEu3lfqOhmQf7Dr0bPfGd3u8MN4TCv2ZRfEwtuoc/eMFhsU58s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028067; c=relaxed/simple; bh=pp2SixJcCNbM9ouP1cQ4wZ06wECMdT8iJOt4pVovses=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Uljsug3rB8IySAYZgcxPSIgruz2W8am1APGlQgWApBBowrHlgOdIR5d68ROMXotog+PO+4ArJv3eppBlLQItkErpj7SLz6ZiH/3o3TiTipBdQyEbfZzshKQ9j4MC2YhVI2BKqEpkexEREMfVf9RwzqiC8c8MsaqepQicU5u9O4I= 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=ngjjsKZf; 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-6dd4f3f696aso2396452eaf.1 for ; Wed, 14 Oct 2026 18:34:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028062; x=1792632862; 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=vV+y+As1/xEWZJVIUOnWi1zmF397GSE51b2dM1xKJWs=; b=ngjjsKZfspSZj6yjtwMioBtW66GDq20MlvNF10Ltaxtq9jMKZ0fVLljo0jlrj5sxxI fTCMoYIpQIj9GuDZe4atHQmgUzpKGoxBXTTx/Mag3IPFJYv58iZIi4o63qcsoxMVZKx5 DoIk+Vci9RrTrJIaWEfYJ2T4Yb5SM0r3u+VpT31+XOTwTU+JI//fbl4lzJawWKCyfK9B pFNL58dI41kiERcs2DY192w6CT/wvJBWHmpGecAkgqFizyTStx/KtKp3Gv9KEUGd5y7c Ey9oR5RnOIzzjqGJ4OSKLD0K0nHkZ7coOUuFHZLPIoRWOYjUd4Lg7NKEsIOhPjOGQ4ST C9SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028062; x=1792632862; 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=vV+y+As1/xEWZJVIUOnWi1zmF397GSE51b2dM1xKJWs=; b=2ydRDOMSN5/WpQv5P6XQj/gfT1JMF/btt3UEMz6/LpJsqYItQqMRZVYHXdqPb5MnRR 8L8TbR01L8t6NRp5a39jyA4abCyzzWPTt/Tjebf1uL2jfE9k6CvtLcHvJLWDm9lKqkmu A/be/LkyIoGFgyf3nvcTbYbaJj+R44IOPsWcJ7d41dj++caWcPIH5IgyNCVOHri3NV9x MflGhrzMD/CgyWVJNs4Jvur9gXpQguzRYod+76WuAkl+zW1gWF61cWzDCzlTbIRO0t9T NTnuOQS+9dQPriWy0b2q2YbBT8fh0ybE6Y309YEFKVOPl/VCCKTrtUMnBftDh2G038Mw oLdA== X-Forwarded-Encrypted: i=1; AKwUvBw35QvaWrQ5JdcbdPDywHWW+Dxd//8M3CM8UPnmAXb66Dr+lgB659WR/S412BGUi+dy+9EcLa2m5k9nAA==@lists.linux.dev X-Gm-Message-State: AFq9FYLbxoVQSAbEZ78C2b6U4MIK1dJReYVJlvkb7bX7/xQ3P+AZ5Lio Y4YX72sh5WwyJh+Zgo8U7163xpMYXQYGeDuqF1L63wpaq5WpPvRJyewE X-Gm-Gg: AYBFou2ykHSxmlY9kRLfcphSdhqwkboEbj5+rsRkbrA4pjk0OBfa4mYuX07JjaCHKfI wdpUKAbKpX4BXM3fMKpVkcKxWll50KGIeG4gMg0y+fuST+zxLl7Dm0ydwKL/0cYoGQs7NJna91i rSWxKgiQm0alMQgF63wz4nt33fZsY3sp0wtgXsw0mldYNtMuUTqqzOtn75lBBoKPa16ECuT4D+9 ikNkR/c+Z7psivwcKlczar9ndek3Szr9cY212U+ow+sxI+ACCwdvxC515nyaDVeGipZwIgqMM+o 8jtxwsqFqZIT7fKS+2nh1pX9r15ugyVDUfnzzsSw3tSfCe1t4vZK6nFGyeuwhBBHFlwOvFc6LiN 6LFBvor0RaOSuPe1npncWDSNwolmtQSwE7tzfmQ0GUUnJ5F4lWQ6+/C8LjoErjTepynv1hvxqkm GriJSDg3KOvUaH3YwTIQ3QJHXcIQ7QBEFeFXaeiaUyFVw2yBKoP8gEhoXAtaRPgDpOvho/1nEEM hRXOLFIpaIvv7V1ZNKeGEOAfxHm14C/mWmOtH8ZIzdwb9S4A2Iu2QjQnfKan5tM5IDIBVfiWSsK Oi+dKlxn8WvC23DfJKcw6UzgHvdWk+q2GyRLhktSOEzS+kCqOg301qF1i26xQBaHpkxnlk7jcd7 kojip+XxXWQlWU9242G5O X-Received: by 2002:a05:6820:1517:b0:6cd:3fdc:a936 with SMTP id 006d021491bc7-6ef1144ff66mr12723501eaf.83.1792028061915; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:21 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:53 -0600 Subject: [PATCH v7 06/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-6-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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 57df88099206..8256982d1d56 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1101,7 +1101,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 Thu Oct 15 01:33:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3613 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 87B481C2272 for ; Thu, 15 Oct 2026 03:34:29 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26654-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26654-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 9D26260C320 for ; Thu, 15 Oct 2026 01:34:27 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B6F4531B101; Thu, 15 Oct 2026 01:34:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="S3gwpfvD" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A98A433E35B for ; Thu, 15 Oct 2026 01:34:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028066; cv=none; b=R5B3C2RU7hbDzktfP80Cv43CsX3rIQ7mM4KXI6M2pCSBSsxNTuqIKNX13QONx7GjMlzKqxC2Bq9AXr+Liqa3rJZYwzuAdVNIKNxp7r7cjYLQaAAi8nvlHBnRLjg8dQNkCJax1FxgKBEC1pTqEKoZx2/X3j5ZPa3FIo7PNrQSYzQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028066; c=relaxed/simple; bh=3inu8PcvWtNWB4hfZexNO9HD0p5ZfghyPzBUWdP/498=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bMQFiCs9cErs68UOOPZfd09+d5x6zzyw30cGuSiU9DNgRbr3LckShjKFYOIVr/ybT1Gxx2nif4clxl709IGEIc/oikYG6JxQKVSgdi5ahpBbmPAVTAsjrFuBAyI1wYX3LILB+sT3TOSMSu8p40QdhgGW6/LhSL+8unCFCZ0v4FI= 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=S3gwpfvD; arc=none smtp.client-ip=209.85.160.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-490d838b425so2770166fac.3 for ; Wed, 14 Oct 2026 18:34:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028063; x=1792632863; 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=Cx9GKNoh1ry+92yCt58yhjO9StAttIXiG8BntxokAOc=; b=S3gwpfvDpeASXwpWacqlZwSBRUjQrjqqaxWmOg7t0InPLrgBjsrgi0NWuYDq/TdAlt lUFsaHQJF3L0cUrYFvI6DxIRHZpLjtd7o2lHTPs3c8/VQZewRxWHpeyvf5WmMMvMXmws Htee5V0AT3bef2pjpzawY862A1X6Ju1rlv/xoIZHa7JmWE2pKfq+HrISgAmtv/GblFkG sXBXixsUXe41Ijespm9h0sWMMgKmCWxUgu/5zFjSIG60DtO6MOMOQEaV4mc9zh2YH+Em dn0y1icnckrTEleTljzzuhBOxMFtGeHyCAVvil8/ANoLqgA0Y+XQpWaa+yyLCb8i17A2 VRsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028063; x=1792632863; 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=Cx9GKNoh1ry+92yCt58yhjO9StAttIXiG8BntxokAOc=; b=QbeevIY1NN33NowRPhp0bI5tORS+pR4kNqrMQHBcG/7awQh9fHV21Yad5+Ag51WIR2 y16q7Yl7mqdRgH2HaYtaAb/zm9H7uFAb8fYRWUil8nmi4YDbea/dsXxpaZ8fwEK01Qx5 Xek761o33gOqXptLvgKNppWkqpJTlo0m7iA2A1kz4Khl2Y2htjQAZ8hLuqn7vDBQYHF5 LiX1r5wIMF8e29QJfZcusKb309DIjb8/7Xe9q+Ho8uBPoALEnDLuWxnImTYvct+OPpFo MCW4cYEj/zh3LaLjdCZN7K0rr5RYJpjPASK09UQXB1HQEDVPpDJ0rEiGhgLo6mUyI2bf JBEw== X-Forwarded-Encrypted: i=1; AKwUvByxRdLKz3ZoigcOgBZA3rTEeKA+ORTJpqsSB8NQR9McOWQ0L5d0FiO08Pf2Sua+Veb5RfmhRl20fazxQw==@lists.linux.dev X-Gm-Message-State: AFq9FYJwfSTmuYzwCrwQADcGx3W3ottzAM3z5HvHCx9tHZyxo9BDn5vb 9kAZZSXQVXEuS5WnLXWIFcP0Ju1SgGczBZhNQOMcH7ne4b29IADpmMq6 X-Gm-Gg: AYBFou1SX7WSfOkfCn/EFg432n/K/nOXP4XK+Pe1Z0J1iQCNzl5yH1+sZgQBcSFng2P +bUR+uv74j09HvwO2/DrC4FenkoqkvIIO1h644YJ6GXqLv7jSoP9mc+BU9pL9kP0dpmy0nRFKMU MA5B86OUTU0vCjHX21kQfxKSl/hpwcOSgH6/1yDFk/SKeWW7yjdC13jnfyDRKNk6gh++t/oejCw y4HwImSNvy3Ith7ED7nCu0LFChvcNcJ0AXSsqx1W+uB96W9YcWkyMizUGu49bYNsFfesFq0wFdv 1/RB+CA5NQQpRTPuQnUG5PLB9X1d/IqKHAikRHxFGs6biuDJez0Nbsrzcve7FXfN1b/IQnijYF0 rsJs9FktI/vlaVXqCR9k6VdkUSqiMu989umJgUfGJx+RkICqGo1m2bRSi5FbhpBrKj7bnhOqRY1 67wrYrD9P02R0eJvA6i2uH2/0bNZtOl1DrgkEf8QNKjz2OQn6uEG96aztH3RsQYOjJ53srg4zaC 7GBath0v8UZsvihwaFpZcQRR76oHg2gcc2ftIZYdvTTjARaofntOAOxqJQTG7rLFuwkAgizAAvb HRRuB3GJ4MLX/CyBfhpH+6ecQjc6SmhhiZQz4C4hs4RdN4pP1o+xkwRSdaAofqCTMwK+hr5KHDj ykmUyIpVZc0aK1vIKzNFR X-Received: by 2002:a05:6870:f622:b0:475:a1ec:961f with SMTP id 586e51a60fabf-4a2a8a0bf68mr15629287fac.33.1792028063354; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:23 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:54 -0600 Subject: [PATCH v7 07/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-7-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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.232.135.74:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74]; TO_DN_SOME(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.232.135.74:from]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26654-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 87B481C2272 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= sunxi_nfc_read_buf() and sunxi_nfc_write_buf() move data through controller SRAM, waiting for FIFO space and transfer completion. On timeout they stop their loop but return void, so their callers cannot distinguish a complete transfer from a partial one. The hardware-ECC paths also ignore some NAND column-change errors, including extra-OOB transfers performed after DMA. Reads can thus succeed with incomplete data or bytes from the wrong column; writes can issue PAGEPROG after failing to transfer all the intended bytes. Return the transfer status through the randomizer and OOB helpers to the page callbacks. A read with a NULL destination still fills controller SRAM for ECC and must report errors even though it does not copy to memory. Disable the randomizer after either transfer outcome, and use the page callbacks' error exits to disable ECC and skip program-end. Update a tracked OOB column only after the requested transfer succeeds. Keep transport status separate from the maximum corrected-bit count: zero from a successful OOB read must not erase a positive correction result. If an OOB read after DMA fails, restore that attempt's corrected/failed counters before the caller retries the page in PIO. Leave successful command sequences and the returned OOB representation unchanged. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 170 +++++++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 8256982d1d56..dfdd8d8aaa6f 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -663,7 +663,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); @@ -679,7 +679,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; @@ -691,17 +691,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); @@ -717,7 +719,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); @@ -731,10 +733,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 */ @@ -884,23 +888,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) @@ -1150,31 +1162,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. */ @@ -1222,15 +1242,19 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ - nand_change_read_column_op(nand, mtd->writesize + oob_off, - read->dma ? oob : NULL, - read->dma ? ecc->bytes + user_data_sz : 0, - false); + ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0, + false); + if (ret) + return ret; if (!read->dma) { - sunxi_nfc_randomizer_read_buf(nand, oob, - ecc->bytes + user_data_sz, - true, read->page); + ret = sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, read->page); + if (ret) + return ret; } sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, @@ -1270,9 +1294,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; } @@ -1291,13 +1320,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) @@ -1420,13 +1457,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) @@ -1452,27 +1497,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, @@ -1620,8 +1673,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); @@ -1746,10 +1799,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 Thu Oct 15 01:33:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3623 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 B53D81C6190 for ; Thu, 15 Oct 2026 03:37: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-26656-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-26656-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 7D9853F034 for ; Thu, 15 Oct 2026 01:34:29 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9957B33F8D4; Thu, 15 Oct 2026 01:34:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dz+zAgFm" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f41.google.com (mail-oa1-f41.google.com [209.85.160.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 BF8F3344031 for ; Thu, 15 Oct 2026 01:34:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028068; cv=none; b=ug/rWn1x+RsSG2o2+IjqWf8lAGPetUtErmwIHXAvB3JOo2nJu8TT/Zn4KRLixa5tiJAFrZNYZDPYZ1x4B13ov8YUOJg+y65+Fb4siD9u7aKjJSRJVqL0n4ALpr1an8ur+CbUzGOOrf7QYSHhflCdeYmbZE5sqTAEMK5oK2VB2FA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028068; c=relaxed/simple; bh=UsPtr5D7TcSTYM7m33I6oYw05r53iguxnK0xi3GQO2A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sv9RhYPyaatkcELWFrTiiu06Juxn4fZAj/NNiSBSlylYl0XdGfwPNcUL6fZ/utRLHg+EZ50UKCpWf5bt5qNFJhCAaF+Ftj63X4TiqABd1oS6WVHwL3N8aECyxn3Gb6iNm3hFpSsTTWzPffWG/6te3KBypb4rpO75d0WvgtgeCQA= 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=dz+zAgFm; arc=none smtp.client-ip=209.85.160.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-oa1-f41.google.com with SMTP id 586e51a60fabf-4a691d29614so1673406fac.2 for ; Wed, 14 Oct 2026 18:34:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028065; x=1792632865; 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=W8HSeNHmGWx6gPVnRbfeK4ulo5XYre5+Djy0Qjqqgio=; b=dz+zAgFmWXbu0HgJ6KsOJ3eo1se//21mko8ZsZBi1jDNKiCYutVo7/modwmNFTAwge 4P/IV1jUuVcx3mHbiootnJfnF+vOitq81Pd6yxle+CxJnYtn5oAuVFzpASm+J7Z0ctbi JRJbV4xUu3RRjZMFEB95aW2GlrLxjZXEhLjpVGqi/hsW5lKo/h2gr4M0fainBluWkaLQ JFb5kb6dVApRSEgdB2DoW/Qk09DDYnaWgKMF3GkWmvHhE084LuSiJhcHEQFDSMz5KIqM XxL4qvZ3shPTK1sq9GPruEcBFgEsICAKGPuwctr2TPuHwJ3ntrCbrs0KfnREaJqUU28r HFUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028065; x=1792632865; 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=W8HSeNHmGWx6gPVnRbfeK4ulo5XYre5+Djy0Qjqqgio=; b=tc0q7W6hDH2xZd9EL3Xu5WAumIctcIu3ESh1rh3HEnij03gOPzdpsrO+HkxdbXKQeR d5+S28lOEhhLI+o+Cfi62M/fxd0RpX6SCFIUEX5N8qTlcFatv/zxHS1jIezck7COafAX TYfApJF6+9/dV2Tqb0ttnwWig5ECPLd6OEqtozwwsscaOTexluz7r6TrmBR4He6YPzC3 5gxRMuMWvAGnz+sYmxDdVdSxfWBZ4eDv3veeI2Ob048rPX1GSeDKH1XcinQYFY0nv/6V ThGxCjwZ0HNGEVqPQnFhZdXBKlWC8Pt7lF7qSCc3g5xSnW0w9EmlI97COZQVv9YUmskU 54tA== X-Forwarded-Encrypted: i=1; AKwUvBwJtfHdmSB8lW6LxP/WHDwphv4Sfe8Y1caeNzXqt0taEtaOFIFkVlXG2/jowDUYZGNq+uhyBM41oIHL7g==@lists.linux.dev X-Gm-Message-State: AFq9FYIro0ID5U2HdOd64Odhbm1EU225/p2sa/K4/TcmFwxVutoroGDm V0vFUDV9kvTnylFrcy73l+lQ4mZsZclr90163Yt2Ecs9k4NkhC147C/V X-Gm-Gg: AYBFou1VDI0YPKSd6KFFzUI2x9XfmPK82OaVhDhw0nmVm1mWkuva1kL6UUV8rretwfG LRCQ1fYWOEAdVDxbOdE/wYAC8aSf2nAXckF/QjPhje2eAOyEKyofmvOBCGroAkwLprtd7JV11Vd 4hVw8wmVGAEYfIpXMke2EJM7hwU6w/nndtYSDuWyjxiH3jU2R4VGJ3EB/cmSZ0Ugba5QyzbYs0l 1WolRVeCvH2Hzua69JyDebCJb6rzX8Jh9qh/ReiGRF7KNvru8RphqMQYHq0fFT0pmUsE3xzO+CH fbBLi3RGnDN7xCpAmE3PAzjckRIHz+0Dzbamo5MUdpI/4VYpZdET+/kYcAzOBoEZsya+OJfl9kt 3/r87LHPAipHRrnX9kYUuDmHW8ebWn98iklVze/IiyAh/iOGZrsuxWDZEfFZmv2tXF0MlGAQr4d UDGygA3iJ0qjZNx6OHREKL+51J1ThXqrQDBE35b4TkpamDQ+tlSDQb056R9bgqveUc/qjme48vw TaTyhSh2GOy4xZvI6JJ3ZneJUMvH1r14hGziJWk+lREVYDRnsV9AsKmJltG7Wdwad0cUg0I5eXs imIiueaxet9FWIfZu3b7UV3ozRBEnwSMwX4C1PAehaqR69qHMPWvOrbLjBo59P9RUrDzhSKEkVT wP5R+pfu+0SHJ85HVcp/7 X-Received: by 2002:a05:6870:4066:b0:4a6:c1cc:e1 with SMTP id 586e51a60fabf-4a6c1cc0336mr6240528fac.5.1792028065404; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:24 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:55 -0600 Subject: [PATCH v7 08/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-8-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; 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)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[209.85.160.41:received,100.90.174.1:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26656-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: B53D81C6190 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 dfdd8d8aaa6f..6c4e1740a245 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1824,15 +1824,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 Thu Oct 15 01:33: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: 3624 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 C8B0F1C1E5F for ; Thu, 15 Oct 2026 03:38:19 +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-26658-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-26658-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 930B53A55F for ; Thu, 15 Oct 2026 01:34:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B4EC133C194; Thu, 15 Oct 2026 01:34:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="geWe5OIP" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f51.google.com (mail-oa1-f51.google.com [209.85.160.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDEA034752F for ; Thu, 15 Oct 2026 01:34:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028075; cv=none; b=Ok7R2jYGM34Gwp/jhi2MmoajwL9kzODrZZkyDKiSSRc8sVTS9rAgAzfUQuUcnhWhb/9HvNAfqwoviNrzfywGgcWBXqj34qXBZNrLg0vWQtKr6bl6LHTtFhUMYZuzqQhbZPcLwtrXNx0mzqnt/ipkygWNTlijVA8ZJGWNJuClpvA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028075; c=relaxed/simple; bh=fIW/vMdm44Bsxi2J9pSdPVSnRlU2o1NOr7LGQ9C8GmI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UzddHAFkA5yvVmVVm7YIcP6MChCl93fnORRIvLfXdMRql1mySuImAxMoFhAg5+ZbKkeS7UKHXz5teghryk++ZLB1LZPKibF28WJrCL222zg83lZt7FfYohprNkcRom5X+X+03sgLGuJ5tEHBzMGoSrKd/Qjl2NP/tGp5TbX7ysk= 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=geWe5OIP; arc=none smtp.client-ip=209.85.160.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f51.google.com with SMTP id 586e51a60fabf-49e08af5fd4so464195fac.1 for ; Wed, 14 Oct 2026 18:34:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028068; x=1792632868; 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=V8zDMiUEBwO1gulkBzoLNFoNTmgcXEIIu2kuyTI/+xI=; b=geWe5OIPpDAUNyTYZ9ElAWoZ/Pst27/zosGYyO+KlO/jwiFaIScc4/6ZWZjXtnnReY XAj4nDnca88mtRf1FBpuexVCmUwwnmyV7x0GhVNQBZyTnZ8eWn/SAdJ5hvQZ59VDEpR3 bPy8G8e4YwIQfMtmcmOrVZDK6R6O3jVsjpUGSoL3DcXTj/atj2djqG2ZlJK2YDJEog7P AjYCkwI4keBwGJIszsHXK8Fi32JxN+G8tiOtoO2qomdQlIjlZvfckDOwPgttz6pecwK8 sPEBANClDYjpP9vFYzttiTGfwuoBGs5tbjafa8CWlHxFCgE0yUVw0BadNB0bl0O2KDGY Lx+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028068; x=1792632868; 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=V8zDMiUEBwO1gulkBzoLNFoNTmgcXEIIu2kuyTI/+xI=; b=MGuG0gL6x3Uo36fN6wrNc6nVp9L+STab9yNxgYRReESvrTyLjPHUFoltxiIBgA5qNV b6FpFZt/ApwUpskfPHLSWNJ24MOEVazH0IULN0sFcoQCaxwroVm/PryLhtTJh6hDrnMp 5pWBJ+YiDKF2QEbi2H8UFZgaVpqyOOxSHB133HNoAwTTRbyYO/JefRkOMIE95Xj8uHJE 4Kmd2gRjvVnhBmFOyDGW9zq2vM4EJvjbYzpzfrY4sWoqT9DPbT7O+FmqFkA78Pboe7QW NNW8CSXhpwfqGT9Ui7tqEiYtyiMyZLygJ/AaVoCMtGvypwefgvlZsRHzPKmcbx9rChfk Ya/Q== X-Forwarded-Encrypted: i=1; AKwUvBx6xKjZ28FPBoIK1zOwyPri7XDv1quF2cl4gImTIlhC7Wev+ulR9EbUx7y6GG2ANPtR1XZ9oJXlHG7ZUw==@lists.linux.dev X-Gm-Message-State: AFq9FYJT5rFGvEcvO+CtbMdsjIeQ/6IfIRb8XUNLnyx2p0u9Azk63MBu pgiNbLHaAWSS6hWquJKvrqzPyohZDs25fdH6YoS1z2ygcE5AGuED31DR X-Gm-Gg: AYBFou37xk2wGa5RBluw87MJN5PmNRMkapBVa8Y4fmhes9vx3KokQq/o8YZFZSsyOcR QryXWsdq1DKodYNqgyqROWglgoxQcPd5yCSRGOlmBnYJM9AixAn0iKZPxmg2Yzsq4lCrLW4EDcc 1H4jhdDDie6fugmlnMCl1lQTT1eVA8293+tl3wmsMJ3SzTotMaHcscxhOuKIj43bMk0E+/I3ane gpV9cpNKzVpwG6OQVyOgn/xJS55DrzuFZarigR7QjiqNs1VDsXppYpe9dB2MJ49lYdaRt3F3kCU nXvCma2FOnj0BCp2EJdCPMQDrUKR3jQKsBjpPNHkpJL+foCqCogijWgFWvg8ltng5kj8I0wkvkw jwF5iKM0kqMytQLTg6b2Vr3SVxK1pjhP2m8FWYGshLd1kUMhvwtdXsfNNwy+w+ca8d5cWOOWbC6 mDab19yhddDmjGXPwuD0ijmVeNEeUDe2WJBxwqSWaFASvBkAAlvwrK+1AO3UmpBlhMTFFdc0KhP 1p4DdL962FT+y6QtbeZarxE5aE7+s0vGL7EtNyTBf/mUd207tdeKWAkBnzeSV4Sw4bZlZmABHwe rLVsPksaAK4OcMhvHS0uAjWiqRYxRAQA2WSv2Ro2sKVJS7bry08FDv8GHm+MdH9Ad6VOUyH6Cuv nan8Sz7E5Uk+iplD86xPQ X-Received: by 2002:a05:6870:a40a:b0:494:76db:2aa8 with SMTP id 586e51a60fabf-4a2a86a7ebemr15214415fac.5.1792028067725; Wed, 14 Oct 2026 18:34:27 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:27 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:56 -0600 Subject: [PATCH v7 09/16] 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: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-9-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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 hardware-ECC reader moves between main data and OOB, and rereads raw bytes when checking a possibly erased ECC step. It uses nand_change_read_column_op(), which sends large-page random-output commands and rejects NAND pages of 512 bytes or less. For a small-page geometry accepted by hardware-ECC setup, these reads therefore fail when they need to reposition, rather than using the small-page read commands. Add a read-column helper that uses nand_read_page_op() on small pages. The core selects READ0, READ1 or READOOB for the requested column and sends the row address again. Pass the page number through the erased-check path as well, and preserve errors from the resulting operation. Keep the existing random-column operation for larger pages. Select PIO for small pages even when DMA is available: the DMA PAGE_OP sequencer uses large-page random-column commands internally. This corrects read-side repositioning only; the write-column helper still rejects small pages. Software-ECC and raw callbacks are unchanged. This is a command-path correction found by inspection, not a claim that ordinary 512+16 NAND becomes supported. The existing controller-ECC limits still apply: it needs 512-byte ECC support and at least 28 parity bytes plus four user-data bytes, so 512+16 remains rejected. No small-page hardware validation is claimed. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6c4e1740a245..f8abcb46f7f0 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1054,6 +1054,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. @@ -1062,7 +1072,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; @@ -1070,13 +1080,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; @@ -1177,8 +1186,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; } @@ -1242,10 +1251,9 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ - ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, - read->dma ? oob : NULL, - read->dma ? ecc->bytes + user_data_sz : 0, - false); + ret = sunxi_nfc_read_column(nand, read->page, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0); if (ret) return ret; @@ -1281,7 +1289,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) @@ -1321,7 +1329,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; } @@ -1331,7 +1339,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; } @@ -2304,7 +2312,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 Thu Oct 15 01:33: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: 3618 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 2BD2B1C2272 for ; Thu, 15 Oct 2026 03:35:10 +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-26657-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-26657-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 9EFF5389DB for ; Thu, 15 Oct 2026 01:34:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 43C033446A7; Thu, 15 Oct 2026 01:34:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="js2+WSnw" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f178.google.com (mail-oi1-f178.google.com [209.85.167.178]) (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 7509733F58D for ; Thu, 15 Oct 2026 01:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028075; cv=none; b=ELyyHOjnnv1cR5XoJ5p3nVt3rJKqO1Zd2dfTGi3cabtwsPq/g13IxoB7FsbPB1H/BQQK5mhv+mXD9q0xWtt1iqnBsiAnTPKPZcKyYKrmgRmEaaE8R9QTaa9dnGsv8tnOcUtV+vwP/Pj830LpTIfV0bO2hTZ1z6HTk2JCU2WLH9k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028075; c=relaxed/simple; bh=ZEKjLdrQvIkgydjVw4i2vZt9v4LnkMBrUPI5IXpMP30=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ozVZZ9d+3t6GOV3uJfhfzjQT3Oqdv3p22EO+wRA8CfRgHu3xiR1IbYzjFO6rbAg+WnPwrRD3Q+5d5quMOCAM4yey7fCMCAzFBikW1zKKGCAUuK6YvqtgIG9Bkr4sN5GITI04utWH4KDZqEWiAlhSnn7FPPupPg5FkNyniekT+uo= 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=js2+WSnw; arc=none smtp.client-ip=209.85.167.178 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-f178.google.com with SMTP id 5614622812f47-5058b105df7so1705832b6e.1 for ; Wed, 14 Oct 2026 18:34:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028070; x=1792632870; 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=CQCXnCBoKTXRiFJPMtozb/9z1MKfV5eVFxvBnHn0o9s=; b=js2+WSnwlmKD5TG0qaXyXJbC84pu/StBZ+YZfgmHyWHmAwCKjBAKjQFXlV4pNlZGTz JdVNTsfPClJhjCfD+p3ld3P3R5bY8cqiRgENaDXxzvrqOwEpfycQOi3fE/0JCj4yGhtX 52Xhu8/0HYVfqt6QqvL0l4kP+1peNs6Av+pqfWWQIKQ14uwi8rRcyQLedsf30ymm8Ley zZd6owlowrmfH7sjBhn1+Z0prggnJj+ZSe6Ndcnxe8Tn6EJAZ0cqQHKl8766Qny6Uooy HgoSYhbKiLuYNMOzHpLZdYj4Y1ahIkWL5LN9U7t3+2l3Aq/IOODR0m+/HWWWLHwUy6M6 4OjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028070; x=1792632870; 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=CQCXnCBoKTXRiFJPMtozb/9z1MKfV5eVFxvBnHn0o9s=; b=oK09pIFg02Vy++dEvwVkJ27UcZi4mvl+OrrTVwqb3+WEXUvrO8EmvFDGEZsdp/Fl/u cX93SMRNWmRyRhTAsUdNOi54uAF1wgREjFYxJwHtI2k+Nu6HP8hdyvFEf1StKH+5pOiL xdAmhgJwzhvMAJbaz4bYb5rhwQPnCZq2Z7BWJNplK3Necm7D50ybVsha4sMqp2zVOXcj hCPLR1FnN1oPTzPnMCEjL53vKOfspN8Utqw+TjoPGe3U0dvUl4rxoL4Rw+NDeZLGiBmv I+qJ1neIcKQv0xCdESh7L8oYcU3NpHyREOKKh6H3ZmtRxbgPh6KY8l1g4HdlhbmDQiUb Rprg== X-Forwarded-Encrypted: i=1; AKwUvBxmmTJ5QBZXyxc0S1luSKuu4E+//phNp989kI3054/gOmuGgDJxoIlLjF6FzVzAcEmOhZCW3evTNmAO5Q==@lists.linux.dev X-Gm-Message-State: AFq9FYKjk0U9VhhEUKEqe6qMaJQMM1BPAg8otwMihX6HN3n5ti/qmLdC ZWChMYoqp/E2TozpNLuyvQ9/3S7dYjrcD7SQBvMWYb7869aBYLaUysYB X-Gm-Gg: AYBFou0zl9OuEGKjsAqSM/NOa9JxUOfYrVKK+au4LUrBSbZIekYyST4Sf1WFl4TgzHd H3t3+012rZnTPpEe3qcILhvsVI1Z1ygJACXF2VwlE0kWJR20I5jx5hJyXc2Yl9S6ltMEw0qARIO 2aGBf/Gn2yBlGtMyE488kiF0ohY4zJL/PclCLsOBecCLI8YkfKalipt9KwUpcPvmAUc3lk9TcQL KFJwwjTBvp3kYugW069Dt2jKwiJ0qslXY1uE057SDmIw41gx5u99guIiiUTnhePbUmbMWH/vaNo 8R30FYkL8a1wV8UAANFb4Z2XwAuDupcytC6hrdUnpTa0oajJmDHQqBYPMRLjV0NiVE+Ml9rWf7n YE2P229dggqrZG2zqVkjYhTSIlgTZg6hmSXs/vBDBSe5DLww5jkhiB5rGVbU2fWBzgX43Lm5Of5 0E6M10l/nA62FH2y27ojeU1F235w3hddoFtsJOutQg2qVQlv2OC2p+KGuk/CRHyZwvguWa3YCQd zYi12YKfl/V8yOQtHOzJvVGuHoXG2U64tXFkZOiH7gcktWVbs9oEUF0gbCfZiFcISEnUz48sMvR 9gsmgkV6291coEZ4C60nIHXmzdrnf02e2yjLjtX5j3qbTprM0HMlmz3WQUgMXSWPUFkBTkaPVfY n3JKoBUKJRT3UYJ2jnWFgO08kf7BrNOU= X-Received: by 2002:a05:6808:1241:b0:4f6:808e:3838 with SMTP id 5614622812f47-50c582328f9mr16041562b6e.52.1792028069956; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:29 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:57 -0600 Subject: [PATCH v7 10/16] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-10-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= H6/H616 store ECC-protected OOB metadata, called user data, in 32 four-byte registers. The fields for successive ECC steps are concatenated in that 128-byte bank. However, the existing allocator fills the OOB space left after parity, allowing up to 32 user-data bytes per step without limiting the page total. A whole-page DMA transfer can exceed the bank. For example, 16 KiB main data plus 1280 OOB bytes with BCH40/1024 leaves 160 user-data bytes; with 1664 OOB bytes it allocates 512. Register accesses then extend beyond the user-data bank. PIO can handle these layouts because it reuses register zero for each step. Capping the page's allocation would instead move parity offsets on flash and break compatibility with pages written through PIO. Split DMA transfers without changing that allocation or the logical main-data and OOB offsets. Fill the first batch up to the 128-byte limit. Transfer each remaining step in a separate batch, using hardware slot and user-data register zero after explicitly selecting its main column and spare-area base. PAGE_OP generates later main-data columns from hardware slot numbers, not relative to the selected initial column. A multi-slot batch starting partway through a page would therefore revisit an earlier column. Single-slot later batches avoid those generated column changes. Pages that already fit keep one DMA batch. Program length fields from the batch's logical starting step, and consume its protected OOB and ECC status before reusing the registers. Keep erased state, correction counts and trailing OOB handling page-wide. On a failed DMA read, discard all partial statistics before the existing PIO retry. Use one page-read setup or program-begin for the whole page, and send program-end only after every batch and any trailing OOB succeed. A write may fall back to PIO only if DMA preparation fails before its first batch; never retry a write after part of the page has been transferred. Raw access and the OOB layout reported to MTD remain unchanged. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 202 ++++++++++++++++++++++++++------------ 1 file changed, 139 insertions(+), 63 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index f8abcb46f7f0..c27cd8e04739 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 */ @@ -951,7 +952,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) @@ -1369,30 +1399,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; @@ -1400,7 +1432,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); @@ -1432,10 +1469,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) @@ -1741,71 +1800,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 Thu Oct 15 01:33: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: 3625 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 17DC51C618D for ; Thu, 15 Oct 2026 03:38:39 +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-26660-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-26660-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 A156C415F1 for ; Thu, 15 Oct 2026 01:34:40 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E7938272E6D; Thu, 15 Oct 2026 01:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M8VlXrwb" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A442340DA6 for ; Thu, 15 Oct 2026 01:34:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028077; cv=none; b=gHSqxkoZmuQDkeodfdJeEVi0AR4VqNg3pAhl6gOepOSCtIn7/GhNC+I9GKWcxxM0vn+OkTfa1S1w1dhUSnB2KQSlSBjd4oHt8RRFxmnW/4DvE0IidvkHQiOgP20J+HC+IdJdxrw3lWwcsE7kxV2emiR7+7ipQSpU10VoXU8bYBg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028077; c=relaxed/simple; bh=/BnEzNdJn0yCUc0/5V8pCZ/H7UotnnA6rAgc31gHaME=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BlPmP4dJTzd0aKmH0Y+NP9ldYu61hHE+FL/agykPNBgeVKQtj75efhA2SGrITp6uArsIv9qrxPPOycjsPZ/oR20us81cxhY3S6KfaHW/K8CAjcIf/k8HijRucMrxgZsjF7tOd+kKZFRewywKmaHdDq5aHVziro6keTEp5W9sUNk= 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=M8VlXrwb; arc=none smtp.client-ip=209.85.160.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-483c607ccb4so622989fac.0 for ; Wed, 14 Oct 2026 18:34:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028072; x=1792632872; 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=bNTA8wpqaz3QuKzYKJPWBZ0ACcTPYNOhXhk9kMH+rig=; b=M8VlXrwb50OLl1KxUbpZVyAg8R8XdFOaM2Lnvu0zlEDJtpAtTpPZV9F5zx1RJLXKdD 33IyP2ck7geBvDHNn1YStdf4eXcpvpjx5U3uUh+fVpiCdcrlQFs7BT+uVjt6Api1db2B uWVEt+OrxSnXM7uj2wFKJyMpggYiD1XdMYs/WScxqHmNTIxOXj7/5e064j6xNlxLegwr 7FdW1qsGeNW7JzFDdtjWM7a+M8JlcIMrwIVPMj/rWzMwfGrSSajiUBfPpKoYWHdwuVZD JlfYyORGUOsFv08+mRgsmwWOnvmFslVyNKlNnQRJv/gJ1zbv8XWKSi9UtaCA+R9CLBv9 xcQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028072; x=1792632872; 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=bNTA8wpqaz3QuKzYKJPWBZ0ACcTPYNOhXhk9kMH+rig=; b=Gphxv19UyLIWqNppWtQbh8O3+KB7nhEwn6i6UyNsPffqpYMycHhcbZkjdrYGiTQNko TMW+1mVHrKdOERb0BlgCImX/QChJn4cqhRQMUUYMOWv9t9FJFR9LGbc2mEO8r3aNOE8Y QpXlci0JsMHJxwge9DXJAjp/D4UshPhRxZqVxuBCKJffC+UIWHzmlLw119dAaBy6//zL qC6m5BauxRy/soxngzQeYEgH85hw2YM0/r5txu+zmGFsnUVKQv3TS9snRTiJuefNsj2J uWt2iOe6iVYWQxal5UqpyLM6RxSOEZrCbYsxoptkRPf4NFbefXmcjc0yzB0cfijZCibv 6saw== X-Forwarded-Encrypted: i=1; AKwUvBzuhVhMD50tcgYLv1lvPXrJ5ehDwuuPnAjigtIYnYpcTz80m1APxMuoP605Jcs8e1FjptVTR5sEUAxMtA==@lists.linux.dev X-Gm-Message-State: AFq9FYIIXop1DdSlxyIIZFsLDaLHhw0JpiRNK9kGSZQ1qlIpgg3s6ey2 SQmhYOEXNWnj49/njCmGI+LOrXhKbKuQfqbq/WsemYSdFa5Wbr+HySmg X-Gm-Gg: AYBFou3iPBQUucth+SNlArJ7lc7UuINqNnhOaWq7gofRTws0B0FVRmrGTwx47bz/EBp KyJ7XtrcVjBvn3FpZXYxSn8bGq7W4xFib9VZ6GEpMNyM1D8N3sO7j3H3SnyTI8z0zCzu1Rtkrdt 8I8Wdh+j7MPjWhyXuL8EFyEjQ7KMgFDpm1eTT0G2IKz20/ggkyGNQ9USH7ek3m4vvDR4Gymaah8 llSVpY8H2z6Cb0LY3jC1iVfLZHA2/HGsv6kUV2maEVfL0/kPFIraHHHG3IWHMv+NaohdYhreSVz mLN4tI63BG4ZDzSEPAM9Bgq5JVeCd6qD1wb/VJ3qMscHFbtEKNSiBZEffqTLYHPi2vtIoKFVoXb sGxjmZwnV0wnF6Jgpy1m+zLpRtqYljVKnWZW1DMWa+dPOiaDDHUMoar9UBATcc075nk4Nl+iHiq rK2gMhWNpLHmBENocboujxEnMVDZ41LFy7ay3FuXGRliI+f4HQgJLQ6VDpXxkrCA7QMzm5bnzIQ fpuj+B/f6/E0dc1OyImiXLij68CNf1khoiprTEVu8gVFI2So14QYes7yL9T3aFdSM8wPahcpq1T r5nHBWA34uhEgmIP+2bNpVRpzJdTdrHL8sACSBU3/1affp+cMTGOaFImipt2gIyjsz7kPKzBN19 BPJyUWew2Fd3ZpwasXAzG X-Received: by 2002:a05:6870:c2a5:b0:493:8be5:4271 with SMTP id 586e51a60fabf-4a2a8a2a2f1mr15479440fac.33.1792028071864; Wed, 14 Oct 2026 18:34:31 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:31 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:58 -0600 Subject: [PATCH v7 11/16] mtd: rawnand: sunxi: reuse ECC status within each transfer Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-11-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= A completed DMA batch leaves one ECC status bitmap and one pattern bitmap for all its steps. Four consecutive steps also share a packed correction-counter register. Reading the pattern ID for every matching step and the counter word for every corrected step repeats MMIO accesses to the same completed result. Snapshot status and pattern information once per completed transfer. Reuse the status read when the controller places pattern-found bits in the same register, and read the pattern ID only when a non-error step needs it. Cache each packed counter word while consuming its steps. Keep the snapshot local to a single transfer and invalidate the cached counter before processing it. Each PIO step gets a fresh snapshot, as does each DMA batch. The ECC decisions and returned correction counts are unchanged, as is the page layout; only redundant register reads are removed. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 88 +++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index c27cd8e04739..8d83882592de 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -258,6 +258,7 @@ struct sunxi_nfc_timings { }; struct sunxi_nfc_ecc_read; +struct sunxi_nfc_ecc_snapshot; /* OOB interpretation is independent of PIO/DMA command sequencing. */ struct sunxi_nfc_oob_ops { @@ -268,7 +269,7 @@ struct sunxi_nfc_oob_ops { void (*transform_bbm)(struct nand_chip *nand, int page, u8 *bbm); /* Consume one PIO step or a DMA batch; negative values are I/O errors. */ int (*read_batch)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, - u32 status, u32 pattern_found, int first_step, int nsteps); + struct sunxi_nfc_ecc_snapshot *snapshot, int first_step, int nsteps); /* Read any remaining OOB and return the maximum correction count. */ int (*finish_read)(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, int *cur_off); @@ -1136,23 +1137,64 @@ struct sunxi_nfc_ecc_read { bool has_erased_chunk; }; +struct sunxi_nfc_ecc_snapshot { + u32 status; + u32 pattern_found; + u32 pattern_id; + u32 count_reg; + u32 count; +}; + +static void sunxi_nfc_hw_ecc_read_status(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 pattern_found; + + pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); + snapshot->pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + if (nfc->caps->reg_pat_found == NFC_REG_ECC_ST) + snapshot->status = pattern_found; + else + snapshot->status = readl(nfc->regs + NFC_REG_ECC_ST); + snapshot->pattern_id = 0; + if (snapshot->pattern_found & ~snapshot->status) + snapshot->pattern_id = readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + /* A new operation, including every PIO step, invalidates the count word. */ + snapshot->count_reg = ~0U; +} + +static unsigned int +sunxi_nfc_hw_ecc_read_count(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot, int step) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 reg = NFC_REG_ECC_ERR_CNT(nfc, step); + + /* Four consecutive DMA steps share one error-counter register. */ + if (snapshot->count_reg != reg) { + snapshot->count = readl(nfc->regs + reg); + snapshot->count_reg = reg; + } + + return NFC_ECC_ERR_CNT(step, snapshot->count); +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob, - int step, u32 status, u32 pattern_found, + int step, struct sunxi_nfc_ecc_snapshot *snapshot, unsigned int user_data_sz, bool *erased) { - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; - u32 tmp; *erased = false; - if (status & NFC_ECC_ERR(step)) + if (snapshot->status & NFC_ECC_ERR(step)) return -EBADMSG; - if (pattern_found & BIT(step)) { + if (snapshot->pattern_found & BIT(step)) { u8 pattern; - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { + if (unlikely(!(snapshot->pattern_id & BIT(step)))) { pattern = 0x0; } else { pattern = 0xff; @@ -1168,9 +1210,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); } /* @@ -1239,7 +1279,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); @@ -1262,8 +1302,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) @@ -1302,7 +1341,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. */ @@ -1310,7 +1349,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; @@ -1352,10 +1391,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) { @@ -1391,12 +1430,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, @@ -1407,10 +1443,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, @@ -1466,12 +1503,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 Thu Oct 15 01:33: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: 3626 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 A5FAC1C1E5F for ; Thu, 15 Oct 2026 03:38: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-26659-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-26659-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 6E36D414EF for ; Thu, 15 Oct 2026 01:34:40 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C0DA433C194; Thu, 15 Oct 2026 01:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qG9bi3V3" 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 75E0C33D509 for ; Thu, 15 Oct 2026 01:34:34 +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=1792028077; cv=none; b=MolaNZ1dIXHR2AhOls44QiHzNLKBdQ2YyGKCCowtZt4qIAPCNLp4iS+NlPGwvCcirpyv/vSGIWqjDVrz4sQU9s5JB2wKWVdTGAHtIO5M3sRshPKTl5caSwbvAtX2kR6lAplcO7e6Rlml2CmzeIWuUrtoW9Gngxs5HKrzsMnPLzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028077; c=relaxed/simple; bh=N6VYX2y4jRer8ibxun+86X1ICDnbdaEYXj+AGFjjsL0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fcuAwYGR6b7Hk/Fmit138FqrXwZKOGbL8BlhzKlmy9PSNfBlhXwt6okYkTiq0ir98WLk5uh/CgOW560YJOT5T9tu3y3zMTJa/CZjcWkcvdeLXqehQg/7XjYsL4KOig+oITEjz7O/VuWkQJ025o9RQxmE1mbiaJgy/LbDHSSlB8s= 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=qG9bi3V3; 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-6df7f544919so3160867eaf.1 for ; Wed, 14 Oct 2026 18:34:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028074; x=1792632874; 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=P1wjwZJLHUWptclLLQZn3mtfqh+PMZO/1RuhWVrz5Xc=; b=qG9bi3V3cH9gvW4pJKhNqKm/zYXGbLxGarK0e0R1y+xFHl6T+lJ6HpH3gbMG/wUNi3 WpIUNmzw0E4+ElKDDH8EarfyjXyisrGD2gDcmRT8j0wmtedtW655c1qBZKJHnYhm67Kk ejbFNQL1JT7K4t9bewrPn6xn0ecx/xwFtNwvbScs6jgso/u5D8/YwK4HaL7kZWlr8KWD BLopsGDYstXJdJWrQhCY+51XlHmu0HhFcaTDoabCAkFN5A5Z//vxAokj0LJp5zqbrCLS gv2F58BM/K915bjftk35Sd++DTqrL3ugUkNGKGysNvFLGAURfF4UMVpj7TN0jEbkSGzC dSUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028074; x=1792632874; 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=P1wjwZJLHUWptclLLQZn3mtfqh+PMZO/1RuhWVrz5Xc=; b=qAqV1iPK1ymk5WVoLV2x0hMvvr052RRKulIwv0d92nT5xCjT45TRJIqm9IzuR0ZiOb J5dXspUNd/3DTWAQC3qv4D/wacBJmd+yLbldmVyUqZVzxe7WTX7LdslkeH3jV1M/Nn8p VxzkeiI99Bzi0USSoPU4u2m/koHx/ghFkJI0aie5UDYdrQfHXtuuZ82dU7NokjCOZny2 D2zL2wRdCnGBs8YFMUW6zdyLKw8kpDoEznqHqSylNDbEe6uq/JoBSv+A/GZedgOamsAf e4MCicqtmZmgxuw6mRjyL1SJ/pfavxfwH2nVuUJoJpuRRcJv0V7B62erx6bMUWU+LVXY rySg== X-Forwarded-Encrypted: i=1; AKwUvBz7eLOpcCTZ/VdPotSmNHjRFZoTLU/smBtFJ7NZzu55kjhWvmLy1KICUKh5H8c5U3TlWqX6knwqVf6k5g==@lists.linux.dev X-Gm-Message-State: AFq9FYJJZYQ1SxVMPFYv26yLhJyIz8wlGRx/lR/yL+o24PS3jOY7iXbW yO9+070K7WAez2mUYeFEwyeXakW8KfiRBksrnvicfIa5JptUMfHDhRWL X-Gm-Gg: AYBFou0rB05w9V03iBMLSUWJNDSdfW7JQslYIr8io3r/4hwJlJXhFuffxLH7HGQrB67 iFZbL20gayZ/KqAvuOoppl9dCxgZmhYrBYxLnYGOKH8mNrOkO1auzbSwX+QtfSu13rJ3I9JKZQs nXo7FnQfmruVWh2+/WNFzT+WAPfhISO4BakHdh4GRc+Vyxx2a8sspeHxtYat/WNUQ7ghIJjquiM GK+SDIQbZ9BsR1kXSIYn91CttUPiIj9TYgacsjnyG1nssB6FsbNdO8X3XqU5ssC6REjEN61wZPh zzoK0s9DB7vienCT1peG4GI6Z+zuCcpQ1ag3qvnh03HEKX8jgTRGQnsSWKRu44rmAQwcdzE8/JX IQhdhH6ORg0TSGm7lvly87jIRWLduUuhvxyXG4lq+ywYfYNrC3kGbKCk319pAnvb906jC0OHWjb fn0MYow9fqtc8RkOKkuhf2C2nRDglOY+dACarxj/Z+nva11FZKEW+yibTnUiT6YwSmNB6NW6dNx QQdVV4+d6FLQFdD/g2XIuncj4mDmfD/h8lQ6sLRgvf5AMA2h2nb9NW2f0rCH0jbuXEAwnTd80NX /43T1fU/M4fozD0UnxEnfgUBgaUDcGelhCBRBmBcXuofO5n6cKMbY1tTVut6uWJ5BxUHzZc+SHP Pr4WCcBAgUSLDJRFi40w3 X-Received: by 2002:a05:6820:81c6:b0:6de:1071:8b18 with SMTP id 006d021491bc7-6ef107958eamr11840974eaf.75.1792028073754; Wed, 14 Oct 2026 18:34:33 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:33 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:33:59 -0600 Subject: [PATCH v7 12/16] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-12-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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.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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FROM_HAS_DN(0.00)[]; PRECEDENCE_BULK(0.00)[]; TAGGED_RCPT(0.00)[dt]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-26659-noreply=patchwork.local]; 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,209.85.161.49:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: A5FAC1C1E5F 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 8d83882592de..74fdca27ba10 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1612,7 +1612,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 Thu Oct 15 01:34: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: 3627 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 EB0371C1E5F for ; Thu, 15 Oct 2026 03:38:56 +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-26661-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-26661-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 D62A5420CE for ; Thu, 15 Oct 2026 01:34:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E86B9347BC4; Thu, 15 Oct 2026 01:34:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ovy4rBef" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f52.google.com (mail-oa1-f52.google.com [209.85.160.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 F2C5D34A76F for ; Thu, 15 Oct 2026 01:34:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028078; cv=none; b=mq/DjhLiuEFdnBy2yHgBlIpqyvfDd+SsBjjXyJmM70Pqg1bMB1nHLjDblKw+rt+r8mHdlBFI4z7GXV4T1+7rT7VEz86BvwEIrBL4mcF1L/dWdjBiF7Pskuoq53PtDBHvQzsnxGT9xx/x8NHDB4tOakbcdbj1m2X5tPEC64rDN4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028078; c=relaxed/simple; bh=0kxWl9QWVm1G3QyRQQoFBKdw9ex2r5DsXOknVXwQkMk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=duRazK35GRxNwCQbnU7hp9KPlIIouPPyeA9zUCYyRrNKjPqKph/3uz6t56urICVCVLwpBSBAmb/u8eWcw3ALVydD5ut7zp5rkFlJ8wxtoJs48vntGgUtGxiYpNsRUvfmcQ79Z7OXv0ceTUsmkBv/h5Wlr+CkNSwnxPBK23aerdU= 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=Ovy4rBef; arc=none smtp.client-ip=209.85.160.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-oa1-f52.google.com with SMTP id 586e51a60fabf-483c607ccb4so623015fac.0 for ; Wed, 14 Oct 2026 18:34:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028076; x=1792632876; 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=oafE3Y1G60hqD5AuR17ZSRtdy2A1IL7jrwTpft1hiNc=; b=Ovy4rBefm/Errtqc8IcIIRsZdhmBoCoWfCqfgD/Bquf1GLASwT1SocNTiAPzenmHyZ n3+cx7ml/h5iWk828trWqEuIIBOTcNy+r8q42n9g1jLTcT8aF0BCIedMmUQqIMvW9TQQ a+aaV0xqOH0tcOkwBEiI675F0V/HdtEXQgBkUvHh2bOf7JkW0p/Wh6gIOC804HhZVAdW c+GMA9SkN5Lij8wrmQHOCmVJaycJg8s1GgnHk94rgmID7H97e2LzqxfzJrGzK6rW9PvR qMEIS3n5x7xK8K5EXp1DC/xE44rPrP052nhedmwnaNcGGxQRFzR9P8DR8vYLc38U4bst /O3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028076; x=1792632876; 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=oafE3Y1G60hqD5AuR17ZSRtdy2A1IL7jrwTpft1hiNc=; b=2wmFtgtdcZ+p05vp+W/jnqGygYGen8CKomEweBuCvDK8DpXfYp44/M3bz/D3tHIyWy F6f5igB6UXTYoHZjC+QoBqyKT2jTRA5ZEHatBtTC7Eo+RcV54Bs0oHSWispPqPY/iZjy kaaPNlKO/1vYpzFH5P0w3NILrGllfZJIMz+qvYBv2UELhFGE94Gh4KxkGTfKAgPtYGhv KiePP1W1B71KC9lI0WLpoIOd3brS0etVtA4X8OE7dEdJ9Q2eWzZLS8hXVWEQkcwnGf4y 5apVTfokljy/TUgBbxEO0crZLcf3hElW5Z3KBUhPM1eD2NU4v+pG6vfX46+Q6ceFJSfy s61Q== X-Forwarded-Encrypted: i=1; AKwUvBzi8z06gXDGbqrAZGhG7Ecnp49UNvXWJojxmo0yq/tBkp+I6dC+DAua+Uc1EJkI8k94oFJpdp889h06fw==@lists.linux.dev X-Gm-Message-State: AFq9FYLadQsGNt4eSJZRSs+L2/SxAv4m3V5nekzDKcnFmL7u+bDrNxI4 uAYel57pk4T9gCX4xaBVuj1EQ6klij0QqWP8DrWSsltDMcAhcfm0R4en X-Gm-Gg: AYBFou3PMT1zOvLsVfw+OBZtjk23/S+e/vBz6TaiucCSLGUoxA/fGVDrnP4prDXW9F7 s5rqZoLk7bcvU6NhJqHNYbHcZajnUqQJTDRoooHwYPwlfZQJ2nRy1+uTenraO3ELjvdfPEbJcJb UR3czjAJ+gS5cV+mQJpfPFFGJtu7rfo9V002VCnYRQOY4a+nyeTeZDdtp8d3WMcv8FJobgPofPy S0y3VRBl6drONdqFrlUo1a5qmcjiHyYWMQF0k2TN00eFBB6Bp3lSnMu95+cbUeWNPRFyXMgDm70 u0VX6DVce845kiG+/7QBfCQYf27b0Dxg+Itqr5fIHRombc6Sy2a7yYSrRDWY3QCwuJgHOZx9P78 Q6oA9t7C0x0ILKsWRi9da1sUEX0WXO3rTqevz3VU0LXylv9xDtwbj1IvGEi3bDOTziBjY+iVL5z 92qTcm9QUOVEF1HwN5XLO1/5gW8AJDTwyTLMrpmcxRZQ7HAjl7HFgTFZP656nz8EWpCfeYHYF7r 0FUVIr4soUPHY+oEFbkna3HiHoaa5K0fG+IJuvLTSasDtt+HT8unSkFpQNOsFeEyOgOwn62wA17 VTjRu2jJNTbRx64PBjfK9AwqDQa1S3xjtC3wksyiqnM+4jijLE8220gpUvjY081hYfRMD30Yk5v sIIj+IBuUqyKteAiSZnnO X-Received: by 2002:a05:6871:722:b0:48f:e0f6:bd5f with SMTP id 586e51a60fabf-4a2a8b0964amr15694991fac.48.1792028075784; Wed, 14 Oct 2026 18:34:35 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:35 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:34:00 -0600 Subject: [PATCH v7 13/16] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-13-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; 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)[209.85.160.52:received,100.90.174.1:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26661-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: EB0371C1E5F 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 74fdca27ba10..4e6fcf1e7aaf 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1642,8 +1642,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; @@ -1669,8 +1667,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; @@ -1696,8 +1692,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; @@ -1726,8 +1720,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; @@ -1751,8 +1743,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; @@ -1796,8 +1786,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 Thu Oct 15 01:34: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: 3620 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 9B8211C2272 for ; Thu, 15 Oct 2026 03:35: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-26662-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-26662-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 8E8923CCAA for ; Thu, 15 Oct 2026 01:34:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 257D3347BC4; Thu, 15 Oct 2026 01:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iWRyCeVp" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f42.google.com (mail-oa1-f42.google.com [209.85.160.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26FFF353A99 for ; Thu, 15 Oct 2026 01:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028082; cv=none; b=hBZ/hEZ+PqK1DA2uqPSnfPWHdAE3E4P22u0j83U2FQth2KlkpSCAcfpEMR7u3FIn0cmMxFt9ce4CGXWDcb8fveWfAsPyw6/wJcHAakFNfph/z/bmtgifilPT3zaaj1oZ732zzdX2qiacPKDeY4KUBFHh3zRZDXPF0U7teoDlYaQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028082; c=relaxed/simple; bh=FgRIeZq0vBdVC5LoWFzee1DIYH44/aMP7otHatXZZIM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P8KwAtjbfe+m/4ybee70idWyWpcxDbBC0mHXmIx0hcYFMNxESfxd8OBPaC+zkJLTWrSY+bylFHLwBSlHcbbN1ffqd7yXTP4Gwz1VLLW9DtgBHM6v762tKyG5yI+fqhD+sW7MJfHZZozxRHELPsDUBqwu1d22ymz437Ug5+SczPM= 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=iWRyCeVp; arc=none smtp.client-ip=209.85.160.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f42.google.com with SMTP id 586e51a60fabf-4932b13c4ccso650095fac.3 for ; Wed, 14 Oct 2026 18:34:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028078; x=1792632878; 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=UFOJulppXNuW58TbWJxKvDHpAzEnFrxmkp8urYvlaAM=; b=iWRyCeVpKsVookjLU9n/JCGpN6+o7bGgZDA24cDipxJ6qWpojygmf0DG/8tGvb89ID 1LEDd8OEHg+1JJiI6PvoHkH1QBjC/YHw/A5d7D2+9uWUEGe1O9BkApyosLpwNYHM2Q48 eFYKR11OA3ldsE/6+OBCgH6NzfnQugF6aCMgMjhpgWId42fM7y9yq+i94CTraGiUD09J 9gYHPzDBh9ZmC6A42I4s85dgwzWmnPCsqHvC8KxsEYpXCQwHOAAFaJkIOvk+thsV6xr4 t8EhgjMkx0/O0ghvzB6LzaJsnkxnIMUrxDPrfaQXnUEJpTsXFL0HnFkYxrxWTihikQhc fYuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028078; x=1792632878; 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=UFOJulppXNuW58TbWJxKvDHpAzEnFrxmkp8urYvlaAM=; b=bHcfAeYto3VrBwjvTV+woA3iAF9BOsf8K+wtLEY5Q6/C7mmdilGAtqEphGsGBnMs/B RYNKMzzN7D098grzWwS3uBgIozMXNpb1NctQsHuhCDIyefOPKEU6mCjulRHigdp2k5h9 JIqRtqjFBWinEMxfM9ywLQqCR91XK1tlbAzX25yJgLWsr4+kI7teluRqcSJbuO6WpQ5c AGm6mqmslbaoWDIK5hsSbDelCRVH/WkbSVWP8ExDuoYNUVhjjSv1oo2DGO9wWG5yX4D7 Y/1Ot0qCaDRg//ap2qCHM1uH38Q03FcNkkQ+25CRMp0/5IGwx0EdY8SG5r4a0e2UEpkc aN9g== X-Forwarded-Encrypted: i=1; AKwUvBw2HI1C5EpqgewEKMPfuZTrD+CaR/coBgngPN2Y5oSOzMQPav7DGrPkMSjDKVle+OxPxZIKQImGv/3r3w==@lists.linux.dev X-Gm-Message-State: AFq9FYIcDxridHrSUpgfV4zTQIdEfbmPK6gYNCROkpizlvoWHXFggySv Ci71XDFA9VWRTu30yvIHkPn9OUqZUMarx/hI2eUMeR+7vmBm2c13w8Z4o4yHF7vr X-Gm-Gg: AYBFou3VpNxmDlDu8zi+EIaV7vkwYM7/UHNYwB6n5vBaUwozmD7OZap1bYKARdD1yL3 6FOt4pdF2X9mSkW4TAYWPKQHJEB2HaIyhIORPnT+G90mQUMMC46Nf2/JsKnGDN9217luOHCAO2S QUeHmyw9lbhHr68IANrmoIuCTzHcBHCJcKd2RyQRgkPrhD3o+UMemvvw7K1E0g65GxvGC0KlYe4 +4yBKL/+QKNL5Gpe+xEYc/4bv5os8gHPb+gP2w4Ip4h3eLz108EcOQy9GG7MVLdnP8aWmzvrtbL SjMaTaTk8Fi1QYq9iYZzYieLcGwFULsvZAHhqec862h1IYJKueEvrjh5adsoERIBWKxuRkHrYOZ 7GqfLH4HE9UWxrURNt+AF2XT1aeC3z1b1A8+NN0bF9l0clBxba0XgjBmaz3IlMPBkFsptWGossf JjqvoEJtyi7kCHZqDiC8xWNTOF6OkgPWxE0+sVxUQVFhb7oZEnKAe/CmG/szIJPXf3dkT82QdNC +x82oOG0aUpDe+bXGpNiLZ6d5uuvYR56Bt5EfmjvsckJg6jP1ciQS6B6BjQuZhksCadwuPHtSqq gJH4LMaJ1mvvQFHEcyLBlrpK/LouSxhTngcTgz6FJza3hOx90iUeRvPHuN0mApxwaAuxHBfntCD HunmfQ/NuyArvyKDLxLcUrdnWZMiAA2g= X-Received: by 2002:a05:6870:b3ca:b0:47b:7709:5568 with SMTP id 586e51a60fabf-4a2a89dc998mr15538918fac.10.1792028077989; Wed, 14 Oct 2026 18:34: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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:37 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:34:01 -0600 Subject: [PATCH v7 14/16] mtd: rawnand: sunxi: reduce user-data length register accesses Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-14-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.105.105.114:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[tor.lore.kernel.org:rdns,tor.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.105.96.0/20, country:SG]; FREEMAIL_FROM(0.00)[gmail.com]; R_SPF_ALLOW(0.00)[+ip4:172.105.105.114]; TO_DN_SOME(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.105.105.114:from]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26662-noreply=patchwork.local]; RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 9B8211C2272 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 4e6fcf1e7aaf..601c272d8c54 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 + \ @@ -1018,35 +1018,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, @@ -1417,7 +1442,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, @@ -1446,7 +1471,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) { @@ -1467,10 +1492,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), @@ -1580,7 +1602,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); @@ -1847,7 +1869,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); @@ -1855,7 +1877,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 Thu Oct 15 01:34: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: 3628 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 790C91C1E5F for ; Thu, 15 Oct 2026 03:40: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-26663-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-26663-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 7CE4743E9B for ; Thu, 15 Oct 2026 01:34:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B461734750F; Thu, 15 Oct 2026 01:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BdV22Yl2" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo1-f42.google.com (mail-oo1-f42.google.com [209.85.161.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7ED1363C46 for ; Thu, 15 Oct 2026 01:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028082; cv=none; b=cFPFF768hQARVNUszSRPBmm3aPFJuVH9reWkJigUDSU15v1O1taQQmteGJktHmBroN+LfrAdfRolUA1BCFBlep5pSNnRC5iqPp3CXQB5uV0yzTgD2P/jIkI/hP1nQ8pr5D61QU6FIxbQ54gCzpDiSXh/nmANkx6hYxIME+BhJl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028082; c=relaxed/simple; bh=A1STkpE9307vxyyhV24//arWM0j0kn3Imh1Mn5JF96w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PnQ+RNceNICG3HX2c8JXGaQSz1rb4gvCVdD+J5TTWeXaN0pVkEhezYhlipfB8186Ipan3f8SaO4W2R5i177aa5ikzxJhrSuBzqiWG7UtWLC8RJ6e/Fw4PNf+yVRLDVqAc8BvizlLPVPseWz3nLGrRb13v+wKdQfISHpgNPm1y3E= 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=BdV22Yl2; arc=none smtp.client-ip=209.85.161.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo1-f42.google.com with SMTP id 006d021491bc7-6fbf1ba31fbso814321eaf.0 for ; Wed, 14 Oct 2026 18:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028080; x=1792632880; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=BdV22Yl2tYV/fHYoVkmBju3SjIsI6aRiVVQ0WJVD5Mc8cECV+AbbiL7g1bL52Zft3P fh7763Jd6aGPT0g1PNmtyspiV/7g4K1b56593a2z+YBTxGqhWG/Wxet2ERRiSErg0lVG QdOpAdzrURcucKmBCSdeDHmK2b/DAbluTEXARyR7GJDAoHixfP3mVwmdPTZne68t6MBM BU5DL5ZdkadH1lVhfiPJM3T1wgLK6d4wfbwJC71UJ3jcMILUW5DHGOL1qc/pDJJMt3Oc IzS4RebpJWc4hq0szQhJ+5GXLAhsDHWCXjikHUeRHfFWZVMpHVeo5vQqQh52E4S++45I LBQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028080; x=1792632880; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ZlPUbRtpg3L6gM16/NW0SgMi7XxBEFvrpndyBx+kMc4=; b=QJCcLedSPtcQyAb43lkwEr/9DmmUbqltxGyBsJUDDx0KfKaDataUN+dnw6tIneJf0c ADOQmXRyWUhxERIPqIO2F44QzSR6jnIsKrEmwmvH79h8uSecUzlWfE5WBvPGU6Ok3Reu 5a4Xqct97CQxiIPqrZ+lnV3usf51htHdIbEX6CfIcHEMNTmFLJ7tdrd/ZS64d+Hp1tSw C84vjoRW34WYvs3GpB+6K81/hkiEzP+iBhnRtHlL7Kb4FQr54nv8kT1NSlFkoHQ87YW3 DHj6xfsOORCp116uL66mmdTz7txuhODlVAN8rY9M37zum1CHAYumxamABRC1/0NjRL7l ZH0Q== X-Forwarded-Encrypted: i=1; AKwUvBzc6TlLhfnAyTRf6W2jYQEDhGjnJ2/M/hNLiDcr+HTHtWNmpNKXU1FsS2ednfy0AyzN1NXGTv1EajWI2Q==@lists.linux.dev X-Gm-Message-State: AFq9FYJ9CmBSIgtvVfFFyS1kzi4mfx5tmzrw4Pd3xKH9ocGAwqXXUY83 WjdwlddH2QeBHsDwzHMQ3/bX4ljQwEQ2NvZdKM/THOsqA3l1WJ2ksZ/q X-Gm-Gg: AYBFou3N7tYnsp45qKhWLxzbkOdgRNsEpJxyOIXh6ceLKd1w93x1ZG8nYx8BUWw3nea sOnye4F+NBvn0NxHTp0SdzztsACMi/jlBH7zR8/Nizt5sjAJ+cJSQ2LIgEB87f+fn5/Z6fUjecu PBQ9XPynT6V6EZfcLbKD5UtoFtYkHd8Mx/2jBj9eW1THJV2NHm41KJGNSyn/0S0BZbSqJo4QBVM uQlayEnYPlfuE3rygWE5gu7lCuFHlLhLfJTNOFOmJN7RAbx5TN+lDPyTnkNnQnvUriLDfcof6i7 PUh+G6AORVT83958KbH46f/PqYr1XbtUPR/N+tKozUu1OM+qPSQ2ItGiET1ek+cqv5C8oD5IoLC jSEtT9isdbxbqXAU6IRjC8JyixsY1RATP4eM3HpLBu3LGirLqPaG3gonzevXDvodAulciemhSid sTzJPYQ5LKpWw6foHsHk/nRxG06dSkRK4mtPOX6uX4Xft0JUehpK8MwbKEy7W9Sa4GCCPdg8Uz5 ZsXTbZvQvNwubJtnn5hTl5AJ+x8BKkoEnDQMjS9f/4kOQ+JjH0/BWwpFhi7BxF6c+cZXoSMjdt4 YoeyNLRVDZt2gHOfDRMmJu1sK3hc8/xg1Up3ENG6U5E+lQKDwGmsufxsQRI9MOCoNETUne+xDyw 2VeTNAQ7LzRRbglqEYoOr X-Received: by 2002:a05:6820:4b0c:b0:6dc:3be3:bb81 with SMTP id 006d021491bc7-6ef10492c39mr14343257eaf.35.1792028079883; Wed, 14 Oct 2026 18:34:39 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:39 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:34:02 -0600 Subject: [PATCH v7 15/16] dt-bindings: mtd: sunxi: Add randomized OOB flag Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-15-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard , Conor Dooley X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Allwinner NAND firmware writes the bad-block marker as part of the controller's randomizer stream. The mainline driver compensates those two bytes so that the physical marker instead remains plain, even when the rest of the page is scrambled. On H6/H616, the firmware also places a fixed amount of ECC-protected user data before the first parity region, whereas mainline distributes available OOB space among the ECC steps. Add an opt-in property selecting that firmware page format for the configured controller hardware-ECC geometry. It identifies how existing flash contents must be interpreted, rather than changing the format of all NAND attached to a controller compatible. Without it, retain the mainline marker representation and protected-OOB placement. The property applies to normal ECC transfers. Raw operations still bypass ECC and randomization and expose physical main and OOB bytes, including the physical randomized marker. Acked-by: Conor Dooley Signed-off-by: James Hilliard --- .../devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml index 9d061e2216cb..8ecafc40ddcb 100644 --- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml @@ -79,6 +79,16 @@ patternProperties: minimum: 0 maximum: 1 + allwinner,randomized-oob: + type: boolean + description: + Select the normal-page format used by Allwinner NAND firmware for + the configured controller hardware-ECC geometry. Normal page + transfers use the controller randomizer, the bad block marker remains + in its data stream instead of being compensated to stay plain on + flash, and protected user data uses the controller-specific placement + expected by the firmware. + unevaluatedProperties: false required: From patchwork Thu Oct 15 01:34: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: 3621 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 7DD4E1C2272 for ; Thu, 15 Oct 2026 03:36:42 +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-26664-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-26664-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 AEEA53A2D6 for ; Thu, 15 Oct 2026 01:34:57 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BBDE93403FA; Thu, 15 Oct 2026 01:34:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nndnekXk" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF9EE33C1B7 for ; Thu, 15 Oct 2026 01:34:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028088; cv=none; b=lr5RSkru4LC984FujLAsrk93bgbSAk9tzi2V4gn+NgrRJcYJAz22GvwdtiVSzwvq+N60VNLVbwGOhJqYcCz90DVQDzMrG0866dFexN5MJdjaORnc8u8tw9Yed+Dk0vxm/q6m/QdFDMRvN8/TQa/M96SvGK4FKv14C3lLXyZhvQc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792028088; c=relaxed/simple; bh=4CmP3QgscD5N3ASZ9dEtkxEz69O9YhFz5InUqd0TrE4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XID+HezRofE8SIs02avS5nXFIZ7wyNLz1lpS4t9TosP/wECBu3aNVBl9+La//klEKQdB8gtTVNPLiw5crNfi1X5ggxganf97AjSYDIXcqOHggHdtq/wZC6NA1MTIQpQ5bNbakgs0LgH2YinM+9Rxut5yZsfrBxnkZ+AuAnioe7Q= 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=nndnekXk; arc=none smtp.client-ip=209.85.160.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-48ed0b68895so2857869fac.1 for ; Wed, 14 Oct 2026 18:34:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792028083; x=1792632883; 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=IMIbzz93pPGIXE8KhL0wpHMv2rJ4Nia+N9ttVvNg89c=; b=nndnekXkS82Gl5YQuBG8Sm1ThcUgs5+nxkMwLXrhrRJX7hSF4NMl/jBFKQQZd/sytY Z8xM3l2P5DSW50DeD6WBJQYwug10CojYLmbp4B0Gf+XtR6TYaeoF8XIIv6nJQyeXbTaN nYYdRqAJeOj5ePiOLEI2sHXRvagIKAo6qNS/BYdN9Hv//zW8oAQz7oGoCXZt7y0aqr70 6iIpD/YCzOKHKY8FtRdhr728orc5emrz+jq/6mfSBH8od8F1nJ26g+XQ/vizpjlduD19 KpmitugUdz6mU6bfTMAqTjgOxrGaqfvSUPg2TLTuYeMMD89Q8j/4OCHnuSw0UtG3GwXj pBeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792028083; x=1792632883; 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=IMIbzz93pPGIXE8KhL0wpHMv2rJ4Nia+N9ttVvNg89c=; b=D4OgUlv68ST9WzUzrHgRlW87NQ7nnpUOVmkbPeWxuYtbc4pBPtDhiWCn6XpZI0JwBH sPE1WOHRPp5ZazYGhD9erPnnCZPNoQamB8UA3BQYVKEhXg0dGFqxtZn1Fvk5LOE6nVmR hu9GOOc4L7UBQ2dAMLkecFgGoE+eCbF5xvlJm7GMwvShKTCOngBZBfE+lJYltW4GzxiB jc1kIqNsA/SSu0K/OyHfBtj5P8s77z+IoZbxMXRc+YrdvT2XtsqMxgRLJHm8R7vHurSW DKxKGrOvHmcTA4YFFe7Nvu9Zr7XxgyNgT1y1Y3QUZpPJpOFYUqCGF8jeKAnGY1aXVnz7 Ev/g== X-Forwarded-Encrypted: i=1; AKwUvBy4hNkW+ntwOsZzjwtgtD8w8WPy3bYMxS5DycMO38+Qs43TxVnBlGa788rdxkVYBn5cKyEgCZaRki9xqg==@lists.linux.dev X-Gm-Message-State: AFq9FYJI3DbD8pkhRBYdizXTWT57kN1wTUZxVDsZEk3DoadcvWb3+gBR q61l6q5rp3aDruWZgIr3nIIwx/0+2GjYAf+htNVrC9o9PE/G52UdCjvl X-Gm-Gg: AYBFou2jzd8W8jkVLlJX9DYC55Xlv16MJSFU4Zjno5rklrrABcZsyXlOh2W3h2b9zwH 4E30GhBVr1ikRCry/mqzMnQsQiw1R+PRhHombEk3BZhEhqpZAbu1WbkrWX1prLsYn8dWHVqKDPb gjMdW6Gt/n5fi0qe4RfGllLDeH9SoXJZ5GUX3mob7gxwYOXBG1LPuPuu4kiELBylH1VtSS8gWRa GxpPRTkv1NU2B7kk6vzmjR5IMeo5lZl/8E2yNtxXeqyrFAqpZPHbEbGtFj390D8ucEwKjPBzs6U bvxBdWyQMGLs0E00q/NU4cljQUQS6gHyU4AxQ5afd9Plce01wcktkDR+zSLVLJJUn5163wXhJzn 9Li64X1n+LGeaRkoPrMMzt/BHNHYz3alnsarbbWicGwOPAlRU3kLib+VGG+YgnPMryCNmDiENWi TCp53hFEMpHtStrIjJYzb3In+sq90XF2u+UFmpFZSUdGbrNx9haP4Ov4oU6BkfUzI9AEq6qcIp+ QHP0apzGJ94fFoZRjmAXoAYG9cbxgE3sfBJbMnZnBaZ2E0sIymvNfXxBXyDZzyf9dFPyVEVDcZ+ 2p3GlgiUyDN8KznQi/lvH+JvZcVVdlm60BM1nCMb7U5KOVEQoTxdbGcFSE46Ht22UBY1HZb4lnD 0+Y/k8cezHRTYU4OqeSUAwnmwoQfdhnA= X-Received: by 2002:a05:6870:2803:b0:49d:6a41:29ff with SMTP id 586e51a60fabf-4a2a89b4321mr15305264fac.51.1792028083525; Wed, 14 Oct 2026 18:34:43 -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 586e51a60fabf-4a6dfb41452sm3428139fac.4.2026.10.14.18.34.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 18:34:41 -0700 (PDT) From: James Hilliard Date: Wed, 14 Oct 2026 19:34:03 -0600 Subject: [PATCH v7 16/16] mtd: rawnand: sunxi: support the Allwinner randomized OOB format Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-16-5d3fc6ad2da1@gmail.com> References: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@gmail.com> In-Reply-To: <20261014-submit-sunxi-nand-vendor-oob-layout-v1-v7-0-5d3fc6ad2da1@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?= Normal hardware-ECC reads also decode protected OOB, including the bad-block marker and metadata used in bad-block-table scans. Allwinner firmware leaves the marker in the randomizer stream, but the existing driver compensates it to keep a plain physical marker. On H6/H616, firmware also packs protected user data before the first parity region rather than maximizing its allocation across the page. Those mismatches prevent normal ECC reads from interpreting firmware-formatted pages and their markers. Honor allwinner,randomized-oob through a separate operations table selected by an opt-in attach helper. Enable scrambling for normal controller-ECC transfers and omit marker compensation. Reject software or disabled ECC, and reject a step larger than the page before the core can fall back to software ECC. Without the property, keep the existing operations and geometry, including the plain marker on otherwise scrambled NAND. For H6/H616, reserve four user-data bytes per ECC step, capped at 16 bytes per page, and put the entire reservation in step zero. Later steps have only parity. Apply the same reservation when maximizing ECC strength so strength selection and actual layout agree. Older controllers retain their fixed four-byte user-data field per step. An erased page physically contains 0xff, which the randomizer turns into non-0xff decoded bytes. Select the Allwinner firmware's controller-specific erased-page predicate instead of the generic bit-count check. Apply it to ECC-decoded protected bytes re-encoded with the OOB randomizer stream. This is not a raw reread: bytes corrected by ECC retain their corrected values. Older controllers require eight exact 0xff bytes, with a four-byte shortcut at block page zero and pages 127 modulo 128 for 1 KiB steps. The H6-generation predicate requires byte zero and at least nine of ten bytes to be 0xff. ECC exception mode can suppress errors for uniform physical data. Include pattern-found steps in classification even without an ECC-error bit, and ignore their correction counters. Keep decoded bytes until the page-wide decision: an all-zero physical page takes precedence over the spare check and returns zeroed data/OOB with ECC failures; an accepted erased page returns all 0xff. Other failures retain decoded main and protected OOB so bad-block and table scans can still inspect the marker or signature. Read complete pages for subpage requests because these checks classify a whole page. Collect status during each PIO step or DMA batch, and defer statistics until requested OOB reads succeed. Read unprotected OOB only when requested, combining adjacent parity/tail ranges without crossing protected user data. Preserve each step's randomizer phase and the existing PIO/DMA representation of parity. Raw callbacks remain unchanged. All format policy is in the new callbacks and attach helper. Apart from the opt-in dispatch, existing functions are unchanged: geometry allocation, marker compensation, status collection and PIO/DMA transfer sequencing continue to serve the existing operations tables as before. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 332 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 601c272d8c54..0b75713c04fa 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -349,6 +349,8 @@ struct sunxi_nfc_mdma_desc { * @nuser_data_tab: Size of @user_data_len_tab * @sram_size: Size of the NAND controller SRAM * @timings: Controller timing characteristics + * @spare_is_erased: Allwinner randomized-OOB erased-page check on + * re-encoded protected OOB bytes */ struct sunxi_nfc_caps { bool has_mdma; @@ -377,6 +379,7 @@ struct sunxi_nfc_caps { unsigned int max_ecc_steps; int sram_size; const struct sunxi_nfc_timings *timings; + bool (*spare_is_erased)(struct nand_chip *nand, const u8 *spare, int page); }; /** @@ -1153,7 +1156,15 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_chip *nand, return ret >= 0; } +struct sunxi_nfc_allwinner_oob_status { + u32 error_steps; + u32 zero_steps; + unsigned int corrected; + unsigned int max_bitflips; +}; + struct sunxi_nfc_ecc_read { + struct sunxi_nfc_allwinner_oob_status allwinner_oob; u8 *buf; int page; unsigned int max_bitflips; @@ -2334,6 +2345,299 @@ static const struct sunxi_nfc_oob_ops sunxi_nfc_scrambled_plain_bbm_oob_ops = { .finish_read = sunxi_nfc_oob_finish_read, }; +/* Allwinner randomized-OOB format, selected only by allwinner,randomized-oob. */ +#define SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ 16 + +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len) +{ + while (len--) { + *buf++ ^= state; + state = sunxi_nfc_randomizer_step(state, 8); + } +} + +static void +sunxi_nfc_allwinner_oob_record_status(struct nand_chip *nand, + struct sunxi_nfc_allwinner_oob_status *result, + int logical_step, int hw_step, + struct sunxi_nfc_ecc_snapshot *snapshot) +{ + u32 count; + + if ((snapshot->pattern_found & BIT(hw_step)) && + !(snapshot->pattern_id & BIT(hw_step))) + result->zero_steps |= BIT(logical_step); + + /* + * Exception mode can suppress the ECC error for a physical pattern. + * Classify these steps with the Allwinner randomized-OOB page check too, + * and do not use their correction counters. Keep their decoded data until + * then. + */ + if ((snapshot->status & NFC_ECC_ERR(hw_step)) || + (snapshot->pattern_found & BIT(hw_step))) { + result->error_steps |= BIT(logical_step); + return; + } + + count = sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); + result->corrected += count; + result->max_bitflips = max(result->max_bitflips, count); +} + +static bool sun4i_a10_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + unsigned int block_page = page % mtd_div_by_ws(mtd->erasesize, mtd); + + /* + * Older Allwinner firmware recognizes exact four-byte erased + * signatures on page zero and pages 127 modulo 128. With their + * 1 KiB ECC steps these correspond to four physical 0xff bytes. + * Other pages require all eight spare bytes to be 0xff. + */ + if (nand->ecc.size == 1024 && + (!block_page || block_page % 128 == 127) && + !memchr_inv(spare, 0xff, USER_DATA_SZ)) + return true; + + return !memchr_inv(spare, 0xff, 8); +} + +static bool sun50i_h6_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + unsigned int erased = 0; + int i; + + /* Byte zero and at least nine of ten bytes must be 0xff. */ + for (i = 0; i < 10; i++) + erased += spare[i] == 0xff; + + return spare[0] == 0xff && erased >= 9; +} + +static bool sunxi_nfc_allwinner_oob_spare_is_erased(struct nand_chip *nand, + int page) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + u16 state = sunxi_nfc_randomizer_state(nand, page, true); + u8 spare[10]; + unsigned int len, pos = 0; + int i, off; + + /* + * Re-encode ECC-decoded protected OOB for the firmware's spare check. + * This is not a raw reread: ECC-corrected bytes stay corrected. Each + * step restarts the OOB randomizer; H6/H616 pack the entire prefix in + * step zero. Pad unavailable bytes with 0xff. + */ + memset(spare, 0xff, sizeof(spare)); + for (i = 0; i < ecc->steps && pos < sizeof(spare); i++) { + len = min_t(unsigned int, sunxi_nfc_user_data_sz(sunxi_nand, i), + sizeof(spare) - pos); + off = sunxi_get_oob_offset(sunxi_nand, ecc, i); + memcpy(spare + pos, nand->oob_poi + off, len); + sunxi_nfc_randomize_buf(state, spare + pos, len); + pos += len; + } + + return nfc->caps->spare_is_erased(nand, spare, page); +} + +static int sunxi_nfc_allwinner_oob_read_unprotected(struct nand_chip *nand, + bool dma, int page) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int len, off; + u16 state; + int ret, i; + + for (i = 0; i < ecc->steps; i++) { + off = sunxi_get_ecc_offset(sunxi_nand, ecc, i); + len = ecc->bytes; + /* Keep decoded user data, but combine adjacent parity regions. */ + while (i + 1 < ecc->steps && + !sunxi_nfc_user_data_sz(sunxi_nand, i + 1)) { + len += ecc->bytes; + i++; + } + if (i + 1 == ecc->steps) + len = mtd->oobsize - off; + + ret = sunxi_nfc_read_column(nand, page, mtd->writesize + off, + nand->oob_poi + off, len); + if (ret) + return ret; + } + + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + for (i = 0; i < ecc->steps; i++) { + len = sunxi_nfc_user_data_sz(sunxi_nand, i); + off = sunxi_get_ecc_offset(sunxi_nand, ecc, i); + state = sunxi_nfc_randomizer_state(nand, page, true); + state = sunxi_nfc_randomizer_step(state, len * 8 + 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, + ecc->bytes); + } + } + + off = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); + len = mtd->oobsize - off; + if (len) { + /* The unprotected tail uses the page seed and its 15-bit advance. */ + state = sunxi_nfc_randomizer_state(nand, page, false); + state = sunxi_nfc_randomizer_step(state, 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, len); + } + + return 0; +} + +static int sunxi_nfc_allwinner_oob_read_batch(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + struct sunxi_nfc_ecc_snapshot *snapshot, + int first_step, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc = &nand->ecc; + unsigned int reg_index = 0, user_data_sz; + int i; + + /* + * The normal snapshot skips pattern IDs when every pattern has an + * ECC error. Allwinner randomized-OOB page classification needs those IDs + * as well. + */ + if (snapshot->pattern_found && + !(snapshot->pattern_found & ~snapshot->status)) + snapshot->pattern_id = readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + + for (i = 0; i < nsteps; i++, reg_index += user_data_sz / 4) { + int step = first_step + i; + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, step); + u8 *oob = nand->oob_poi + oob_off; + + user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); + sunxi_nfc_allwinner_oob_record_status(nand, &read->allwinner_oob, + step, i, snapshot); + if (!read->dma) + memcpy_fromio(read->buf + step * ecc->size, + nfc->regs + NFC_RAM0_BASE, ecc->size); + /* Page classification needs protected OOB even for data-only reads. */ + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, + read->page, user_data_sz); + } + + return 0; +} + +static int sunxi_nfc_allwinner_oob_finish_read(struct nand_chip *nand, + struct sunxi_nfc_ecc_read *read, + int *cur_off) +{ + struct sunxi_nfc_allwinner_oob_status *result = &read->allwinner_oob; + u8 *buf = read->buf; + bool oob_required = read->oob_required; + bool dma = read->dma; + int page = read->page; + struct mtd_info *mtd = nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc = &nand->ecc; + int ret; + + /* + * Allwinner firmware treats an all-zero physical page as bad, even without + * ECC errors. This takes precedence over the spare-byte heuristic. + */ + if (result->zero_steps == GENMASK(ecc->steps - 1, 0)) { + memset(buf, 0, mtd->writesize); + memset(nand->oob_poi, 0, mtd->oobsize); + mtd->ecc_stats.failed += ecc->steps; + return 0; + } + + if (result->error_steps && sunxi_nfc_allwinner_oob_spare_is_erased(nand, page)) { + memset(buf, 0xff, mtd->writesize); + memset(nand->oob_poi, 0xff, mtd->oobsize); + return 0; + } + + /* + * Keep the original decoded main and protected OOB bytes on ECC failure. + * BBT pattern scans inspect them even when an ECC error is reported. + * Read the remaining OOB only when requested, not to classify the page. + */ + if (oob_required) { + ret = sunxi_nfc_allwinner_oob_read_unprotected(nand, dma, page); + if (ret) + return ret; + } + + mtd->ecc_stats.corrected += result->corrected; + mtd->ecc_stats.failed += hweight32(result->error_steps); + + return result->max_bitflips; +} + +static int sunxi_nfc_allwinner_oob_read_subpage(struct nand_chip *nand, + u32 data_offs, u32 readlen, + u8 *buf, int page) +{ + return nand->ecc.read_page(nand, buf, false, page); +} + +static unsigned int sunxi_nfc_h6_allwinner_oob_user_data_sz(int nsectors) +{ + return min(nsectors * USER_DATA_SZ, + SUNXI_NFC_H6_ALLWINNER_OOB_MAX_USER_DATA_SZ); +} + +static unsigned int sunxi_nfc_allwinner_oob_min_user_data(struct nand_chip *nand, + int nsteps) +{ + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!nfc->caps->reg_user_data_len) + return sunxi_nfc_oob_min_user_data(nand, nsteps); + + return sunxi_nfc_h6_allwinner_oob_user_data_sz(nsteps); +} + +static int sunxi_nfc_allwinner_oob_init_user_data(struct nand_chip *nand, int nsteps) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + /* Do not let the core fall back to software ECC for this format. */ + if (nsteps <= 0) + return -EINVAL; + + if (!nfc->caps->reg_user_data_len) + return 0; + + sunxi_nand->user_data_bytes = devm_kzalloc(nfc->dev, nsteps, GFP_KERNEL); + if (!sunxi_nand->user_data_bytes) + return -ENOMEM; + + /* H6/H616 pack all protected user data before step-zero parity. */ + sunxi_nand->user_data_bytes[0] = sunxi_nfc_h6_allwinner_oob_user_data_sz(nsteps); + return 0; +} + +static const struct sunxi_nfc_oob_ops sunxi_nfc_allwinner_oob_ops = { + .min_user_data = sunxi_nfc_allwinner_oob_min_user_data, + .init_user_data = sunxi_nfc_allwinner_oob_init_user_data, + .read_batch = sunxi_nfc_allwinner_oob_read_batch, + .finish_read = sunxi_nfc_allwinner_oob_finish_read, +}; + static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) @@ -2465,6 +2769,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); @@ -2490,6 +2816,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; @@ -2987,6 +3316,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 = { @@ -3010,6 +3340,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 = { @@ -3036,6 +3367,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[] = {