From 4883a60c17eda6bf52d1c817ee7ead65b4a02da2 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 21 Dec 2020 11:00:13 +0100 Subject: [PATCH 1/5] mtd: rawnand: gpmi: fix dst bit offset when extracting raw payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-add the multiply by 8 to "step * eccsize" to correct the destination bit offset when extracting the data payload in gpmi_ecc_read_page_raw(). Fixes: e5e5631cc889 ("mtd: rawnand: gpmi: Use nand_extract_bits()") Cc: stable@vger.kernel.org Reported-by: Martin Hundebøll Signed-off-by: Sean Nyekjaer Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20201221100013.2715675-1-sean@geanix.com --- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 5cdf05bcbf8f..3fa8c22d3f36 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1615,7 +1615,7 @@ static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf, /* Extract interleaved payload data and ECC bits */ for (step = 0; step < nfc_geo->ecc_chunk_count; step++) { if (buf) - nand_extract_bits(buf, step * eccsize, tmp_buf, + nand_extract_bits(buf, step * eccsize * 8, tmp_buf, src_bit_off, eccsize * 8); src_bit_off += eccsize * 8; From 3c97be6982e689d7b2430187a11f8c78e573abdb Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 4 Jan 2021 10:30:57 +0100 Subject: [PATCH 2/5] mtd: rawnand: nandsim: Fix the logic when selecting Hamming soft ECC engine I have been fooled by the logic picking the right ECC engine which is spread across two functions: *init_module() and *_attach(). I thought this driver was not impacted by the recent changes around the ECC engines DT parsing logic but in fact it is. Reported-by: kernel test robot Fixes: d7157ff49a5b ("mtd: rawnand: Use the ECC framework user input parsing bits") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210104093057.31178-1-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nandsim.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index f2b9250c0ea8..0750121ac371 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2210,6 +2210,9 @@ static int ns_attach_chip(struct nand_chip *chip) { unsigned int eccsteps, eccbytes; + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; + chip->ecc.algo = bch ? NAND_ECC_ALGO_BCH : NAND_ECC_ALGO_HAMMING; + if (!bch) return 0; @@ -2233,8 +2236,6 @@ static int ns_attach_chip(struct nand_chip *chip) return -EINVAL; } - chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; - chip->ecc.algo = NAND_ECC_ALGO_BCH; chip->ecc.size = 512; chip->ecc.strength = bch; chip->ecc.bytes = eccbytes; @@ -2273,8 +2274,6 @@ static int __init ns_init_module(void) nsmtd = nand_to_mtd(chip); nand_set_controller_data(chip, (void *)ns); - chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ /* and 'badblocks' parameters to work */ chip->options |= NAND_SKIP_BBTSCAN; From 18f62614308be69a2752afb5f6bbad60096ad774 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Wed, 6 Jan 2021 15:09:43 +0100 Subject: [PATCH 3/5] mtd: rawnand: intel: check the mtd name only after setting the variable Move the check for mtd->name after the mtd variable has actually been initialized. While here, also drop the NULL assignment to the mtd variable as it's overwritten later on anyways and the NULL value is never read. Fixes: 0b1039f016e8a3 ("mtd: rawnand: Add NAND controller support on Intel LGM SoC") Signed-off-by: Martin Blumenstingl Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210106140943.98072-1-martin.blumenstingl@googlemail.com --- drivers/mtd/nand/raw/intel-nand-controller.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c index fdb112e8a90d..a304fda5d1fa 100644 --- a/drivers/mtd/nand/raw/intel-nand-controller.c +++ b/drivers/mtd/nand/raw/intel-nand-controller.c @@ -579,7 +579,7 @@ static int ebu_nand_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ebu_nand_controller *ebu_host; struct nand_chip *nand; - struct mtd_info *mtd = NULL; + struct mtd_info *mtd; struct resource *res; char *resname; int ret; @@ -647,12 +647,13 @@ static int ebu_nand_probe(struct platform_device *pdev) ebu_host->ebu + EBU_ADDR_SEL(cs)); nand_set_flash_node(&ebu_host->chip, dev->of_node); + + mtd = nand_to_mtd(&ebu_host->chip); if (!mtd->name) { dev_err(ebu_host->dev, "NAND label property is mandatory\n"); return -EINVAL; } - mtd = nand_to_mtd(&ebu_host->chip); mtd->dev.parent = dev; ebu_host->dev = dev; From e708789c4a87989faff1131ccfdc465a1c1eddbc Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 7 Jan 2021 09:38:13 +0100 Subject: [PATCH 4/5] mtd: spinand: Fix MTD_OPS_AUTO_OOB requests The initial change breaking the logic is commit 3d1f08b032dc ("mtd: spinand: Use the external ECC engine logic") It inadvertently dropped proper OOB support while doing something else. Shortly later, half of it got re-integrated by commit 868cbe2a6dce ("mtd: spinand: Fix OOB read") (pointing by the way to a more early change which had nothing to do with the issue). Problem is, this commit failed to revert the faulty change entirely and missed the logic handling MTD_OPS_AUTO_OOB requests. Let's fix this mess by re-inserting the missing part now. Fixes: 868cbe2a6dce ("mtd: spinand: Fix OOB read") Reported-by: Felix Fietkau Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210107083813.24283-1-miquel.raynal@bootlin.com --- drivers/mtd/nand/spi/core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 8ea545bb924d..61d932c1b718 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -343,6 +343,7 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, const struct nand_page_io_req *req) { struct nand_device *nand = spinand_to_nand(spinand); + struct mtd_info *mtd = spinand_to_mtd(spinand); struct spi_mem_dirmap_desc *rdesc; unsigned int nbytes = 0; void *buf = NULL; @@ -382,9 +383,16 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, memcpy(req->databuf.in, spinand->databuf + req->dataoffs, req->datalen); - if (req->ooblen) - memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs, - req->ooblen); + if (req->ooblen) { + if (req->mode == MTD_OPS_AUTO_OOB) + mtd_ooblayout_get_databytes(mtd, req->oobbuf.in, + spinand->oobbuf, + req->ooboffs, + req->ooblen); + else + memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs, + req->ooblen); + } return 0; } From b135b3358d73aa2a8b2be35d08e422421d1c609e Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 Jan 2021 16:55:10 +0100 Subject: [PATCH 5/5] mtd: rawnand: omap: Use BCH private fields in the specific OOB layout The OMAP driver may leverage software BCH logic to locate errors while using its own hardware to detect the presence of errors. This is achieved with a "mixed" mode which initializes manually the software BCH internal logic while providing its own OOB layout. The issue here comes from the fact that the BCH driver has been updated to only use generic NAND objects, and no longer depend on raw NAND structures as it is usable from SPI-NAND as well. However, at the end of the BCH context initialization, the driver checks the validity of the OOB layout. At this stage, the raw NAND fields have not been populated yet while being used by the layout helpers, leading to an invalid layout. The chosen solution here is to include the BCH structure definition and to refer to the BCH fields directly (de-referenced as a const pointer here) to know as early as possible the number of steps and ECC bytes which have been chosen. Note: I don't know which commit exactly triggered the error, but the entire migration to a generic BCH driver got merged in one go, so this should not be a problem for stable backports. Reported-by: Adam Ford Fixes: 80fe603160a4 ("mtd: nand: ecc-bch: Stop using raw NAND structures") Signed-off-by: Miquel Raynal Tested-by: Adam Ford #logicpd-torpedo-37xx-devkit-28.dts Link: https://lore.kernel.org/linux-mtd/20210119155510.5655-1-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/omap2.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index fbb9955f2467..2c3e65cb68f3 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1866,18 +1867,19 @@ static const struct mtd_ooblayout_ops omap_ooblayout_ops = { static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_device *nand = mtd_to_nanddev(mtd); + const struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv; int off = BADBLOCK_MARKER_LENGTH; - if (section >= chip->ecc.steps) + if (section >= engine_conf->nsteps) return -ERANGE; /* * When SW correction is employed, one OMAP specific marker byte is * reserved after each ECC step. */ - oobregion->offset = off + (section * (chip->ecc.bytes + 1)); - oobregion->length = chip->ecc.bytes; + oobregion->offset = off + (section * (engine_conf->code_size + 1)); + oobregion->length = engine_conf->code_size; return 0; } @@ -1885,7 +1887,8 @@ static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section, static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_device *nand = mtd_to_nanddev(mtd); + const struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv; int off = BADBLOCK_MARKER_LENGTH; if (section) @@ -1895,7 +1898,7 @@ static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section, * When SW correction is employed, one OMAP specific marker byte is * reserved after each ECC step. */ - off += ((chip->ecc.bytes + 1) * chip->ecc.steps); + off += ((engine_conf->code_size + 1) * engine_conf->nsteps); if (off >= mtd->oobsize) return -ERANGE;