aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/mtdcore.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 11:25:54 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 11:25:54 -0800
commitac53b2e053fffc74372da94e734b92f37e70d32c (patch)
treecda82af0fcded5d230e9f56104d3988b7a75c8aa /drivers/mtd/mtdcore.c
parentcf09112d160e6db21ff8427ce696f819b957423b (diff)
parent9146cbd52b11d4ade62dba8f238ec5e421c3fa2b (diff)
Merge tag 'for-linus-20160112' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris: "Generic MTD: - populate the MTD device 'of_node' field (and get a proper 'of_node' symlink in sysfs) This yielded some new helper functions, and changes across a variety of drivers - partitioning cleanups, to prepare for better device-tree based partitioning in the future Eliminate a lot of boilerplate for drivers that want to use OF-based partition parsing The DT bindings for this didn't settle yet, so most non-cleanup portions are deferred for a future release NAND: - embed a struct mtd_info inside struct nand_chip This is really long overdue; too many drivers have to do the same silly boilerplate to allocate and link up two "independent" structs, when in fact, everyone is assuming there is an exact 1:1 relationship between a NAND chips struct and its underlying MTD. This aids improved helpers and should make certain abstractions easier in the future. Also causes a lot of churn, helped along by some automated code transformations - add more core support for detecting (and "correcting") bitflips in erased pages; requires opt-in by drivers, but at least we kill a few bad implementations and hopefully stave off future ones - pxa3xx_nand: cleanups, a few fixes, and PM improvements - new JZ4780 NAND driver SPI NOR: - provide default erase function, for controllers that just want to send the SECTOR_ERASE command directly - fix some module auto-loading issues with device tree ("jedec,spi-nor") - error handling fixes - new Mediatek QSPI flash driver Other: - cfi: force valid geometry Kconfig (finally!) This one used to trip up randconfigs occasionally, since bots aren't deterred by big scary "advanced configuration" menus More? Probably. See the commit logs" * tag 'for-linus-20160112' of git://git.infradead.org/linux-mtd: (168 commits) mtd: jz4780_nand: replace if/else blocks with switch/case mtd: nand: jz4780: Update ecc correction error codes mtd: nandsim: use nand_get_controller_data() mtd: jz4780_nand: remove useless mtd->priv = chip assignment staging: mt29f_spinand: make use of nand_set/get_controller_data() helpers mtd: nand: make use of nand_set/get_controller_data() helpers ARM: make use of nand_set/get_controller_data() helpers mtd: nand: add helpers to access ->priv mtd: nand: jz4780: driver for NAND devices on JZ4780 SoCs mtd: nand: jz4740: remove custom 'erased check' implementation mtd: nand: diskonchip: remove custom 'erased check' implementation mtd: nand: davinci: remove custom 'erased check' implementation mtd: nand: use nand_check_erased_ecc_chunk in default ECC read functions mtd: nand: return consistent error codes in ecc.correct() implementations doc: dt: mtd: new binding for jz4780-{nand,bch} mtd: cfi_cmdset_0001: fixing memory leak and handling failed kmalloc mtd: spi-nor: wait until lock/unlock operations are ready mtd: tests: consolidate kmalloc/memset 0 call to kzalloc jffs2: use to_delayed_work mtd: nand: assign reasonable default name for NAND drivers ...
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r--drivers/mtd/mtdcore.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index ffa288474820..309625130b21 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -32,6 +32,7 @@
#include <linux/err.h>
#include <linux/ioctl.h>
#include <linux/init.h>
+#include <linux/of.h>
#include <linux/proc_fs.h>
#include <linux/idr.h>
#include <linux/backing-dev.h>
@@ -445,6 +446,7 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->dev.devt = MTD_DEVT(i);
dev_set_name(&mtd->dev, "mtd%d", i);
dev_set_drvdata(&mtd->dev, mtd);
+ of_node_get(mtd_get_of_node(mtd));
error = device_register(&mtd->dev);
if (error)
goto fail_added;
@@ -467,6 +469,7 @@ int add_mtd_device(struct mtd_info *mtd)
return 0;
fail_added:
+ of_node_put(mtd_get_of_node(mtd));
idr_remove(&mtd_idr, i);
fail_locked:
mutex_unlock(&mtd_table_mutex);
@@ -508,6 +511,7 @@ int del_mtd_device(struct mtd_info *mtd)
device_unregister(&mtd->dev);
idr_remove(&mtd_idr, mtd->index);
+ of_node_put(mtd_get_of_node(mtd));
module_put(THIS_MODULE);
ret = 0;
@@ -519,9 +523,10 @@ out_error:
}
static int mtd_add_device_partitions(struct mtd_info *mtd,
- struct mtd_partition *real_parts,
- int nbparts)
+ struct mtd_partitions *parts)
{
+ const struct mtd_partition *real_parts = parts->parts;
+ int nbparts = parts->nr_parts;
int ret;
if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
@@ -590,29 +595,29 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
const struct mtd_partition *parts,
int nr_parts)
{
+ struct mtd_partitions parsed;
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,
- GFP_KERNEL);
- if (!real_parts)
- ret = -ENOMEM;
- else
- ret = nr_parts;
- }
- /* Didn't come up with either parsed OR fallback partitions */
- if (ret < 0) {
+ memset(&parsed, 0, sizeof(parsed));
+
+ ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
+ if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) {
+ /* Fall back to driver-provided partitions */
+ parsed = (struct mtd_partitions){
+ .parts = parts,
+ .nr_parts = nr_parts,
+ };
+ } else if (ret < 0) {
+ /* Didn't come up with parsed OR fallback partitions */
pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
ret);
/* Don't abort on errors; we can still use unpartitioned MTD */
- ret = 0;
+ memset(&parsed, 0, sizeof(parsed));
}
- ret = mtd_add_device_partitions(mtd, real_parts, ret);
+ ret = mtd_add_device_partitions(mtd, &parsed);
if (ret)
goto out;
@@ -632,7 +637,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
}
out:
- kfree(real_parts);
+ /* Cleanup any parsed partitions */
+ mtd_part_parser_cleanup(&parsed);
return ret;
}
EXPORT_SYMBOL_GPL(mtd_device_parse_register);