[openwrt/openwrt] kernel: QCOM SPI NAND: backport multiple fixes

LEDE Commits lede-commits at lists.infradead.org
Sun Jan 4 15:24:51 PST 2026


hauke pushed a commit to openwrt/openwrt.git, branch openwrt-25.12:
https://git.openwrt.org/a78f0078c49ac90df4a274696df4ffd6c23cac0e

commit a78f0078c49ac90df4a274696df4ffd6c23cac0e
Author: Hauke Mehrtens <hauke at hauke-m.de>
AuthorDate: Thu Jan 1 19:40:06 2026 +0100

    kernel: QCOM SPI NAND: backport multiple fixes
    
    These patches fix bugs in a patch we backported.
    
    These patch were cherry picked from upstream Linux because it references
    a patch we backported in the fixes tag.
    
    The patches were reordered to match the ordering in the upstream Linux kernel.
    
    Fixes: 93173aee96e7 ("qualcommbe: ipq95xx: Add initial support for new target")
    Link: https://github.com/openwrt/openwrt/pull/21366
    (cherry picked from commit 5230157a165aa513416de7e959d315301e06a0a3)
    Link: https://github.com/openwrt/openwrt/pull/21390
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 ...op-explicit-test-for-built-in-CONFIG_SPI_.patch |  37 +++++++
 ...lidate-user-chip-specific-ECC-properties.patch} |   0
 ...i-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch | 113 +++++++++++++++++++++
 ...pi-qpic-snand-reallocate-BAM-transactions.patch |  81 +++++++++++++++
 ...i-spi-qpic-snand-don-t-hardcode-ECC-steps.patch |  31 ++++++
 ...c-common-add-defines-for-ECC_MODE-values.patch} |   2 +-
 ...nand-add-support-for-8-bits-ECC-strength.patch} |   2 +-
 ...c-snand-use-correct-CW_PER_PAGE-value-for.patch |  56 ++++++++++
 ...c-snand-fix-calculating-of-ECC-OOB-region.patch |  69 +++++++++++++
 ...c-snand-unregister-ECC-engine-on-probe-er.patch |  48 +++++++++
 .../generic/hack-6.12/430-mtk-bmt-support.patch    |   4 +-
 ...1-spi-spi-qpic-snand-default-to-4-bit-ECC.patch |   2 +-
 ...021-v6.18-mtd-nand-add-realtek-ecc-engine.patch |   2 +-
 13 files changed, 441 insertions(+), 6 deletions(-)

diff --git a/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch b/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch
new file mode 100644
index 0000000000..8019d2ccac
--- /dev/null
+++ b/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch
@@ -0,0 +1,37 @@
+From 36c6468724aa98d33fea9a1d7e07ddda6302f5d4 Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas at glider.be>
+Date: Fri, 28 Mar 2025 09:24:01 +0100
+Subject: mtd: nand: Drop explicit test for built-in CONFIG_SPI_QPIC_SNAND
+
+If CONFIG_SPI_QPIC_SNAND=m, but CONFIG_MTD_NAND_QCOM=n:
+
+    ERROR: modpost: "qcom_nandc_unalloc" [drivers/spi/spi-qpic-snand.ko] undefined!
+    ...
+
+Fix this by dropping the explicit test for a built-in
+CONFIG_SPI_QPIC_SNAND completely.  Kbuild handles multiple and mixed
+obj-y/obj-m rules for the same object file fine.
+
+Reported-by: kernel test robot <lkp at intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202503280759.XhwLcV7m-lkp@intel.com/
+Fixes: 7304d1909080ef0c ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ drivers/mtd/nand/Makefile | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -3,11 +3,8 @@
+ nandcore-objs := core.o bbt.o
+ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
+ obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
+-ifeq ($(CONFIG_SPI_QPIC_SNAND),y)
+ obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o
+-else
+ obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o
+-endif
+ obj-y	+= onenand/
+ obj-y	+= raw/
+ obj-y	+= spi/
diff --git a/target/linux/generic/backport-6.12/421-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch b/target/linux/generic/backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch
similarity index 100%
rename from target/linux/generic/backport-6.12/421-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch
rename to target/linux/generic/backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch
diff --git a/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch b/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch
new file mode 100644
index 0000000000..10c1651b3b
--- /dev/null
+++ b/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch
@@ -0,0 +1,113 @@
+From 2abf107dcd797c60c86e9f17319cd1658862f6b2 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Thu, 15 May 2025 20:58:05 +0200
+Subject: spi: spi-qpic-snand: use CW_PER_PAGE_MASK bitmask
+
+Change the code to use the already defined CW_PER_PAGE_MASK
+bitmask along with the FIELD_PREP() macro instead of using
+magic values.
+
+This makes the code more readable. It also syncs the affected
+codes with their counterparts in the 'qcom_nandc' driver, so it
+makes it easier to spot the differences between the two
+implementations.
+
+No functional changes intended.
+
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Reviewed-by: Md Sadre Alam <quic_mdalam at quicinc.com>
+Link: https://patch.msgid.link/20250515-qpic-snand-use-bitmasks-v1-1-11729aeae73b@gmail.com
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -483,7 +483,8 @@ static int qcom_spi_block_erase(struct q
+ 	snandc->regs->cmd = snandc->qspi->cmd;
+ 	snandc->regs->addr0 = snandc->qspi->addr1;
+ 	snandc->regs->addr1 = snandc->qspi->addr2;
+-	snandc->regs->cfg0 = cpu_to_le32(ecc_cfg->cfg0_raw & ~(7 << CW_PER_PAGE));
++	snandc->regs->cfg0 = cpu_to_le32((ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) |
++					 FIELD_PREP(CW_PER_PAGE_MASK, 0));
+ 	snandc->regs->cfg1 = cpu_to_le32(ecc_cfg->cfg1_raw);
+ 	snandc->regs->exec = cpu_to_le32(1);
+ 
+@@ -544,8 +545,8 @@ static int qcom_spi_read_last_cw(struct
+ 	snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col));
+ 	snandc->regs->addr1 = snandc->qspi->addr2;
+ 
+-	cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) |
+-		0 << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, 0);
+ 	cfg1 = ecc_cfg->cfg1_raw;
+ 	ecc_bch_cfg = ECC_CFG_ECC_DISABLE;
+ 
+@@ -687,8 +688,8 @@ static int qcom_spi_read_cw_raw(struct q
+ 	qcom_clear_bam_transaction(snandc);
+ 	raw_cw = num_cw - 1;
+ 
+-	cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) |
+-				0 << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, 0);
+ 	cfg1 = ecc_cfg->cfg1_raw;
+ 	ecc_bch_cfg = ECC_CFG_ECC_DISABLE;
+ 
+@@ -808,8 +809,8 @@ static int qcom_spi_read_page_ecc(struct
+ 	snandc->buf_start = 0;
+ 	qcom_clear_read_regs(snandc);
+ 
+-	cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) |
+-				(num_cw - 1) << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
+ 	cfg1 = ecc_cfg->cfg1;
+ 	ecc_bch_cfg = ecc_cfg->ecc_bch_cfg;
+ 
+@@ -904,8 +905,8 @@ static int qcom_spi_read_page_oob(struct
+ 	qcom_clear_read_regs(snandc);
+ 	qcom_clear_bam_transaction(snandc);
+ 
+-	cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) |
+-				(num_cw - 1) << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
+ 	cfg1 = ecc_cfg->cfg1;
+ 	ecc_bch_cfg = ecc_cfg->ecc_bch_cfg;
+ 
+@@ -1015,8 +1016,8 @@ static int qcom_spi_program_raw(struct q
+ 	int num_cw = snandc->qspi->num_cw;
+ 	u32 cfg0, cfg1, ecc_bch_cfg;
+ 
+-	cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) |
+-			(num_cw - 1) << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
+ 	cfg1 = ecc_cfg->cfg1_raw;
+ 	ecc_bch_cfg = ECC_CFG_ECC_DISABLE;
+ 
+@@ -1098,8 +1099,8 @@ static int qcom_spi_program_ecc(struct q
+ 	int num_cw = snandc->qspi->num_cw;
+ 	u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg;
+ 
+-	cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) |
+-				(num_cw - 1) << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
+ 	cfg1 = ecc_cfg->cfg1;
+ 	ecc_bch_cfg = ecc_cfg->ecc_bch_cfg;
+ 	ecc_buf_cfg = ecc_cfg->ecc_buf_cfg;
+@@ -1175,8 +1176,8 @@ static int qcom_spi_program_oob(struct q
+ 	int num_cw = snandc->qspi->num_cw;
+ 	u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg;
+ 
+-	cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) |
+-				(num_cw - 1) << CW_PER_PAGE;
++	cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) |
++	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
+ 	cfg1 = ecc_cfg->cfg1;
+ 	ecc_bch_cfg = ecc_cfg->ecc_bch_cfg;
+ 	ecc_buf_cfg = ecc_cfg->ecc_buf_cfg;
diff --git a/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch b/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch
new file mode 100644
index 0000000000..6d61016556
--- /dev/null
+++ b/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch
@@ -0,0 +1,81 @@
+From d85d0380292a7e618915069c3579ae23c7c80339 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Wed, 18 Jun 2025 22:22:49 +0200
+Subject: spi: spi-qpic-snand: reallocate BAM transactions
+
+Using the mtd_nandbiterrs module for testing the driver occasionally
+results in weird things like below.
+
+1. swiotlb mapping fails with the following message:
+
+  [   85.926216] qcom_snand 79b0000.spi: swiotlb buffer is full (sz: 4294967294 bytes), total 512 (slots), used 0 (slots)
+  [   85.932937] qcom_snand 79b0000.spi: failure in mapping desc
+  [   87.999314] qcom_snand 79b0000.spi: failure to write raw page
+  [   87.999352] mtd_nandbiterrs: error: write_oob failed (-110)
+
+  Rebooting the board after this causes a panic due to a NULL pointer
+  dereference.
+
+2. If the swiotlb mapping does not fail, rebooting the board may result
+   in a different panic due to a bad spinlock magic:
+
+  [  256.104459] BUG: spinlock bad magic on CPU#3, procd/2241
+  [  256.104488] Unable to handle kernel paging request at virtual address ffffffff0000049b
+  ...
+
+Investigating the issue revealed that these symptoms are results of
+memory corruption which is caused by out of bounds access within the
+driver.
+
+The driver uses a dynamically allocated structure for BAM transactions,
+which structure must have enough space for all possible variations of
+different flash operations initiated by the driver. The required space
+heavily depends on the actual number of 'codewords' which is calculated
+from the pagesize of the actual NAND chip.
+
+Although the qcom_nandc_alloc() function allocates memory for the BAM
+transactions during probe, but since the actual number of 'codewords'
+is not yet know the allocation is done for one 'codeword' only.
+
+Because of this, whenever the driver does a flash operation, and the
+number of the required transactions exceeds the size of the allocated
+arrays the driver accesses memory out of the allocated range.
+
+To avoid this, change the code to free the initially allocated BAM
+transactions memory, and allocate a new one once the actual number of
+'codewords' required for a given NAND chip is known.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Reviewed-by: Md Sadre Alam <quic_mdalam at quicinc.com>
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Link: https://patch.msgid.link/20250618-qpic-snand-avoid-mem-corruption-v3-1-319c71296cda@gmail.com
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -315,6 +315,22 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ 
+ 	mtd_set_ooblayout(mtd, &qcom_spi_ooblayout);
+ 
++	/*
++	 * Free the temporary BAM transaction allocated initially by
++	 * qcom_nandc_alloc(), and allocate a new one based on the
++	 * updated max_cwperpage value.
++	 */
++	qcom_free_bam_transaction(snandc);
++
++	snandc->max_cwperpage = cwperpage;
++
++	snandc->bam_txn = qcom_alloc_bam_transaction(snandc);
++	if (!snandc->bam_txn) {
++		dev_err(snandc->dev, "failed to allocate BAM transaction\n");
++		ret = -ENOMEM;
++		goto err_free_ecc_cfg;
++	}
++
+ 	ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) |
+ 			FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) |
+ 			FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) |
diff --git a/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch b/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch
new file mode 100644
index 0000000000..eab7b792aa
--- /dev/null
+++ b/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch
@@ -0,0 +1,31 @@
+From f820034864dd463cdcd2bebe7940f2eca0eb4223 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Wed, 23 Jul 2025 10:06:43 +0200
+Subject: spi: spi-qpic-snand: don't hardcode ECC steps
+
+NAND devices with different page sizes requires different number
+of ECC steps, yet the qcom_spi_ecc_init_ctx_pipelined() function
+sets 4 steps in 'ecc_cfg' unconditionally.
+
+The correct number of the steps is calculated earlier in the
+function already, so use that instead of the hardcoded value.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Link: https://patch.msgid.link/20250723-qpic-snand-fix-steps-v1-1-d800695dde4c@gmail.com
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -308,7 +308,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ 	ecc_cfg->bch_enabled = true;
+ 	ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
+ 
+-	ecc_cfg->steps = 4;
++	ecc_cfg->steps = cwperpage;
+ 	ecc_cfg->cw_data = 516;
+ 	ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes;
+ 	bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1;
diff --git a/target/linux/generic/backport-6.12/426-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch b/target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch
similarity index 97%
rename from target/linux/generic/backport-6.12/426-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch
rename to target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch
index c232410549..7ddf15ef70 100644
--- a/target/linux/generic/backport-6.12/426-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch
+++ b/target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch
@@ -52,7 +52,7 @@ Signed-off-by: Mark Brown <broonie at kernel.org>
  				host->ecc_bytes_hw = 8;
 --- a/drivers/spi/spi-qpic-snand.c
 +++ b/drivers/spi/spi-qpic-snand.c
-@@ -349,7 +349,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+@@ -365,7 +365,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
  			       FIELD_PREP(ECC_SW_RESET, 0) |
  			       FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
  			       FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
diff --git a/target/linux/generic/backport-6.12/427-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch b/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch
similarity index 97%
rename from target/linux/generic/backport-6.12/427-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch
rename to target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch
index acf5d603b6..4eff84f419 100644
--- a/target/linux/generic/backport-6.12/427-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch
+++ b/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch
@@ -55,7 +55,7 @@ Signed-off-by: Mark Brown <broonie at kernel.org>
  	ecc_cfg->bbm_size = 1;
  	ecc_cfg->bch_enabled = true;
  	ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
-@@ -349,7 +360,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+@@ -365,7 +376,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
  			       FIELD_PREP(ECC_SW_RESET, 0) |
  			       FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
  			       FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
diff --git a/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch b/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch
new file mode 100644
index 0000000000..b67645e07c
--- /dev/null
+++ b/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch
@@ -0,0 +1,56 @@
+From 6bc829220b33da8522572cc50fdf5067c51d3bf3 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Fri, 1 Aug 2025 09:58:35 +0200
+Subject: spi: spi-qpic-snand: use correct CW_PER_PAGE value for OOB write
+
+The qcom_spi_program_oob() function uses only the last codeword to write
+the OOB data into the flash, but it sets the CW_PER_PAGE field in the
+CFG0 register as it would use all codewords.
+
+It seems that this confuses the hardware somehow, and any access to the
+flash fails with a timeout error after the function is called. The problem
+can be easily reproduced with the following commands:
+
+    # dd if=/dev/zero bs=2176 count=1 > /tmp/test.bin
+    1+0 records in
+    1+0 records out
+    # flash_erase /dev/mtd4 0 0
+    Erasing 128 Kibyte @ 0 -- 100 % complete
+    # nandwrite -O /dev/mtd4 /tmp/test.bin
+    Writing data to block 0 at offset 0x0
+    # nanddump -o /dev/mtd4 >/dev/null
+    ECC failed: 0
+    ECC corrected: 0
+    Number of bad blocks: 0
+    Number of bbt blocks: 0
+    Block size 131072, page size 2048, OOB size 128
+    Dumping data starting at 0x00000000 and ending at 0x00020000...
+    [   33.197605] qcom_snand 79b0000.spi: failure to read oob
+    libmtd: error!: MEMREADOOB64 ioctl failed for mtd4, offset 0 (eraseblock 0)
+            error 110 (Operation timed out)
+    [   35.277582] qcom_snand 79b0000.spi: failure in submitting cmd descriptor
+    libmtd: error!: cannot read 2048 bytes from mtd4 (eraseblock 0, offset 2048)
+            error 110 (Operation timed out)
+    nanddump: error!: mtd_read
+
+Change the code to use the correct CW_PER_PAGE value to avoid this.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Link: https://patch.msgid.link/20250801-qpic-snand-oob-cwpp-fix-v1-1-f5a41b86af2e@gmail.com
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -1204,7 +1204,7 @@ static int qcom_spi_program_oob(struct q
+ 	u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg;
+ 
+ 	cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) |
+-	       FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1);
++	       FIELD_PREP(CW_PER_PAGE_MASK, 0);
+ 	cfg1 = ecc_cfg->cfg1;
+ 	ecc_bch_cfg = ecc_cfg->ecc_bch_cfg;
+ 	ecc_buf_cfg = ecc_cfg->ecc_buf_cfg;
diff --git a/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch b/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch
new file mode 100644
index 0000000000..35d5d30232
--- /dev/null
+++ b/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch
@@ -0,0 +1,69 @@
+From 13d0fe84a214658254a7412b2b46ec1507dc51f0 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Tue, 5 Aug 2025 18:05:42 +0200
+Subject: spi: spi-qpic-snand: fix calculating of ECC OOB regions' properties
+
+The OOB layout used by the driver has two distinct regions which contains
+hardware specific ECC data, yet the qcom_spi_ooblayout_ecc() function sets
+the same offset and length values for both regions which is clearly wrong.
+
+Change the code to calculate the correct values for both regions.
+
+For reference, the following table shows the computed offset and length
+values for various OOB size/ECC strength configurations:
+
+                              +-----------------+-----------------+
+                              |before the change| after the change|
+  +-------+----------+--------+--------+--------+--------+--------+
+  |  OOB  |   ECC    | region | region | region | region | region |
+  |  size | strength | index  | offset | length | offset | length |
+  +-------+----------+--------+--------+--------+--------+--------+
+  |  128  |     8    |    0   |   113  |   15   |    0   |   49   |
+  |       |          |    1   |   113  |   15   |   65   |   63   |
+  +-------+----------+--------+--------+--------+--------+--------+
+  |  128  |     4    |    0   |   117  |   11   |    0   |   37   |
+  |       |          |    1   |   117  |   11   |   53   |   75   |
+  +-------+----------+--------+--------+--------+--------+--------+
+  |   64  |     4    |    0   |    53  |   11   |    0   |   37   |
+  |       |          |    1   |    53  |   11   |   53   |   11   |
+  +-------+----------+--------+--------+--------+--------+--------+
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
+Link: https://patch.msgid.link/20250805-qpic-snand-oob-ecc-fix-v2-1-e6f811c70d6f@gmail.com
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -216,13 +216,21 @@ static int qcom_spi_ooblayout_ecc(struct
+ 	struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand);
+ 	struct qpic_ecc *qecc = snandc->qspi->ecc;
+ 
+-	if (section > 1)
+-		return -ERANGE;
++	switch (section) {
++	case 0:
++		oobregion->offset = 0;
++		oobregion->length = qecc->bytes * (qecc->steps - 1) +
++				    qecc->bbm_size;
++		return 0;
++	case 1:
++		oobregion->offset = qecc->bytes * (qecc->steps - 1) +
++				    qecc->bbm_size +
++				    qecc->steps * 4;
++		oobregion->length = mtd->oobsize - oobregion->offset;
++		return 0;
++	}
+ 
+-	oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes;
+-	oobregion->offset = mtd->oobsize - oobregion->length;
+-
+-	return 0;
++	return -ERANGE;
+ }
+ 
+ static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section,
diff --git a/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch b/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch
new file mode 100644
index 0000000000..46184b53c5
--- /dev/null
+++ b/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch
@@ -0,0 +1,48 @@
+From 1991a458528588ff34e98b6365362560d208710f Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7 at gmail.com>
+Date: Wed, 3 Sep 2025 13:56:24 +0200
+Subject: spi: spi-qpic-snand: unregister ECC engine on probe error and device
+ remove
+
+The on-host hardware ECC engine remains registered both when
+the spi_register_controller() function returns with an error
+and also on device removal.
+
+Change the qcom_spi_probe() function to unregister the engine
+on the error path, and add the missing unregistering call to
+qcom_spi_remove() to avoid possible use-after-free issues.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7 at gmail.com>
+Message-ID: <20250903-qpic-snand-unregister-ecceng-v1-1-ef5387b0abdc at gmail.com>
+Signed-off-by: Mark Brown <broonie at kernel.org>
+---
+ drivers/spi/spi-qpic-snand.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -1632,11 +1632,13 @@ static int qcom_spi_probe(struct platfor
+ 	ret = spi_register_controller(ctlr);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "spi_register_controller failed.\n");
+-		goto err_spi_init;
++		goto err_register_controller;
+ 	}
+ 
+ 	return 0;
+ 
++err_register_controller:
++	nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng);
+ err_spi_init:
+ 	qcom_nandc_unalloc(snandc);
+ err_snand_alloc:
+@@ -1658,7 +1660,7 @@ static void qcom_spi_remove(struct platf
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 
+ 	spi_unregister_controller(ctlr);
+-
++	nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng);
+ 	qcom_nandc_unalloc(snandc);
+ 
+ 	clk_disable_unprepare(snandc->aon_clk);
diff --git a/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch b/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch
index 90b5a64b51..8d1c16503f 100644
--- a/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch
+++ b/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch
@@ -28,6 +28,6 @@ Subject: [PATCH] mtd/nand: add MediaTek NAND bad block managment table
  obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
  obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
 +obj-$(CONFIG_MTD_NAND_MTK_BMT)	+= mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o
- ifeq ($(CONFIG_SPI_QPIC_SNAND),y)
  obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o
- else
+ obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o
+ obj-y	+= onenand/
diff --git a/target/linux/qualcommax/patches-6.12/0401-spi-spi-qpic-snand-default-to-4-bit-ECC.patch b/target/linux/qualcommax/patches-6.12/0401-spi-spi-qpic-snand-default-to-4-bit-ECC.patch
index d9e64ef32b..156d4118c7 100644
--- a/target/linux/qualcommax/patches-6.12/0401-spi-spi-qpic-snand-default-to-4-bit-ECC.patch
+++ b/target/linux/qualcommax/patches-6.12/0401-spi-spi-qpic-snand-default-to-4-bit-ECC.patch
@@ -19,7 +19,7 @@ Signed-off-by: Robert Marko <robimarko at gmail.com>
 
 --- a/drivers/spi/spi-qpic-snand.c
 +++ b/drivers/spi/spi-qpic-snand.c
-@@ -296,6 +296,24 @@ static int qcom_spi_ecc_init_ctx_pipelin
+@@ -304,6 +304,24 @@ static int qcom_spi_ecc_init_ctx_pipelin
  		ecc_cfg->spare_bytes = 2;
  		break;
  
diff --git a/target/linux/realtek/patches-6.12/021-v6.18-mtd-nand-add-realtek-ecc-engine.patch b/target/linux/realtek/patches-6.12/021-v6.18-mtd-nand-add-realtek-ecc-engine.patch
index 17c63fcdcb..7c7811e707 100644
--- a/target/linux/realtek/patches-6.12/021-v6.18-mtd-nand-add-realtek-ecc-engine.patch
+++ b/target/linux/realtek/patches-6.12/021-v6.18-mtd-nand-add-realtek-ecc-engine.patch
@@ -51,7 +51,7 @@ Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 +obj-$(CONFIG_MTD_NAND_ECC_REALTEK) += ecc-realtek.o
  obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
  obj-$(CONFIG_MTD_NAND_MTK_BMT)	+= mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o
- ifeq ($(CONFIG_SPI_QPIC_SNAND),y)
+ obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o
 --- /dev/null
 +++ b/drivers/mtd/nand/ecc-realtek.c
 @@ -0,0 +1,464 @@




More information about the lede-commits mailing list