@@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = {
761
761
* cpufreq_add_dev - add a CPU device
762
762
*
763
763
* Adds the cpufreq interface for a CPU device.
764
+ *
765
+ * The Oracle says: try running cpufreq registration/unregistration concurrently
766
+ * with with cpu hotplugging and all hell will break loose. Tried to clean this
767
+ * mess up, but more thorough testing is needed. - Mathieu
764
768
*/
765
769
static int cpufreq_add_dev (struct sys_device * sys_dev )
766
770
{
@@ -804,23 +808,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
804
808
goto nomem_out ;
805
809
}
806
810
if (!alloc_cpumask_var (& policy -> cpus , GFP_KERNEL )) {
807
- kfree (policy );
808
811
ret = - ENOMEM ;
809
- goto nomem_out ;
812
+ goto err_free_policy ;
810
813
}
811
814
if (!zalloc_cpumask_var (& policy -> related_cpus , GFP_KERNEL )) {
812
- free_cpumask_var (policy -> cpus );
813
- kfree (policy );
814
815
ret = - ENOMEM ;
815
- goto nomem_out ;
816
+ goto err_free_cpumask ;
816
817
}
817
818
818
819
policy -> cpu = cpu ;
819
820
cpumask_copy (policy -> cpus , cpumask_of (cpu ));
820
821
821
822
/* Initially set CPU itself as the policy_cpu */
822
823
per_cpu (policy_cpu , cpu ) = cpu ;
823
- lock_policy_rwsem_write (cpu );
824
+ ret = (lock_policy_rwsem_write (cpu ) < 0 );
825
+ WARN_ON (ret );
824
826
825
827
init_completion (& policy -> kobj_unregister );
826
828
INIT_WORK (& policy -> update , handle_update );
@@ -833,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
833
835
ret = cpufreq_driver -> init (policy );
834
836
if (ret ) {
835
837
dprintk ("initialization failed\n" );
836
- goto err_out ;
838
+ goto err_unlock_policy ;
837
839
}
838
840
policy -> user_policy .min = policy -> min ;
839
841
policy -> user_policy .max = policy -> max ;
@@ -858,15 +860,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
858
860
/* Check for existing affected CPUs.
859
861
* They may not be aware of it due to CPU Hotplug.
860
862
*/
861
- managed_policy = cpufreq_cpu_get (j ); /* FIXME: Where is this released? What about error paths? */
863
+ managed_policy = cpufreq_cpu_get (j );
862
864
if (unlikely (managed_policy )) {
863
865
864
866
/* Set proper policy_cpu */
865
867
unlock_policy_rwsem_write (cpu );
866
868
per_cpu (policy_cpu , cpu ) = managed_policy -> cpu ;
867
869
868
- if (lock_policy_rwsem_write (cpu ) < 0 )
869
- goto err_out_driver_exit ;
870
+ if (lock_policy_rwsem_write (cpu ) < 0 ) {
871
+ /* Should not go through policy unlock path */
872
+ if (cpufreq_driver -> exit )
873
+ cpufreq_driver -> exit (policy );
874
+ ret = - EBUSY ;
875
+ cpufreq_cpu_put (managed_policy );
876
+ goto err_free_cpumask ;
877
+ }
870
878
871
879
spin_lock_irqsave (& cpufreq_driver_lock , flags );
872
880
cpumask_copy (managed_policy -> cpus , policy -> cpus );
@@ -877,12 +885,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
877
885
ret = sysfs_create_link (& sys_dev -> kobj ,
878
886
& managed_policy -> kobj ,
879
887
"cpufreq" );
880
- if (ret )
881
- goto err_out_driver_exit ;
882
-
883
- cpufreq_debug_enable_ratelimit ();
884
- ret = 0 ;
885
- goto err_out_driver_exit ; /* call driver->exit() */
888
+ if (!ret )
889
+ cpufreq_cpu_put (managed_policy );
890
+ /*
891
+ * Success. We only needed to be added to the mask.
892
+ * Call driver->exit() because only the cpu parent of
893
+ * the kobj needed to call init().
894
+ */
895
+ goto out_driver_exit ; /* call driver->exit() */
886
896
}
887
897
}
888
898
#endif
@@ -892,25 +902,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
892
902
ret = kobject_init_and_add (& policy -> kobj , & ktype_cpufreq , & sys_dev -> kobj ,
893
903
"cpufreq" );
894
904
if (ret )
895
- goto err_out_driver_exit ;
905
+ goto out_driver_exit ;
896
906
897
907
/* set up files for this cpu device */
898
908
drv_attr = cpufreq_driver -> attr ;
899
909
while ((drv_attr ) && (* drv_attr )) {
900
910
ret = sysfs_create_file (& policy -> kobj , & ((* drv_attr )-> attr ));
901
911
if (ret )
902
- goto err_out_driver_exit ;
912
+ goto err_out_kobj_put ;
903
913
drv_attr ++ ;
904
914
}
905
915
if (cpufreq_driver -> get ) {
906
916
ret = sysfs_create_file (& policy -> kobj , & cpuinfo_cur_freq .attr );
907
917
if (ret )
908
- goto err_out_driver_exit ;
918
+ goto err_out_kobj_put ;
909
919
}
910
920
if (cpufreq_driver -> target ) {
911
921
ret = sysfs_create_file (& policy -> kobj , & scaling_cur_freq .attr );
912
922
if (ret )
913
- goto err_out_driver_exit ;
923
+ goto err_out_kobj_put ;
914
924
}
915
925
916
926
spin_lock_irqsave (& cpufreq_driver_lock , flags );
@@ -928,12 +938,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
928
938
continue ;
929
939
930
940
dprintk ("CPU %u already managed, adding link\n" , j );
931
- cpufreq_cpu_get (cpu );
941
+ managed_policy = cpufreq_cpu_get (cpu );
932
942
cpu_sys_dev = get_cpu_sysdev (j );
933
943
ret = sysfs_create_link (& cpu_sys_dev -> kobj , & policy -> kobj ,
934
944
"cpufreq" );
935
- if (ret )
945
+ if (ret ) {
946
+ cpufreq_cpu_put (managed_policy );
936
947
goto err_out_unregister ;
948
+ }
937
949
}
938
950
939
951
policy -> governor = NULL ; /* to assure that the starting sequence is
@@ -965,17 +977,20 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
965
977
per_cpu (cpufreq_cpu_data , j ) = NULL ;
966
978
spin_unlock_irqrestore (& cpufreq_driver_lock , flags );
967
979
980
+ err_out_kobj_put :
968
981
kobject_put (& policy -> kobj );
969
982
wait_for_completion (& policy -> kobj_unregister );
970
983
971
- err_out_driver_exit :
984
+ out_driver_exit :
972
985
if (cpufreq_driver -> exit )
973
986
cpufreq_driver -> exit (policy );
974
987
975
- err_out :
988
+ err_unlock_policy :
976
989
unlock_policy_rwsem_write (cpu );
990
+ err_free_cpumask :
991
+ free_cpumask_var (policy -> cpus );
992
+ err_free_policy :
977
993
kfree (policy );
978
-
979
994
nomem_out :
980
995
module_put (cpufreq_driver -> owner );
981
996
module_out :
@@ -1070,8 +1085,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1070
1085
spin_unlock_irqrestore (& cpufreq_driver_lock , flags );
1071
1086
#endif
1072
1087
1073
- unlock_policy_rwsem_write (cpu );
1074
-
1075
1088
if (cpufreq_driver -> target )
1076
1089
__cpufreq_governor (data , CPUFREQ_GOV_STOP );
1077
1090
@@ -1088,6 +1101,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
1088
1101
if (cpufreq_driver -> exit )
1089
1102
cpufreq_driver -> exit (data );
1090
1103
1104
+ unlock_policy_rwsem_write (cpu );
1105
+
1091
1106
free_cpumask_var (data -> related_cpus );
1092
1107
free_cpumask_var (data -> cpus );
1093
1108
kfree (data );
0 commit comments