Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Revert "mtd: core: always create master device"

The idea behind this patch was to always let a "master" mtd device
available to anchor runtime PM. Historically, there was no mtd device
representing the whole storage as soon as partitions were coming into
play. The introduction of CONFIG_MTD_PARTITIONED_MASTER allowed to keep
this "master" device, but was not enabled by default to avoid breaking
existing users (otherwise the mtd device numbering would be totally
messed up with an off by 1, at least).

The approach of adding an mtd_master class on top of partitioned mtd
devices is breaking the mtd core in many creative ways, so better think
again this approach and revert the faulty changes for now.

This reverts commit 0aa7b390fc40a871267a2328bbbefca8b37ad307.

Fixes: 0aa7b390fc40 ("mtd: core: always create master device")
Tested-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

+51 -123
+1 -1
drivers/mtd/mtdchar.c
··· 559 559 /* Sanitize user input */ 560 560 p.devname[BLKPG_DEVNAMELTH - 1] = '\0'; 561 561 562 - return mtd_add_partition(mtd, p.devname, p.start, p.length, NULL); 562 + return mtd_add_partition(mtd, p.devname, p.start, p.length); 563 563 564 564 case BLKPG_DEL_PARTITION: 565 565
+40 -112
drivers/mtd/mtdcore.c
··· 68 68 .pm = MTD_CLS_PM_OPS, 69 69 }; 70 70 71 - static struct class mtd_master_class = { 72 - .name = "mtd_master", 73 - .pm = MTD_CLS_PM_OPS, 74 - }; 75 - 76 71 static DEFINE_IDR(mtd_idr); 77 - static DEFINE_IDR(mtd_master_idr); 78 72 79 73 /* These are exported solely for the purpose of mtd_blkdevs.c. You 80 74 should not use them for _anything_ else */ ··· 83 89 84 90 static LIST_HEAD(mtd_notifiers); 85 91 86 - #define MTD_MASTER_DEVS 255 92 + 87 93 #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2) 88 - static dev_t mtd_master_devt; 89 94 90 95 /* REVISIT once MTD uses the driver model better, whoever allocates 91 96 * the mtd_info will probably want to use the release() hook... ··· 102 109 103 110 /* remove /dev/mtdXro node */ 104 111 device_destroy(&mtd_class, index + 1); 105 - } 106 - 107 - static void mtd_master_release(struct device *dev) 108 - { 109 - struct mtd_info *mtd = dev_get_drvdata(dev); 110 - 111 - idr_remove(&mtd_master_idr, mtd->index); 112 - of_node_put(mtd_get_of_node(mtd)); 113 - 114 - if (mtd_is_partition(mtd)) 115 - release_mtd_partition(mtd); 116 112 } 117 113 118 114 static void mtd_device_release(struct kref *kref) ··· 365 383 .name = "mtd", 366 384 .groups = mtd_groups, 367 385 .release = mtd_release, 368 - }; 369 - 370 - static const struct device_type mtd_master_devtype = { 371 - .name = "mtd_master", 372 - .release = mtd_master_release, 373 386 }; 374 387 375 388 static bool mtd_expert_analysis_mode; ··· 634 657 /** 635 658 * add_mtd_device - register an MTD device 636 659 * @mtd: pointer to new MTD device info structure 637 - * @partitioned: create partitioned device 638 660 * 639 661 * Add a device to the list of MTD devices present in the system, and 640 662 * notify each currently active MTD 'user' of its arrival. Returns 641 663 * zero on success or non-zero on failure. 642 664 */ 643 - int add_mtd_device(struct mtd_info *mtd, bool partitioned) 665 + 666 + int add_mtd_device(struct mtd_info *mtd) 644 667 { 645 668 struct device_node *np = mtd_get_of_node(mtd); 646 669 struct mtd_info *master = mtd_get_master(mtd); ··· 687 710 ofidx = -1; 688 711 if (np) 689 712 ofidx = of_alias_get_id(np, "mtd"); 690 - if (partitioned) { 691 - if (ofidx >= 0) 692 - i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); 693 - else 694 - i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); 695 - } else { 696 - if (ofidx >= 0) 697 - i = idr_alloc(&mtd_master_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); 698 - else 699 - i = idr_alloc(&mtd_master_idr, mtd, 0, 0, GFP_KERNEL); 700 - } 713 + if (ofidx >= 0) 714 + i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); 715 + else 716 + i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); 701 717 if (i < 0) { 702 718 error = i; 703 719 goto fail_locked; ··· 738 768 /* Caller should have set dev.parent to match the 739 769 * physical device, if appropriate. 740 770 */ 741 - if (partitioned) { 742 - mtd->dev.type = &mtd_devtype; 743 - mtd->dev.class = &mtd_class; 744 - mtd->dev.devt = MTD_DEVT(i); 745 - dev_set_name(&mtd->dev, "mtd%d", i); 746 - error = dev_set_name(&mtd->dev, "mtd%d", i); 747 - } else { 748 - mtd->dev.type = &mtd_master_devtype; 749 - mtd->dev.class = &mtd_master_class; 750 - mtd->dev.devt = MKDEV(MAJOR(mtd_master_devt), i); 751 - error = dev_set_name(&mtd->dev, "mtd_master%d", i); 752 - } 771 + mtd->dev.type = &mtd_devtype; 772 + mtd->dev.class = &mtd_class; 773 + mtd->dev.devt = MTD_DEVT(i); 774 + error = dev_set_name(&mtd->dev, "mtd%d", i); 753 775 if (error) 754 776 goto fail_devname; 755 777 dev_set_drvdata(&mtd->dev, mtd); ··· 749 787 of_node_get(mtd_get_of_node(mtd)); 750 788 error = device_register(&mtd->dev); 751 789 if (error) { 752 - pr_err("mtd: %s device_register fail %d\n", mtd->name, error); 753 790 put_device(&mtd->dev); 754 791 goto fail_added; 755 792 } ··· 760 799 761 800 mtd_debugfs_populate(mtd); 762 801 763 - if (partitioned) { 764 - device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, 765 - "mtd%dro", i); 766 - } 802 + device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, 803 + "mtd%dro", i); 767 804 768 - pr_debug("mtd: Giving out %spartitioned device %d to %s\n", 769 - partitioned ? "" : "un-", i, mtd->name); 805 + pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); 770 806 /* No need to get a refcount on the module containing 771 807 the notifier, since we hold the mtd_table_mutex */ 772 808 list_for_each_entry(not, &mtd_notifiers, list) ··· 771 813 772 814 mutex_unlock(&mtd_table_mutex); 773 815 774 - if (partitioned) { 775 - if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { 776 - if (IS_BUILTIN(CONFIG_MTD)) { 777 - pr_info("mtd: setting mtd%d (%s) as root device\n", 778 - mtd->index, mtd->name); 779 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); 780 - } else { 781 - pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", 782 - mtd->index, mtd->name); 783 - } 816 + if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { 817 + if (IS_BUILTIN(CONFIG_MTD)) { 818 + pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); 819 + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); 820 + } else { 821 + pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", 822 + mtd->index, mtd->name); 784 823 } 785 824 } 786 825 ··· 793 838 fail_added: 794 839 of_node_put(mtd_get_of_node(mtd)); 795 840 fail_devname: 796 - if (partitioned) 797 - idr_remove(&mtd_idr, i); 798 - else 799 - idr_remove(&mtd_master_idr, i); 841 + idr_remove(&mtd_idr, i); 800 842 fail_locked: 801 843 mutex_unlock(&mtd_table_mutex); 802 844 return error; ··· 811 859 812 860 int del_mtd_device(struct mtd_info *mtd) 813 861 { 814 - struct mtd_notifier *not; 815 - struct idr *idr; 816 862 int ret; 863 + struct mtd_notifier *not; 817 864 818 865 mutex_lock(&mtd_table_mutex); 819 866 820 - idr = mtd->dev.class == &mtd_class ? &mtd_idr : &mtd_master_idr; 821 - if (idr_find(idr, mtd->index) != mtd) { 867 + if (idr_find(&mtd_idr, mtd->index) != mtd) { 822 868 ret = -ENODEV; 823 869 goto out_error; 824 870 } ··· 1056 1106 const struct mtd_partition *parts, 1057 1107 int nr_parts) 1058 1108 { 1059 - struct mtd_info *parent; 1060 1109 int ret, err; 1061 1110 1062 1111 mtd_set_dev_defaults(mtd); ··· 1064 1115 if (ret) 1065 1116 goto out; 1066 1117 1067 - ret = add_mtd_device(mtd, false); 1068 - if (ret) 1069 - goto out; 1070 - 1071 1118 if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { 1072 - ret = mtd_add_partition(mtd, mtd->name, 0, MTDPART_SIZ_FULL, &parent); 1119 + ret = add_mtd_device(mtd); 1073 1120 if (ret) 1074 1121 goto out; 1075 - 1076 - } else { 1077 - parent = mtd; 1078 1122 } 1079 1123 1080 1124 /* Prefer parsed partitions over driver-provided fallback */ 1081 - ret = parse_mtd_partitions(parent, types, parser_data); 1125 + ret = parse_mtd_partitions(mtd, types, parser_data); 1082 1126 if (ret == -EPROBE_DEFER) 1083 1127 goto out; 1084 1128 1085 1129 if (ret > 0) 1086 1130 ret = 0; 1087 1131 else if (nr_parts) 1088 - ret = add_mtd_partitions(parent, parts, nr_parts); 1089 - else if (!IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) 1090 - ret = mtd_add_partition(parent, mtd->name, 0, MTDPART_SIZ_FULL, NULL); 1132 + ret = add_mtd_partitions(mtd, parts, nr_parts); 1133 + else if (!device_is_registered(&mtd->dev)) 1134 + ret = add_mtd_device(mtd); 1135 + else 1136 + ret = 0; 1091 1137 1092 1138 if (ret) 1093 1139 goto out; ··· 1102 1158 register_reboot_notifier(&mtd->reboot_notifier); 1103 1159 } 1104 1160 1105 - return 0; 1106 1161 out: 1107 - nvmem_unregister(mtd->otp_user_nvmem); 1108 - nvmem_unregister(mtd->otp_factory_nvmem); 1162 + if (ret) { 1163 + nvmem_unregister(mtd->otp_user_nvmem); 1164 + nvmem_unregister(mtd->otp_factory_nvmem); 1165 + } 1109 1166 1110 - del_mtd_partitions(mtd); 1111 - 1112 - if (device_is_registered(&mtd->dev)) { 1167 + if (ret && device_is_registered(&mtd->dev)) { 1113 1168 err = del_mtd_device(mtd); 1114 1169 if (err) 1115 1170 pr_err("Error when deleting MTD device (%d)\n", err); ··· 1267 1324 mtd = mtd->parent; 1268 1325 } 1269 1326 1270 - kref_get(&master->refcnt); 1327 + if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) 1328 + kref_get(&master->refcnt); 1271 1329 1272 1330 return 0; 1273 1331 } ··· 1362 1418 mtd = parent; 1363 1419 } 1364 1420 1365 - kref_put(&master->refcnt, mtd_device_release); 1421 + if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) 1422 + kref_put(&master->refcnt, mtd_device_release); 1366 1423 1367 1424 module_put(master->owner); 1368 1425 ··· 2530 2585 if (ret) 2531 2586 goto err_reg; 2532 2587 2533 - ret = class_register(&mtd_master_class); 2534 - if (ret) 2535 - goto err_reg2; 2536 - 2537 - ret = alloc_chrdev_region(&mtd_master_devt, 0, MTD_MASTER_DEVS, "mtd_master"); 2538 - if (ret < 0) { 2539 - pr_err("unable to allocate char dev region\n"); 2540 - goto err_chrdev; 2541 - } 2542 - 2543 2588 mtd_bdi = mtd_bdi_init("mtd"); 2544 2589 if (IS_ERR(mtd_bdi)) { 2545 2590 ret = PTR_ERR(mtd_bdi); ··· 2554 2619 bdi_unregister(mtd_bdi); 2555 2620 bdi_put(mtd_bdi); 2556 2621 err_bdi: 2557 - unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS); 2558 - err_chrdev: 2559 - class_unregister(&mtd_master_class); 2560 - err_reg2: 2561 2622 class_unregister(&mtd_class); 2562 2623 err_reg: 2563 2624 pr_err("Error registering mtd class or bdi: %d\n", ret); ··· 2567 2636 if (proc_mtd) 2568 2637 remove_proc_entry("mtd", NULL); 2569 2638 class_unregister(&mtd_class); 2570 - class_unregister(&mtd_master_class); 2571 - unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS); 2572 2639 bdi_unregister(mtd_bdi); 2573 2640 bdi_put(mtd_bdi); 2574 2641 idr_destroy(&mtd_idr); 2575 - idr_destroy(&mtd_master_idr); 2576 2642 } 2577 2643 2578 2644 module_init(init_mtd);
+1 -1
drivers/mtd/mtdcore.h
··· 8 8 extern struct backing_dev_info *mtd_bdi; 9 9 10 10 struct mtd_info *__mtd_next_device(int i); 11 - int __must_check add_mtd_device(struct mtd_info *mtd, bool partitioned); 11 + int __must_check add_mtd_device(struct mtd_info *mtd); 12 12 int del_mtd_device(struct mtd_info *mtd); 13 13 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); 14 14 int del_mtd_partitions(struct mtd_info *);
+8 -8
drivers/mtd/mtdpart.c
··· 86 86 * parent conditional on that option. Note, this is a way to 87 87 * distinguish between the parent and its partitions in sysfs. 88 88 */ 89 - child->dev.parent = &parent->dev; 89 + child->dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ? 90 + &parent->dev : parent->dev.parent; 90 91 child->dev.of_node = part->of_node; 91 92 child->parent = parent; 92 93 child->part.offset = part->offset; ··· 243 242 } 244 243 245 244 int mtd_add_partition(struct mtd_info *parent, const char *name, 246 - long long offset, long long length, struct mtd_info **out) 245 + long long offset, long long length) 247 246 { 248 247 struct mtd_info *master = mtd_get_master(parent); 249 248 u64 parent_size = mtd_is_partition(parent) ? ··· 276 275 list_add_tail(&child->part.node, &parent->partitions); 277 276 mutex_unlock(&master->master.partitions_lock); 278 277 279 - ret = add_mtd_device(child, true); 278 + ret = add_mtd_device(child); 280 279 if (ret) 281 280 goto err_remove_part; 282 281 283 282 mtd_add_partition_attrs(child); 284 - 285 - if (out) 286 - *out = child; 287 283 288 284 return 0; 289 285 ··· 413 415 list_add_tail(&child->part.node, &parent->partitions); 414 416 mutex_unlock(&master->master.partitions_lock); 415 417 416 - ret = add_mtd_device(child, true); 418 + ret = add_mtd_device(child); 417 419 if (ret) { 418 420 mutex_lock(&master->master.partitions_lock); 419 421 list_del(&child->part.node); ··· 590 592 int ret, err = 0; 591 593 592 594 dev = &master->dev; 595 + /* Use parent device (controller) if the top level MTD is not registered */ 596 + if (!IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) && !mtd_is_partition(master)) 597 + dev = master->dev.parent; 593 598 594 599 np = mtd_get_of_node(master); 595 600 if (mtd_is_partition(master)) ··· 711 710 if (ret < 0 && !err) 712 711 err = ret; 713 712 } 714 - 715 713 return err; 716 714 } 717 715
+1 -1
include/linux/mtd/partitions.h
··· 108 108 deregister_mtd_parser) 109 109 110 110 int mtd_add_partition(struct mtd_info *master, const char *name, 111 - long long offset, long long length, struct mtd_info **part); 111 + long long offset, long long length); 112 112 int mtd_del_partition(struct mtd_info *master, int partno); 113 113 uint64_t mtd_get_device_size(const struct mtd_info *mtd); 114 114