@@ -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+
7176static 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
8490static 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+
107125static 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+
370393static 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)
793838fail_added :
794839 of_node_put (mtd_get_of_node (mtd ));
795840fail_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 );
797845fail_locked :
798846 mutex_unlock (& mtd_table_mutex );
799847 return error ;
@@ -811,12 +859,14 @@ int add_mtd_device(struct mtd_info *mtd)
811859
812860int 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 ;
11051162out :
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 );
25562621err_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 );
25582627err_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
25752647module_init (init_mtd );
0 commit comments