Skip to content

Commit 0aa7b39

Browse files
ausyskinmiquelraynal
authored andcommitted
mtd: core: always create master device
Create master device without partition when CONFIG_MTD_PARTITIONED_MASTER flag is unset. This streamlines device tree and allows to anchor runtime power management on master device in all cases. Signed-off-by: Alexander Usyskin <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent 91b7163 commit 0aa7b39

File tree

5 files changed

+123
-51
lines changed

5 files changed

+123
-51
lines changed

drivers/mtd/mtdchar.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
559559
/* Sanitize user input */
560560
p.devname[BLKPG_DEVNAMELTH - 1] = '\0';
561561

562-
return mtd_add_partition(mtd, p.devname, p.start, p.length);
562+
return mtd_add_partition(mtd, p.devname, p.start, p.length, NULL);
563563

564564
case BLKPG_DEL_PARTITION:
565565

drivers/mtd/mtdcore.c

Lines changed: 112 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,13 @@ static struct class mtd_class = {
6868
.pm = MTD_CLS_PM_OPS,
6969
};
7070

71+
static struct class mtd_master_class = {
72+
.name = "mtd_master",
73+
.pm = MTD_CLS_PM_OPS,
74+
};
75+
7176
static DEFINE_IDR(mtd_idr);
77+
static DEFINE_IDR(mtd_master_idr);
7278

7379
/* These are exported solely for the purpose of mtd_blkdevs.c. You
7480
should not use them for _anything_ else */
@@ -83,8 +89,9 @@ EXPORT_SYMBOL_GPL(__mtd_next_device);
8389

8490
static LIST_HEAD(mtd_notifiers);
8591

86-
92+
#define MTD_MASTER_DEVS 255
8793
#define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
94+
static dev_t mtd_master_devt;
8895

8996
/* REVISIT once MTD uses the driver model better, whoever allocates
9097
* the mtd_info will probably want to use the release() hook...
@@ -104,6 +111,17 @@ static void mtd_release(struct device *dev)
104111
device_destroy(&mtd_class, index + 1);
105112
}
106113

114+
static void mtd_master_release(struct device *dev)
115+
{
116+
struct mtd_info *mtd = dev_get_drvdata(dev);
117+
118+
idr_remove(&mtd_master_idr, mtd->index);
119+
of_node_put(mtd_get_of_node(mtd));
120+
121+
if (mtd_is_partition(mtd))
122+
release_mtd_partition(mtd);
123+
}
124+
107125
static void mtd_device_release(struct kref *kref)
108126
{
109127
struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
@@ -367,6 +385,11 @@ static const struct device_type mtd_devtype = {
367385
.release = mtd_release,
368386
};
369387

388+
static const struct device_type mtd_master_devtype = {
389+
.name = "mtd_master",
390+
.release = mtd_master_release,
391+
};
392+
370393
static bool mtd_expert_analysis_mode;
371394

372395
#ifdef CONFIG_DEBUG_FS
@@ -634,13 +657,13 @@ static void mtd_check_of_node(struct mtd_info *mtd)
634657
/**
635658
* add_mtd_device - register an MTD device
636659
* @mtd: pointer to new MTD device info structure
660+
* @partitioned: create partitioned device
637661
*
638662
* Add a device to the list of MTD devices present in the system, and
639663
* notify each currently active MTD 'user' of its arrival. Returns
640664
* zero on success or non-zero on failure.
641665
*/
642-
643-
int add_mtd_device(struct mtd_info *mtd)
666+
int add_mtd_device(struct mtd_info *mtd, bool partitioned)
644667
{
645668
struct device_node *np = mtd_get_of_node(mtd);
646669
struct mtd_info *master = mtd_get_master(mtd);
@@ -687,10 +710,17 @@ int add_mtd_device(struct mtd_info *mtd)
687710
ofidx = -1;
688711
if (np)
689712
ofidx = of_alias_get_id(np, "mtd");
690-
if (ofidx >= 0)
691-
i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL);
692-
else
693-
i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
713+
if (partitioned) {
714+
if (ofidx >= 0)
715+
i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL);
716+
else
717+
i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
718+
} else {
719+
if (ofidx >= 0)
720+
i = idr_alloc(&mtd_master_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL);
721+
else
722+
i = idr_alloc(&mtd_master_idr, mtd, 0, 0, GFP_KERNEL);
723+
}
694724
if (i < 0) {
695725
error = i;
696726
goto fail_locked;
@@ -738,17 +768,26 @@ int add_mtd_device(struct mtd_info *mtd)
738768
/* Caller should have set dev.parent to match the
739769
* physical device, if appropriate.
740770
*/
741-
mtd->dev.type = &mtd_devtype;
742-
mtd->dev.class = &mtd_class;
743-
mtd->dev.devt = MTD_DEVT(i);
744-
error = dev_set_name(&mtd->dev, "mtd%d", i);
771+
if (partitioned) {
772+
mtd->dev.type = &mtd_devtype;
773+
mtd->dev.class = &mtd_class;
774+
mtd->dev.devt = MTD_DEVT(i);
775+
dev_set_name(&mtd->dev, "mtd%d", i);
776+
error = dev_set_name(&mtd->dev, "mtd%d", i);
777+
} else {
778+
mtd->dev.type = &mtd_master_devtype;
779+
mtd->dev.class = &mtd_master_class;
780+
mtd->dev.devt = MKDEV(MAJOR(mtd_master_devt), i);
781+
error = dev_set_name(&mtd->dev, "mtd_master%d", i);
782+
}
745783
if (error)
746784
goto fail_devname;
747785
dev_set_drvdata(&mtd->dev, mtd);
748786
mtd_check_of_node(mtd);
749787
of_node_get(mtd_get_of_node(mtd));
750788
error = device_register(&mtd->dev);
751789
if (error) {
790+
pr_err("mtd: %s device_register fail %d\n", mtd->name, error);
752791
put_device(&mtd->dev);
753792
goto fail_added;
754793
}
@@ -760,24 +799,30 @@ int add_mtd_device(struct mtd_info *mtd)
760799

761800
mtd_debugfs_populate(mtd);
762801

763-
device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
764-
"mtd%dro", i);
802+
if (partitioned) {
803+
device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
804+
"mtd%dro", i);
805+
}
765806

766-
pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
807+
pr_debug("mtd: Giving out %spartitioned device %d to %s\n",
808+
partitioned ? "" : "un-", i, mtd->name);
767809
/* No need to get a refcount on the module containing
768810
the notifier, since we hold the mtd_table_mutex */
769811
list_for_each_entry(not, &mtd_notifiers, list)
770812
not->add(mtd);
771813

772814
mutex_unlock(&mtd_table_mutex);
773815

774-
if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) {
775-
if (IS_BUILTIN(CONFIG_MTD)) {
776-
pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name);
777-
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
778-
} else {
779-
pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n",
780-
mtd->index, mtd->name);
816+
if (partitioned) {
817+
if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) {
818+
if (IS_BUILTIN(CONFIG_MTD)) {
819+
pr_info("mtd: setting mtd%d (%s) as root device\n",
820+
mtd->index, mtd->name);
821+
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
822+
} else {
823+
pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n",
824+
mtd->index, mtd->name);
825+
}
781826
}
782827
}
783828

@@ -793,7 +838,10 @@ int add_mtd_device(struct mtd_info *mtd)
793838
fail_added:
794839
of_node_put(mtd_get_of_node(mtd));
795840
fail_devname:
796-
idr_remove(&mtd_idr, i);
841+
if (partitioned)
842+
idr_remove(&mtd_idr, i);
843+
else
844+
idr_remove(&mtd_master_idr, i);
797845
fail_locked:
798846
mutex_unlock(&mtd_table_mutex);
799847
return error;
@@ -811,12 +859,14 @@ int add_mtd_device(struct mtd_info *mtd)
811859

812860
int del_mtd_device(struct mtd_info *mtd)
813861
{
814-
int ret;
815862
struct mtd_notifier *not;
863+
struct idr *idr;
864+
int ret;
816865

817866
mutex_lock(&mtd_table_mutex);
818867

819-
if (idr_find(&mtd_idr, mtd->index) != mtd) {
868+
idr = mtd->dev.class == &mtd_class ? &mtd_idr : &mtd_master_idr;
869+
if (idr_find(idr, mtd->index) != mtd) {
820870
ret = -ENODEV;
821871
goto out_error;
822872
}
@@ -1056,6 +1106,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
10561106
const struct mtd_partition *parts,
10571107
int nr_parts)
10581108
{
1109+
struct mtd_info *parent;
10591110
int ret, err;
10601111

10611112
mtd_set_dev_defaults(mtd);
@@ -1064,25 +1115,30 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
10641115
if (ret)
10651116
goto out;
10661117

1118+
ret = add_mtd_device(mtd, false);
1119+
if (ret)
1120+
goto out;
1121+
10671122
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
1068-
ret = add_mtd_device(mtd);
1123+
ret = mtd_add_partition(mtd, mtd->name, 0, MTDPART_SIZ_FULL, &parent);
10691124
if (ret)
10701125
goto out;
1126+
1127+
} else {
1128+
parent = mtd;
10711129
}
10721130

10731131
/* Prefer parsed partitions over driver-provided fallback */
1074-
ret = parse_mtd_partitions(mtd, types, parser_data);
1132+
ret = parse_mtd_partitions(parent, types, parser_data);
10751133
if (ret == -EPROBE_DEFER)
10761134
goto out;
10771135

10781136
if (ret > 0)
10791137
ret = 0;
10801138
else if (nr_parts)
1081-
ret = add_mtd_partitions(mtd, parts, nr_parts);
1082-
else if (!device_is_registered(&mtd->dev))
1083-
ret = add_mtd_device(mtd);
1084-
else
1085-
ret = 0;
1139+
ret = add_mtd_partitions(parent, parts, nr_parts);
1140+
else if (!IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
1141+
ret = mtd_add_partition(parent, mtd->name, 0, MTDPART_SIZ_FULL, NULL);
10861142

10871143
if (ret)
10881144
goto out;
@@ -1102,13 +1158,14 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
11021158
register_reboot_notifier(&mtd->reboot_notifier);
11031159
}
11041160

1161+
return 0;
11051162
out:
1106-
if (ret) {
1107-
nvmem_unregister(mtd->otp_user_nvmem);
1108-
nvmem_unregister(mtd->otp_factory_nvmem);
1109-
}
1163+
nvmem_unregister(mtd->otp_user_nvmem);
1164+
nvmem_unregister(mtd->otp_factory_nvmem);
11101165

1111-
if (ret && device_is_registered(&mtd->dev)) {
1166+
del_mtd_partitions(mtd);
1167+
1168+
if (device_is_registered(&mtd->dev)) {
11121169
err = del_mtd_device(mtd);
11131170
if (err)
11141171
pr_err("Error when deleting MTD device (%d)\n", err);
@@ -1267,8 +1324,7 @@ int __get_mtd_device(struct mtd_info *mtd)
12671324
mtd = mtd->parent;
12681325
}
12691326

1270-
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
1271-
kref_get(&master->refcnt);
1327+
kref_get(&master->refcnt);
12721328

12731329
return 0;
12741330
}
@@ -1362,8 +1418,7 @@ void __put_mtd_device(struct mtd_info *mtd)
13621418
mtd = parent;
13631419
}
13641420

1365-
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
1366-
kref_put(&master->refcnt, mtd_device_release);
1421+
kref_put(&master->refcnt, mtd_device_release);
13671422

13681423
module_put(master->owner);
13691424

@@ -2530,6 +2585,16 @@ static int __init init_mtd(void)
25302585
if (ret)
25312586
goto err_reg;
25322587

2588+
ret = class_register(&mtd_master_class);
2589+
if (ret)
2590+
goto err_reg2;
2591+
2592+
ret = alloc_chrdev_region(&mtd_master_devt, 0, MTD_MASTER_DEVS, "mtd_master");
2593+
if (ret < 0) {
2594+
pr_err("unable to allocate char dev region\n");
2595+
goto err_chrdev;
2596+
}
2597+
25332598
mtd_bdi = mtd_bdi_init("mtd");
25342599
if (IS_ERR(mtd_bdi)) {
25352600
ret = PTR_ERR(mtd_bdi);
@@ -2554,6 +2619,10 @@ static int __init init_mtd(void)
25542619
bdi_unregister(mtd_bdi);
25552620
bdi_put(mtd_bdi);
25562621
err_bdi:
2622+
unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS);
2623+
err_chrdev:
2624+
class_unregister(&mtd_master_class);
2625+
err_reg2:
25572626
class_unregister(&mtd_class);
25582627
err_reg:
25592628
pr_err("Error registering mtd class or bdi: %d\n", ret);
@@ -2567,9 +2636,12 @@ static void __exit cleanup_mtd(void)
25672636
if (proc_mtd)
25682637
remove_proc_entry("mtd", NULL);
25692638
class_unregister(&mtd_class);
2639+
class_unregister(&mtd_master_class);
2640+
unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS);
25702641
bdi_unregister(mtd_bdi);
25712642
bdi_put(mtd_bdi);
25722643
idr_destroy(&mtd_idr);
2644+
idr_destroy(&mtd_master_idr);
25732645
}
25742646

25752647
module_init(init_mtd);

drivers/mtd/mtdcore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern struct mutex mtd_table_mutex;
88
extern struct backing_dev_info *mtd_bdi;
99

1010
struct mtd_info *__mtd_next_device(int i);
11-
int __must_check add_mtd_device(struct mtd_info *mtd);
11+
int __must_check add_mtd_device(struct mtd_info *mtd, bool partitioned);
1212
int del_mtd_device(struct mtd_info *mtd);
1313
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
1414
int del_mtd_partitions(struct mtd_info *);

0 commit comments

Comments
 (0)