From 472b444eef934eb7e90334efdd7fc7954cfe5132 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 11 Dec 2015 15:58:01 -0800 Subject: [PATCH 1/3] mtd: fix cmdlinepart parser, early naming for auto-filled MTD Commit 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set") attempted to provide some default settings for MTDs that (a) assign the parent device and (b) don't provide their own name or owner However, this isn't a perfect drop-in replacement for the boilerplate found in some drivers, because the MTD name is used by partition parsers like cmdlinepart, but the name isn't set until add_mtd_device(), after the parsing is completed. This means cmdlinepart sees a NULL name and therefore will not work properly. Fix this by moving the default name and owner assignment to be first in the MTD registration process. [Note: this does not fix all reported issues, particularly with NAND drivers. Will require an additional fix for drivers/mtd/nand/] Fixes: 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set") Reported-by: Heiko Schocher Signed-off-by: Brian Norris Cc: Heiko Schocher Cc: Frans Klaver --- drivers/mtd/mtdcore.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 95c13b2ffa79..ffa288474820 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -426,15 +426,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; - if (mtd->dev.parent) { - if (!mtd->owner && mtd->dev.parent->driver) - mtd->owner = mtd->dev.parent->driver->owner; - if (!mtd->name) - mtd->name = dev_name(mtd->dev.parent); - } else { - pr_debug("mtd device won't show a device symlink in sysfs\n"); - } - /* Some chips always power up locked. Unlock them now */ if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { error = mtd_unlock(mtd, 0, mtd->size); @@ -549,6 +540,21 @@ static int mtd_add_device_partitions(struct mtd_info *mtd, return 0; } +/* + * Set a few defaults based on the parent devices, if not provided by the + * driver + */ +static void mtd_set_dev_defaults(struct mtd_info *mtd) +{ + if (mtd->dev.parent) { + if (!mtd->owner && mtd->dev.parent->driver) + mtd->owner = mtd->dev.parent->driver->owner; + if (!mtd->name) + mtd->name = dev_name(mtd->dev.parent); + } else { + pr_debug("mtd device won't show a device symlink in sysfs\n"); + } +} /** * mtd_device_parse_register - parse partitions and register an MTD device. @@ -587,6 +593,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, int ret; struct mtd_partition *real_parts = NULL; + mtd_set_dev_defaults(mtd); + ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); if (ret <= 0 && nr_parts && parts) { real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, From 67b9bcd36906e12a15ffec19463afbbd6a41660e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 15 Dec 2015 10:48:20 -0800 Subject: [PATCH 2/3] mtd: spi-nor: fix Spansion regressions (aliased with Winbond) Spansion and Winbond have occasionally used the same manufacturer ID, and they don't support the same features. Particularly, writing SR=0 seems to break read access for Spansion's s25fl064k. Unfortunately, we don't currently have a way to differentiate these Spansion and Winbond parts, so rather than regressing support for these Spansion flash, let's drop the new Winbond lock/unlock support for now. We can try to address Winbond support during the next release cycle. Original discussion: http://patchwork.ozlabs.org/patch/549173/ http://patchwork.ozlabs.org/patch/553683/ Fixes: 357ca38d4751 ("mtd: spi-nor: support lock/unlock/is_locked for Winbond") Fixes: c6fc2171b249 ("mtd: spi-nor: disable protection for Winbond flash at startup") Signed-off-by: Brian Norris Reported-by: Felix Fietkau Cc: Felix Fietkau --- drivers/mtd/spi-nor/spi-nor.c | 6 ++---- include/linux/mtd/spi-nor.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 49883905a434..f5d59de1ee6e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1200,8 +1200,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || JEDEC_MFR(info) == SNOR_MFR_INTEL || - JEDEC_MFR(info) == SNOR_MFR_SST || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + JEDEC_MFR(info) == SNOR_MFR_SST) { write_enable(nor); write_sr(nor, 0); } @@ -1217,8 +1216,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->_read = spi_nor_read; /* NOR protection support for STmicro/Micron chips and similar */ - if (JEDEC_MFR(info) == SNOR_MFR_MICRON || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { nor->flash_lock = stm_lock; nor->flash_unlock = stm_unlock; nor->flash_is_locked = stm_is_locked; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index c8723b62c4cd..bc742dac7d3a 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -25,7 +25,7 @@ #define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX #define SNOR_MFR_SPANSION CFI_MFR_AMD #define SNOR_MFR_SST CFI_MFR_SST -#define SNOR_MFR_WINBOND 0xef +#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ /* * Note on opcode nomenclature: some opcodes have a format like From a32d5b726ff8cf32bf491522b0ac8ae2545a063e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 15 Dec 2015 10:48:21 -0800 Subject: [PATCH 3/3] mtd: spi-nor: fix stm_is_locked_sr() parameters stm_is_locked_sr() takes the status register (SR) value as the last parameter, not the second. Reported-by: Bayi Cheng Signed-off-by: Brian Norris Cc: Bayi Cheng --- drivers/mtd/spi-nor/spi-nor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f5d59de1ee6e..32477c4eb421 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -516,8 +516,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_old = read_sr(nor); /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize, - mtd->erasesize)) + if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, + status_old)) return -EINVAL; /*