summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-09-17 16:24:31 +0100
committerMark Brown <broonie@kernel.org>2026-09-17 16:24:31 +0100
commitca01ebd9e2ed0ea7ed4a068bcd666b0f394581ac (patch)
tree4e01c4d37fda32cec54c2e30f734feeb0ad41068
parent333c6f61629bff9921813208f1a92f9ba845abdd (diff)
parent8d691164547832f43289a7d5f3450738ead98c2d (diff)
downloadlinux-next-ca01ebd9e2ed0ea7ed4a068bcd666b0f394581ac.tar.gz
linux-next-ca01ebd9e2ed0ea7ed4a068bcd666b0f394581ac.zip
spi: spi-qpic-snand: fix the stale ECC context pointer
Johan Alvarado <contact@c127.dev> says: qcom_spi_ecc_init_ctx_pipelined() installs the ooblayout but never publishes the ECC context it allocates, so qcom_spi_ooblayout_ecc() and qcom_spi_ooblayout_free() run against a pointer that describes something else - a zeroed struct on a first probe, the previous attempt's freed context on a retry. On IPQ5018 the qcom,smem-part parser makes that retry routine, and like half the boots on a Mercusys MR80X failed to mount the rootfs. Patch 1 is the fix and is unchanged from v1. Patch 2 removes what becomes redundant once the context is published. It is a cleanup with no functional change, so it carries no Fixes: tag and is not marked for stable. Patch 1 was applied to mtd/fixes as 93bc7c4d2f41 on 2026-09-04 and dropped the same day, so nothing from this series is queued. Link: https://patch.msgid.link/20260911184416.109790-1-contact@c127.dev
-rw-r--r--drivers/spi/spi-qpic-snand.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c
index abb1015073ec..9e626ffbe63a 100644
--- a/drivers/spi/spi-qpic-snand.c
+++ b/drivers/spi/spi-qpic-snand.c
@@ -411,6 +411,8 @@ static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand)
dev_dbg(snandc->dev, "ECC strength: %u bits per %u bytes\n",
ecc_cfg->strength, ecc_cfg->step_size);
+ snandc->qspi->ecc = ecc_cfg;
+
return 0;
err_free_ecc_cfg:
@@ -427,6 +429,7 @@ static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand)
kfree(snandc->qspi->oob_buf);
snandc->qspi->oob_buf = NULL;
+ snandc->qspi->ecc = NULL;
kfree(ecc_cfg);
}
@@ -434,9 +437,7 @@ static int qcom_spi_ecc_prepare_io_req_pipelined(struct nand_device *nand,
struct nand_page_io_req *req)
{
struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand);
- struct qpic_ecc *ecc_cfg = nand_to_ecc_ctx(nand);
- snandc->qspi->ecc = ecc_cfg;
snandc->qspi->raw_rw = false;
snandc->qspi->oob_rw = false;
snandc->qspi->page_rw = false;
@@ -1579,14 +1580,9 @@ static int qcom_spi_probe(struct platform_device *pdev)
struct spi_controller *ctlr;
struct qcom_nand_controller *snandc;
struct qpic_spi_nand *qspi;
- struct qpic_ecc *ecc;
struct resource *res;
int ret;
- ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
- if (!ecc)
- return -ENOMEM;
-
qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL);
if (!qspi)
return -ENOMEM;
@@ -1606,7 +1602,6 @@ static int qcom_spi_probe(struct platform_device *pdev)
snandc->dev = dev;
snandc->qspi = qspi;
snandc->qspi->ctlr = ctlr;
- snandc->qspi->ecc = ecc;
snandc->props = of_device_get_match_data(dev);
if (!snandc->props) {