@@ -68,7 +68,13 @@ static struct class mtd_class = {
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
+
71
76
static DEFINE_IDR (mtd_idr );
77
+ static DEFINE_IDR (mtd_master_idr );
72
78
73
79
/* These are exported solely for the purpose of mtd_blkdevs.c. You
74
80
should not use them for _anything_ else */
@@ -83,8 +89,9 @@ EXPORT_SYMBOL_GPL(__mtd_next_device);
83
89
84
90
static LIST_HEAD (mtd_notifiers );
85
91
86
-
92
+ #define MTD_MASTER_DEVS 255
87
93
#define MTD_DEVT (index ) MKDEV(MTD_CHAR_MAJOR, (index)*2)
94
+ static dev_t mtd_master_devt ;
88
95
89
96
/* REVISIT once MTD uses the driver model better, whoever allocates
90
97
* the mtd_info will probably want to use the release() hook...
@@ -104,6 +111,17 @@ static void mtd_release(struct device *dev)
104
111
device_destroy (& mtd_class , index + 1 );
105
112
}
106
113
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
+
107
125
static void mtd_device_release (struct kref * kref )
108
126
{
109
127
struct mtd_info * mtd = container_of (kref , struct mtd_info , refcnt );
@@ -367,6 +385,11 @@ static const struct device_type mtd_devtype = {
367
385
.release = mtd_release ,
368
386
};
369
387
388
+ static const struct device_type mtd_master_devtype = {
389
+ .name = "mtd_master" ,
390
+ .release = mtd_master_release ,
391
+ };
392
+
370
393
static bool mtd_expert_analysis_mode ;
371
394
372
395
#ifdef CONFIG_DEBUG_FS
@@ -634,13 +657,13 @@ static void mtd_check_of_node(struct mtd_info *mtd)
634
657
/**
635
658
* add_mtd_device - register an MTD device
636
659
* @mtd: pointer to new MTD device info structure
660
+ * @partitioned: create partitioned device
637
661
*
638
662
* Add a device to the list of MTD devices present in the system, and
639
663
* notify each currently active MTD 'user' of its arrival. Returns
640
664
* zero on success or non-zero on failure.
641
665
*/
642
-
643
- int add_mtd_device (struct mtd_info * mtd )
666
+ int add_mtd_device (struct mtd_info * mtd , bool partitioned )
644
667
{
645
668
struct device_node * np = mtd_get_of_node (mtd );
646
669
struct mtd_info * master = mtd_get_master (mtd );
@@ -687,10 +710,17 @@ int add_mtd_device(struct mtd_info *mtd)
687
710
ofidx = -1 ;
688
711
if (np )
689
712
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
+ }
694
724
if (i < 0 ) {
695
725
error = i ;
696
726
goto fail_locked ;
@@ -738,17 +768,26 @@ int add_mtd_device(struct mtd_info *mtd)
738
768
/* Caller should have set dev.parent to match the
739
769
* physical device, if appropriate.
740
770
*/
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
+ }
745
783
if (error )
746
784
goto fail_devname ;
747
785
dev_set_drvdata (& mtd -> dev , mtd );
748
786
mtd_check_of_node (mtd );
749
787
of_node_get (mtd_get_of_node (mtd ));
750
788
error = device_register (& mtd -> dev );
751
789
if (error ) {
790
+ pr_err ("mtd: %s device_register fail %d\n" , mtd -> name , error );
752
791
put_device (& mtd -> dev );
753
792
goto fail_added ;
754
793
}
@@ -760,24 +799,30 @@ int add_mtd_device(struct mtd_info *mtd)
760
799
761
800
mtd_debugfs_populate (mtd );
762
801
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
+ }
765
806
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 );
767
809
/* No need to get a refcount on the module containing
768
810
the notifier, since we hold the mtd_table_mutex */
769
811
list_for_each_entry (not , & mtd_notifiers , list )
770
812
not -> add (mtd );
771
813
772
814
mutex_unlock (& mtd_table_mutex );
773
815
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
+ }
781
826
}
782
827
}
783
828
@@ -793,7 +838,10 @@ int add_mtd_device(struct mtd_info *mtd)
793
838
fail_added :
794
839
of_node_put (mtd_get_of_node (mtd ));
795
840
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 );
797
845
fail_locked :
798
846
mutex_unlock (& mtd_table_mutex );
799
847
return error ;
@@ -811,12 +859,14 @@ int add_mtd_device(struct mtd_info *mtd)
811
859
812
860
int del_mtd_device (struct mtd_info * mtd )
813
861
{
814
- int ret ;
815
862
struct mtd_notifier * not ;
863
+ struct idr * idr ;
864
+ int ret ;
816
865
817
866
mutex_lock (& mtd_table_mutex );
818
867
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 ) {
820
870
ret = - ENODEV ;
821
871
goto out_error ;
822
872
}
@@ -1056,6 +1106,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
1056
1106
const struct mtd_partition * parts ,
1057
1107
int nr_parts )
1058
1108
{
1109
+ struct mtd_info * parent ;
1059
1110
int ret , err ;
1060
1111
1061
1112
mtd_set_dev_defaults (mtd );
@@ -1064,25 +1115,30 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
1064
1115
if (ret )
1065
1116
goto out ;
1066
1117
1118
+ ret = add_mtd_device (mtd , false);
1119
+ if (ret )
1120
+ goto out ;
1121
+
1067
1122
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 );
1069
1124
if (ret )
1070
1125
goto out ;
1126
+
1127
+ } else {
1128
+ parent = mtd ;
1071
1129
}
1072
1130
1073
1131
/* 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 );
1075
1133
if (ret == - EPROBE_DEFER )
1076
1134
goto out ;
1077
1135
1078
1136
if (ret > 0 )
1079
1137
ret = 0 ;
1080
1138
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 );
1086
1142
1087
1143
if (ret )
1088
1144
goto out ;
@@ -1102,13 +1158,14 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
1102
1158
register_reboot_notifier (& mtd -> reboot_notifier );
1103
1159
}
1104
1160
1161
+ return 0 ;
1105
1162
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 );
1110
1165
1111
- if (ret && device_is_registered (& mtd -> dev )) {
1166
+ del_mtd_partitions (mtd );
1167
+
1168
+ if (device_is_registered (& mtd -> dev )) {
1112
1169
err = del_mtd_device (mtd );
1113
1170
if (err )
1114
1171
pr_err ("Error when deleting MTD device (%d)\n" , err );
@@ -1267,8 +1324,7 @@ int __get_mtd_device(struct mtd_info *mtd)
1267
1324
mtd = mtd -> parent ;
1268
1325
}
1269
1326
1270
- if (IS_ENABLED (CONFIG_MTD_PARTITIONED_MASTER ))
1271
- kref_get (& master -> refcnt );
1327
+ kref_get (& master -> refcnt );
1272
1328
1273
1329
return 0 ;
1274
1330
}
@@ -1362,8 +1418,7 @@ void __put_mtd_device(struct mtd_info *mtd)
1362
1418
mtd = parent ;
1363
1419
}
1364
1420
1365
- if (IS_ENABLED (CONFIG_MTD_PARTITIONED_MASTER ))
1366
- kref_put (& master -> refcnt , mtd_device_release );
1421
+ kref_put (& master -> refcnt , mtd_device_release );
1367
1422
1368
1423
module_put (master -> owner );
1369
1424
@@ -2530,6 +2585,16 @@ static int __init init_mtd(void)
2530
2585
if (ret )
2531
2586
goto err_reg ;
2532
2587
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
+
2533
2598
mtd_bdi = mtd_bdi_init ("mtd" );
2534
2599
if (IS_ERR (mtd_bdi )) {
2535
2600
ret = PTR_ERR (mtd_bdi );
@@ -2554,6 +2619,10 @@ static int __init init_mtd(void)
2554
2619
bdi_unregister (mtd_bdi );
2555
2620
bdi_put (mtd_bdi );
2556
2621
err_bdi :
2622
+ unregister_chrdev_region (mtd_master_devt , MTD_MASTER_DEVS );
2623
+ err_chrdev :
2624
+ class_unregister (& mtd_master_class );
2625
+ err_reg2 :
2557
2626
class_unregister (& mtd_class );
2558
2627
err_reg :
2559
2628
pr_err ("Error registering mtd class or bdi: %d\n" , ret );
@@ -2567,9 +2636,12 @@ static void __exit cleanup_mtd(void)
2567
2636
if (proc_mtd )
2568
2637
remove_proc_entry ("mtd" , NULL );
2569
2638
class_unregister (& mtd_class );
2639
+ class_unregister (& mtd_master_class );
2640
+ unregister_chrdev_region (mtd_master_devt , MTD_MASTER_DEVS );
2570
2641
bdi_unregister (mtd_bdi );
2571
2642
bdi_put (mtd_bdi );
2572
2643
idr_destroy (& mtd_idr );
2644
+ idr_destroy (& mtd_master_idr );
2573
2645
}
2574
2646
2575
2647
module_init (init_mtd );
0 commit comments