From 5230157a165aa513416de7e959d315301e06a0a3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 1 Jan 2026 19:40:06 +0100 Subject: [PATCH] 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 Signed-off-by: Hauke Mehrtens --- ...plicit-test-for-built-in-CONFIG_SPI_.patch | 37 ++++++ ...e-user-chip-specific-ECC-properties.patch} | 0 ...c-snand-use-CW_PER_PAGE_MASK-bitmask.patch | 113 ++++++++++++++++++ ...ic-snand-reallocate-BAM-transactions.patch | 81 +++++++++++++ ...-qpic-snand-don-t-hardcode-ECC-steps.patch | 31 +++++ ...mon-add-defines-for-ECC_MODE-values.patch} | 2 +- ...add-support-for-8-bits-ECC-strength.patch} | 2 +- ...nd-use-correct-CW_PER_PAGE-value-for.patch | 56 +++++++++ ...nd-fix-calculating-of-ECC-OOB-region.patch | 69 +++++++++++ ...nd-unregister-ECC-engine-on-probe-er.patch | 48 ++++++++ .../hack-6.12/430-mtk-bmt-support.patch | 4 +- ...-spi-qpic-snand-default-to-4-bit-ECC.patch | 2 +- ...6.18-mtd-nand-add-realtek-ecc-engine.patch | 2 +- 13 files changed, 441 insertions(+), 6 deletions(-) create mode 100644 target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch rename target/linux/generic/backport-6.12/{421-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch => 412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch} (100%) create mode 100644 target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch create mode 100644 target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch create mode 100644 target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch rename target/linux/generic/backport-6.12/{426-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch => 416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch} (97%) rename target/linux/generic/backport-6.12/{427-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch => 417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch} (97%) create mode 100644 target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch create mode 100644 target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch create mode 100644 target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch 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 00000000000..8019d2ccaca --- /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 +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 +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 +Signed-off-by: Miquel Raynal +--- + 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 00000000000..10c1651b3b1 --- /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 +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 +Reviewed-by: Md Sadre Alam +Link: https://patch.msgid.link/20250515-qpic-snand-use-bitmasks-v1-1-11729aeae73b@gmail.com +Signed-off-by: Mark Brown +--- + 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 00000000000..6d610165566 --- /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 +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 +Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250618-qpic-snand-avoid-mem-corruption-v3-1-319c71296cda@gmail.com +Signed-off-by: Mark Brown +--- + 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 00000000000..eab7b792aad --- /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 +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 +Link: https://patch.msgid.link/20250723-qpic-snand-fix-steps-v1-1-d800695dde4c@gmail.com +Signed-off-by: Mark Brown +--- + 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 c2324105498..7ddf15ef706 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 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 acf5d603b6f..4eff84f4197 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 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 00000000000..b67645e07cf --- /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 +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 +Link: https://patch.msgid.link/20250801-qpic-snand-oob-cwpp-fix-v1-1-f5a41b86af2e@gmail.com +Signed-off-by: Mark Brown +--- + 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 00000000000..35d5d302323 --- /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 +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 +Reviewed-by: Konrad Dybcio +Link: https://patch.msgid.link/20250805-qpic-snand-oob-ecc-fix-v2-1-e6f811c70d6f@gmail.com +Signed-off-by: Mark Brown +--- + 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 00000000000..46184b53c5c --- /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 +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 +Message-ID: <20250903-qpic-snand-unregister-ecceng-v1-1-ef5387b0abdc@gmail.com> +Signed-off-by: Mark Brown +--- + 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 90b5a64b51b..8d1c16503f3 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 d9e64ef32ba..156d4118c76 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 --- 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 17c63fcdcb0..7c7811e7072 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 +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 @@ -- 2.47.3