From 007b4e8b705a4eff184d567c5a8b496622f9e116 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Thu, 5 Apr 2018 14:57:59 +0200 Subject: mtd: rawnand: tango: Fix struct clk memory leak Use devm_clk_get() to let Linux manage struct clk memory. Fixes: 6956e2385a16 ("add tango NAND flash controller support") Cc: stable@vger.kernel.org Reported-by: Xidong Wang Signed-off-by: Marc Gonzalez Reviewed-by: Miquel Raynal Signed-off-by: Boris Brezillon --- drivers/mtd/nand/raw/tango_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index f54518ffb36a..f2052fae21c7 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -645,7 +645,7 @@ static int tango_nand_probe(struct platform_device *pdev) writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE); - clk = clk_get(&pdev->dev, NULL); + clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); -- cgit v1.2.3 From 23566c3798f315058862564ab3d01882316054eb Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 10 Apr 2018 17:15:13 +0200 Subject: mtd: nand: Fix nanddev_mtd_erase() Commit e7bfb3fdbde3 ("mtd: Stop updating erase_info->state and calling mtd_erase_callback()") removed the einfo->state field and the MTD_ERASE_XXX macros. At the same time, the generic NAND layer was added and made sure to update the erase info state. It did not result in a build failure after merging the nand/for-4.17 branch in mtd/next because the generic NAND layer is not selected yet. Let's fix that before a config option starts selecting MTD_NAND_CORE. Fixes: e7bfb3fdbde3 ("mtd: Stop updating erase_info->state and calling mtd_erase_callback()") Signed-off-by: Boris Brezillon --- drivers/mtd/nand/core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index d0cd6f8635d7..9c9f8936b63b 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c @@ -162,7 +162,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo) ret = nanddev_erase(nand, &pos); if (ret) { einfo->fail_addr = nanddev_pos_to_offs(nand, &pos); - einfo->state = MTD_ERASE_FAILED; return ret; } @@ -170,8 +169,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo) nanddev_pos_next_eraseblock(nand, &pos); } - einfo->state = MTD_ERASE_DONE; - return 0; } EXPORT_SYMBOL_GPL(nanddev_mtd_erase); -- cgit v1.2.3 From 47016b341fc3b3fd4909e058c6fa38f165b53646 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 23 Apr 2018 12:45:11 -0500 Subject: mtd: spi-nor: cadence-quadspi: Fix page fault kernel panic The current Cadence QSPI driver caused a kernel panic when loading a Root Filesystem from QSPI. The problem was caused by reading more bytes than needed because the QSPI operated on 4 bytes at a time. [ 7.947754] spi_nor_read[1048]:from 0x037cad74, len 1 [bfe07fff] [ 7.956247] cqspi_read[910]:offset 0x58502516, buffer=bfe07fff [ 7.956247] [ 7.966046] Unable to handle kernel paging request at virtual address bfe08002 [ 7.973239] pgd = eebfc000 [ 7.975931] [bfe08002] *pgd=2fffb811, *pte=00000000, *ppte=00000000 Notice above how only 1 byte needed to be read but by reading 4 bytes into the end of a mapped page, an unrecoverable page fault occurred. This patch uses a temporary buffer to hold the 4 bytes read and then copies only the bytes required into the buffer. A min() function is used to limit the length to prevent buffer overflows. Request testing of this patch on other platforms. This was tested on the Intel Arria10 SoCFPGA DevKit. Fixes: 0cf1725676a97fc8 ("mtd: spi-nor: cqspi: Fix build on arches missing readsl/writesl") Signed-off-by: Thor Thayer Cc: Reviewed-by: Marek Vasut Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/cadence-quadspi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 4b8e9183489a..5872f31eaa60 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -501,7 +501,9 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf, void __iomem *reg_base = cqspi->iobase; void __iomem *ahb_base = cqspi->ahb_base; unsigned int remaining = n_rx; + unsigned int mod_bytes = n_rx % 4; unsigned int bytes_to_read = 0; + u8 *rxbuf_end = rxbuf + n_rx; int ret = 0; writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); @@ -530,11 +532,24 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf, } while (bytes_to_read != 0) { + unsigned int word_remain = round_down(remaining, 4); + bytes_to_read *= cqspi->fifo_width; bytes_to_read = bytes_to_read > remaining ? remaining : bytes_to_read; - ioread32_rep(ahb_base, rxbuf, - DIV_ROUND_UP(bytes_to_read, 4)); + bytes_to_read = round_down(bytes_to_read, 4); + /* Read 4 byte word chunks then single bytes */ + if (bytes_to_read) { + ioread32_rep(ahb_base, rxbuf, + (bytes_to_read / 4)); + } else if (!word_remain && mod_bytes) { + unsigned int temp = ioread32(ahb_base); + + bytes_to_read = mod_bytes; + memcpy(rxbuf, &temp, min((unsigned int) + (rxbuf_end - rxbuf), + bytes_to_read)); + } rxbuf += bytes_to_read; remaining -= bytes_to_read; bytes_to_read = cqspi_get_rd_sram_level(cqspi); -- cgit v1.2.3 From 6510bbc88e3258631831ade49033537081950605 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Thu, 1 Mar 2018 14:39:39 +0100 Subject: mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase block. Currently it is possible to read and/or write to suspend EB's. Writing /dev/mtdX or /dev/mtdblockX from several processes may break the flash state machine. Signed-off-by: Joakim Tjernlund Cc: Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon --- drivers/mtd/chips/cfi_cmdset_0001.c | 16 +++++++++++----- include/linux/mtd/flashchip.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index d4c07b85f18e..8833115fbc11 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -831,21 +831,25 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) goto sleep; + /* Do not allow suspend iff read/write to EB address */ + if ((adr & chip->in_progress_block_mask) == + chip->in_progress_block_addr) + goto sleep; /* Erase suspend */ - map_write(map, CMD(0xB0), adr); + map_write(map, CMD(0xB0), chip->in_progress_block_addr); /* If the flash has finished erasing, then 'erase suspend' * appears to make some (28F320) flash devices switch to * 'read' mode. Make sure that we switch to 'read status' * mode so we get the right data. --rmk */ - map_write(map, CMD(0x70), adr); + map_write(map, CMD(0x70), chip->in_progress_block_addr); chip->oldstate = FL_ERASING; chip->state = FL_ERASE_SUSPENDING; chip->erase_suspended = 1; for (;;) { - status = map_read(map, adr); + status = map_read(map, chip->in_progress_block_addr); if (map_word_andequal(map, status, status_OK, status_OK)) break; @@ -1041,8 +1045,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad sending the 0x70 (Read Status) command to an erasing chip and expecting it to be ignored, that's what we do. */ - map_write(map, CMD(0xd0), adr); - map_write(map, CMD(0x70), adr); + map_write(map, CMD(0xd0), chip->in_progress_block_addr); + map_write(map, CMD(0x70), chip->in_progress_block_addr); chip->oldstate = FL_READY; chip->state = FL_ERASING; break; @@ -1933,6 +1937,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, map_write(map, CMD(0xD0), adr); chip->state = FL_ERASING; chip->erase_suspended = 0; + chip->in_progress_block_addr = adr; + chip->in_progress_block_mask = ~(len - 1); ret = INVAL_CACHE_AND_WAIT(map, chip, adr, adr, len, diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index b63fa457febd..3529683f691e 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -85,6 +85,7 @@ struct flchip { unsigned int write_suspended:1; unsigned int erase_suspended:1; unsigned long in_progress_block_addr; + unsigned long in_progress_block_mask; struct mutex mutex; wait_queue_head_t wq; /* Wait on here when we're waiting for the chip -- cgit v1.2.3 From 46a16a2283f9e678a4e26829175e0c37a5191860 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Thu, 1 Mar 2018 14:39:40 +0100 Subject: mtd: cfi: cmdset_0001: Workaround Micron Erase suspend bug. Some Micron chips does not work well wrt Erase suspend for boot blocks. This avoids the issue by not allowing Erase suspend for the boot blocks for the 28F00AP30(1GBit) chip. Signed-off-by: Joakim Tjernlund Cc: Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon --- drivers/mtd/chips/cfi_cmdset_0001.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 8833115fbc11..f5695be14499 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -45,6 +45,7 @@ #define I82802AB 0x00ad #define I82802AC 0x00ac #define PF38F4476 0x881c +#define M28F00AP30 0x8963 /* STMicroelectronics chips */ #define M50LPW080 0x002F #define M50FLW080A 0x0080 @@ -375,6 +376,17 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi, extp->MinorVersion = '1'; } +static int cfi_is_micron_28F00AP30(struct cfi_private *cfi, struct flchip *chip) +{ + /* + * Micron(was Numonyx) 1Gbit bottom boot are buggy w.r.t + * Erase Supend for their small Erase Blocks(0x8000) + */ + if (cfi->mfr == CFI_MFR_INTEL && cfi->id == M28F00AP30) + return 1; + return 0; +} + static inline struct cfi_pri_intelext * read_pri_intelext(struct map_info *map, __u16 adr) { @@ -836,6 +848,11 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long chip->in_progress_block_addr) goto sleep; + /* do not suspend small EBs, buggy Micron Chips */ + if (cfi_is_micron_28F00AP30(cfi, chip) && + (chip->in_progress_block_mask == ~(0x8000-1))) + goto sleep; + /* Erase suspend */ map_write(map, CMD(0xB0), chip->in_progress_block_addr); -- cgit v1.2.3 From 7b70eb14392a7cf505f9b358d06c33b5af73d1e7 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Thu, 1 Mar 2018 14:39:41 +0100 Subject: mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase block. Currently it is possible to read and/or write to suspend EB's. Writing /dev/mtdX or /dev/mtdblockX from several processes may break the flash state machine. Taken from cfi_cmdset_0001 driver. Signed-off-by: Joakim Tjernlund Cc: Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon --- drivers/mtd/chips/cfi_cmdset_0002.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 668e2cbc155b..692902df2598 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -816,9 +816,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) goto sleep; - /* We could check to see if we're trying to access the sector - * that is currently being erased. However, no user will try - * anything like that so we just wait for the timeout. */ + /* Do not allow suspend iff read/write to EB address */ + if ((adr & chip->in_progress_block_mask) == + chip->in_progress_block_addr) + goto sleep; /* Erase suspend */ /* It's harmless to issue the Erase-Suspend and Erase-Resume @@ -2267,6 +2268,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->state = FL_ERASING; chip->erase_suspended = 0; chip->in_progress_block_addr = adr; + chip->in_progress_block_mask = ~(map->size - 1); INVALIDATE_CACHE_UDELAY(map, chip, adr, map->size, @@ -2356,6 +2358,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, chip->state = FL_ERASING; chip->erase_suspended = 0; chip->in_progress_block_addr = adr; + chip->in_progress_block_mask = ~(len - 1); INVALIDATE_CACHE_UDELAY(map, chip, adr, len, -- cgit v1.2.3 From f6997bec6af43396ff530caee79e178d32774a49 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 25 Apr 2018 16:16:32 +0200 Subject: mtd: rawnand: marvell: fix the chip-select DT parsing logic The block responsible of parsing the DT for the number of chip-select lines uses an 'if/else if/else if' block. The content of the second and third 'else if' conditions are: 1/ the actual condition to enter the sub-block and 2/ the operation to do in this sub-block. [...] else if (condition1_to_enter && action1() == failed) raise_error(); else if (condition2_to_enter && action2() == failed) raise_error(); [...] In case of failure, the sub-block is entered and an error raised. Otherwise, in case of success, the code would continue erroneously in the next 'else if' statement because it did not failed (and did not enter the first 'else if' sub-block). The first 'else if' refers to legacy bindings while the second 'else if' refers to new bindings. The second 'else if', which is entered erroneously, checks for the 'reg' property, which, for old bindings, does not mean anything because it would not be the number of CS available, but the regular register map of almost any DT node. This being said, the content of the 'reg' property being the register map offset and length, it has '2' values, so the number of CS in this situation is assumed to be '2'. When running nand_scan_ident() with 2 CS, the core will check for an array of chips. It will first issue a RESET and then a READ_ID. Of course this will trigger two timeouts because there is no chip in front of the second CS: [ 1.367460] marvell-nfc f2720000.nand: Timeout on CMDD (NDSR: 0x00000080) [ 1.474292] marvell-nfc f2720000.nand: Timeout on CMDD (NDSR: 0x00000280) Indeed, this is harmless and the core will then assume there is only one valid CS. Fix the logic in the whole block by entering each sub-block just on the 'is legacy' condition, doing the action inside the sub-block. This way, when the action succeeds, the whole block is left. Furthermore, for both the old bindings and the new bindings the same logic was applied to retrieve the number of CS lines: using of_get_property() to get a size in bytes, converted in the actual number of lines by dividing it per sizeof(u32) (4 bytes). This is fine for the 'reg' property which is a list of the CS IDs but not for the 'num-cs' property which is directly the value of the number of CS. Anyway, no existing DT uses another value than 'num-cs = <1>' and no other value has ever been supported by the old driver (pxa3xx_nand.c). Remove this condition and apply a number of 1 CS anyway, as already described in the bindings. Finally, the 'reg' property of a 'nand' node (with the new bindings) gives the IDs of each CS line in use. marvell_nand.c driver first look at the number of CS lines that are present in this property. Better use of_property_count_elems_of_size() than dividing by 4 the size of the number of bytes returned by of_get_property(). Fixes: 02f26ecf8c772 ("mtd: nand: add reworked Marvell NAND controller driver") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Tested-by: Chris Packham Signed-off-by: Boris Brezillon --- drivers/mtd/nand/raw/marvell_nand.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 10e953218948..1d779a35ac8e 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2299,29 +2299,20 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, /* * The legacy "num-cs" property indicates the number of CS on the only * chip connected to the controller (legacy bindings does not support - * more than one chip). CS are only incremented one by one while the RB - * pin is always the #0. + * more than one chip). The CS and RB pins are always the #0. * * When not using legacy bindings, a couple of "reg" and "nand-rb" * properties must be filled. For each chip, expressed as a subnode, * "reg" points to the CS lines and "nand-rb" to the RB line. */ - if (pdata) { + if (pdata || nfc->caps->legacy_of_bindings) { nsels = 1; - } else if (nfc->caps->legacy_of_bindings && - !of_get_property(np, "num-cs", &nsels)) { - dev_err(dev, "missing num-cs property\n"); - return -EINVAL; - } else if (!of_get_property(np, "reg", &nsels)) { - dev_err(dev, "missing reg property\n"); - return -EINVAL; - } - - if (!pdata) - nsels /= sizeof(u32); - if (!nsels) { - dev_err(dev, "invalid reg property size\n"); - return -EINVAL; + } else { + nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); + if (nsels <= 0) { + dev_err(dev, "missing/invalid reg property\n"); + return -EINVAL; + } } /* Alloc the nand chip structure */ -- cgit v1.2.3