From c9ec3900abf279d9276a0661c9bed2550c1f0bb5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 13 Aug 2015 15:46:03 -0700 Subject: mtd: spi-nor: assign mtd->priv in spi_nor_scan() Layering suggests that the SPI NOR layer (not the hardware driver) should be initializing the MTD layer. Signed-off-by: Brian Norris Tested-by: Joachim Eastwood --- drivers/mtd/devices/m25p80.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 9cd3631170ef..24965ae9f7aa 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -205,7 +205,6 @@ static int m25p_probe(struct spi_device *spi) nor->priv = flash; spi_set_drvdata(spi, flash); - flash->mtd.priv = nor; flash->spi = spi; if (spi->mode & SPI_RX_QUAD) -- cgit v1.2.3 From 1976367173a47f801c67b5f456922d79c60d0d42 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 13 Aug 2015 15:46:05 -0700 Subject: mtd: spi-nor: embed struct mtd_info within struct spi_nor This reflects the proper layering, so let's do it. Signed-off-by: Brian Norris Tested-by: Joachim Eastwood --- drivers/mtd/devices/m25p80.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 24965ae9f7aa..b6bc9a2a5f87 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -31,7 +31,6 @@ struct m25p { struct spi_device *spi; struct spi_nor spi_nor; - struct mtd_info mtd; u8 command[MAX_CMD_SIZE]; }; @@ -159,7 +158,7 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset) struct m25p *flash = nor->priv; dev_dbg(nor->dev, "%dKiB at 0x%08x\n", - flash->mtd.erasesize / 1024, (u32)offset); + flash->spi_nor.mtd.erasesize / 1024, (u32)offset); /* Set up command buffer. */ flash->command[0] = nor->erase_opcode; @@ -201,7 +200,6 @@ static int m25p_probe(struct spi_device *spi) nor->read_reg = m25p80_read_reg; nor->dev = &spi->dev; - nor->mtd = &flash->mtd; nor->priv = flash; spi_set_drvdata(spi, flash); @@ -213,7 +211,7 @@ static int m25p_probe(struct spi_device *spi) mode = SPI_NOR_DUAL; if (data && data->name) - flash->mtd.name = data->name; + nor->mtd.name = data->name; /* For some (historical?) reason many platforms provide two different * names in flash_platform_data: "name" and "type". Quite often name is @@ -231,7 +229,7 @@ static int m25p_probe(struct spi_device *spi) ppdata.of_node = spi->dev.of_node; - return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, + return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, data ? data->parts : NULL, data ? data->nr_parts : 0); } @@ -242,7 +240,7 @@ static int m25p_remove(struct spi_device *spi) struct m25p *flash = spi_get_drvdata(spi); /* Clean up MTD stuff. */ - return mtd_device_unregister(&flash->mtd); + return mtd_device_unregister(&flash->spi_nor.mtd); } /* -- cgit v1.2.3 From 11bff0b70cc003b995cf4c2acec4adab90957b02 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Sep 2015 18:35:36 +0200 Subject: mtd: spi-nor: Decouple SPI NOR's device_node from controller device The problem this patch is trying to address is such, that SPI NOR flash devices attached to a dedicated SPI NOR controller cannot read their properties from the associated struct device_node. A couple of facts first: 1) Each SPI NOR flash has a struct spi_nor associated with it. 2) Each SPI NOR flash has certain device properties associated with it, for example the OF property 'm25p,fast-read' is a good pick. These properties are used by the SPI NOR core to select which opcodes are sent to such SPI NOR flash. These properties are coming from spi_nor .dev->of_node . The problem is, that for SPI NOR controllers, the struct spi_nor .dev element points to the struct device of the SPI NOR controller, not the SPI NOR flash. Therefore, the associated dev->of_node also is the one of the controller and therefore the SPI NOR core code is trying to parse the SPI NOR controller's properties, not the properties of the SPI NOR flash. Note: The m25p80 driver is not affected, because the controller and the flash are the same device, so the associated device_node of the controller and the flash are the same. This patch adjusts the SPI NOR core such that the device_node is not picked from spi_nor .dev directly, but from a new separate spi_nor .flash_node element. This let's the SPI NOR controller drivers set up a different spi_nor .flash_node element for each SPI NOR flash. This patch also fixes the controller drivers to be compatible with this modification and correctly set the spi_nor .flash_node element. This patch is inspired by 5844feeaa4154d1c46d3462c7a4653d22356d8b4 mtd: nand: add common DT init code Signed-off-by: Marek Vasut Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index b6bc9a2a5f87..05bf0d71abea 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -200,6 +200,7 @@ static int m25p_probe(struct spi_device *spi) nor->read_reg = m25p80_read_reg; nor->dev = &spi->dev; + nor->flash_node = spi->dev.of_node; nor->priv = flash; spi_set_drvdata(spi, flash); -- cgit v1.2.3 From f9f3ce835ddce3c669eee869253105f88819888b Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Wed, 19 Aug 2015 15:26:44 +0530 Subject: mtd: spi-nor: Zap unneeded write_enable from write_reg The 'write_enable' argument is unused and unneeded, so remove it from the API. Signed-off-by: Jagan Teki Cc: David Woodhouse Cc: Han Xu [Brian: fixed for nxp-spifi.c] Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 05bf0d71abea..4b5d7a4655fd 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -61,8 +61,7 @@ static int m25p_cmdsz(struct spi_nor *nor) return 1 + nor->addr_width; } -static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, - int wr_en) +static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) { struct m25p *flash = nor->priv; struct spi_device *spi = flash->spi; -- cgit v1.2.3 From 7827e3acad2df1c6537e5fe7211d216dabc60399 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Tue, 21 Jul 2015 16:30:20 +0800 Subject: mtd: mtdram: check offs and len in mtdram->erase We should prevent user to erasing mtd device with an unaligned offset or length. Signed-off-by: Dongsheng Yang Signed-off-by: Brian Norris --- drivers/mtd/devices/mtdram.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 8e285089229c..73fa297d81d2 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -32,8 +32,29 @@ MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); // We could store these in the mtd structure, but we only support 1 device.. static struct mtd_info *mtd_info; +static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + int ret = 0; + + /* Start address must align on block boundary */ + if (ofs % mtd->erasesize) { + pr_debug("%s: unaligned address\n", __func__); + ret = -EINVAL; + } + + /* Length must align on block boundary */ + if (len % mtd->erasesize) { + pr_debug("%s: length not block aligned\n", __func__); + ret = -EINVAL; + } + + return ret; +} + static int ram_erase(struct mtd_info *mtd, struct erase_info *instr) { + if (check_offs_len(mtd, instr->addr, instr->len)) + return -EINVAL; memset((char *)mtd->priv + instr->addr, 0xff, instr->len); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); -- cgit v1.2.3 From d489ff42db9179647004ca2b12c614cb71ac81ea Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 29 Sep 2015 17:28:44 -0700 Subject: Revert "mtd: mtdram: check offs and len in mtdram->erase" This reverts commit 7827e3acad2df1c6537e5fe7211d216dabc60399. There are some 64-bit arithmetic issues on some architectures, so let's wait until we get a better patch for this. Signed-off-by: Brian Norris --- drivers/mtd/devices/mtdram.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 73fa297d81d2..8e285089229c 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -32,29 +32,8 @@ MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); // We could store these in the mtd structure, but we only support 1 device.. static struct mtd_info *mtd_info; -static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - int ret = 0; - - /* Start address must align on block boundary */ - if (ofs % mtd->erasesize) { - pr_debug("%s: unaligned address\n", __func__); - ret = -EINVAL; - } - - /* Length must align on block boundary */ - if (len % mtd->erasesize) { - pr_debug("%s: length not block aligned\n", __func__); - ret = -EINVAL; - } - - return ret; -} - static int ram_erase(struct mtd_info *mtd, struct erase_info *instr) { - if (check_offs_len(mtd, instr->addr, instr->len)) - return -EINVAL; memset((char *)mtd->priv + instr->addr, 0xff, instr->len); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); -- cgit v1.2.3 From eb98198f23d0c6a77afe692b25e8ad634f0404c5 Mon Sep 17 00:00:00 2001 From: Frans Klaver Date: Wed, 10 Jun 2015 22:38:17 +0200 Subject: mtd: devices: bcm47xxflash: show parent device in sysfs Fix a bug where mtd parent device symlinks aren't shown in sysfs. While at it, make use of the default owner value set by mtdcore. Signed-off-by: Frans Klaver Signed-off-by: Brian Norris --- drivers/mtd/devices/bcm47xxsflash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 3d008a9410be..347bb83db864 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -237,13 +237,14 @@ static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len, return 0; } -static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) +static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s, + struct device *dev) { struct mtd_info *mtd = &b47s->mtd; mtd->priv = b47s; + mtd->dev.parent = dev; mtd->name = "bcm47xxsflash"; - mtd->owner = THIS_MODULE; mtd->type = MTD_NORFLASH; mtd->flags = MTD_CAP_NORFLASH; @@ -300,7 +301,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) b47s->blocksize = sflash->blocksize; b47s->numblocks = sflash->numblocks; b47s->size = sflash->size; - bcm47xxsflash_fill_mtd(b47s); + bcm47xxsflash_fill_mtd(b47s, &pdev->dev); err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); if (err) { -- cgit v1.2.3 From 1560d2132ae95b36b25cc78811af8eaf9bbb2f8e Mon Sep 17 00:00:00 2001 From: Frans Klaver Date: Wed, 10 Jun 2015 22:38:18 +0200 Subject: mtd: devices: docg3: show parent device in sysfs Fix a bug where mtd parent device symlinks aren't shown in sysfs. While at it, make use of the default owner value set by mtdcore. Signed-off-by: Frans Klaver Signed-off-by: Brian Norris --- drivers/mtd/devices/docg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 5e67b4acde78..f00d0dae917f 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1843,7 +1843,6 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) mtd->erasesize /= 2; mtd->writebufsize = mtd->writesize = DOC_LAYOUT_PAGE_SIZE; mtd->oobsize = DOC_LAYOUT_OOB_SIZE; - mtd->owner = THIS_MODULE; mtd->_erase = doc_erase; mtd->_read = doc_read; mtd->_write = doc_write; @@ -1885,6 +1884,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) if (!mtd) goto nomem2; mtd->priv = docg3; + mtd->dev.parent = dev; bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE); docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); -- cgit v1.2.3 From 57eea0f5fb221f88c3c9b0ddc967c004bfff7e9c Mon Sep 17 00:00:00 2001 From: Frans Klaver Date: Wed, 10 Jun 2015 22:38:20 +0200 Subject: mtd: devices: mtd_dataflash: drop owner assignment Owner is automatically set by mtdcore. Make use of that. Signed-off-by: Frans Klaver Signed-off-by: Brian Norris --- drivers/mtd/devices/mtd_dataflash.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index df6f61137376..39666d552682 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -648,7 +648,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, device->size = nr_pages * pagesize; device->erasesize = pagesize; device->writesize = pagesize; - device->owner = THIS_MODULE; device->type = MTD_DATAFLASH; device->flags = MTD_WRITEABLE; device->_erase = dataflash_erase; -- cgit v1.2.3 From 7d24272253594abcdca8f52758a574367a5912bf Mon Sep 17 00:00:00 2001 From: Frans Klaver Date: Wed, 10 Jun 2015 22:38:21 +0200 Subject: mtd: devices: spear_smi: show parent device in sysfs Fix a bug where mtd parent device symlinks aren't shown in sysfs. Signed-off-by: Frans Klaver Signed-off-by: Brian Norris --- drivers/mtd/devices/spear_smi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 04b24d2b03f2..64c7458344d4 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -854,6 +854,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev, else flash->mtd.name = flash_devices[flash_index].name; + flash->mtd.dev.parent = &pdev->dev; flash->mtd.type = MTD_NORFLASH; flash->mtd.writesize = 1; flash->mtd.flags = MTD_CAP_NORFLASH; -- cgit v1.2.3 From 90b997527ecbaac44485a52a01768d5ae32f3818 Mon Sep 17 00:00:00 2001 From: Frans Klaver Date: Wed, 10 Jun 2015 22:38:22 +0200 Subject: mtd: devices: sst251: show parent device in sysfs Fix a bug where mtd parent device symlinks aren't shown in sysfs. While at it, make use of the default owner value set by mtdcore. Signed-off-by: Frans Klaver Signed-off-by: Brian Norris --- drivers/mtd/devices/sst25l.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index c63ecbcad0b7..3928014f83ac 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -374,9 +374,8 @@ static int sst25l_probe(struct spi_device *spi) data = dev_get_platdata(&spi->dev); if (data && data->name) flash->mtd.name = data->name; - else - flash->mtd.name = dev_name(&spi->dev); + flash->mtd.dev.parent = &spi->dev; flash->mtd.type = MTD_NORFLASH; flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.erasesize = flash_info->erase_size; -- cgit v1.2.3 From ab84fce518175aa09ec6e1bb50c2b41dad3e610a Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Wed, 30 Sep 2015 09:01:19 +0800 Subject: mtd: mtdram: check offs and len in mtdram->erase We should prevent user to erasing mtd device with an unaligned offset or length. Signed-off-by: Dongsheng Yang Signed-off-by: Brian Norris --- drivers/mtd/devices/mtdram.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 8e285089229c..627a9bc37679 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -32,8 +32,29 @@ MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); // We could store these in the mtd structure, but we only support 1 device.. static struct mtd_info *mtd_info; +static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + int ret = 0; + + /* Start address must align on block boundary */ + if (mtd_mod_by_eb(ofs, mtd)) { + pr_debug("%s: unaligned address\n", __func__); + ret = -EINVAL; + } + + /* Length must align on block boundary */ + if (mtd_mod_by_eb(len, mtd)) { + pr_debug("%s: length not block aligned\n", __func__); + ret = -EINVAL; + } + + return ret; +} + static int ram_erase(struct mtd_info *mtd, struct erase_info *instr) { + if (check_offs_len(mtd, instr->addr, instr->len)) + return -EINVAL; memset((char *)mtd->priv + instr->addr, 0xff, instr->len); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); -- cgit v1.2.3 From 2382960793c2480277ae98a891ea5aa566e06ff1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 19 Oct 2015 13:20:05 +0300 Subject: mtd: docg3: off by one in doc_register_sysfs() Smatch found a bug in the error handling: drivers/mtd/devices/docg3.c:1634 doc_register_sysfs() error: buffer overflow 'doc_sys_attrs' 4 <= 4 The problem is that if the very last device_create_file() fails, then we are beyond the end of the array. Actually, any time i == 3 then there is a problem. We can fix this an simplify the code at the same time by moving the !ret conditions out of the for loops and using a goto instead. Signed-off-by: Dan Carpenter Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/devices/docg3.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/mtd/devices') diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index f00d0dae917f..c3a2695a4420 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1620,20 +1620,30 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = { static int doc_register_sysfs(struct platform_device *pdev, struct docg3_cascade *cascade) { - int ret = 0, floor, i = 0; struct device *dev = &pdev->dev; + int floor; + int ret; + int i; - for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && - cascade->floors[floor]; floor++) - for (i = 0; !ret && i < 4; i++) + for (floor = 0; + floor < DOC_MAX_NBFLOORS && cascade->floors[floor]; + floor++) { + for (i = 0; i < 4; i++) { ret = device_create_file(dev, &doc_sys_attrs[floor][i]); - if (!ret) - return 0; + if (ret) + goto remove_files; + } + } + + return 0; + +remove_files: do { while (--i >= 0) device_remove_file(dev, &doc_sys_attrs[floor][i]); i = 4; } while (--floor >= 0); + return ret; } -- cgit v1.2.3