aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Ehrenberg <dehrenberg@chromium.org>2015-04-02 18:15:10 -0400
committerBrian Norris <computersforpeace@gmail.com>2015-04-05 20:44:01 -0400
commit727dc612c46b8f3858537ea23805b3e897cf127e (patch)
tree5bcda420d5f0071fc8d8c8c02dc68166256323e7 /drivers
parent9cd5196ed25979a3760f97225aae3e17caf21512 (diff)
mtd: part: Create the master device node when partitioned
For many use cases, it helps to have a device node for the entire MTD device as well as device nodes for the individual partitions. For example, this allows querying the entire device's properties. A common idiom is to create an additional partition which spans over the whole device. This patch makes a config option, CONFIG_MTD_PARTITIONED_MASTER, which makes the master partition present even when the device is partitioned. This isn't turned on by default since it presents a backwards-incompatible device numbering. The patch also makes the parent of a partition device be the master, if the config flag is set, now that the master is a full device. Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/Kconfig13
-rw-r--r--drivers/mtd/mtdcore.c52
-rw-r--r--drivers/mtd/mtdpart.c18
3 files changed, 62 insertions, 21 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 71fea895ce38..a03ad2951c7b 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -309,6 +309,19 @@ config MTD_SWAP
309 The driver provides wear leveling by storing erase counter into the 309 The driver provides wear leveling by storing erase counter into the
310 OOB. 310 OOB.
311 311
312config MTD_PARTITIONED_MASTER
313 bool "Retain master device when partitioned"
314 default n
315 depends on MTD
316 help
317 For historical reasons, by default, either a master is present or
318 several partitions are present, but not both. The concern was that
319 data listed in multiple partitions was dangerous; however, SCSI does
320 this and it is frequently useful for applications. This config option
321 leaves the master in even if the device is partitioned. It also makes
322 the parent of the partition device be the master device, rather than
323 what lies behind the master.
324
312source "drivers/mtd/chips/Kconfig" 325source "drivers/mtd/chips/Kconfig"
313 326
314source "drivers/mtd/maps/Kconfig" 327source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 11883bd26d9d..d172195fbd15 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -38,6 +38,7 @@
38#include <linux/gfp.h> 38#include <linux/gfp.h>
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <linux/reboot.h> 40#include <linux/reboot.h>
41#include <linux/kconfig.h>
41 42
42#include <linux/mtd/mtd.h> 43#include <linux/mtd/mtd.h>
43#include <linux/mtd/partitions.h> 44#include <linux/mtd/partitions.h>
@@ -501,6 +502,29 @@ out_error:
501 return ret; 502 return ret;
502} 503}
503 504
505static int mtd_add_device_partitions(struct mtd_info *mtd,
506 struct mtd_partition *real_parts,
507 int nbparts)
508{
509 int ret;
510
511 if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
512 ret = add_mtd_device(mtd);
513 if (ret == 1)
514 return -ENODEV;
515 }
516
517 if (nbparts > 0) {
518 ret = add_mtd_partitions(mtd, real_parts, nbparts);
519 if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
520 del_mtd_device(mtd);
521 return ret;
522 }
523
524 return 0;
525}
526
527
504/** 528/**
505 * mtd_device_parse_register - parse partitions and register an MTD device. 529 * mtd_device_parse_register - parse partitions and register an MTD device.
506 * 530 *
@@ -523,7 +547,8 @@ out_error:
523 * found this functions tries to fallback to information specified in 547 * found this functions tries to fallback to information specified in
524 * @parts/@nr_parts. 548 * @parts/@nr_parts.
525 * * If any partitioning info was found, this function registers the found 549 * * If any partitioning info was found, this function registers the found
526 * partitions. 550 * partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
551 * as a whole is registered first.
527 * * If no partitions were found this function just registers the MTD device 552 * * If no partitions were found this function just registers the MTD device
528 * @mtd and exits. 553 * @mtd and exits.
529 * 554 *
@@ -534,27 +559,21 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
534 const struct mtd_partition *parts, 559 const struct mtd_partition *parts,
535 int nr_parts) 560 int nr_parts)
536{ 561{
537 int err; 562 int ret;
538 struct mtd_partition *real_parts; 563 struct mtd_partition *real_parts = NULL;
539 564
540 err = parse_mtd_partitions(mtd, types, &real_parts, parser_data); 565 ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
541 if (err <= 0 && nr_parts && parts) { 566 if (ret <= 0 && nr_parts && parts) {
542 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, 567 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
543 GFP_KERNEL); 568 GFP_KERNEL);
544 if (!real_parts) 569 if (!real_parts)
545 err = -ENOMEM; 570 ret = -ENOMEM;
546 else 571 else
547 err = nr_parts; 572 ret = nr_parts;
548 } 573 }
549 574
550 if (err > 0) { 575 if (ret >= 0)
551 err = add_mtd_partitions(mtd, real_parts, err); 576 ret = mtd_add_device_partitions(mtd, real_parts, ret);
552 kfree(real_parts);
553 } else if (err == 0) {
554 err = add_mtd_device(mtd);
555 if (err == 1)
556 err = -ENODEV;
557 }
558 577
559 /* 578 /*
560 * FIXME: some drivers unfortunately call this function more than once. 579 * FIXME: some drivers unfortunately call this function more than once.
@@ -569,7 +588,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
569 register_reboot_notifier(&mtd->reboot_notifier); 588 register_reboot_notifier(&mtd->reboot_notifier);
570 } 589 }
571 590
572 return err; 591 kfree(real_parts);
592 return ret;
573} 593}
574EXPORT_SYMBOL_GPL(mtd_device_parse_register); 594EXPORT_SYMBOL_GPL(mtd_device_parse_register);
575 595
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index e779de315ade..a19ec5a4e409 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -30,6 +30,7 @@
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/err.h> 32#include <linux/err.h>
33#include <linux/kconfig.h>
33 34
34#include "mtdcore.h" 35#include "mtdcore.h"
35 36
@@ -379,10 +380,17 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
379 slave->mtd.name = name; 380 slave->mtd.name = name;
380 slave->mtd.owner = master->owner; 381 slave->mtd.owner = master->owner;
381 382
382 /* NOTE: we don't arrange MTDs as a tree; it'd be error-prone 383 /* NOTE: Historically, we didn't arrange MTDs as a tree out of
383 * to have the same data be in two different partitions. 384 * concern for showing the same data in multiple partitions.
385 * However, it is very useful to have the master node present,
386 * so the MTD_PARTITIONED_MASTER option allows that. The master
387 * will have device nodes etc only if this is set, so make the
388 * parent conditional on that option. Note, this is a way to
389 * distinguish between the master and the partition in sysfs.
384 */ 390 */
385 slave->mtd.dev.parent = master->dev.parent; 391 slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
392 &master->dev :
393 master->dev.parent;
386 394
387 slave->mtd._read = part_read; 395 slave->mtd._read = part_read;
388 slave->mtd._write = part_write; 396 slave->mtd._write = part_write;
@@ -631,8 +639,8 @@ EXPORT_SYMBOL_GPL(mtd_del_partition);
631 * and registers slave MTD objects which are bound to the master according to 639 * and registers slave MTD objects which are bound to the master according to
632 * the partition definitions. 640 * the partition definitions.
633 * 641 *
634 * We don't register the master, or expect the caller to have done so, 642 * For historical reasons, this function's caller only registers the master
635 * for reasons of data integrity. 643 * if the MTD_PARTITIONED_MASTER config option is set.
636 */ 644 */
637 645
638int add_mtd_partitions(struct mtd_info *master, 646int add_mtd_partitions(struct mtd_info *master,