From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C09DE3A874C for ; Wed, 9 Sep 2026 08:30:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942657; cv=none; b=uSejo0U+sm62PH6+3iqByuuWRsonf/0fsM6dbI/BtutfTudVRzQBDjnpUUogCYl+OAI/2rRLL4U3p8HfH9drFwXqSkSBnIv7eI5WlBNXdQ218abMIGsfjJguccyWYaW9+aq7QDcSb8AiYko9r7l4MGYSKWprgDajGcZg7SytLBw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942657; c=relaxed/simple; bh=5dneiBhhffoEYowN5rHUIUIaXuJyOIeTYGA3L5t8iSc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BaDS4HHbXJdlab65d8Zz6TGM4aTgNujvj2me30ddLgIAo416g/bDJCYCoIoezkl+lVdVdHUxYr2Xw3ilqvFytHVkVH+K2f5cJaaKaLnK6+KbWHA3IqvKMjqNLwm4Zhajqw2LhV8TRq/z58l4Qz/p6UnKvk7STg9X2gzpuPhxQUA= 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=phHd/X/K; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="phHd/X/K" Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7f4b94d72acso4636960a34.1 for ; Wed, 09 Sep 2026 01:30:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942653; x=1789547453; darn=vger.kernel.org; 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=87D8oi8Qz4sYFsjJ5uXw0JnqD9Cz19yUtQkLE1CMv/c=; b=phHd/X/K2rfN8pLqflGC18s2o615uiF47M1hGLRf5WTOf9cFzT/ciJ4qCKTUOsmRMy GTdolOceu8BrGsMgkByAkM8soaBj6kNi8yxqhoG5nTGsX3Ks819T+2t0oEELxBZL2TDX y3/CGlPa6TSdCkYJu2xbfDzFTE975FTEVStoq54cqOCEZB1RSn6Nf9OkXARPp79oUINq kfb0aOAtBWq8YoA2WYMMYGEWNi5SPqgu7tySlRL4gfzDQzsqmg2H7nEXhJfy/jxxltxi +s/GFOpGixg+yWghZG4kog7REqjGWCEhEfD/VkhppoLpJPjdu8ocy+Vr9PVv8+zNC7BS p6GQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942653; x=1789547453; 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=87D8oi8Qz4sYFsjJ5uXw0JnqD9Cz19yUtQkLE1CMv/c=; b=WoNdxE3EH6Mv5C5NV7disJa13evKjTSe7IdVDPlStUkGShjfWGlhisxE1GBNMii39T NSSMdZAPv7UFx3T2J8gFQrk+B69T9Y0QFf+o7v/J7J2MGDa7VwWQMnTnekLZRwCPFFk0 6xgl2j4f/I1lKCyLiqtU78Nf+QPREzmyjGWuxkPkKtGJjPPXvly+5MBlvRhIv2NONk3G 6dINciPiEZuzkOldgb6pEWB1kInOkY+yQ+Vl7zmhSKbonjxUahrQimSr1jj3quKAWb+W 3uRDWR3lEpXC+RZkOuRBxpx9NOsgXV4UrFaGZuoMZiacPR8j6NzMId4ekZ5rUM/IxOYd JZDw== X-Forwarded-Encrypted: i=1; AKwUvBzSxZoYpviSY0DMXUkb6PF4IsYf5mmdZjJa4aWkd9WXzAXVbk5POGuLjsPavXzrJSlB0qT0onVpUutdk8M=@vger.kernel.org X-Gm-Message-State: AFuF++l4R2zNnwjAAtbG2xzvP4fAFjkzq52g3DEvF/nen+onAHOrIgT4 ZN4iCKXDLtrJCTAWfxehO+UyJSw244NRh1PJfyAK2iDpnx0Jkpqtbc80 X-Gm-Gg: AYBFou0taet6ezJ4pnMi5BfvLccXRGlO7LAka0RSB9PHj8POFxwKEj+zqaCq7BdBqvU jsXtUqNfbz870EPmy/YqpjSqarJCf8YDhkVet/Eib2nlayXxQDzMXSKdMV8D39jtqL7fk3KHqwB anFy5IV4nWeZfWHc51Q7dno9EdCCnQEjquBlHbcc8r1mv+wmk/AO291itsy1yx1aeHBuzhvyo1M IUCX4OtIdAjWaxqnpxjncGjTgZ89Y4Tb5Kp8zVt12aOkB6UCr9yDJhUxrOWbpNgfbvR0je8gzkU x+EQkvwk3q+0cMzI4TliB7Z9N9+WaKHdGrW6BHXXfXyAkR4x6cKm8L3dBMs97bMZm57SQ4Qsivx xgQ15Q4NSGXA1EAWZ6IsaulQLDb9dBNFnyAQOVIlbYeA5oWjHwkGI9sA69qSSnd23zoTjPHfd7R xkGx6j9SxSBCiozXEWT+FrJtYineaTiRzGLYgkcgojm6hHkein+YHwgk2htfQDdWR+ERBqSkOBn hfdCc4LMMb44+GzGHDiawJBtLgadtFtI0J3ETSwDwtCX/X4vEEZsj+rPe+Prb0XshXUlJpJHjBS AMHytdFiZFTU+Y/mHSQ1VvBM1Rko484VjCYVJCz7cAGFQCBI9VElwtTSOmSVgc1O9A8b/0gcX/h 4KmJ9y4Sz/TSYdoJmDVT9wHJ0TSSwYw== X-Received: by 2002:a05:6820:3107:b0:6b7:46fc:1df with SMTP id 006d021491bc7-6b746fc028cmr18530314eaf.62.1788942653399; Wed, 09 Sep 2026 01:30:53 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:30:52 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:34 -0600 Subject: [PATCH v3 01/15] mtd: rawnand: sunxi: use the logical step's OOB length in PIO Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-1-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 PIO transfers always use hardware ECC slot zero, even when transferring a later logical step. The user-data length programmed into that slot can differ from the first step's length on H6/H616 controllers. The ECC correction and protected-OOB write helpers instead derive the length from the hardware slot. Pattern handling can consequently fill beyond the current step's OOB region, including beyond the page's OOB buffer for its last step. Writes can also fetch bytes outside the current step's protected user data. Pass the logical step's user-data length to both helpers, as the protected OOB read helper already does. Keep the hardware slot for register access. DMA callers pass their existing per-step length, without changing the on-flash layout. Fixes: 54dcd6aa69db ("mtd: rawnand: sunxi: introduce maximize variable user= data length") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index f41feebe4257..ab4003ea6fc4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -999,11 +999,11 @@ static void sunxi_nfc_set_user_data_len(struct sunxi_= nfc *nfc, =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, const u8 *oob, int step, - bool bbm, int page) + bool bbm, int page, + unsigned int user_data_sz) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; =20 /* Randomize the Bad Block Marker. */ @@ -1057,11 +1057,9 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nan= d_chip *nand, =20 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 =3D to_sunxi_nfc(nand->controller); - struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; u32 tmp; =20 @@ -1143,7 +1141,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, =20 ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, &erased); + pattern_found, user_data_sz, &erased); if (erased) return 1; =20 @@ -1311,7 +1309,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf ret =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, - &erased); + user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ if (ret < 0) @@ -1408,7 +1406,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *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); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, @@ -1672,7 +1671,8 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *oob =3D nand->oob_poi + oob_off; =20 - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page, + user_data_sz); sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 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 43C3746AEEA for ; Wed, 9 Sep 2026 08:30:56 +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=1788942661; cv=none; b=Wffd1XyWiqgxGkE4lcxMi45Octvf4nH+YekvVDPvP7XHpCBuH2sy+qO8AuHXaStU/fzIhvGO/Gop8BUz7NINzFALUWEJLwEFsrVvmOsAo7IfMq8TjGHy0veNHIl1HBvWQ1i2XcyWKGDj69sopYJ4nv2Ff3Yq8/9k7qUtDZUldos= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942661; c=relaxed/simple; bh=INVPCo9loZHqDMUNO+XVhGP57eMmNVJkeuMOWBHeYHI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uUjXsAC7nwmKKEJJH/SpWfrzrwR3H6BQlCeN15vb9eBp1dqCPwisepZ+mER8vHMSOvTD/shnRuFNNXYxXnUUAcr1ERL8OzrLpwOkAWphhzHvCFxMdh6GSVrbEgz1EgWiPhTjmnWnEhyHO3PX3Ge6OxfJNWqkYWPuAb1Bt6J9hJw= 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=b2sp/7B+; 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b2sp/7B+" Received: by mail-oo1-f47.google.com with SMTP id 006d021491bc7-6be1f18687bso279477eaf.2 for ; Wed, 09 Sep 2026 01:30:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942655; x=1789547455; darn=vger.kernel.org; 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=oFX62AXoyl3FxsiGA0PjAmm/T3mqKPnSwH2wCNYEBT8=; b=b2sp/7B+Ke+UcUKyiN3CWjeCERAlsZmMoyzKsm2+KVfLM5pcxvlH85oNIHsOr7geVY nw7xyoD66HJmdXg05NH1TpvTCt/Zg6x3+sHU5mc0DgvEvyCP/xsCCM0L6Cv1IOOxSOgV H1msCG/2qBhGhaXVivIydwGmRu4YMuFOJxey/DK456pjpHL1Fzph52mq6QzKOPp2OaDz UDW5OdQTUIeB4OPjqQmzs0zveKvIMWb+z3MuFLU6R8/cU//JuRmIgBR1CMo0ns+eikHx 59bYFi3EmYJ7228hiwYWgnD1H3TP7tv1wiYYNRAn7WsgcRui/FZa0xOErmX7Aqh0IOUO qJ7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942655; x=1789547455; 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=oFX62AXoyl3FxsiGA0PjAmm/T3mqKPnSwH2wCNYEBT8=; b=ezXKG4IvLi8tp/GjRa+Vs+MOTqrY0eQe3BDPR1BSNVQ5XPfUr2c3Od6QDj4cD+AIOp 7CzHr/tDzAVPwEi9CdZzPN7akbik22bcgkN4N5BcoFZSir2WcDmhNlWR8Q75v0BXrMLB WNlt+jvSBuRHzevfzJbBxXTQxvI/VmbUhReOJ8SD4yoStkLH1SrEn2+EBO27DXdwE0R2 89j6+53MBqd56g3cC+xbNFEKfoy1GqJOlZCRm+IQPgGxzAtYUzWpNOT6RMuMrvqXgTtY N7VtWjvfmGLAL7olxfEtGmLmyDE85+QEYruR3ktp+x8Cn2loD1PE9mRzv8VAugLZsKSx ALjQ== X-Forwarded-Encrypted: i=1; AKwUvBwzSo3PyrUcIr5ZdoIaHMlinYvyq+epnpkm2EhfHAHzf/gwtkShucIWtXFMoG1/eky7rS4Gmh7w9x7CEoE=@vger.kernel.org X-Gm-Message-State: AFuF++kqd7PTH5oqMPaYA6tEJy2iGilh+s6/0Xj/d0N83vQwyKSeq8be Sr+R1a5i+zhM4CpJXLFF0kZoKhYukKZD8BDETYrLv8vp6IOYBPinXSto X-Gm-Gg: AYBFou3ofCWadDUdNd1LJMOIW7G0HsAf4n/p0xAJKTgsgJQn6bxJFt8FmGa+nOEsIS7 DeZAVN8YOLh2vx6tBSyEbiguH07WIEjhg6xALQ4dKbBqqlI4xs77f112DMwsErAvahcG116l9X7 SJjDFyE5TkGScHBZlLkg07JsxVS9escu1ArsJX6H16foPDridkVLN7f6HaIZ4LHxSmA8o2CaAts QEtoexvSWwzvDT7tjtF4azqvUeSzHyhi+Waxf/uo+YDHyFTKIAui7K2Tk2hqYOsGc7E/WHYRQtn yYO7Fv/bkuxzfQ3StIJ9tJ3cLsnd+DmPTSNqbd+EVAbXCQDow5EmMkGRBYiv7DYzTnNVekPhD5q mb3MrriwzsFOccsNMLleMq2P3SqXtye7nnKvkysfnzkpIDQkhbOAB0gq1eF/M56YS5nS0E7AoHo 7EezheDA/jhvBdP8JjloWvXBoFxI6fYZuCP3OoExalExUJlL9a/whbOTyqaUzL9fpfbewZAdztV EI6dx73W/+MLp7BmW9LoQXIwj9s+SBoJuFCyGWGXTuOuhD3h+CZQ8aeihp1fbBl02yzlF/8zsOC av+GMRu+UEgb7j5OY6v7yKt0hs6WVa0XFHmnnv/sWaCD+8Kk0CLjfjjth/DHiZKeF9yurHFmWJ2 XBayRjXrkOTl962glzyGwS99p7+80 X-Received: by 2002:a05:6820:4b8c:b0:6b7:83d6:2930 with SMTP id 006d021491bc7-6b783d62ed8mr16163242eaf.51.1788942654859; Wed, 09 Sep 2026 01:30:54 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:30:54 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:35 -0600 Subject: [PATCH v3 02/15] mtd: rawnand: sunxi: propagate page-setup and erased-check errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-2-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The hardware-ECC read callbacks ignore errors from nand_read_page_op(). A failed page-setup command can leave the previous page available, so a later successful transfer can return stale data instead of the requested page. Stop before starting the PIO or DMA transfer when page setup fails. The physical rereads used to check an uncorrectable chunk for erased contents also ignore errors from nand_change_read_column_op(). A failed transfer can therefore leave stale data in the buffers used for the erased check and turn an I/O failure into an ECC result. Share the erased-chunk fallback between PIO and DMA and stop before checking the buffers when either reread fails. Preserve the existing erased-chunk test and corrected-bit accounting when both reads succeed. Before retrying a failed DMA read in PIO, restore only its corrected and failed counters so partial results are not counted twice. Leave bad-block and BBT counters alone. Route PIO page and subpage error exits through ECC disable before returning the transfer error. 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 | 120 +++++++++++++++++++++++-----------= ---- 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index ab4003ea6fc4..5190b39aec5a 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1055,6 +1055,40 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nan= d_chip *nand, } } =20 +/* + * Return 1 for an erased chunk or 0 for an uncorrectable chunk, with ECC + * statistics updated in either case. Negative values report transport err= ors. + */ +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 =3D &nand->ecc; + unsigned int oob_len =3D ecc->bytes + user_data_sz; + int ret; + + /* Check the physical representation for bitflips in erased pages. */ + if (nand->options & NAND_NEED_SCRAMBLING) { + ret =3D nand_change_read_column_op(nand, data_off, data, + ecc->size, false); + if (ret) + return ret; + } + + ret =3D nand_change_read_column_op(nand, oob_off, oob, oob_len, false); + if (ret) + return ret; + + ret =3D 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 >=3D 0; +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, int step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) @@ -1103,7 +1137,6 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int raw_mode =3D 0; u32 pattern_found; bool bbm =3D !step; bool erased; @@ -1146,25 +1179,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, return 1; =20 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 + if (!(nand->options & NAND_NEED_SCRAMBLING)) memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 - nand_change_read_column_op(nand, oob_off, oob, - ecc->bytes + user_data_sz, false); - - ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, ecc->strength); - if (ret >=3D 0) - raw_mode =3D 1; + return sunxi_nfc_hw_ecc_read_error(nand, data, data_off, + oob, oob_off, user_data_sz, + max_bitflips); } else { memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 @@ -1181,7 +1202,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, =20 sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); =20 - return raw_mode; + return 0; } =20 /* @@ -1248,6 +1269,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + unsigned int corrected =3D mtd->ecc_stats.corrected; + unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; int ret, i, raw_mode =3D 0; struct scatterlist sg; @@ -1342,29 +1365,18 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf if (!(status & NFC_ECC_ERR(i))) continue; =20 - /* - * 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 =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + user_data_sz, - NULL, 0, - ecc->strength); - if (ret >=3D 0) + ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, + mtd->writesize + oob_off, + user_data_sz, + &max_bitflips); + if (ret < 0) { + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected =3D corrected; + mtd->ecc_stats.failed =3D failed; + return ret; + } + if (ret) raw_mode =3D 1; - - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); } } =20 @@ -1459,7 +1471,9 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1475,7 +1489,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, &cur_off, &max_bitflips, i, oob_required, page); if (ret < 0) - return ret; + goto out; else if (ret) raw_mode =3D true; } @@ -1484,9 +1498,11 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_ch= ip *nand, uint8_t *buf, sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !raw_mode, page); =20 + ret =3D max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); =20 - return max_bitflips; + return ret; } =20 static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf, @@ -1496,7 +1512,9 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand= _chip *nand, u8 *buf, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 ret =3D sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page, nand->ecc.steps); @@ -1520,7 +1538,9 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1538,12 +1558,14 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nan= d_chip *nand, &cur_off, &max_bitflips, i, false, page); if (ret < 0) - return ret; + goto out; } =20 + ret =3D max_bitflips; +out: sunxi_nfc_hw_ecc_disable(nand); =20 - return max_bitflips; + return ret; } =20 static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand, @@ -1555,7 +1577,9 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_read_page_op(nand, page, 0, NULL, 0); + ret =3D nand_read_page_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 ret =3D sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks); if (ret >=3D 0) --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-oi2-f12.google.com (mail-oi2-f12.google.com [74.125.231.204]) (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 E04F83624A5 for ; Wed, 9 Sep 2026 08:30:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.204 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942659; cv=none; b=JeIJBpx1q8y9SnyH7AneVH9KVsVrU6q1SHm+r7u3ndy3wzqci41bGHD1CGBtjTwUGEdg9SoD1PRYnaRCqkLCA2el98nSu+B7koVjcfqW9qizryQOianrMdzPZu5eccazwCCHPVJi1uH5MRQrEtKg5dlRkpAiWOSS2DRdTfMEOzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942659; c=relaxed/simple; bh=JjcfMNv/ryMPrxdyyGEQfKzKotCCfWbAANdXEfsoU6Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HNZow5Uu1BINT1+kCb6VvuynupiYOqZM0MmINmXBUvv/nQdEtv3f/wO5iOPSD9AbKb37hzn/yQ7IZ2UKGDysao7RiicpPfqZgpC/k3HWHxrRMCcb8k7nEmVFvaPeWqGl8DUfz6akoAL6Z+WCVPokda1mPaRi5pZ7fig7Y1OlCmE= 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=ZWFolYZc; arc=none smtp.client-ip=74.125.231.204 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZWFolYZc" Received: by mail-oi2-f12.google.com with SMTP id 5614622812f47-4b37a30eb3bso688794b6e.1 for ; Wed, 09 Sep 2026 01:30:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942656; x=1789547456; darn=vger.kernel.org; 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=TAI1w8ATMKnIgdhqgRiA5pqnRC7cEUdZiCb1QZM8MYQ=; b=ZWFolYZczaPCbDhcYVrPKQ1+yhEdhacDH/pfYkRBBqeKV9oQxS0gutQf+o+wFigIde U8Vwc6caUU2lkt0QIvLxIkf8d9dA2dlcLhW1lfeoRaTLugZSXM8YxVf4Yfg8GsPoryIP QIdImxNP4OfytcLj8sX3uz3xO5LVEYwXnihmLj76W5UuGZxi+LNSpDAiW/3wqfxAwQU0 v0GTg4Lx4ZpX9cMSb6PvmpHrvcGq7mdN++kBZeHIwBWfGI2K54szekUvWEgwrhlKxtLW CDhFiDwxaHSLWLc7OLhomQqnINZNu0j7gfjdBrniwXt5nkMt3cxwEBKZxdNDYZ/gCZZc WV8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942656; x=1789547456; 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=TAI1w8ATMKnIgdhqgRiA5pqnRC7cEUdZiCb1QZM8MYQ=; b=fDSQdNC/q6SPR6yqRbWVvX9QVLyPfCwvrvEKsi+OEV7uoXSdavCAaTaoy9xhh3n2qb Jk/22kL19pUky/d4Y9CYGZMdXP2lVRk+Odc4JYI0prlpilaY7izkF3mlWKZ5xBBIdKVJ EuxuUrAsHqDIh69b/ECQhHmFRvd0GF05Pm3IQGOh9RTBKronGNHDTvgMObtmbuA27UAh faRWm1+57JU+HqVP+b+X6yEQklzuwCbvADbdLbwih71sX5mDXEMv+M2HxTfh5ROCiktq PsrsBjOr/4exFCrdxHRna24iOI0qDJzH/B5BLn4Jb30JBWpyNsxNT/rKz3HUXdFCtPLK yOGQ== X-Forwarded-Encrypted: i=1; AKwUvBx0sNf4zVRitAfBvJjVi2ZDVyxn8D3Cpj2hi0Of++5hWgB9ONkgbyY0iYgNNLD8gpG0VBEco4AXg2b81BI=@vger.kernel.org X-Gm-Message-State: AFuF++nBXW9WO2MSpthB9a2HxpXY26VR9PXjdbBaStvpIs/97aLfs2f0 QASl4bSWxLyPtQDsEJGhK7ZBGWxwMp39+OsAVIMTP6RIy/KFq2y1tn05 X-Gm-Gg: AYBFou0uTc9JKRkNH9swfyeiGDZzyTTcRVdwx+8yav2Tjg06MVXQA0yqmw8XQwN9xGJ 8DUm/6W3Fp9ACMRkFnQjrucumg+hA38ODCBcYbiqiO9Btd9bLe4IrWv1WvdwgSaX8OLuQJPeAYt J3PVec7SF6IYOsMnBHOzky5+nkGz4NfGi46Wbt/0KTTdKIPYnUN2ciA1UPQ7KbabEpAiRIGAPn7 MF6UIUmfOyrQb7ZwllX34t1ljR9bmwHF6nUHlYS0jLO6PSKnE0bvDDatKW2Gn1OFrbib7Ph90wW BK5E9LEHEyPEWiKQQnALHzELlhOY2fvd/Kx61YqfRxAaWA/u2UI/255glgBUrNEtoCYhvQjk0l4 O5ETye3s4XIRet4dK+E6d9mAHtIU/SRgUkwuvJNiP55CCur+mRSdqV20+QWpNxPJP8VRTsG9/AQ GER/AMX44tT46zwyLZGRWvbM0qL9fMcNqx+QVNgYSJLsRQRGHana2lyZUS+p3UukZwfyq8YbddL DmzmU60JAuxM223Xi9OSYI9DA2d9GXYzXhATmQb4RDKikZ+C2mJ9JAaStaigTym0QC4mRIeShAR qRjrKvF1DQVUF9sPOzCU/LIc8Mop+WxcXZwawapTqNgEOG2x42w74O/s9Jvhl7Be3o++jljqqob aSqtnvcL9wg9ULl0LJsEWb8iaA0dn/ld/KXRqBtQ= X-Received: by 2002:a05:6820:61a:b0:6b1:ba66:6998 with SMTP id 006d021491bc7-6bdca848f71mr4429570eaf.14.1788942656520; Wed, 09 Sep 2026 01:30:56 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:30:55 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:36 -0600 Subject: [PATCH v3 03/15] mtd: rawnand: sunxi: stop failed program operations and disable ECC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-3-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The PIO page and subpage write callbacks leave ECC enabled if a chunk transfer fails. They also ignore program-setup errors, as does the DMA page writer, and can continue transferring data and issuing PAGEPROG after the setup command has failed. Check program setup before enabling ECC or transferring data. If DMA preparation has already succeeded, abort the queued operation and unmap its buffer before returning the setup error. Route PIO chunk failures through ECC disable and return the original error. Issue the program-end command only after the transfers succeed, preserving the existing successful-write sequence. 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 5190b39aec5a..af8ba2d9f7a0 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1598,11 +1598,13 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_= chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int ret, i, cur_off =3D 0; + int ret =3D 0, i, cur_off =3D 0; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1617,14 +1619,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; } =20 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, &cur_off, page); =20 +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; =20 return nand_prog_page_end_op(nand); } @@ -1638,11 +1643,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct na= nd_chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int ret, i, cur_off =3D 0; + int ret =3D 0, i, cur_off =3D 0; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_enable(nand); =20 @@ -1658,10 +1665,13 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct na= nd_chip *nand, oob_off + mtd->writesize, &cur_off, i, page); if (ret) - return ret; + goto out; } =20 +out: sunxi_nfc_hw_ecc_disable(nand); + if (ret) + return ret; =20 return nand_prog_page_end_op(nand); } @@ -1700,7 +1710,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct na= nd_chip *nand, sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 - nand_prog_page_begin_op(nand, page, 0, NULL, 0); + ret =3D 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; + } =20 sunxi_nfc_hw_ecc_enable(nand); sunxi_nfc_randomizer_config(nand, page, false); --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 228CA450418 for ; Wed, 9 Sep 2026 08:30:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942661; cv=none; b=I602yecE2+Th6K1eNarD1vW3jpb0Ih2/LQyrqFamz0KeFKh2bwDvvlCpt8oYlo/oCpvmR2fKFCRwDQWGn26NRClEC1ds8nJtfSv8CQkDxf+4/DuvpE1PEORQeJ/0fSR0I0BUhnIAQAdTG1h3bXMF855f2ikn3GMWgffZ1tKbyKA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942661; c=relaxed/simple; bh=M5gOmxNVEYBWCZddIshPvl/AuXs4iPCkuaNTOjovIfs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mrrC3a4MX0uiYpSXx+kxaz9fdlcQ2XmrQUt4JUkqiNtjfIBpVeqbSydeykO3ZueLiDg0sV3rHJ6fhi2g5DpA0hNRLswQHQAQ+Lz5qJgdIOKg1ODe3x/Vej9wwPoyKl+SFXlqaFvqA5DbNKnUjKY/fJfnQYbx9Kr61cyq5Jqgb5s= 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=BvjU6WvE; arc=none smtp.client-ip=209.85.210.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BvjU6WvE" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-8016ab5f277so327363a34.3 for ; Wed, 09 Sep 2026 01:30:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942658; x=1789547458; darn=vger.kernel.org; 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=fr9GqqlcZjpJ8b9Wsl+mydOW8kr4IAMiGLW3BSwW8ho=; b=BvjU6WvExhhxPpTrJ5lvNGguXUJEKG/lEFmCQiJs5nrd7yhH1hBXZmJYKUP0Eb5S4C ndb81ExTztpeFETqxmyWqHtH/Sw34+tkprOkUzqGZrlgi/WrwwZY14LfUvFFZtIfEhp2 jvmAQoeiOujMka2Auh4uVxNXAmdkiho+ZkOsA3ENE+SLigLoDUey1bqme67Ikor8AvWT AMvNej2WmaNqJysoVAuyqZmLQ7M5fxibmsDqcqjeJr9etAHlYkq9lUOn01NEbeZTdwIW /TEcol49N4rhcJD6E4YGPbEx78fhEwP2Y3QVlqBHp84Nt3plqweVmNVMEYnrDn4fjwL6 b7Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942658; x=1789547458; 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=fr9GqqlcZjpJ8b9Wsl+mydOW8kr4IAMiGLW3BSwW8ho=; b=MB4CMGgXYC0Q824jcsd/93cpW4ZJay4THbKVLHurUyRvbWH0lIBlb9lc6xLzvI5m8G L0Q8rn/VEGVnkaDePTMYJI/wzY9pfuelndBYSmHKemN2gN8hEtxDPyFcZz3V5krR/t85 sJc4mwvWeu6mkZkYhvWlhD2RgVeSRUZFjptPX2weoHE9x7BtDxY0DGrpTfUs2olslIe0 bp4W1b78rhsY8vRXvS2OGA9wnSNgoJ176TVptA+4KMuu2QkGBXAANdR5plv2pb2DNexu cLCek3VNVn6l/8yYRPD856DOiOZBxWW+EYDA+ctVgRjjWsg8qwyJajwOyRvAkUjcqOVD LyQw== X-Forwarded-Encrypted: i=1; AKwUvBy3a+zo6UlO9IYJNj9Cm9e6zS1wJpojiFQSzScdlgNrQbpg+Mp4kzSo9du0nx9zmVmT+eLC1y2ue3/h49k=@vger.kernel.org X-Gm-Message-State: AFuF++l/UoQYS5kb1wxnGohuHxqj4v/c0gpyoQuphVkG4xmXIUly8cy1 GjeekjMi3I9KWiw3ECbBBFSCbVfCQuFc/f75RrX5vJngIXJSSEvHDy65 X-Gm-Gg: AYBFou1ziY5sOe5sSeInwmhomEy/MmLN7hIj+IznODLi9jXpHmMGIBU4nRev9jdLBWY J3yqXvj4418nXLDi2hLIk2zY3HYjD1AOnG6f4WVP8jrBrq23oSyI0iNQMmRGtkrj5B0yGu9f0XM qckyvCVb4Q+I/DBrqNs6TZddkdWZsQjwgvM2oI+Qzmym2G6kGqXlB8Aaphzex/g/TB3KQ4wTZ4p NhQ2rg9utGf47mmzxHJwecbQGnRhCdQPOj8U1x/JeZ6CWnB+575nyataX8VdTPlllcgeT+7OPMI gA+Wi4ISCN2+I45wqFopJ5JRfw89oNVWJV1JuCc4NJUIpwsT8a+Txkfz6D9yVxLBrv9Yw5GwdwY 2MwuqnojR/vk8Q/ICYrw/Hm3k/IHvIbYIkdwOCpzD25oG9wqYEBYPfr/Za8TJSj00KxpqI5nXeI yTwibYP5wzU8pSdzcTwzrgema9PaubHWkiqQmotQX31X81hSRhN6YZrkWuipQYyPbo3GtM7JAUj VUSay/T5WJG+Pa1X65INeAN0l3Kyx5GexWlFMJfuK0vqpYjv1tB6FD1pjSH4KAL+wOnDjNCeUxM doygZpjSexH5TtWAGn7m8GFttp70AyzTiZMCaLssX9wyGL/n/OGPIzrX1vV+kiB8Vj8gT8YEawY VE3Fy4tpY4Tc3SLi+A+G3CjtGu1oz X-Received: by 2002:a4a:e914:0:b0:6b2:69bf:c8d7 with SMTP id 006d021491bc7-6b6fb3df17emr20147370eaf.10.1788942657854; Wed, 09 Sep 2026 01:30:57 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:30:57 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:37 -0600 Subject: [PATCH v3 04/15] mtd: rawnand: sunxi: select the pattern ID for the current ECC step Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-4-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The pattern ID register has one bit per hardware ECC step, distinguishing all-zero from all-ones data. The correction helper checks the current step's pattern-found bit but always reads pattern ID bit zero. PIO reuses hardware step zero, so this works there. DMA processes several steps at once: a later all-ones step can be filled with zeros and reported as a successful read if pattern ID bit zero is clear. Conversely, a later all-zero step can be treated as erased when bit zero is set. Use the current hardware step's pattern ID bit, matching the error and pattern-found bits already checked by the helper. Fixes: 614049a8d904 ("mtd: nand: sunxi: add support for DMA assisted operat= ions") 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 af8ba2d9f7a0..1bc94565e9e8 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1105,7 +1105,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, if (pattern_found & BIT(step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1))) { + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-oo1-f43.google.com (mail-oo1-f43.google.com [209.85.161.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 0549A476690 for ; Wed, 9 Sep 2026 08:31:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942664; cv=none; b=hIiBXO/mUVS04NkMzqEajTL3GG0Lo0zCKReaF0k9IXCifCOb/nnli092fMi7mgrgx8sUINhOWw6hdBmzb8qB9ct4MCzSNQsVaVjf+FPAnse8ycwmjOYF/wDwHjrHmOPzYjXK91Uu5fJiwuciel0R19CR0eAyqYSWI9sh+DkDuv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942664; c=relaxed/simple; bh=RVqGVXQUJeISiEcx5IgnCpMhNKRA1FoC04a/+LaFAXY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dEra6nsXNEmjDWMBGhqgxoyaXTZHzdZPRV6TrjHwUTMwiGAXZyLOFHQsXa2sWVRuhr9l+plWLmgRbyp82c28dve652sLVYvup1H2y/wf+Vw3a6wbTzczGEwrAQuMT0FuEARHZsUTH/F8pcqL1ykiTbU39pA23M+/3C6vdakzt6o= 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=bIBWQHri; arc=none smtp.client-ip=209.85.161.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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bIBWQHri" Received: by mail-oo1-f43.google.com with SMTP id 006d021491bc7-6b1598d3f73so3295787eaf.2 for ; Wed, 09 Sep 2026 01:31:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942659; x=1789547459; darn=vger.kernel.org; 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=bs355GQcNdyXLmSFCPmXMNpmCIkqcr3KcfubGPkH/gA=; b=bIBWQHri1Ir76JgaDprsfCA4+hDKNmBYw+M13AZFhp9Bu3PK63Dmh4wK3y6huscvEa 1OgKi07LqUeQ6laZuPUb5pXojYKX2xopWf6z7gEwV2lANv2tJGjmy5P0MrPFGtjwLPuI TDHh33hEdGiXvgpfiK7PtF2jhV4ybUk+dlX1ZmBdQmfBlJkkCuHWNZeF9S8mibx8PNBB tquPRctgzAEndyqYBbBLkjgQMZJYrLdrwHzODv5Wx4n2+gaz7CxbwGQgjVpfGQiMhckn qCgYSBTWhEyCjEBd4dsV9r1GDoP90omqjH6I+FmbMOV/+loRBnTnMUfdjyLbx28R0FMa PGIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942659; x=1789547459; 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=bs355GQcNdyXLmSFCPmXMNpmCIkqcr3KcfubGPkH/gA=; b=RRWS2q/sJleopmwSh0mJ7AM5zMxpDZnsg/73bB74dulkOo9QBpEjSFFlgbUHLnW5Ri lHtf7sUY7JegRsHzgtYbeZ38jRSkDA1i65qRJ3fbFct1lWFUTnzCxyraKQm8OCAc73KT N7fw3jsmKR7voR6XLz++2K2Zuo5KhFAOBAEQ7DN3JFrfD6YgVTMvzyKTc+lrfGtIXrcs Q0kF+dHGXJFX17JT59ENf36iP6wC7Wdcgyn1s0g4XrW7Jy92gaQgAs9sI4RLMkWMCLVv Z9XRVGWBUksWsC4oTOt7ng9ccN7JyGlLBvjJ1Iu/STKkJypVezVQytx7qfLjlL/rpjEp fW4A== X-Forwarded-Encrypted: i=1; AKwUvByvUb+sGKnn59jeghz8R6M2lEaoINLrTCIdfCRUrkJ28Hg5TiL1ijkPqKEk6zIIKlX6Lllfu0Mp/3q31X8=@vger.kernel.org X-Gm-Message-State: AFuF++nMshbcYF6+giTSZ0PaVUz3Rw41wN6Ghywh8fApF1276JQ6haX3 Nzl0rY5vPFSl0TiYdiRLTqCzNeH/GgF+Esa3sWvQO213Zg7D5gWB0bMP X-Gm-Gg: AYBFou2qCadpqT7BCs5JtMq0aY8FyG+P6P01iKuCGTpar4ybi5m+pJr3y+nswVS5vyJ 23drqskTEKMDGeKBiitiJzHYoGUKKUYga0ZZ7XKfsnh4V5vfyxyFpsmW0bbq2BOvS4FvjUOBa9W pWuafE9TlJpXFBbdQVHSB8FAMXLRcHLnbFSbS6lA/n2gY6t1lBs2spchmU1M/XLytv4rmfZjG/A g/LD87unDP9Cx2YWLfd2h72wBwqFMh9QZK9FQ+ejiHtZg/eTS6Anyt6VvPK5fy7uDiU7NWOslLw Uf/KypEidk5ONZjFv/NTmf3shBT9w9UsAw4Rw+O2oGBdMnSTmZ9kmBopMxXXWBKwixivHMENxT3 LJAIhlz3S4ruX9fAd4D2l/b0ckXHl/BXnve38e1NQnvoAsLy6mkgejoz58XRmoYO3elE2yvkESf KPtsW2Q2UsgX2nZHvLz9llqq3DC1/WAgqLvxBO4HfNtFuGzSs0/OtJ/uUo6STa2AwpxvwfIaa0c 9Sj2Fiziaz+G+0ay4cHGyzUxTmtDS2NEnF9H0C0wvf1vR2YsA0HSIfeMaep5BH45DpLpmDJYmfu x6YGZA8hloolAX+TBpe3ixY0QHRYZ/KLpI9zaH6tltud/THhyUQKTZIbZ3F9kvje41zkc5IgEeS m0+FXa04m814+y92Ram/BxJvdm3bb X-Received: by 2002:a05:6820:4b14:b0:6be:7782:5a51 with SMTP id 006d021491bc7-6be7782655emr1244864eaf.10.1788942659380; Wed, 09 Sep 2026 01:30:59 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:30:58 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:38 -0600 Subject: [PATCH v3 05/15] mtd: rawnand: sunxi: propagate buffer and column transfer errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-5-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The PIO buffer helpers stop on a FIFO or completion timeout but return no status. Their hardware-ECC callers also ignore column-change failures, including the extra-OOB paths used after DMA. A read can therefore report success with incomplete data, and a write can issue PAGEPROG after a failed transfer. Return transfer errors through the randomizer and OOB helpers to the page callbacks. Always disable the randomizer after a buffer transfer, and let the existing page error exits disable ECC and skip program-end. Only advance the extra-OOB cursor after a successful transfer. Keep the corrected-bit count separate from transport status so successful OOB reads do not overwrite it. If any legacy DMA OOB read fails, discard the ECC statistics from that attempt before the caller retries in PIO. Leave the successful transfer sequence and 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 | 220 ++++++++++++++++++++++++----------= ---- 1 file changed, 141 insertions(+), 79 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 1bc94565e9e8..7081df77f63e 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -632,7 +632,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nan= d, unsigned int cs) writel(ctl, nfc->regs + NFC_REG_CTL); } =20 -static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int l= en) +static int sunxi_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(sunxi_nand->nand.controller); @@ -648,7 +648,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, = uint8_t *buf, int len) =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; =20 writel(cnt, nfc->regs + NFC_REG_CNT); tmp =3D NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; @@ -660,17 +660,19 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand= , uint8_t *buf, int len) =20 ret =3D sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; =20 if (buf) memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, cnt); offs +=3D cnt; } + + return 0; } =20 -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 =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(sunxi_nand->nand.controller); @@ -686,7 +688,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand,= const uint8_t *buf, =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; =20 writel(cnt, nfc->regs + NFC_REG_CNT); memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); @@ -700,10 +702,12 @@ static void sunxi_nfc_write_buf(struct nand_chip *nan= d, const uint8_t *buf, =20 ret =3D sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; =20 offs +=3D cnt; } + + return 0; } =20 /* These seed values have been extracted from Allwinner's BSP */ @@ -853,23 +857,31 @@ static void sunxi_nfc_randomize_bbm(struct nand_chip = *nand, int page, u8 *bbm) bbm[1] ^=3D sunxi_nfc_randomizer_step(state, 8); } =20 -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 =3D sunxi_nfc_write_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } =20 -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 =3D sunxi_nfc_read_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } =20 static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand) @@ -1140,17 +1152,25 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, u32 pattern_found; bool bbm =3D !step; bool erased; - int ret; + int ret, bitflips; /* From the controller point of view, we are at step 0 */ const int nfc_step =3D 0; =20 - if (*cur_off !=3D data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (*cur_off !=3D data_off) { + ret =3D nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + ret =3D sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + if (ret) + return ret; =20 - if (data_off + ecc->size !=3D oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size !=3D oob_off) { + ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1172,13 +1192,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 - ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, user_data_sz, &erased); + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, + nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found, user_data_sz, &erased); if (erased) return 1; =20 - if (ret < 0) { + if (bitflips < 0) { if (!(nand->options & NAND_NEED_SCRAMBLING)) memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); @@ -1190,17 +1210,22 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); =20 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); + ret =3D nand_change_read_column_op(nand, oob_off, NULL, 0, + false); + if (ret) + return ret; + ret =3D sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, page); + if (ret) + return ret; =20 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, bbm, page, user_data_sz); } } =20 - sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, bitflips); =20 return 0; } @@ -1233,31 +1258,39 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_c= hip *sunxi_nand, sunxi_nfc_user_data_sz(sunxi_nand, step); } =20 -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 =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; + int ret; =20 if (len <=3D 0) - return; + return 0; =20 - if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) - nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) { + ret =3D nand_change_read_column_op(nand, mtd->writesize + offset, + NULL, 0, false); + if (ret) + return ret; + } =20 if (!randomize) - sunxi_nfc_read_buf(nand, oob + offset, len); + ret =3D sunxi_nfc_read_buf(nand, oob + offset, len); else - sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, - false, page); + ret =3D sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, + false, page); + if (ret) + return ret; =20 if (cur_off) *cur_off =3D mtd->oobsize + mtd->writesize; + + return 0; } =20 static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_= t *buf, @@ -1328,21 +1361,24 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; bool erased; + int bitflips; =20 - ret =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, - oob_required ? oob : NULL, - i, status, pattern_found, - user_data_sz, &erased); + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, + oob_required ? oob : NULL, + i, status, pattern_found, + user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ - if (ret < 0) + if (bitflips < 0) continue; =20 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); + ret =3D nand_change_read_column_op(nand, mtd->writesize + oob_off, + oob, ecc->bytes + user_data_sz, + false); + if (ret) + goto err_stats; =20 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, page, user_data_sz); @@ -1351,7 +1387,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf if (erased) raw_mode =3D 1; =20 - sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret); + sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 if (status & NFC_ECC_ERR_MSK(nfc)) { @@ -1369,23 +1405,27 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf mtd->writesize + oob_off, user_data_sz, &max_bitflips); - if (ret < 0) { - /* The caller retries the whole read in PIO mode. */ - mtd->ecc_stats.corrected =3D corrected; - mtd->ecc_stats.failed =3D failed; - return ret; - } + if (ret < 0) + goto err_stats; if (ret) raw_mode =3D 1; } } =20 - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, - page); + if (oob_required) { + ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, + NULL, !raw_mode, page); + if (ret) + goto err_stats; + } =20 return max_bitflips; + +err_stats: + /* The caller retries the whole read in PIO mode. */ + mtd->ecc_stats.corrected =3D corrected; + mtd->ecc_stats.failed =3D failed; + return ret; } =20 static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, @@ -1403,13 +1443,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 =3D 0; =20 - if (data_off !=3D *cur_off) - nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (data_off !=3D *cur_off) { + ret =3D nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + ret =3D sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page= ); + if (ret) + return ret; =20 - if (data_off + ecc->size !=3D oob_off) - nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size !=3D oob_off) { + ret =3D nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1435,27 +1483,35 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand= _chip *nand, return 0; } =20 -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 =3D nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; + int ret; =20 if (len <=3D 0) - return; + return 0; =20 - if (!cur_off || *cur_off !=3D offset) - nand_change_write_column_op(nand, offset + mtd->writesize, - NULL, 0, false); + if (!cur_off || *cur_off !=3D offset) { + ret =3D nand_change_write_column_op(nand, offset + mtd->writesize, + NULL, 0, false); + if (ret) + return ret; + } =20 - sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + ret =3D sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, pa= ge); + if (ret) + return ret; =20 if (cur_off) *cur_off =3D mtd->oobsize + mtd->writesize; + + return 0; } =20 static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, @@ -1494,9 +1550,12 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_ch= ip *nand, uint8_t *buf, raw_mode =3D true; } =20 - if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); + if (oob_required) { + ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, + !raw_mode, page); + if (ret) + goto out; + } =20 ret =3D max_bitflips; out: @@ -1623,8 +1682,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_ch= ip *nand, } =20 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - &cur_off, page); + ret =3D sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + &cur_off, page); =20 out: sunxi_nfc_hw_ecc_disable(nand); @@ -1747,10 +1806,13 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct n= and_chip *nand, if (ret) return ret; =20 - 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 =3D sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + NULL, page); + if (ret) + return ret; + } =20 return nand_prog_page_end_op(nand); =20 --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 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 7B4E3473C8D for ; Wed, 9 Sep 2026 08:31:02 +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=1788942665; cv=none; b=f11uoIiqIcljYo2jdwjtYoiK176tZ1ZPGwOzUloFpgZE2QnqUTPd3hZQncicJUaCFkzAd9rPAhMTNncty/qlC9yy1GScqWLU0gT01s2oK3a9dZeCPoHdiRZ4uYNs4Ln99qDqFz7wvYD/Q9KcPYwYq3TvfE5DwjMXfTp3XUvqc3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942665; c=relaxed/simple; bh=Tmcas4j0s3Gf2d4qRloLyZr+HYYU6fTALfwrcrP6U1E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eBksb010gqn1kcPqpma2HVwjG603moHG45roLX9CE8PNv/B8Z2ufQTDeJVYUOMjsgCmittm9HjJqyuMWi0gKefcLO8uISCE1DonBdt1UTmk8LvY7o7/HJZ6qn7jTOKcC8pzHCvI+GgqR4VlI6O5mS6Swzt5RWURmGZllF5vr88U= 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=csggK5j6; 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="csggK5j6" Received: by mail-oa1-f52.google.com with SMTP id 586e51a60fabf-43b7e186a0cso2946415fac.0 for ; Wed, 09 Sep 2026 01:31:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942661; x=1789547461; darn=vger.kernel.org; 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=Wvg8aSvAJDl+PROcGB7AxVuyh80XuZxIbfxWbHKxpV8=; b=csggK5j6a1Hpp6vJPgctXds4Hzg921R8zHgTNUqrOD5zC8DVA0LVKo/gJsTEQVPCK9 pDpmxjiy8OCZzG4/nsqRjzsSoFw2vUciZBnGE/OWDhxfgYcSpYTdus+xTXTI2/pkbujA 8Nm+mrsa3THA1TtaT0LwIW1dam4y7FzhT206SyRr5w9vEzNWMWh6oGDpKWMCUCFXx9ml Kkrnlai5vvGtZbcyDazrkckVLnsk+nAqiKUMQ6FyFZJRtUDjt1l4DEYDweK5H/s+m+Ny bHDjAR+4FrSx9V9Epz2SWzc5dhCmAd/SnRN6xWJTzlxwLuBzJhTUWLqRZRFMX96/OaEV uF/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942661; x=1789547461; 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=Wvg8aSvAJDl+PROcGB7AxVuyh80XuZxIbfxWbHKxpV8=; b=QGFfx+/Z0Z7YYFgWSGwNvWjF6jIwt79s+XSeHecopxIX+ZlhOMDH2TWpoI69GuYpOe xDV0eTQL5TnuBVy/RFn0riuq52PJ2bRwtfkbpuUkvNYL7ye8oSqxZRvL1WEltWUrhOgN Dup8XKhp6vtjQSJQcq6/U2rsNExruMdkTebTwSxH7m7iE6D01Fpmvb96tUX0Lm53pnih c8PUc2ts+udAkznrVSJdXHtfJ4W9ysJIT+iAZE9hQL0WWzi//kQxJlq9d5jDI8e1n1mQ 0k/X9ztF5iHpBh1u7R4OOwg7sntotzmExhDi0raWVuQ5BJbDOkn0uOMrzdBaN7CrSfKb cIvg== X-Forwarded-Encrypted: i=1; AKwUvBx5u7Rm2qcM9AzD253VMSVHjIDeyaAbSehDkQdlLOcuYG3Hk0EJHu3ptpxeaHOyXc8fgADHcPKtY1iwV/E=@vger.kernel.org X-Gm-Message-State: AFuF++kbFdRhqCFSDIphYX5Kkb5kAhhuFuV/waLqjfqp/jNWZHSZjHjA hY1NA/QXnKVgmfO4XsRbS3q8ph4ZgkiDi1HNGG/7SFWjhly4O9aJe7p4 X-Gm-Gg: AYBFou1I6sS3I9dMdXji2KLiTVsTb8P4sHK7Tln9d8gpbYGwy4jaK+TGnH2o9S8Hpl8 QDc/ehqM0ggG3AZyOj4w3Vyx9JLwVF+GCnvnrfJPHxXU97ZuID6q00ExWSJb4Amfil9BUG7FJbU t0MQBzBpzoMdSD5t5MsTsHToA9FAVcLR5VHM0UW18BGy5iaVP3Aq+sof7oWYjehyyM8bNDExcsZ aWJJ4uMaahKe+cn+7oNXRQnIPXEodOAC+g+/Ft+RhXb8KstClzSxWaM1Is8c5K7fyy3JciR3rjs d0bb9GhcYBvCLZ5G5FfjIvZCh5sQiK79fDwsP6jvXhVw+GnzMaAYdB6S+g9lEz6NnytXZHAT/5C c2Q/Bk+Ou908sbS3wSxvC2PnOb9C2R8dnd4ez7jM/1ecJ/jae7jGF6GXApDTwDR/OMbfewZ6NQe dXAZd7/TZXM9yu42GyRQSsHqp3kFkGCLz8kq7DDcDHMQQzzcJOC5hnVFIJtWvdQNrFl4R0MQhmg ScNDGBy0EyoAf3sdZSELrLhIq2reMzWiNtQ26CImA1NLU7dCvfbb3hikaAZaBlzHuEEOTuOb32B oSYDA2f28Mg28TubInZWuqNuj3geXVQKSNWRa/ogT0A8SF9vL1xhPkNb2q24KWRdF2xtC7sj5PP NKG0t/bCTqEnE1gANlEVIn80P+LuD X-Received: by 2002:a05:6820:1613:b0:6aa:da04:b56f with SMTP id 006d021491bc7-6b6fa7e183amr19522399eaf.3.1788942660818; Wed, 09 Sep 2026 01:31:00 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.30.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:00 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:39 -0600 Subject: [PATCH v3 06/15] mtd: rawnand: sunxi: avoid a second program confirm for OOB writes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-6-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The hardware-ECC OOB writer delegates to the page writer, which already issues PAGEPROG, waits for completion and checks the NAND status. The OOB wrapper then calls nand_prog_page_end_op() again, sending an extra program confirm without a corresponding program setup. An error on this redundant operation is returned even though the page writer has already succeeded. Return the page writer's result directly. This leaves both PIO and DMA responsible for completing their own program operation and preserves their error results, including for bad-block-marker writes. 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 7081df77f63e..545da54b8908 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1831,15 +1831,10 @@ static int sunxi_nfc_hw_ecc_write_oob(struct nand_c= hip *nand, int page) { struct mtd_info *mtd =3D nand_to_mtd(nand); u8 *buf =3D nand_get_data_buf(nand); - int ret; =20 memset(buf, 0xff, mtd->writesize); - ret =3D nand->ecc.write_page(nand, buf, 1, page); - if (ret) - return ret; =20 - /* Send command to program the OOB data */ - return nand_prog_page_end_op(nand); + return nand->ecc.write_page(nand, buf, 1, page); } =20 static const struct sunxi_nfc_timings sun4i_a10_nfc_timings =3D { --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0A2B471CE9 for ; Wed, 9 Sep 2026 08:31:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942666; cv=none; b=KPewbNpTaEE/inLbQWswbvGLJQjL9S6WomOExanHHMBf7jmPocYpTQf/kiiAQwGNY/h0034hef1ug+tRXT8woq1n0qqQAD7+XtZFfMgvYb9eFsAiI2LuVKjRhPILLktn6oj0LPoWQxqxDQ9eGu+ThR6gtSeku90RivAh2KIAy/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942666; c=relaxed/simple; bh=E0Hu13NVGjVcdOOasuN/FpRSk1aK5eY3ouDDcya/TIg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eiOSOYHYHIl9NSvkan7rPzj8x5uKA28VKPQ4ERzqgAnhhsV3cZGy2F8apgELNLNao0D6LemhLk43cVxwCo5HDlNoWpy5LlvGfoPDVpFPmYfkZi/9sqNhsiULgxXoX80S6zp+1+Lj+LMUZPgAO6UyPsrgyjaCMQUMVAq2w3EGaCg= 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=E+BQpDdk; arc=none smtp.client-ip=209.85.210.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="E+BQpDdk" Received: by mail-ot1-f42.google.com with SMTP id 46e09a7af769-7f5a781972fso3769281a34.3 for ; Wed, 09 Sep 2026 01:31:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942662; x=1789547462; darn=vger.kernel.org; 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=1Y8ZddL9dHiRh8qGBH1XBVf3Fk4YPspd9rKTcsO7FCo=; b=E+BQpDdkE4FdCIXjPuvlVP8rPJwkzu+vd61j221VllIWWCeSNT8xHOMyRbL/rJfwSn NYLIJqEymlC6F0YI3mpDIcJ2Ye0sMtsu1w3q5HGd5UfyhU+U4sF+Fg89d0SSKMhHp0Wk vujhNH7HdVCkKPYBodTjUXjZ0mn326D4q0oUwlZXFo+xZXwb8dl1nplNhT5nqDSoYgxk 6NQy6FrLIidNWlbyuCSLM/kO8uEWjTV7qWuI606GR01el7S/DHvJNgr/dg2GNQ3mbN08 6K0GSvxrA4zM7/Xo0b2iJlAZsE9TaddzrQJNitgFMnbZxVGJxlRp3k21pcGlaxqYOHe4 secQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942662; x=1789547462; 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=1Y8ZddL9dHiRh8qGBH1XBVf3Fk4YPspd9rKTcsO7FCo=; b=E9yUrD1G4G5Q/IkNbzdPXC5bst1HNrTr1ZCiPTTWUlsZPGbwodSxBWJ/SyEbvm69cx rimfDO6ikAJjZwRfR7TnFr/Nmnj6W8U3KiJVeF6EOpqs22v4kh0bbeSq3HpAvDvT8QPz Q3l1YWZfD04/fT0iy9yngiz5tXlwVql28rIXQQqW/b5sHXMslkxP7bwlH1ncFE206OzP cs2gPprQBT+E0lgycMVxZBeTfOGNPJeLkQsv5U0q3aD2dKE2OrVeyuYXpIjfWL5Ql6Xb tBnUyt5WJS1tbFWepN06swb9Y2KZklxO4edKQdzKbl9AvUZlh/SqapoQL6MqIG0n/mmY Cz3A== X-Forwarded-Encrypted: i=1; AKwUvBxjMN/oScED2OHpDaq1aQClV/nB0FkRiN3epC3kHaCNmyuKVuscoNWHshFUyQxQq9o0kQ5z8rtsbYt2k9s=@vger.kernel.org X-Gm-Message-State: AFuF++nsY5UvrLm3H4IyQaAquJgXILpJzEmf9eCAKg1veDwCf44ho4xp xz32bi+Q84uLhqKRiFsHw29uBD7uR4+z3AZJSWpVFMD8p3sdxizvCniN X-Gm-Gg: AYBFou2Pq0jfnfF4rEUFZq8hnsDB6vH0WtIVrVXun7VNyLMkBuJjmcrcnLtuJKEr/az inlZ+7YbJhqThcySCqImwzgifq0yb90j+0es8Wv2BukJjKJpk/1lRWJgFThVup1UG51JHaohiB6 kDl+Fzb99tEeEboWrYHFze4S77kJ5v7m+34DmJ/RPABniuy11tWcdUkgAPUVgIxV6iu1T6hP2QS qLKMInCJceCmpQeKMfts11tepOV+N1tR1sc7mvIo/ougSNitjMjG+jGEzbSRXnZMItg40x84x/o R7TmhH003JkQsqtUfQiIGHVyKr5BfvRbBcAJkKEE9OTUrIJoGEEvMhDhRJjsV/la/0+alSgOeLO Uj2Uvmjnv5SjJLEIBcK6yGVar2xYRNPFSg7Q13R/mc5h4hJvuHKIw+6pFJKDD5RPJPOF17GUnkt ruSeszQmxFHVMQc76EkhGHkstT4EkpeXpA0+8iw5j30AA0czQhuEjwIEdE2viNKz5QMLGKtW6Ff zQ2KntWQ9UUXU6Q9EKZasynUlKomUx8hHKikSW7wJbE/4ulRiLFixkixDDm5VPyjTVJE9VZR7Sg HUIDjZ0RBKYcivO9FXyPC2XgMye//xIJJwjmsHWotw9fbRv4k4aeZPOcTh3qXdczW/ZJI9SnQjR HQ5GMY8Zu45WptisrucbHeR43/z9R X-Received: by 2002:a05:6820:162b:b0:6b6:f16d:d672 with SMTP id 006d021491bc7-6b6fdfb6581mr30282006eaf.16.1788942662447; Wed, 09 Sep 2026 01:31:02 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:01 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:40 -0600 Subject: [PATCH v3 07/15] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-7-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The PIO write loop tracks the absolute NAND column in cur_off, while the extra-OOB helper computes an offset relative to the start of OOB. Comparing these values directly always requests a column change, even when the last ECC step has already left the cursor at the start of the extra OOB bytes. Include the page size in the comparison, matching the extra-OOB read helper. Keep the explicit column change when the caller does not track the cursor, as in the DMA path, or when the current column differs. 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 545da54b8908..16b2b39524a7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1497,7 +1497,7 @@ static int sunxi_nfc_hw_ecc_write_extra_oob(struct na= nd_chip *nand, if (len <=3D 0) return 0; =20 - if (!cur_off || *cur_off !=3D offset) { + if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) { ret =3D nand_change_write_column_op(nand, offset + mtd->writesize, NULL, 0, false); if (ret) --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f54.google.com (mail-ot1-f54.google.com [209.85.210.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FFF147CC6C for ; Wed, 9 Sep 2026 08:31:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942668; cv=none; b=PXHp5vLxQGvZDmNqlPHIurkNdLvvJwr3y/qJ/kl39dpEGMNE5xHKUJKvj1CKTzgrO9NEAqjEJlBnI+6ecXlkLuPkjrMz3hl+ogvm6Opua1tTP7YGfVzGmpIeDDIvuXLe0J4DxoesHB7cMyrzb04U7AFLQe7nfAx7Rt1j1YBlD4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942668; c=relaxed/simple; bh=RWio02EAftpave3S+sbI1+YFYXCV2Eq76V2GGV5Bl4c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lC5DX4/Xog429N5iF2D54QjOwfXSKwVGNpbV4KEl/88KUoHB+r28J7Pva56iI3fpkWpyd8Ayca3VQuaQcEdXCKLhAcU5pIhtDKLSk+DfzHoVyOzOYpNEpM0RqpGLhKFtakZja6wkovdcU7bUtgLFu+oSP7v6dOIfr8ROptpe1rw= 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=NmoZ4H0A; arc=none smtp.client-ip=209.85.210.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NmoZ4H0A" Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-7f84a55cc06so4084451a34.2 for ; Wed, 09 Sep 2026 01:31:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942664; x=1789547464; darn=vger.kernel.org; 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=WcUOmAhLcGtei2/BcCp+jJsQASRhlEZ3b/VByXsoyLM=; b=NmoZ4H0A7EMkFPuPjk+caOIW9FAT/eEE3glbDup8VQI9bLy1knS/fWoFsiFStSJNJC 3H3XaHM7BaUCnn/CNSMWWdVngej1qQhGDe//HTsteeSu2iGGbkMiq5K0WFH3hqxCxPi/ J33kBGEH8hR7Jr1jaztbeZnUtR6ZoCZ8/1EMlrOLeVKMJqwqQEpN7xdxcKbSHxiYDYo3 BGJvgriz0tbKKQsYxdpWesu9lJSeoeP68SonTpXNqjBklSNqgUlRrBBKc+4c2dmsi9sk O62mypwHOYZ2e4naUavCKMeLAcLVZvPbOjr1bTUwRs0EGLQkHRRPi58vjk8t4Z4G+cwi pvYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942664; x=1789547464; 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=WcUOmAhLcGtei2/BcCp+jJsQASRhlEZ3b/VByXsoyLM=; b=Dj995HHkLKWQUi+4LBHWBZP2YqVP0o6AoqQqZu4rhsCc3NjWSzBxvtbtbh459Lh9RG TdiLRqcK1HHxEt8eMcxrh5ppv2aNCK2rvNm/rRC0uv9S250I7GIzts/S/+nWwrA8LVRR 6nvdu0DEHr6TumkbzRl9L7k75HaVML7QOK3zB02IH82DBpJ4BA2Ov5NshUNl7bxtAppB +wMhZIwmCVZnZbT9RbKoUpy4ZwWp4+I/jgP7Mka2w27H3+V/dkNMyJF3xWqG5o52Myoh LVedbTB1FmQ6O5zC9jH3hw0Xfx6nx/wHfbgkcXB3g89K6i8mkrYws6XupSHnMQDxoDXd QlrQ== X-Forwarded-Encrypted: i=1; AKwUvBzn2Qxi1KlDlAJKh8YFGWa5ta0RDbdDSH/0MQNSHn9DNPm0DhWJn27wrHVmpWKetjTD1EureE2M12zseZg=@vger.kernel.org X-Gm-Message-State: AFuF++naEtN/kkdD1gM5PKAls/lQc8yjZD7Yu7x9z7k489qTflr0MgJo cDxXecIDU8AYmrA/Em6Ild4Z/ezEb2bei+jRH/yzms6snpuCX55LJ4Ij X-Gm-Gg: AYBFou36zJKRLqy9cB9HKwLWHAoBXsdQYcjYsvOI8Exw+/4TDS7mW9ysb/tNitAbgk8 OvdQXLLVqRmXJc81IzCHqxiR2WfJ9T+4O3/J8b8qlAo07PP//jiNATFPmQMqpggJC9ZGn6wbSyt pI6uyunNGcWVknxBxbTHn3lUx54y5VtxQFaVvVNy/vtASEEprfRSnQowotxB52Mh1vb6bAhZgOc lJ0/egrfdEXso+cIIQxCaelT3kFsnaTh5k2DABFu+oBgBn1WBnYRBnE0ZvMWJMxeKYBF3kwvI1s QnbweWLbO/oCHuu5tgHjV4KTMlepbHlODXkH5mRzwZmaZkPr4O4otoY1njkSh+TuQ8sqQuSklid k6jnlCN86n9Z0ZaDyahwdx2EkPyc9/YdVzoWtSTtOX5rXtJ8Oz8Z93SpAcM8SydLxdtV09PvU0p mtdUuD/DL2zZKYCQrvCMw8DeW/IKPzhiaZUhicnxvzZHwzDbhsb5jsO13SzSOXLI0EEfw5mDfxU PkkJ6L+tKeSiQ6z3b5WHRpU+WdEXL7jK0JhCzvwbK+XDAXD47n9IUSMQpZfzK/EXzjYey1TuksO EoAlzjjHPrHpopLssY0dNVVWvGeajGiMQVtPq8kiYd54ZPGh41YrkMxGEavdXnYi+fqkNJYBmoH OYuSHrOpBz4/IEotPEE3lAMI14abz X-Received: by 2002:a05:6820:4d04:b0:6a0:f44b:1265 with SMTP id 006d021491bc7-6b6fa8e0837mr19303991eaf.4.1788942664083; Wed, 09 Sep 2026 01:31:04 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:03 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:41 -0600 Subject: [PATCH v3 08/15] mtd: rawnand: sunxi: clarify OOB register and step handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-8-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 PIO reuses hardware slot zero while the user-data length and OOB offset belong to the logical page step. Name the two indices explicitly in the helpers so their different roles are visible at each call site. Share the variable-length user-data register-index calculation between the protected-OOB read and write helpers, keeping the separate MMIO loops and existing fixed-length register accesses. Clarify why the plain-marker format compensates the bad-block marker around hardware randomization. Rename raw_mode to erased_chunk_found in the page readers, using a boolean in both paths. The flag suppresses randomization of the trailing OOB after an erased chunk; it does not select MTD_OPS_RAW. No on-flash format, register-access sequence or ECC accounting changes. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 143 ++++++++++++++++++----------------= ---- 1 file changed, 67 insertions(+), 76 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 16b2b39524a7..390782986a47 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -912,16 +912,33 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8= *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } =20 -static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int s= tep) +static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, + int logical_step) { if (!sunxi_nand->user_data_bytes) return USER_DATA_SZ; =20 - return sunxi_nand->user_data_bytes[step]; + return sunxi_nand->user_data_bytes[logical_step]; +} + +/* + * Variable-length user data is concatenated in four-byte registers. + * PIO uses hardware step zero; DMA slots follow the logical page steps. + */ +static unsigned int +sunxi_nfc_user_data_reg_index(struct sunxi_nand_chip *sunxi_nand, int hw_s= tep) +{ + unsigned int byte_offset =3D 0; + int i; + + for (i =3D 0; i < hw_step; i++) + byte_offset +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + return byte_offset / 4; } =20 static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8= *oob, - int step, bool bbm, int page, + int hw_step, bool bbm, int page, unsigned int user_data_sz) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); @@ -929,35 +946,22 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struc= t nand_chip *nand, u8 *oob, u32 user_data; =20 if (!nfc->caps->reg_user_data_len) { - /* - * For A10, the user data for step n is in the nth - * REG_USER_DATA - */ - user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); + user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, hw_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 =3D 0; + unsigned int reg_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); unsigned int reg_off; u8 *ptr =3D oob; unsigned int i; =20 - for (i =3D 0; i < step; i++) - user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /=3D 4; for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { - reg_off =3D NFC_REG_USER_DATA(nfc, user_data_off + i); + reg_off =3D NFC_REG_USER_DATA(nfc, reg_index + i); user_data =3D readl(nfc->regs + reg_off); sunxi_nfc_user_data_to_buf(user_data, ptr); } } =20 - /* De-randomize the Bad Block Marker. */ + /* Undo hardware de-randomization for a plain on-flash BBM. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) sunxi_nfc_randomize_bbm(nand, page, oob); } @@ -979,7 +983,7 @@ static void sunxi_nfc_reset_user_data_len(struct sunxi_= nfc *nfc) } =20 static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int step) + int len, int hw_step) { bool found =3D false; u32 val; @@ -1002,15 +1006,15 @@ static void sunxi_nfc_set_user_data_len(struct sunx= i_nfc *nfc, return; } =20 - val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); =20 - val &=3D ~NFC_USER_DATA_LEN_MSK(step); - val |=3D field_prep(NFC_USER_DATA_LEN_MSK(step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + val &=3D ~NFC_USER_DATA_LEN_MSK(hw_step); + val |=3D field_prep(NFC_USER_DATA_LEN_MSK(hw_step), i); + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, - const u8 *oob, int step, + const u8 *oob, int hw_step, bool bbm, int page, unsigned int user_data_sz) { @@ -1018,7 +1022,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struc= t nand_chip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; =20 - /* Randomize the Bad Block Marker. */ + /* Pre-randomize the BBM so the hardware writes it plain on flash. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(nand, page, user_data); @@ -1026,32 +1030,18 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(str= uct nand_chip *nand, } =20 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)); + nfc->regs + NFC_REG_USER_DATA(nfc, hw_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 =3D 0; + unsigned int reg_index =3D sunxi_nfc_user_data_reg_index(sunxi_nand, hw_= step); const u8 *ptr =3D oob; unsigned int i; =20 - for (i =3D 0; i < step; i++) - user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); - - user_data_off /=3D 4; for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { writel(sunxi_nfc_buf_to_user_data(ptr), - nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); + nfc->regs + NFC_REG_USER_DATA(nfc, reg_index + i)); } } - } =20 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -1102,7 +1092,7 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_ch= ip *nand, } =20 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, - int step, u32 status, u32 pattern_found, + int hw_step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); @@ -1111,13 +1101,13 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chi= p *nand, u8 *data, u8 *oob, =20 *erased =3D false; =20 - if (status & NFC_ECC_ERR(step)) + if (status & NFC_ECC_ERR(hw_step)) return -EBADMSG; =20 - if (pattern_found & BIT(step)) { + if (pattern_found & BIT(hw_step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(step)))) { + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; @@ -1133,9 +1123,9 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, return 0; } =20 - tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, step)); + tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); =20 - return NFC_ECC_ERR_CNT(step, tmp); + return NFC_ECC_ERR_CNT(hw_step, tmp); } =20 static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, @@ -1143,18 +1133,18 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - int step, bool oob_required, int page) + int logical_step, bool oob_required, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; u32 pattern_found; - bool bbm =3D !step; + bool bbm =3D !logical_step; bool erased; int ret, bitflips; /* From the controller point of view, we are at step 0 */ - const int nfc_step =3D 0; + const int hw_step =3D 0; =20 if (*cur_off !=3D data_off) { ret =3D nand_change_read_column_op(nand, data_off, NULL, 0, false); @@ -1176,7 +1166,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -1193,7 +1183,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, - nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), + hw_step, readl(nfc->regs + NFC_REG_ECC_ST), pattern_found, user_data_sz, &erased); if (erased) return 1; @@ -1220,7 +1210,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); } } @@ -1235,12 +1225,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, * (it includes the user data before the ECC data.) */ static int sunxi_get_oob_offset(struct sunxi_nand_chip *sunxi_nand, - struct nand_ecc_ctrl *ecc, int step) + struct nand_ecc_ctrl *ecc, int logical_step) { - int ecc_off =3D step * ecc->bytes; + int ecc_off =3D logical_step * ecc->bytes; int i; =20 - for (i =3D 0; i < step; i++) + for (i =3D 0; i < logical_step; i++) ecc_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); =20 return ecc_off; @@ -1252,10 +1242,10 @@ static int sunxi_get_oob_offset(struct sunxi_nand_c= hip *sunxi_nand, * but it skips the next user data. */ static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, - struct nand_ecc_ctrl *ecc, int step) + struct nand_ecc_ctrl *ecc, int logical_step) { - return sunxi_get_oob_offset(sunxi_nand, ecc, step) + - sunxi_nfc_user_data_sz(sunxi_nand, step); + return sunxi_get_oob_offset(sunxi_nand, ecc, logical_step) + + sunxi_nfc_user_data_sz(sunxi_nand, logical_step); } =20 static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, @@ -1305,7 +1295,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; - int ret, i, raw_mode =3D 0; + bool erased_chunk_found =3D false; + int ret, i; struct scatterlist sg; u32 status, pattern_found, wait; =20 @@ -1385,7 +1376,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf } =20 if (erased) - raw_mode =3D 1; + erased_chunk_found =3D true; =20 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } @@ -1408,13 +1399,13 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf if (ret < 0) goto err_stats; if (ret) - raw_mode =3D 1; + erased_chunk_found =3D true; } } =20 if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, - NULL, !raw_mode, page); + NULL, !erased_chunk_found, page); if (ret) goto err_stats; } @@ -1431,17 +1422,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off, int step, + int *cur_off, int logical_step, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); - unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - bool bbm =3D !step; + bool bbm =3D !logical_step; int ret; /* From the controller point of view, we are at step 0 */ - const int nfc_step =3D 0; + const int hw_step =3D 0; =20 if (data_off !=3D *cur_off) { ret =3D nand_change_write_column_op(nand, data_off, NULL, 0, false); @@ -1465,8 +1456,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 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_set_user_data_len(nfc, user_data_sz, hw_step); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | @@ -1523,7 +1514,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, struct nand_ecc_ctrl *ecc =3D &nand->ecc; unsigned int max_bitflips =3D 0; int ret, i, cur_off =3D 0; - bool raw_mode =3D false; + bool erased_chunk_found =3D false; =20 sunxi_nfc_select_chip(nand, nand->cur_cs); =20 @@ -1547,12 +1538,12 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_c= hip *nand, uint8_t *buf, if (ret < 0) goto out; else if (ret) - raw_mode =3D true; + erased_chunk_found =3D true; } =20 if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, - !raw_mode, page); + !erased_chunk_found, page); if (ret) goto out; } --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 740DE471247 for ; Wed, 9 Sep 2026 08:31:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942669; cv=none; b=m1smxM8SeDLPhLQu0cmlJ9OsBwmBQ0jpq3PZNLI2r+h19CsA1xRD1jvoWI3maaxaX3kmnec79uRVhf0dVTMs+9KNGCYX7cRJysaU4NAoSjXGFjiq15MdKg/tacvmMTRC5GBHmocjgXUHyvu63tyFlGtUZev2W4girCR4p+B51LA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942669; c=relaxed/simple; bh=TnmhAN7UAS2ynuFEOPQLlzD2wvbIo/yeVWwhOMqNS58=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Vla89V85KjhJpVzoGMmWImfcHCripxxH0f4NOb5Q/LSb+9T7W0aKA4wWorHR239enNlcS+6h6pBiebRpYllrt/g83++Id10OAE7yOuOqo0loMwknb+rowG8o2zBN5QqLhjF9y7an08U4yNXeo4NwASXi8vIzsud6jLlsoGGi1cA= 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=P3vpeS48; arc=none smtp.client-ip=209.85.161.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="P3vpeS48" Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-6b8e2d8df4fso3136422eaf.1 for ; Wed, 09 Sep 2026 01:31:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942666; x=1789547466; darn=vger.kernel.org; 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=SP5FgDVql885MI97WgCQyPWKLiok3M5jguE0MrKj3qI=; b=P3vpeS48JWiWyK4+WoYhfjKUJEDSRSkDAcP5BIff7quilpBnEMOrSh5bnHDHZJLQ/I P4MEsf0O78UAzZYWmUkJJyUkoPLzKNol8qFXvklseN09ejGC0cSXPcy7Hp2quNgcvLDr 6PRfh7QBAcUmoHbryWxEwTwzRj6XV7T5WsrNRuFitTfZK8KZ7qwM1xIk9vi1x8o1m9GH IOFZQizDn0ks2MVTbyNrGj471rQRKfAr5ct5aJcZ+omfKvecNWVqRqDryVAP6FdCbxZT gVSJkcNF8Ij4uU5O8XznjZPaYPeLmL3siwEl5ZlYRBhRUd9/cxeTkikd2SvG7aZk9yni Ll5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942666; x=1789547466; 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=SP5FgDVql885MI97WgCQyPWKLiok3M5jguE0MrKj3qI=; b=dnXKLCxRJ6NuSmmU4wJoK2vt14faE6Wok2Q4qQAbJulgBUPpob99KJT9jpSziCnYGV iQ/1kyDJvQ4pV//mSTKikYXFrISA4C5li7vhIBOxGdK3jNh7vloWLH7y0oQRTu3oZHA+ xgwxxJasuVsZIR3ENL7p0U+abP/tFn3eFZwsANEL63466V7JovSdPF1VFCE66QHRGNtN dAcy/sAWZq/DyBdWvM+V/VXaiEItMAa4L4pSsWR3b6ibvG4GBn1eyEry6zdSFkcWzUXg z1cOLsKX1+c4H0Zp+wqUoPnnbwt2OG1f08GgvAciHEagA/aJAvsysibXEa8rmbzITZSy /k5Q== X-Forwarded-Encrypted: i=1; AKwUvBx/TTYyy87AEwA0h7HYDAfpM65BIRgwrI/Zq5hc2ialaLzCDG/Kii4ZStDtjnchu1WrJam9HKK210gFLxQ=@vger.kernel.org X-Gm-Message-State: AFuF++kpS6GP9O18ZRVd23twiF+Ww2u2oyZRsJ8QVkPsZGWq6A7Ekqvz jvHCZPVY+dMm2jSbmGoMYdElbIlX1zvlchnIloV6A7gIfDg05O5E2lSr X-Gm-Gg: AYBFou1jThuSPbWy6takUUhXb34So0R8ieOsyJExM7e/Nvb2Kv1Zp5N1giHlSvCN3XB brmsySDW7pn8s/B+q3e/mUiDvq66KdvWQpn+Xq4dyl4j3XSEgmExxUwAGKfBcK7PZgRApE4vkZg asZBCWKACHF3GQzwUHLwyUWK7Sw/qWSJ7iIHdlwuJ66wbnW4oLGmkYJLn38ppy34Jj0rdDB3U97 TvhcxI8dfrjS2YIWEMGOcpWcXD7KkYqqu0fUok013P//ApwuBXnfwnIFyxnnLZgUCnwybkwrmA4 jDryCCBcfYUhRcJz0pYi9kwk9x3usQWZhp9duaa5rCGJfEtMVVKwxjjUUBNvXE2o1b+kXqMT4ES Up1EHpBNr5s5f2T3IISARYUnFJTSZDRq9xXz9hyT8iNxrj1pTw2WCAPK5jD+vj0Von3mfRpZs97 tWS24Z5B9KHCcPPPn/P7PXibDgEhykLnUqyr9GvPPlwTtgJ6o0NeDquby6tzCw3GP6cWFvoajzS P5CkpwYZ6RQ9s5qiZuk2Rwqn0Y4/VEtw21pf/nuRJGsbFkiHZcoBl/Ods67UXkoQKevtPgFFlNd uWUDIN5M2gzjmvGj1XnBNsMHCCF4TJkHv7boRaicOPhG3p1H+0Qq0H4V7Onal/kgLG8hqTdDLCj VV4k2yB+j0Danxdkfe7+xuYQda7XP X-Received: by 2002:a05:6820:c84:b0:6b1:a0b6:72d9 with SMTP id 006d021491bc7-6b6fd3d694amr18766040eaf.25.1788942665879; Wed, 09 Sep 2026 01:31:05 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:05 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:42 -0600 Subject: [PATCH v3 09/15] dt-bindings: mtd: sunxi: Add randomized OOB flag Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-9-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 Allwinner NAND firmware stores the bad block marker through the controller randomizer. The mainline driver instead compensates the first two randomized bytes so that the marker remains plain on flash. On H6 and H616, the firmware also uses a fixed protected user-data placement while mainline fills the OOB space left after ECC. Add an opt-in property selecting the firmware's normal-page format for the configured controller hardware-ECC geometry. This covers the vendor-specific randomizer, bad block marker representation and protected user-data placement needed to access BSP-derived images. The property does not change raw-access semantics. Raw operations still bypass ECC and randomization and expose physical main and OOB bytes. 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 =20 + 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 re= mains + in its data stream instead of being compensated to stay plain on + flash, and protected user data uses the controller-specific plac= ement + expected by the firmware. + unevaluatedProperties: false =20 required: --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 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 CD103481FD0 for ; Wed, 9 Sep 2026 08:31:08 +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=1788942671; cv=none; b=F06xkmyovudaCXKbsAMQ+5rhP+LGvRyqqyurmCG3tFrvj8lHxi1CJjuYlukmgMjLW+XH9bsG3TsSPfLIYjHDll87W8BiB697JYEM0Q9U8nmz3EFNPulIzOgQOn6pFzOx/1oY2/3gUT99cq1cLUu8YCqikmqAo4E2TifXUWiYPCk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942671; c=relaxed/simple; bh=TYSqah5XB81AImjVrSL2O8Mnlunetlr6dFWU2gOJD38=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SBMxatqe8ifJU+55uyvZFimV25g8dNnz9nLLwLxaXxu4zTIBSL1VajU6MKjxCx1Gq79RI06xiWTCe7Kp0NiwgFb8cM7W5PERn1onr9rUY+0xkIfCCO4GgAQksS+XJ0gvpV7LglTxcxvFlgbiNCxZhICaMvJ55GwBW8Er05s4ghc= 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=tFzVSM23; 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tFzVSM23" Received: by mail-oo1-f44.google.com with SMTP id 006d021491bc7-6bd209cf210so763162eaf.3 for ; Wed, 09 Sep 2026 01:31:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942667; x=1789547467; darn=vger.kernel.org; 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=SAb1T6YPRz2cL1T89j6JWFc2LHi9KBVTtBcqDoSSbZI=; b=tFzVSM23OM5LiBLEUNmsiRzqpHJFjLV8Y6PNkHYm7RW8APrRXOZTw9whX0C9Aww0Tv G5Kd5Rka1x5oZXnFwzF9y6IJQXJQTDX1QqiI4GIRDy3CMnhsT/ODYQwJrjSw8joROHZm +Jmi9RFjmJdRTthcO62yUK45BW9WYle2wsr5wN6hOpxRknoY7jeFp5z8X859KKXV4i09 mgmudsafRjWgRP+hDSEOqKo7vA0MsdTEi0iCK4XhshU/XccPnutiCfZemOejvyymgXFw 8J8tzH8rR5MpUMp5F5YP9ik1LnvAPv9P1AqOoDM2J7iX7I+X/phMBSmvb6GdPPAH7WTv 3ujA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942667; x=1789547467; 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=SAb1T6YPRz2cL1T89j6JWFc2LHi9KBVTtBcqDoSSbZI=; b=g8SdFivC3S3dh2A3nLttzKVZTjDYakDU/j7mjJI56cn/7+rIivwSaVuSIcffWSPPkb DN9rRtGLxMPh2TlAcgW0MF8k3+v9Fplo22uQtJr4lCNFjpvaa5DxNS79qFpdX5xmSee8 YMXmAprOKMx88BUyp7/CHvYFa9c1k2HR8prKQ66snamKC7DkvxpzQVeUNcyH4yf6flbC 5gKQl/N35JNGHTfl8Fy2ljqZ9yUto7bbiz7sXDxBwk5EYhaThudhvVqAmlzGjQ6dc7ng oTL70eGdR4+moZ3S9rdPPvKOFbHvG6tAPel/rhZ4OdOxkX++4gj2MQ5+H4F4cr4ktZOZ ftYQ== X-Forwarded-Encrypted: i=1; AKwUvBxLcrsUzvkYJ0LYSLijfO0itKpBVh1hmlP5WWGeeaa458nGef7eBkq93J7pNgGepkfm+IvUm7EutRe3R1A=@vger.kernel.org X-Gm-Message-State: AFuF++kq6NVUHZbEwRWxr4YIpsGlVvqjDzGp4oVCKE4cL1+np7kuSXlb PgYTu3blOcgX+J5Y/0II1DKt2X+37jvr2kRwNcqJy9HALYFVlqERGaxf X-Gm-Gg: AYBFou1Xw5A1VydTOjN1PRv/w34loHbjRJ5le2tlrpAJid9IWb2yr1I5/rjOpUQorWn pjK5U6D1Ho4FRGzwmTrEfv94+tSk5TpdI4DczHIiMrBFAVGNCNXmaTZX8aEtzt5q6kYG7EHDvn9 iAQ0nneTRlUSNBsP5e4RQh4kxPubkRspcOlDtIcVxp7iK49gaTjJRXOKJOqAEUCAQllCnil8YWS ENm6tettoMJ5MqEl8Y+Oc5DaFSnpRwvqaDwy4ooaygK7EY5hj+htVaQm+LK7FfagS5mk9nEmg7s Z3zopERu9qaY2eObOPRI4TfjZqTa9yX5BguPwftXnUHd4+sRJ3T+lR4FOv3kJ+iP0Yc+RroBpwL VJkS46tDqRcH6u1AzejliVmJ/wcR5+3Ts6ZSQvbF33th2CO27vNRK7zBZJ2vVQsuZl3aT8ab1tN Ch9T5IdqaYvoDx1qBX9SQ/laqjJTMdHjcgg4SDYqYAVhoiK9Is3Pz/jFso8k73NLfExnxdGj6GH Kzo2iq00LIgJ0lbhT1F0P0C3ny3I5AsvfZdbiLTaj61BLEBr/TX92Tr3R/OYJEdtvtAOqt5s0Qn mF6xNgaTUGO+CRoJWwviIfM/E4LDrAyAQI4hw6SCbtwNFPwOHZ8b4+Guggy5QziB5/p1D+lk5bV NCUn6rAKKYmWFecq/UWdYy/kgn25A X-Received: by 2002:a4a:e847:0:b0:6b7:46e9:9700 with SMTP id 006d021491bc7-6b746e9a360mr17928285eaf.48.1788942667305; Wed, 09 Sep 2026 01:31:07 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:06 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:43 -0600 Subject: [PATCH v3 10/15] mtd: rawnand: sunxi: support randomized OOB formats Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-10-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The controller randomizer covers the bad block marker along with the rest of the OOB data. The driver currently compensates the marker bytes before writes and after reads so that they remain plain on flash. Allwinner NAND firmware instead stores the marker through the randomizer. Media using that format appears to contain bad blocks unless the randomizer is enabled while reading the marker. Honor the allwinner,randomized-oob property by marking the NAND as requiring scrambling during normal hardware-ECC transfers and leaving the marker in the randomizer data stream. Keep the existing plain marker behavior when the property is absent. Reject the property with software or disabled ECC because those paths do not operate the controller randomizer. Also reject an ECC step larger than the page so the NAND core cannot fall back to software ECC after the driver's initial engine-type check. Select the vendor's erased-spare predicate through the SoC capabilities when the randomized format encounters an ECC error. Older controllers require eight exact 0xff spare bytes, with the vendor spare-scan shortcut for four exact bytes on the first page and pages 127 modulo 128 within each eraseblock. Apply that shortcut only with the vendor's 1 KiB ECC steps. H616 requires byte zero and at least nine of ten bytes to be 0xff. Reconstruct the physical spare prefix from the protected user-data registers, padding unavailable bytes with 0xff. Each ECC step restarts its OOB randomizer; account for this when gathering the prefix from fixed four-byte user-data fields. Accepted erased pages return all-0xff main data and OOB without an ECC failure or a raw reread. Also follow the vendor's all-zero-page override: when every ECC step reports an all-zero physical pattern, return zeroed data and OOB with an ECC failure, even if the hardware did not report one. Keep the ECC exception disabled in this mode so uniform data still undergoes decoding. Keep the original hardware-decoded main data and protected OOB on other ECC failures, and report the failure through the ECC statistics. Bad-block and BBT pattern scans inspect these buffers even after an ECC error; they must not see the physical randomized representation. Preserve the normal per-path representation of unprotected OOB bytes when they are requested. Share page classification between PIO and DMA, including subpage reads. Read the whole page for randomized-format subpage requests so that both paths see the same spare prefix and all-zero-page status. Defer statistics until OOB reads have succeeded, so a DMA-to-PIO retry is accounted once. The plain-marker format keeps its existing physical erased-chunk check. MTD_OPS_RAW behavior remains unchanged: raw accesses bypass both ECC and randomization and expose the physical representation. This changes marker handling on all supported controllers; the H6/H616 protected user-data placement is handled separately. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 270 ++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 261 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 390782986a47..75515ad276e7 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -265,6 +265,7 @@ struct sunxi_nfc_timings { * @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 + * @randomized_oob: use the randomized normal-page OOB format * @nsels: number of CS lines required by the NAND chip * @sels: array of CS lines descriptions * @user_data_bytes: array of user data lengths for all ECC steps @@ -277,6 +278,7 @@ struct sunxi_nand_chip { u32 timing_cfg; u32 timing_ctl; u8 *user_data_bytes; + bool randomized_oob; int nsels; struct sunxi_nand_chip_sel sels[] __counted_by(nsels); }; @@ -328,6 +330,7 @@ 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: Vendor erased-page check on the physical spare prefix */ struct sunxi_nfc_caps { bool has_mdma; @@ -356,6 +359,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= ); }; =20 /** @@ -849,12 +853,18 @@ static void sunxi_nfc_randomizer_disable(struct nand_= chip *nand) nfc->regs + NFC_REG_ECC_CTL); } =20 -static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *= bbm) +static void sunxi_nfc_randomize_buf(u16 state, u8 *buf, unsigned int len) { - u16 state =3D sunxi_nfc_randomizer_state(nand, page, true); + while (len--) { + *buf++ ^=3D state; + state =3D sunxi_nfc_randomizer_step(state, 8); + } +} =20 - bbm[0] ^=3D state; - bbm[1] ^=3D sunxi_nfc_randomizer_step(state, 8); +static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *= bbm) +{ + sunxi_nfc_randomize_buf(sunxi_nfc_randomizer_state(nand, page, true), + bbm, 2); } =20 static int sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, @@ -962,7 +972,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct = nand_chip *nand, u8 *oob, } =20 /* Undo hardware de-randomization for a plain on-flash BBM. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) + if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && + !sunxi_nand->randomized_oob) sunxi_nfc_randomize_bbm(nand, page, oob); } =20 @@ -1023,7 +1034,8 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struc= t nand_chip *nand, u8 user_data[SUNXI_NFC_MAX_USER_DATA_SZ] =3D {}; =20 /* Pre-randomize the BBM so the hardware writes it plain on flash. */ - if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { + if (bbm && (nand->options & NAND_NEED_SCRAMBLING) && + !sunxi_nand->randomized_oob) { memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(nand, page, user_data); oob =3D user_data; @@ -1091,6 +1103,37 @@ static int sunxi_nfc_hw_ecc_read_error(struct nand_c= hip *nand, return ret >=3D 0; } =20 +/* Accumulate a whole randomized-OOB page before classifying its spare dat= a. */ +struct sunxi_nfc_ecc_status { + u32 error_steps; + u32 zero_steps; + unsigned int corrected; + unsigned int max_bitflips; +}; + +static void sunxi_nfc_hw_ecc_record_status(struct nand_chip *nand, + struct sunxi_nfc_ecc_status *result, + int logical_step, int hw_step, u32 status, + u32 pattern_found) +{ + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 count; + + if ((pattern_found & BIT(hw_step)) && + !(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step))) + result->zero_steps |=3D BIT(logical_step); + + if (status & NFC_ECC_ERR(hw_step)) { + result->error_steps |=3D BIT(logical_step); + return; + } + + count =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); + count =3D NFC_ECC_ERR_CNT(hw_step, count); + result->corrected +=3D count; + result->max_bitflips =3D max(result->max_bitflips, count); +} + static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, int hw_step, u32 status, u32 pattern_found, unsigned int user_data_sz, bool *erased) @@ -1133,7 +1176,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - int logical_step, bool oob_required, int page) + int logical_step, bool oob_required, int page, + struct sunxi_nfc_ecc_status *result) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); @@ -1182,6 +1226,16 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_c= hip *nand, pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 + if (sunxi_nand->randomized_oob) { + sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, hw_step, + readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found); + memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, + page, user_data_sz); + return 0; + } + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, hw_step, readl(nfc->regs + NFC_REG_ECC_ST), pattern_found, user_data_sz, &erased); @@ -1283,6 +1337,153 @@ static int sunxi_nfc_hw_ecc_read_extra_oob(struct n= and_chip *nand, return 0; } =20 +static bool sun4i_a10_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + struct mtd_info *mtd =3D nand_to_mtd(nand); + unsigned int block_page =3D page % mtd_div_by_ws(mtd->erasesize, mtd); + + /* + * The older vendor spare scans recognize 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 =3D=3D 1024 && + (!block_page || block_page % 128 =3D=3D 127) && + !memchr_inv(spare, 0xff, USER_DATA_SZ)) + return true; + + return !memchr_inv(spare, 0xff, 8); +} + +static bool sun50i_h616_nfc_spare_is_erased(struct nand_chip *nand, + const u8 *spare, int page) +{ + unsigned int erased =3D 0; + int i; + + /* Byte zero and at least nine of ten bytes must be 0xff. */ + for (i =3D 0; i < 10; i++) + erased +=3D spare[i] =3D=3D 0xff; + + return spare[0] =3D=3D 0xff && erased >=3D 9; +} + +static bool sunxi_nfc_hw_ecc_spare_is_erased(struct nand_chip *nand, int p= age) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + u16 state =3D sunxi_nfc_randomizer_state(nand, page, true); + u8 spare[10]; + unsigned int len, pos =3D 0; + int i, off; + + /* + * Reconstruct the physical spare prefix from the hardware's decoded + * user data. Each ECC 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 =3D 0; i < ecc->steps && pos < sizeof(spare); i++) { + len =3D min_t(unsigned int, sunxi_nfc_user_data_sz(sunxi_nand, i), + sizeof(spare) - pos); + off =3D 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 +=3D len; + } + + return nfc->caps->spare_is_erased(nand, spare, page); +} + +static int sunxi_nfc_hw_ecc_read_unprotected_oob(struct nand_chip *nand, + bool dma, int page) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct mtd_info *mtd =3D nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + unsigned int len, off; + u16 state; + int ret, i; + + for (i =3D 0; i < ecc->steps; i++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); + ret =3D nand_change_read_column_op(nand, mtd->writesize + off, + nand->oob_poi + off, + ecc->bytes, false); + if (ret) + return ret; + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + state =3D sunxi_nfc_randomizer_state(nand, page, true); + state =3D sunxi_nfc_randomizer_step(state, len * 8 + 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, + ecc->bytes); + } + } + + off =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); + len =3D mtd->oobsize - off; + if (len) { + ret =3D nand_change_read_column_op(nand, mtd->writesize + off, + nand->oob_poi + off, len, false); + if (ret) + return ret; + /* The unprotected tail uses the page seed and its 15-bit advance. */ + state =3D sunxi_nfc_randomizer_state(nand, page, false); + state =3D sunxi_nfc_randomizer_step(state, 15); + sunxi_nfc_randomize_buf(state, nand->oob_poi + off, len); + } + + return 0; +} + +static int +sunxi_nfc_hw_ecc_finish_randomized_read(struct nand_chip *nand, u8 *buf, + struct sunxi_nfc_ecc_status *result, + bool oob_required, bool dma, int page) +{ + struct mtd_info *mtd =3D nand_to_mtd(nand); + struct nand_ecc_ctrl *ecc =3D &nand->ecc; + int ret; + + /* + * The vendor treats an all-zero physical page as bad, even without + * ECC errors. This takes precedence over the spare-byte heuristic. + */ + if (result->zero_steps =3D=3D GENMASK(ecc->steps - 1, 0)) { + memset(buf, 0, mtd->writesize); + memset(nand->oob_poi, 0, mtd->oobsize); + mtd->ecc_stats.failed +=3D ecc->steps; + return 0; + } + + if (result->error_steps && sunxi_nfc_hw_ecc_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 =3D sunxi_nfc_hw_ecc_read_unprotected_oob(nand, dma, page); + if (ret) + return ret; + } + + mtd->ecc_stats.corrected +=3D result->corrected; + mtd->ecc_stats.failed +=3D hweight32(result->error_steps); + + return result->max_bitflips; +} + static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_= t *buf, int oob_required, int page, int nchunks) @@ -1292,6 +1493,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nfc_ecc_status result =3D {}; unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; @@ -1354,6 +1556,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct n= and_chip *nand, uint8_t *buf bool erased; int bitflips; =20 + if (sunxi_nand->randomized_oob) { + sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, status, + pattern_found); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, + page, user_data_sz); + continue; + } + bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, i, status, pattern_found, @@ -1381,6 +1591,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct n= and_chip *nand, uint8_t *buf sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, bitflips); } =20 + if (sunxi_nand->randomized_oob) + return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, + oob_required, true, page); + if (status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; @@ -1512,6 +1726,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nfc_ecc_status result =3D {}; unsigned int max_bitflips =3D 0; int ret, i, cur_off =3D 0; bool erased_chunk_found =3D false; @@ -1534,13 +1749,19 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_c= hip *nand, uint8_t *buf, ret =3D sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, - i, oob_required, page); + i, oob_required, page, &result); if (ret < 0) goto out; else if (ret) erased_chunk_found =3D true; } =20 + if (sunxi_nand->randomized_oob) { + ret =3D sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, + oob_required, false, page); + goto out; + } + if (oob_required) { ret =3D sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off, !erased_chunk_found, page); @@ -1586,6 +1807,10 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand= _chip *nand, int ret, i, cur_off =3D 0; unsigned int max_bitflips =3D 0; =20 + /* The vendor spare test and all-zero detection classify a whole page. */ + if (sunxi_nand->randomized_oob) + return sunxi_nfc_hw_ecc_read_page(nand, bufpoi, false, page); + sunxi_nfc_select_chip(nand, nand->cur_cs); =20 ret =3D nand_read_page_op(nand, page, 0, NULL, 0); @@ -1606,7 +1831,7 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, i, - false, page); + false, page, NULL); if (ret < 0) goto out; } @@ -1625,6 +1850,9 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, int nchunks =3D DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); int ret; =20 + if (to_sunxi_nand(nand)->randomized_oob) + return sunxi_nfc_hw_ecc_read_page_dma(nand, buf, false, page); + sunxi_nfc_select_chip(nand, nand->cur_cs); =20 ret =3D nand_read_page_op(nand, page, 0, NULL, 0); @@ -2237,6 +2465,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, ecc->strength *=3D 2; } =20 + /* This format requires an ECC step that fits in the page. */ + if (sunxi_nand->randomized_oob && mtd->writesize < ecc->size) + return -EINVAL; + /* Add ECC info retrieval from DT */ for (ecc_mode =3D 0; ecc_mode < nfc->caps->nstrengths; ecc_mode++) { if (ecc->strength <=3D strengths[ecc_mode]) { @@ -2305,6 +2537,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, sunxi_nand->ecc.ecc_ctl =3D NFC_ECC_MODE(nfc, ecc_mode) | NFC_ECC_EXCEPTI= ON | NFC_ECC_PIPELINE | NFC_ECC_EN; =20 + /* Run ECC on uniform data too, so the randomized spare bytes are decoded= . */ + if (sunxi_nand->randomized_oob) + sunxi_nand->ecc.ecc_ctl &=3D ~NFC_ECC_EXCEPTION; + if (ecc->size =3D=3D 512) { if (nfc->caps->has_ecc_block_512) { sunxi_nand->ecc.ecc_ctl |=3D NFC_ECC_BLOCK_512; @@ -2319,6 +2555,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_ch= ip *nand, =20 static int sunxi_nand_attach_chip(struct nand_chip *nand) { + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); const struct nand_ecc_props *requirements =3D nanddev_get_ecc_requirements(&nand->base); struct nand_ecc_ctrl *ecc =3D &nand->ecc; @@ -2328,6 +2566,14 @@ static int sunxi_nand_attach_chip(struct nand_chip *= nand) if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |=3D NAND_BBT_NO_OOB; =20 + if (sunxi_nand->randomized_oob && + ecc->engine_type !=3D NAND_ECC_ENGINE_TYPE_ON_HOST) + return dev_err_probe(nfc->dev, -EINVAL, + "Allwinner OOB format requires controller ECC\n"); + + if (sunxi_nand->randomized_oob) + nand->options |=3D NAND_NEED_SCRAMBLING; + if (nand->options & NAND_NEED_SCRAMBLING) nand->options |=3D NAND_NO_SUBPAGE_WRITE; =20 @@ -2557,6 +2803,9 @@ static int sunxi_nand_chip_init(struct device *dev, s= truct sunxi_nfc *nfc, if (!sunxi_nand) return -ENOMEM; =20 + sunxi_nand->randomized_oob =3D + of_property_read_bool(np, "allwinner,randomized-oob"); + sunxi_nand->nsels =3D nsels; =20 for (i =3D 0; i < nsels; i++) { @@ -2833,6 +3082,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps= =3D { .max_ecc_steps =3D 16, .sram_size =3D 1024, .timings =3D &sun4i_a10_nfc_timings, + .spare_is_erased =3D sun4i_a10_nfc_spare_is_erased, }; =20 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps =3D { @@ -2856,6 +3106,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps= =3D { .max_ecc_steps =3D 16, .sram_size =3D 1024, .timings =3D &sun4i_a10_nfc_timings, + .spare_is_erased =3D sun4i_a10_nfc_spare_is_erased, }; =20 static const struct sunxi_nfc_caps sunxi_nfc_h616_caps =3D { @@ -2882,6 +3133,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_h616_cap= s =3D { .max_ecc_steps =3D 32, .sram_size =3D 8192, .timings =3D &sun50i_h616_nfc_timings, + .spare_is_erased =3D sun50i_h616_nfc_spare_is_erased, }; =20 static const struct of_device_id sunxi_nfc_ids[] =3D { --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47CB144A3EC for ; Wed, 9 Sep 2026 08:31:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942673; cv=none; b=GF90G1KRJDMBv03zXIJzqSWmTDG2paa/52ujoXtzl35Vnl+kiLjH7OTjRneXxbo/ogDzOucticSexq74cXfT1/LGEOPyvxSvqBT36lVqyJJk3XeDba0JQ2kgpNYanxBMJncz8g6V7qEL9mw6tnnQG4EoR5V8TZ/DEHnA9+ZR2P8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942673; c=relaxed/simple; bh=RUHviMp2AdO1fknBD6KbHrx/oNzHzFuAjPBWy7z+Mks=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LOIkbNL9wyn73okkScj+pRkasWqb27syG/e9s/rcf1uaWorNLyR0ZKRzfbu8/TawaCJP8i1rIsCVtfjeJVCLQK46l+/RTP+uHfspTPQAO1/1LzFYgTgMDW9xjkUXR5ElnTVKj9vi3YnLR4llzM5yYdBVPB42l4uySnShYL0vvmE= 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=p50A2s6u; arc=none smtp.client-ip=209.85.210.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="p50A2s6u" Received: by mail-ot1-f42.google.com with SMTP id 46e09a7af769-801b48c329eso140458a34.3 for ; Wed, 09 Sep 2026 01:31:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942669; x=1789547469; darn=vger.kernel.org; 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=ykqLTK8+NebOH/B0kSjt8n6Khfc9TP9alLqheTq5PmQ=; b=p50A2s6u2ink9vDXarvSc8lHvku/hkF2YGPkQq9pialR66XgKhLsUA16hd6SPnzamA 9G14UJcHoHIe6dibUvldi7WRJCbBWp4DD6TLBK+HkVEajQwr9Zff5MhDacxU7NYb49JD ysjuz3ps1FLVKGa1aquEDcWn7iEV2RchqS/Gsy73ME4pnK6CzVD6I/OnD1/sxKVDQhFs 3wSBBHOoupDEAMCkiILokCcIzWFa4hNZer0KIpZXDj0aqV2JnAuUjwsDcFFPclYlUiEw j8eZWyuG89GJlmnY+S31H2DFczipPoMgj+AQjKSdMdeYutUvGZI4XwHK/0DcIeDcqViF Al1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942669; x=1789547469; 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=ykqLTK8+NebOH/B0kSjt8n6Khfc9TP9alLqheTq5PmQ=; b=YIx8iH/PCANI1VC+aAvhc148M5sgxImekKUyCBEfQJZVoGjFWqVjdHgcpu8CGMnuVD 7X4ci2vFI3sgkZN5gF3lhsY0FRY/gpovtQG4kG42trSBJzuztjjHmxn4mZtPFw4oKQoH 5MkTmS5bC6ZzvlA7/d0iz57AsWXQt1+3i8oY3tkTiAopXX7+yboCmZGr481gynHPQ6tw +EIIyXZLnK9hS/wW1aZKHB0Zx1njF3sn76uuHmZ/8B+TFTH7+Ij/H0/LTZADpgzdNriS YvICU0VJGvm6AU5ldkwBG6s/fXVb/wb95fiBSv13WaQ+eOpsD/+IDQ30y2bNpaljDkzU sduQ== X-Forwarded-Encrypted: i=1; AKwUvBy13wJNhzX3ZJJWsbFoejibf+H4ngPSyoOAQxWKkc8loQrWiL/DlpNjSqXUJj7Aoq9spx8FVSGkqLLAyFw=@vger.kernel.org X-Gm-Message-State: AFuF++nSwOn9KrKffkYQTzsL/SVpTqogU1nCdHN3RoZX+nn9BeaVIzId c0yZISmLvSf9jDWH6afg5KRxU/N+NEg3uPaM2f4ubVTEhATip/7cgAJ2 X-Gm-Gg: AYBFou2xa5qKV/107y25xBAaIeoQUCE+YJ49D/LoCH9BOvo4NIVsac3mQ/F/zb8h7NY 4hSZydLRV4m32u0ZGHxuQJTC2CHWQQScOdREhPcvhlU2EgVHbUspBL6NEsn4vrWnAgo02PvH9Wh DGauIKUKc8pg4bfuphy3DeDgj0umwoRBdnZD9W48auXediqPuZ43NX3Z+E2xJ+IZKEy4sPJ9LtC BTCKacEQa8Y+iceN3k2uAL2Px9Qx+20gLLprCEGzDlX4SoIbt7RM4oCrlgxkM1oYkePyN6g14X7 NvOONOm6tU+x7Mzcp1p4liSx13VRHhEL0605qzvSJQ155hNWPcjIQkhnjUniezeOzA5raEe3dL4 GcacPwuaDkfBCoAmm6zmpiCczbb43cRyiTHr9odsBWvK8XdEppRhsOwbTOLoeVMDv5R6DFl9sgk HP4ULdGriGXcL61ujo1gZmLpZMG94zSlWQoZyhBtQk9ozCTq7c/Z1uqKzwane3SVmNy7HxH+Uga Dr7JjRhefV4/rUM3Tjb9Lt4lxnq6jil/KqnlomiSmceSaGAdwQyklpGIhw+QE1KPml8lFCQc2kx +l69pOOyjNztfFpezfBQYqc4lPMOUkwrBnuH/Er794rrvoqhV3xt1Pxb1arImZg5U4qWClQJXND bZvRDSyY/OS3JHlXOnDb9YIOrPi4Y X-Received: by 2002:a4a:e909:0:b0:6b6:87cf:d1dc with SMTP id 006d021491bc7-6b6fcfd90e3mr19776294eaf.24.1788942668737; Wed, 09 Sep 2026 01:31:08 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:08 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:44 -0600 Subject: [PATCH v3 11/15] mtd: rawnand: sunxi: select the packed H6/H616 OOB layout Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-11-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The H6/H616 controller can configure a separate protected user-data length for every ECC step. Mainline fills all space left after ECC with user data. This changes the physical ECC offsets from those used by Allwinner NAND firmware, so pages written by one layout cannot be decoded with the other. The allwinner,randomized-oob property selects the firmware's normal-page format for the configured controller hardware-ECC geometry. Use four protected user-data bytes per 1 KiB ECC step, cap the total at 16 bytes, and assign the entire total to ECC step zero. Reserve the same total before maximizing ECC strength so the selected strength leaves enough room. Keep the existing maximized mainline user-data layout when the property is absent. Older controllers have fixed four-byte user-data registers whose placement already matches the firmware and need no additional change. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 75515ad276e7..6e54d3a92219 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -224,6 +224,9 @@ #define USER_DATA_SZ 4 #define SUNXI_NFC_MAX_USER_DATA_SZ 32 =20 +/* The randomized H6/H616 layout packs at most 16 bytes before ECC step 0.= */ +#define SUNXI_NFC_H6_MAX_USER_DATA_SZ 16 + /** * struct sunxi_nand_chip_sel - stores information related to NAND Chip Se= lect * @@ -2348,8 +2351,14 @@ static void sunxi_nand_detach_chip(struct nand_chip = *nand) sunxi_nand->user_data_bytes =3D NULL; } =20 -static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t o= obsize, - int ecc_bytes, int nsectors) +static unsigned int sunxi_nfc_h6_user_data_sz(int nsectors) +{ + return min(nsectors * USER_DATA_SZ, + SUNXI_NFC_H6_MAX_USER_DATA_SZ); +} + +static int sunxi_nfc_init_user_data(struct nand_chip *nand, uint32_t oobsi= ze, + int ecc_bytes, int nsectors) { struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); @@ -2365,6 +2374,12 @@ static int sunxi_nfc_maximize_user_data(struct nand_= chip *nand, uint32_t oobsize if (!sunxi_nand->user_data_bytes) return -ENOMEM; =20 + if (sunxi_nand->randomized_oob) { + sunxi_nand->user_data_bytes[0] =3D + sunxi_nfc_h6_user_data_sz(nsectors); + return 0; + } + for (step =3D 0; (step < nsectors) && (remaining_bytes > 0); step++) { for (i =3D 0; i < c->nuser_data_tab; i++) { if (c->user_data_len_tab[i] > remaining_bytes) @@ -2425,6 +2440,10 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, bytes -=3D 2; =20 bytes -=3D total_user_data_sz; + } else if (sunxi_nand->randomized_oob) { + total_user_data_sz =3D + sunxi_nfc_h6_user_data_sz(nsectors); + bytes -=3D total_user_data_sz; } else { /* * User-data lengths are encoded in four-byte units. Reserve @@ -2495,12 +2514,12 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_= chip *nand, nsectors =3D mtd->writesize / ecc->size; =20 /* - * The rationale for variable data length is to prioritize maximum ECC - * strength, and then use the remaining space for user data. + * The default variable-length layout prioritizes maximum ECC strength, + * then uses the remaining space for user data. */ if (nfc->caps->reg_user_data_len) { - ret =3D sunxi_nfc_maximize_user_data(nand, mtd->oobsize, - ecc->bytes, nsectors); + ret =3D sunxi_nfc_init_user_data(nand, mtd->oobsize, + ecc->bytes, nsectors); if (ret) return ret; } --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53A7948E0C1 for ; Wed, 9 Sep 2026 08:31:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942675; cv=none; b=gpwg7RWQdsEkTJXd66rPi0YkthsxAxJDq4wt0hOYXwvNfMK8cZ7A6lFH+FI5WkCRw66SZP1Obem/OHvZMaJtV2A85sdDFNWAUhufmkTvvsvBpmmMZaxgOeG1cIfl80bhQO87AfEOdy/9CxpmNwHE9H1ddFPnUVx1j/oIrrpHhjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942675; c=relaxed/simple; bh=cGpmPCWk/z4rj5JVkICnW7HVGVcxN3tvIGoYKX6sOJI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mzozkW47qTClNM4PcZw0WZ535lDqdBHRIjnwontQf5eygDz4t9oX82NGZ4Nss1/oC9x7M447/QdqLLhzL6BsfJPNnngk/A6U1GTF5Nb3yCVNmvIXf+jzzbGK1vwxGL9MveGSPSuNiZ1fy3eDSlc5Umj9cMy7ZmbTcdPzQeOYPKk= 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=RTA6phgM; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RTA6phgM" Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7f3ece23165so4442416a34.0 for ; Wed, 09 Sep 2026 01:31:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942670; x=1789547470; darn=vger.kernel.org; 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=CID5bvCPjR59lMZ6K1AMRWDV5Xq0pdMdX69zJBV2wqs=; b=RTA6phgMngIkyVMYgb7uN2ni0DhpmXkTUwd0WO1NEddw+7776kl5/NrPuhDjn+6kvy Q8c4lhOs54ASDgAo7v3e717NCtQCi5dWfFJDPoXyTPBoWNNrdzusykRd4/dS5fr04BFs ARdL0b2Ta5UcTLFZHWAxToCeSW8kxkn2kXXBBTv2YR7om7vuqhQW8lPl/XHRaf3RaykZ ujJAmWPqnxWaNsn/10z+Tf1RzNc+vYhVewsNJpW7pJKkoZkCq9FmSWhW/14ebn+loW39 5a6ywABAL6jhCqtWFDgCk/hviVJragfID1caf7YVL7jXvZ48/CZ890oY6hNlzOGD1p3E iSvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942670; x=1789547470; 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=CID5bvCPjR59lMZ6K1AMRWDV5Xq0pdMdX69zJBV2wqs=; b=ebthUb3fAQtijFalIWDTAGvj8ndFHCF2e4+t0tcuOwOL8dK3/kTTWUFQlVQ6D18vOU GR5ufPQBJs0RDHPCkyalf/CjXkvxc+hTs0D4yMTtzJkqDW8fNTGojZ89wy0yelNYnQjv ehFvpVVpofQDYo7GqTxK48S8H4SyU/Q6qEsbxETZv8ECzDIEhaR8dE+x5ZRambOkNqTV KRpSO8dkgieP2B/oGH6RrkOoC8VSgTKWbmRqr/a2Q1LdvjLASQ3D87MQq+6CW6BJycAJ syvyXO6ZEoUopRepFJiCl6rKN5OJxAbxsFgUSXIGp5m80E+wZhxGsxDXpul/GdJlQNWQ Pltw== X-Forwarded-Encrypted: i=1; AKwUvBwnGfGFvAfS1J1qHaTAeFdju155X7rpaLRkdf5UUi8gzcE3O/EhqFpeMahp0GXND1O//6bfLDU1qQVVSHo=@vger.kernel.org X-Gm-Message-State: AFuF++lfRW2GvD37P9DDk7hrtt0OyXhMSFx/PWZEE6C2LgPBhX4leJDU gg0auW/0Ge5Fa8OBkexkkyIrbk0OKVIoFpTS42qwMOJ49vEnUvg5caKT X-Gm-Gg: AYBFou2ax5sERcggozhn//37paCAeAxeQJIW/Rw9cgqJgAX7Eyhu3y7vSAOQd6ltHtC lfBA7ml4yMz8tBzRQaFH6kbDrP37sdbHlpLdX+Ud59v1fZRh0+DuxQKKveVKvsyT7ZacfmMkspl DihTBA8cRSnRtM3zy4Uv8Q8YCsx3UXswjYzmLxZd6wPTPREPpLayWsbbyvHIpxw4UIx4pwS8SFA W1ocJf/bK/pi5wKko1LJj1ybLRYkxlS9Ek/uU4PONyVXWCW8GQFrcwYL2UTVhjCqBoEowX8bbhd pjF8VgQR16o/tWKE4IvDl5pI7AdpvRH1xCvphCukZg9vFkInaQ85lqb9jxitv6So0qb3wvTomic 0mIsPPC6hXyI63J18RJKVgngIZA93DKWo619M7xJeI7TduidWl5kNl5XQOfQcoIMaLDO1T/X2vC XEzh6dXNJgyQ+EzdcflxGrwiw0zUAB6ypjT3kMuO7lFzI4cFfJk6/7vu/xf/97Fcgg9/0+hI4GF 4+m1/2Fg6C2qWzBW62duZ7zlVFaMzxgBbMsytTVZEHtPFupBvasgf/oNq6qxy9oIGqIncjKoGkg YHrrqa0mOvY3dnTFlh+HT4xAnXUU9/5TjAImW05gqBiMx7XwZq4pirpEY8mcwYOqUqGwo4CS6am MPV812E11BnJ93uoGfu+p2dzm3uATYg== X-Received: by 2002:a05:6820:1891:b0:6be:731b:5544 with SMTP id 006d021491bc7-6be731b5b5amr683141eaf.37.1788942670338; Wed, 09 Sep 2026 01:31:10 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:09 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:45 -0600 Subject: [PATCH v3 12/15] mtd: rawnand: sunxi: combine contiguous unprotected OOB reads Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-12-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The randomized-format OOB reader fetches each parity region and the unprotected tail separately. H6/H616 pack protected user data before the first ECC step, leaving a contiguous range of parity bytes and tail data. Combine adjacent parity regions without crossing protected user data, and include the tail in the final transfer. Keep software de-randomization separate so each ECC step and the tail retain their existing seed phases and PIO/DMA representations. The NAND operation parser splits transfers which exceed the controller SRAM size. This reduces column commands for OOB reads without changing erased-page classification, data-only reads or the plain-marker paths. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 6e54d3a92219..bbfed22640c8 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1412,15 +1412,28 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(st= ruct nand_chip *nand, int ret, i; =20 for (i =3D 0; i < ecc->steps; i++) { - len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); + len =3D 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 +=3D ecc->bytes; + i++; + } + if (i + 1 =3D=3D ecc->steps) + len =3D mtd->oobsize - off; + ret =3D nand_change_read_column_op(nand, mtd->writesize + off, - nand->oob_poi + off, - ecc->bytes, false); + nand->oob_poi + off, len, false); if (ret) return ret; - /* Preserve each path's normal representation of ECC bytes. */ - if (!dma) { + } + + /* Preserve each path's normal representation of ECC bytes. */ + if (!dma) { + for (i =3D 0; i < ecc->steps; i++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + off =3D sunxi_get_ecc_offset(sunxi_nand, ecc, i); state =3D sunxi_nfc_randomizer_state(nand, page, true); state =3D sunxi_nfc_randomizer_step(state, len * 8 + 15); sunxi_nfc_randomize_buf(state, nand->oob_poi + off, @@ -1431,10 +1444,6 @@ static int sunxi_nfc_hw_ecc_read_unprotected_oob(str= uct nand_chip *nand, off =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); len =3D mtd->oobsize - off; if (len) { - ret =3D nand_change_read_column_op(nand, mtd->writesize + off, - nand->oob_poi + off, len, false); - if (ret) - return ret; /* The unprotected tail uses the page seed and its 15-bit advance. */ state =3D sunxi_nfc_randomizer_state(nand, page, false); state =3D sunxi_nfc_randomizer_step(state, 15); --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A416B48E0DC for ; Wed, 9 Sep 2026 08:31:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942676; cv=none; b=BUYQneFg8qcD8lEfKAK1HuPjhEm2GVEGZ48bg0HdChg6uBFUX8cc3BvABNTGbPn9ZoSiHLiQgEvDR4WUN28aKQARtH22oPxE8ojzZ+8HCfLwnlChShuIgzuvG/2ffnxLO34LWH8OYLkST/P8NRPuke8PcrykFySuFCjshLqrmUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942676; c=relaxed/simple; bh=lMdcdhYtYCAbzv2Kq+ncTMrjUm4c2U4X65RY3mT9uRw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HFrHFpmJW7x8WH6DHi3ANkf3RyRachDwa8fi4u77icibtpWTLX49TaifZTq578f5xT6n/JXhZxOnfxQBoq5YKZ8T2YD7nrd53Br/Cq78lenSZk8pFGDsh1QqAS7jhEWt+2aY6+gu73/+XnOYzLqShUeI1gajp8zkvrP/SvA7Yv0= 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=RwAkivT8; arc=none smtp.client-ip=209.85.210.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RwAkivT8" Received: by mail-ot1-f44.google.com with SMTP id 46e09a7af769-7eb61bbeb25so5154650a34.1 for ; Wed, 09 Sep 2026 01:31:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942672; x=1789547472; darn=vger.kernel.org; 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=BAB7sP/kuv2a2+DjQqOPqA2dsbZemJ16Q3uUsVl6HgY=; b=RwAkivT8WZGrI3jUUHtZvljQkOwa61RJ6VAZuyKdKfo8S1yE947ejuUKCnO1WwQqfM 8xKZBYhzKYQx3ibcqnymJLRR1auWtzug8DmuW7n+A8ocwiUHQnhqSvW2vnbrwyuGHYUf vZBBhcSmQq2K5HKnrxlQrRQMGRuHVjWGTkytSEh6LUq+3sSu4VEf1P7NNMIFxo0rSO0O rLnOTDQdkTsg8797sk6y46tPRpKbZqnAbUvIL3npXjd/t/xwRwLkAM0PSNp995VtUg2F o0BOwSrSSzdW92biCyjGki2S7svi5lxqkPOtLPHpLHqIa7Ji0X0W7F1SoIPZHGeA+6Pw CteA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942672; x=1789547472; 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=BAB7sP/kuv2a2+DjQqOPqA2dsbZemJ16Q3uUsVl6HgY=; b=jRwBdZTQfBLWthe9HHmkDxhrp8dTGojDmfVQYgWkAEbkZLxgOZctHO99GmP8ieLhq+ NOpU/G1708dbuAVTbEsOjW6Ey4hVZq3Ra3hy96PyhFQN6Ke9NE7k9eeGOEdJMZM+aRiB vl6qn9RFdJoLLYpQsIJ6WEkem9/p1BDV/uNZz0bM+tZVJM+8WkeD42E2c/9apctTlVEX xzGWsoZ4pdIFjwMQnqbK8bmYXKARwk54YJcoeri84rUykIpxXeHCI54r+brCkcHQsvpE ybe3dqgCgvhJF25N/YJPjEucU2g+zYeZxp8jzJxdsTUoc4xc+IY8ylnWgYW4lfvJOQdu mPjw== X-Forwarded-Encrypted: i=1; AKwUvBwfPPQthbM9XOKs6hhQuKcpUaezmfcjsSIHvZE61vQ4EZGdYDBMVRCpru+Hc6jq3pPL1C8WGzR9qcyhhoU=@vger.kernel.org X-Gm-Message-State: AFuF++lqupzyaPk0DLEK9I+ntqBMl5y3wqnXY1h6W4/oP4XIBbDtAkqC kgc456sMhx0mff0yDCx8jlQLcH/5ar5G8f40B757jFhFSVTvbG95bGY8 X-Gm-Gg: AYBFou1syrspEMhYoOVT+oQLELNO+tDKVu6DDuYlv9r7v2Aj94hzFAN5aVQASZhMRUZ Ml6VUrq3l4EgTlJdn3KnN4Brw1zDcCJ3qNMQ9MD8uSZsmajC4qpRMSZmF3KgK69d9QzTQy2e0zY Un59Cp+7A2EgcFJRmXZxRHeqWx46tVj4PS9OMIMsKTG7uXWxfGruTl2xqr3h8fLyRyHVMRjIwbC e6EYoT455a1qMghBqh7ROKbZohgUnzzaPVAz4THY5LhOK5paxSgO6drIl6CRuDfKcDpSTkjTbZH BzIRtW7o1N2PV4jxoxPVXND7epMsA3CtvpOnE1W/DyRsa2pAgu8+oYmPvKADx0mOJr+LwDEa41V bioZjBDpafc7autnS1vZ5t7JGXN9lK0KXcB4QStOlLeh4oYJTyKHbhv8pJ46eQDq2zquo7PQQZ7 piXxgUO+h8RkM4egVmBB1QkYVzvsfoapiFp4vSHGa9OutIZ6GDB6lTToz5+Rj+HEyKj4eG8faMV 1HfCsZ+wkux0YFZ32j20DQJcNuxP1sDmSDVrIkgtgtZGllPr34+yxYDrcJn/kIWDpb1wrr1y+gv md+px5Rd1eXsz1Oy1hz41gki80H+z3v8Y1inUG+owUNo485ahEg7r6/xcHfXkP7FpkdEiOzQlnL 0ywlu6s20u4vwwP9YqbVaSOY1UuGUKw== X-Received: by 2002:a05:6820:f00e:b0:6b8:ef7d:e17e with SMTP id 006d021491bc7-6b8ef7de370mr14081411eaf.51.1788942671900; Wed, 09 Sep 2026 01:31:11 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:11 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:46 -0600 Subject: [PATCH v3 13/15] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-13-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The page helpers invoke exec_op(), which selects the chip and programs its timing and spare-area registers. Remove the identical setup directly before those helpers in the read callbacks and PIO write callbacks. Keep explicit selection in the DMA write callback: it accesses controller registers and prepares DMA before issuing the program-begin operation. Do not cache controller state or change selection after a controller reset. 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 bbfed22640c8..9dc742ee4344 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1743,8 +1743,6 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_chi= p *nand, uint8_t *buf, int ret, i, cur_off =3D 0; bool erased_chunk_found =3D false; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1793,8 +1791,6 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct nand= _chip *nand, u8 *buf, { int ret; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1823,8 +1819,6 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, if (sunxi_nand->randomized_oob) return sunxi_nfc_hw_ecc_read_page(nand, bufpoi, false, page); =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1865,8 +1859,6 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct n= and_chip *nand, if (to_sunxi_nand(nand)->randomized_oob) return sunxi_nfc_hw_ecc_read_page_dma(nand, buf, false, page); =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_read_page_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1890,8 +1882,6 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_ch= ip *nand, struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret =3D 0, i, cur_off =3D 0; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; @@ -1935,8 +1925,6 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand= _chip *nand, struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret =3D 0, i, cur_off =3D 0; =20 - sunxi_nfc_select_chip(nand, nand->cur_cs); - ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); if (ret) return ret; --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1BB57471CE9 for ; Wed, 9 Sep 2026 08:31:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942677; cv=none; b=ABdWeqH5BSQUcCqB/Cgs7hs3qhbXIVs+AdCneoT7dd+W6HUDJXHWD09M+dHoBtyYgQ6BORY5+o2eIIMbwcnwGUUcRGvz0TLhrLVy2zBZ3NdRKPDTvaF/1hLBC+dR81clwj/U94Vq5D9QAfYS7PQvl0lxheayNAt7lNL8V4skNZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942677; c=relaxed/simple; bh=4II9N3xTKSJHWx8rbwx7Teb5b9LWc1U4UIiXg8Tsx4o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=a7woq00Kq9zC5YGiap/1u8BcXfj51I2UZnNd9XU9Hz68ams9cpTIXHw29+lJZj2RrFIklQrQ8g/0cVjhorakRdpulmKozSVDcJnYjyyVL9O/ggjUZj4iWITNzJNYv7FNC0JcyiBpKWnkwo0XCWjyd20y+xNABLTBDoDF1rAdG88= 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=JhpXA2rt; arc=none smtp.client-ip=209.85.210.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JhpXA2rt" Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-7f4ea388ba6so5287884a34.0 for ; Wed, 09 Sep 2026 01:31:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942673; x=1789547473; darn=vger.kernel.org; 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=TWYxqME/J0ZGh+4rhdO4kodCM+OpkopMyyvvaFCYW7w=; b=JhpXA2rtfzsRRyt0KCXKZrkmkP9EbY2mnUQTNmOkw9NjASNOei0ZxmXB6Hx14Hd0dV AGyZJ2pR2oX1LqyQRUQulLT2O0PrKVTFb24XbSKzeaC7ytItlYobR8kfuJtME2rftxjF 6B2BnHckMM37eXofxYD5RQ+n4WPH//w6+7BJ9jH6GctoPqsT9W31PfoEUITUW5xMsSLB S0vMkzJ/j29/1ZNhXqbJHyJAfayfyFIuNs8mYCvuzUZgOD2Fgb4rYP9thEeleYhyR0VS TQ73bVOsLqyJ1vnSU9XWCPtopF7908YEHd+jerlolrnZeFvozoxgrOQKlVWwOGfFyiHz cqlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942673; x=1789547473; 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=TWYxqME/J0ZGh+4rhdO4kodCM+OpkopMyyvvaFCYW7w=; b=Xm7ALJfsfC4gb4ySmobj64LJ4xlqjEqaGm+KwGfdwU7K2CwhP3HoYQOC6mElhl5A8p SKayxQc9xYvf9WqAz3ZdqL1dP0xplzi7toPj3e+C0iMJxMuAg47KwzD8BYzHtrj+cQxg f9NtW+m2Ti1arNpvsMQKg4HA40eoGCRLj5XhdfdaPhjVNDyvUR307OfHanSdMNScZuqb YXOO/OrLssb3B8sa+ZD2Ek6tWwtytiwagiuFMnbjnbOw7vOZL/BjyYFngPRrKvmrzSj7 1VhdL28j6TSi7WmzCzpCc/Qk7pPFKLsDm+E+6rs2rSkK/r9g2UOj0hz1ssDOmNSUZNed F0fA== X-Forwarded-Encrypted: i=1; AKwUvBzeKr2yxmsRf+exWB9uiMzuu1X0mLfm6oJJ0WN1bDo4K8QwNlRYLFwcYYnRVU5uUnRaH578UFyjfxnAygM=@vger.kernel.org X-Gm-Message-State: AFuF++k/COZsoUnxJZN/BnudkEnEdXh0h29O9DzoCEICdu4bzum73xM4 85IPQZVIDEUv+X5rtnsioQG6lmkl26BTB84UTJ4OPgLXKIwRMoTVirjH X-Gm-Gg: AYBFou3+z6wDgUTnlpw/buOE65GSan52qCyQqZW2/xFF9y3/d1hJsHdBcKdW6rzyc2q 0ToOk1qI1V/j1iq2+M0VF4hOG82A4NyVC9/qlLlGw1+dfBY5B20PhRYRFSg3OJLeiF7+GR3PGVu ervYKJlrbP8cIpO+TlFQbPzMKiSppwN235C12B3sXe49nM8BVlUzwkbIH15BaD11DM59kNxROKQ A/8WVsCEisBrC3ALzT9mF+Z3VPb2ccYRHSkpOuC1dEt2ioHmbs2B47J/2oDGGhX82okSMMMP/kZ X2cdyZnWroaxhw4emDSuPi0QgIpHAHQW3hLHXZRw0ctb2gZXzFmy8bpELy5vth5Y9H8INPVfG31 yJ+sIF/CTWfglnt+E3QNF8qyg7PlnpoHgt8Ia0xU1ByY9KyxekbXhlMHuBfuGYjPDaGPc5I1iro OhQRTX4vrEL08+SV5bHqiZ+Dn32XKF40IlqVYwiZX0qBOIX1f1RYcQypFX4rCCB+mDLhQu+Wfk7 WHhlTTDct2VardOqjLqvXf+5NixwNsimtqRlmUoNxxbDKfETECI5TzoQQi2ZSRktXLqKQ7Dal7F om5cxGRWnOLZf/jEhWY11KQYGuunujbB7yXlXo45PJ7WfWpktgLCxbJdK8iK0G0LXSbmHmUee2/ tizjXXb8YUT6KO3lCugem+wzl6iBruVXpGwk6Uys= X-Received: by 2002:a05:6820:1987:b0:6b7:46fa:16a2 with SMTP id 006d021491bc7-6b746fa1a6bmr17306489eaf.55.1788942673434; Wed, 09 Sep 2026 01:31:13 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:12 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:47 -0600 Subject: [PATCH v3 14/15] mtd: rawnand: sunxi: reduce user-data length register accesses Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-14-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 DMA reads and writes clear every user-data length register and then read-modify-write one field at a time. Multiple ECC steps share each register, so this repeats MMIO accesses to the same words. Build each register value in memory and write it once, including zero lengths for unused slots. Reprogram every word for every DMA operation instead of caching hardware state, so controller resets and switches between chips need no special cache invalidation. Share the length encoding with a PIO-specific setter. PIO always uses hardware slot zero, and its page callbacks clear all length registers before the chunk loop. Write the slot-zero value directly instead of reading and modifying the same register for every chunk. Keep the per-operation clearing so other slots remain zero after DMA fallback. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 73 +++++++++++++++++++++++++----------= ---- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 9dc742ee4344..1c1fcea69108 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -996,35 +996,59 @@ static void sunxi_nfc_reset_user_data_len(struct sunx= i_nfc *nfc) writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i)); } =20 -static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int hw_step) +static int sunxi_nfc_user_data_len_code(struct sunxi_nfc *nfc, int len) { - bool found =3D false; - u32 val; int i; =20 + for (i =3D 0; i < nfc->caps->nuser_data_tab; i++) { + if (len =3D=3D 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; =20 - for (i =3D 0; i < nfc->caps->nuser_data_tab; i++) { - if (len =3D=3D nfc->caps->user_data_len_tab[i]) { - found =3D true; - break; - } - } - - if (!found) { - dev_warn(nfc->dev, - "Unsupported length for user data reg: %d\n", len); + code =3D sunxi_nfc_user_data_len_code(nfc, len); + if (code < 0) return; - } =20 - val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_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 nc= hunks) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + int first, step, len, code; + u32 val; + + if (!nfc->caps->reg_user_data_len) + return; =20 - val &=3D ~NFC_USER_DATA_LEN_MSK(hw_step); - val |=3D field_prep(NFC_USER_DATA_LEN_MSK(hw_step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, hw_step)); + /* Write each packed register once, including zeroes for unused slots. */ + for (first =3D 0; first < nfc->caps->max_ecc_steps; + first +=3D NFC_REG_USER_DATA_LEN_CAPACITY) { + val =3D 0; + for (step =3D first; step < nchunks && + step < first + NFC_REG_USER_DATA_LEN_CAPACITY; step++) { + len =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + code =3D sunxi_nfc_user_data_len_code(nfc, len); + if (code >=3D 0) + val |=3D field_prep(NFC_USER_DATA_LEN_MSK(step), code); + } + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, first)); + } } =20 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, @@ -1213,7 +1237,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, if (ret) return ret; =20 - sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); + 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, @@ -1524,9 +1548,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf return ret; =20 sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_reset_user_data_len(nfc); - for (i =3D 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_dma(nand, nchunks); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1682,7 +1704,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, hw_step); + sunxi_nfc_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); =20 @@ -1977,7 +1999,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, if (ret) goto pio_fallback; =20 - sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len_dma(nand, ecc->steps); for (i =3D 0; i < ecc->steps; i++) { unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); @@ -1985,7 +2007,6 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, =20 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page, user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 ret =3D nand_prog_page_begin_op(nand, page, 0, NULL, 0); --=20 2.53.0 From nobody Fri Sep 25 19:20:46 2026 Received: from mail-ot1-f45.google.com (mail-ot1-f45.google.com [209.85.210.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62B4E4915A7 for ; Wed, 9 Sep 2026 08:31:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942679; cv=none; b=OemhOqf68bJyKwZdGzcMrixI2AOb4MEeBxheIlTxeMxRt26PG5g5dhiZeemQJK6gmmEKm6fzVKtWJdv5bNILqgMg5YdmA2RHtfH0X+puIc9qBhLGFrmoeGOCe3TKYIEla0mitdbKc9v2+uYGdSCPhhWpvxCljZ8MR4f0SKKYHxY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788942679; c=relaxed/simple; bh=yZNKja0Z9caXLLme/IdLs4HeW5UUaQuGdtowtZBClj8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oJqWoFIjUMOXMlTulrsZSiwAWvDS2xiZ4VwLpoWqf9tRjL1LM7ptPY5U3HYb5BUln95lkct2SZ6txER9fce6Wi4vNBc1VA7Nxt65V/0/OrAkLBGaP0mfVwONLThY+Cinnk4vg6n4uKbxY5q+a/MRc3sWkQrD9N0iN7sI8pnQe+I= 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=Flr/SHl2; arc=none smtp.client-ip=209.85.210.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Flr/SHl2" Received: by mail-ot1-f45.google.com with SMTP id 46e09a7af769-7f18c0e03e3so2878122a34.2 for ; Wed, 09 Sep 2026 01:31:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788942675; x=1789547475; darn=vger.kernel.org; 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=ZVBoL4uLYSK7OhzJyk+4QlEDJCrYxUZn9Ns/nhu2ClA=; b=Flr/SHl2M1SFBg0eCriHLmwNe78GE5KmTbga2Wr0nHSEoUute9MZGPdCRbU1su/LI8 B2dzhXvJ2cIQJlkSIdvOfeNEHiP7+LtQrDIRIoSTeMWwFfsLlPhclrAy9jFLR1Dy9ijP xkQzwv/eO7DgjqsXqYTCfCnx8OhhnrHF+UTOIMoe9hDpc/uXwmJu5okVLz96d+geJV7p Qz9sHSMImXIP1t951RnDhgSUn5DFlxoBiQQys+gV7O8iBfab5b7i44o+ntucwNIhXZSr 0Le3iAoaBK/I/TnD85mVxjeSxnlqRFxEgzbETyPtAcVfJNaZ7cbD8iWNTzcUHCus/iS1 PDvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788942675; x=1789547475; 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=ZVBoL4uLYSK7OhzJyk+4QlEDJCrYxUZn9Ns/nhu2ClA=; b=aFC5rl3qyd6Q1PP/scFbp5sYqDa5p/fOuXeDvGonEQeY25egB5gn6kpEUA/fb7j+JO tEDla36M5WOVro1plTCa2wwEYRNvXE/680oHAjcQARuH2SEdTBMO/iIFqyIOflFjkOI1 gpmSRw3NNfAf1ZKw/LjqhPntl3mv5ffnxFqCxUciCFjVn37zr8Hd8YiIk5Q9u8TcqoqF YGy3tfswvxONaaQibE9soZOw2qskM84LJis082BryYiEDVS8UN0/j8jgrJ6ct7i+r0Fn Tz1ly2MMQ3o/i6dQp0vKBvfTblPiNpabhrkdzanSWXOhx4YadppduImEqIsiBqXuc2Gk EMwQ== X-Forwarded-Encrypted: i=1; AKwUvBwKbAWXuFrxt/IiWr46AePC4mS/g0OFaV1xxwYv2jLsKYxn6W6f7UUsKcKXvWAs7C8aFiph7SlJYYsJZzo=@vger.kernel.org X-Gm-Message-State: AFuF++khhhsxB9TE3iX1mN/lG7+6FscCiOl1VL2AcZqZReuO+ACXysnk qIlZGr2o0OETGsCT4EA7V4Ty3p2OMfu/3pMkZ1Mzkk2DdUHucbXnJGJ0 X-Gm-Gg: AYBFou3eywd17ShKpIYdxDRNBR+MpgcJdSZTTMi8fJXQ62glj6e9gEV8jd7+CoDbO0n JO0LVqvf4pE/Xsr3e8g/0c0Fm9z1VYoUdx/3pZpDv7kxy5pGsB7F7jLZNUAtQfiFBlqjjQDH1ut 1uIoRVW7e1qHAddm997ItKg8Zg3Z51l++Xkug/ymsdPdQFkp+m3+02SOam+VkI+P3d7QraSz8cd /MeGErP6rp6rD6AKBmSI1iFSfV9li3Khb/ufjygYDlMZOFlL0oyRYYzCCdNuZAFWybhDZjMkECq nGGeBL5F/DTkBjgSFnjpo6OwaBQ3yWHAuP/LOU/1SG+pn234PTzw31wsUMD2xFtPthkExxc/0Ud egIlDAqeSgyY2rrbw+grDtcyo/owXVYhTT+4THAOqpXSK7AoVg/P7qseM4x5VeDJKohrVINSebn oZgc2ZrE3mxhhPilt435W+JpHVVgxbVdpBBeJja7GJK+XEq7FKnoDEKs9hNBUNJmL3Fs3v8K79P vlPLTQ/yf8ZURG6f5EYjUmyzL0Q+bAFLcZ2ly7zeIwRRc+9nVcDWrGBAhAG7j06yRxvtt+AAW+Z S8PvpyxPEtKgp0Ope2O4r3P5djKJPypwOEqcM5UTtnhrS6GxWl7ML1+9THfM0Jao2y66Tcc96j9 XdCT9u8Re8oXaQJkZWsuX8T7oTmpAsj5NPeaWLzg5 X-Received: by 2002:a05:6820:1987:b0:6ae:a950:9faa with SMTP id 006d021491bc7-6b6faee2564mr17826769eaf.10.1788942675012; Wed, 09 Sep 2026 01:31:15 -0700 (PDT) Received: from [127.0.1.1] (184-96-151-165.hlrn.qwest.net. [184.96.151.165]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6b6dbedc6a0sm19031004eaf.5.2026.09.09.01.31.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2026 01:31:14 -0700 (PDT) From: James Hilliard Date: Wed, 09 Sep 2026 02:30:48 -0600 Subject: [PATCH v3 15/15] mtd: rawnand: sunxi: reuse ECC status within each DMA read Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-15-838cb0ba1547@gmail.com> References: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> In-Reply-To: <20260909-submit-sunxi-nand-vendor-oob-layout-v1-v3-0-838cb0ba1547@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Masahiro Yamada , Boris Brezillon , Brian Norris Cc: linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 The DMA completion loop reads the pattern ID repeatedly and reads the same packed error-counter word for each of its four ECC steps. Snapshot the completed operation status and pattern ID, and retain the last counter word while visiting consecutive DMA steps. Read counters only for steps which use them. Reuse the shared status register value on older controllers which place the pattern flags in its upper half. Keep the existing error and pattern priority in both the plain-marker and randomized-format paths. Start a fresh snapshot after every PIO ECC operation so reuse of hardware slot zero cannot reuse status from a previous step. The snapshot is local to one callback and does not survive controller resets or DMA-to-PIO retries. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 100 +++++++++++++++++++++++++---------= ---- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 1c1fcea69108..8710e91ffbaa 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1138,46 +1138,87 @@ struct sunxi_nfc_ecc_status { unsigned int max_bitflips; }; =20 +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 =3D to_sunxi_nfc(nand->controller); + u32 pattern_found; + + pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); + snapshot->pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern= _found); + if (nfc->caps->reg_pat_found =3D=3D NFC_REG_ECC_ST) + snapshot->status =3D pattern_found; + else + snapshot->status =3D readl(nfc->regs + NFC_REG_ECC_ST); + snapshot->pattern_id =3D 0; + if (snapshot->pattern_found && + (to_sunxi_nand(nand)->randomized_oob || + (snapshot->pattern_found & ~snapshot->status))) + snapshot->pattern_id =3D readl(nfc->regs + NFC_REG_PAT_ID(nfc)); + /* A new operation, including every PIO step, invalidates the count word.= */ + snapshot->count_reg =3D ~0U; +} + +static unsigned int +sunxi_nfc_hw_ecc_read_count(struct nand_chip *nand, + struct sunxi_nfc_ecc_snapshot *snapshot, int hw_step) +{ + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 reg =3D NFC_REG_ECC_ERR_CNT(nfc, hw_step); + + /* Four consecutive DMA steps share one error-counter register. */ + if (snapshot->count_reg !=3D reg) { + snapshot->count =3D readl(nfc->regs + reg); + snapshot->count_reg =3D reg; + } + + return NFC_ECC_ERR_CNT(hw_step, snapshot->count); +} + static void sunxi_nfc_hw_ecc_record_status(struct nand_chip *nand, struct sunxi_nfc_ecc_status *result, - int logical_step, int hw_step, u32 status, - u32 pattern_found) + int logical_step, int hw_step, + struct sunxi_nfc_ecc_snapshot *snapshot) { - struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); u32 count; =20 - if ((pattern_found & BIT(hw_step)) && - !(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step))) + if ((snapshot->pattern_found & BIT(hw_step)) && + !(snapshot->pattern_id & BIT(hw_step))) result->zero_steps |=3D BIT(logical_step); =20 - if (status & NFC_ECC_ERR(hw_step)) { + if (snapshot->status & NFC_ECC_ERR(hw_step)) { result->error_steps |=3D BIT(logical_step); return; } =20 - count =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); - count =3D NFC_ECC_ERR_CNT(hw_step, count); + count =3D sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); result->corrected +=3D count; result->max_bitflips =3D max(result->max_bitflips, count); } =20 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *= oob, - int hw_step, u32 status, u32 pattern_found, + int hw_step, struct sunxi_nfc_ecc_snapshot *snapshot, unsigned int user_data_sz, bool *erased) { - struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - u32 tmp; =20 *erased =3D false; =20 - if (status & NFC_ECC_ERR(hw_step)) + if (snapshot->status & NFC_ECC_ERR(hw_step)) return -EBADMSG; =20 - if (pattern_found & BIT(hw_step)) { + if (snapshot->pattern_found & BIT(hw_step)) { u8 pattern; =20 - if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & BIT(hw_step)))) { + if (unlikely(!(snapshot->pattern_id & BIT(hw_step)))) { pattern =3D 0x0; } else { pattern =3D 0xff; @@ -1193,9 +1234,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip = *nand, u8 *data, u8 *oob, return 0; } =20 - tmp =3D readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, hw_step)); - - return NFC_ECC_ERR_CNT(hw_step, tmp); + return sunxi_nfc_hw_ecc_read_count(nand, snapshot, hw_step); } =20 static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, @@ -1210,7 +1249,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, logical_= step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - u32 pattern_found; + struct sunxi_nfc_ecc_snapshot snapshot; bool bbm =3D !logical_step; bool erased; int ret, bitflips; @@ -1250,13 +1289,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, =20 *cur_off =3D oob_off + ecc->bytes + user_data_sz; =20 - pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); =20 if (sunxi_nand->randomized_oob) { sunxi_nfc_hw_ecc_record_status(nand, result, logical_step, hw_step, - readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found); + &snapshot); memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, hw_step, bbm, page, user_data_sz); @@ -1264,8 +1301,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, } =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NU= LL, - hw_step, readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, user_data_sz, &erased); + hw_step, &snapshot, user_data_sz, &erased); if (erased) return 1; =20 @@ -1530,13 +1566,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; struct sunxi_nfc_ecc_status result =3D {}; + struct sunxi_nfc_ecc_snapshot snapshot; unsigned int corrected =3D mtd->ecc_stats.corrected; unsigned int failed =3D mtd->ecc_stats.failed; unsigned int max_bitflips =3D 0; bool erased_chunk_found =3D false; int ret, i; struct scatterlist sg; - u32 status, pattern_found, wait; + u32 wait; =20 ret =3D sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1577,9 +1614,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf if (ret) return ret; =20 - status =3D readl(nfc->regs + NFC_REG_ECC_ST); - pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); - pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); + sunxi_nfc_hw_ecc_read_status(nand, &snapshot); =20 for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; @@ -1591,8 +1626,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf int bitflips; =20 if (sunxi_nand->randomized_oob) { - sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, status, - pattern_found); + sunxi_nfc_hw_ecc_record_status(nand, &result, i, i, &snapshot); sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, page, user_data_sz); continue; @@ -1600,7 +1634,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf =20 bitflips =3D sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL, oob_required ? oob : NULL, - i, status, pattern_found, + i, &snapshot, user_data_sz, &erased); =20 /* ECC errors are handled in the second loop. */ @@ -1629,7 +1663,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf return sunxi_nfc_hw_ecc_finish_randomized_read(nand, buf, &result, oob_required, true, page); =20 - if (status & NFC_ECC_ERR_MSK(nfc)) { + if (snapshot.status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); @@ -1637,7 +1671,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 - if (!(status & NFC_ECC_ERR(i))) + if (!(snapshot.status & NFC_ECC_ERR(i))) continue; =20 ret =3D sunxi_nfc_hw_ecc_read_error(nand, data, data_off, oob, --=20 2.53.0