diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ff57c40e9b8b..75d293eeb3ee 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -64,14 +64,14 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); | |||
64 | * - Lock should not be held across | 64 | * - Lock should not be held across |
65 | * __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 65 | * __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
66 | */ | 66 | */ |
67 | static DEFINE_PER_CPU(int, policy_cpu); | 67 | static DEFINE_PER_CPU(int, cpufreq_policy_cpu); |
68 | static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem); | 68 | static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem); |
69 | 69 | ||
70 | #define lock_policy_rwsem(mode, cpu) \ | 70 | #define lock_policy_rwsem(mode, cpu) \ |
71 | int lock_policy_rwsem_##mode \ | 71 | int lock_policy_rwsem_##mode \ |
72 | (int cpu) \ | 72 | (int cpu) \ |
73 | { \ | 73 | { \ |
74 | int policy_cpu = per_cpu(policy_cpu, cpu); \ | 74 | int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \ |
75 | BUG_ON(policy_cpu == -1); \ | 75 | BUG_ON(policy_cpu == -1); \ |
76 | down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ | 76 | down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \ |
77 | if (unlikely(!cpu_online(cpu))) { \ | 77 | if (unlikely(!cpu_online(cpu))) { \ |
@@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(lock_policy_rwsem_write); | |||
90 | 90 | ||
91 | void unlock_policy_rwsem_read(int cpu) | 91 | void unlock_policy_rwsem_read(int cpu) |
92 | { | 92 | { |
93 | int policy_cpu = per_cpu(policy_cpu, cpu); | 93 | int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); |
94 | BUG_ON(policy_cpu == -1); | 94 | BUG_ON(policy_cpu == -1); |
95 | up_read(&per_cpu(cpu_policy_rwsem, policy_cpu)); | 95 | up_read(&per_cpu(cpu_policy_rwsem, policy_cpu)); |
96 | } | 96 | } |
@@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read); | |||
98 | 98 | ||
99 | void unlock_policy_rwsem_write(int cpu) | 99 | void unlock_policy_rwsem_write(int cpu) |
100 | { | 100 | { |
101 | int policy_cpu = per_cpu(policy_cpu, cpu); | 101 | int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); |
102 | BUG_ON(policy_cpu == -1); | 102 | BUG_ON(policy_cpu == -1); |
103 | up_write(&per_cpu(cpu_policy_rwsem, policy_cpu)); | 103 | up_write(&per_cpu(cpu_policy_rwsem, policy_cpu)); |
104 | } | 104 | } |
@@ -647,6 +647,21 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) | |||
647 | return policy->governor->show_setspeed(policy, buf); | 647 | return policy->governor->show_setspeed(policy, buf); |
648 | } | 648 | } |
649 | 649 | ||
650 | /** | ||
651 | * show_scaling_driver - show the current cpufreq HW/BIOS limitation | ||
652 | */ | ||
653 | static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) | ||
654 | { | ||
655 | unsigned int limit; | ||
656 | int ret; | ||
657 | if (cpufreq_driver->bios_limit) { | ||
658 | ret = cpufreq_driver->bios_limit(policy->cpu, &limit); | ||
659 | if (!ret) | ||
660 | return sprintf(buf, "%u\n", limit); | ||
661 | } | ||
662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); | ||
663 | } | ||
664 | |||
650 | #define define_one_ro(_name) \ | 665 | #define define_one_ro(_name) \ |
651 | static struct freq_attr _name = \ | 666 | static struct freq_attr _name = \ |
652 | __ATTR(_name, 0444, show_##_name, NULL) | 667 | __ATTR(_name, 0444, show_##_name, NULL) |
@@ -666,6 +681,7 @@ define_one_ro(cpuinfo_transition_latency); | |||
666 | define_one_ro(scaling_available_governors); | 681 | define_one_ro(scaling_available_governors); |
667 | define_one_ro(scaling_driver); | 682 | define_one_ro(scaling_driver); |
668 | define_one_ro(scaling_cur_freq); | 683 | define_one_ro(scaling_cur_freq); |
684 | define_one_ro(bios_limit); | ||
669 | define_one_ro(related_cpus); | 685 | define_one_ro(related_cpus); |
670 | define_one_ro(affected_cpus); | 686 | define_one_ro(affected_cpus); |
671 | define_one_rw(scaling_min_freq); | 687 | define_one_rw(scaling_min_freq); |
@@ -750,7 +766,7 @@ static void cpufreq_sysfs_release(struct kobject *kobj) | |||
750 | complete(&policy->kobj_unregister); | 766 | complete(&policy->kobj_unregister); |
751 | } | 767 | } |
752 | 768 | ||
753 | static struct sysfs_ops sysfs_ops = { | 769 | static const struct sysfs_ops sysfs_ops = { |
754 | .show = show, | 770 | .show = show, |
755 | .store = store, | 771 | .store = store, |
756 | }; | 772 | }; |
@@ -767,8 +783,9 @@ static struct kobj_type ktype_cpufreq = { | |||
767 | * 0: Success | 783 | * 0: Success |
768 | * Positive: When we have a managed CPU and the sysfs got symlinked | 784 | * Positive: When we have a managed CPU and the sysfs got symlinked |
769 | */ | 785 | */ |
770 | int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, | 786 | static int cpufreq_add_dev_policy(unsigned int cpu, |
771 | struct sys_device *sys_dev) | 787 | struct cpufreq_policy *policy, |
788 | struct sys_device *sys_dev) | ||
772 | { | 789 | { |
773 | int ret = 0; | 790 | int ret = 0; |
774 | #ifdef CONFIG_SMP | 791 | #ifdef CONFIG_SMP |
@@ -801,7 +818,7 @@ int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, | |||
801 | 818 | ||
802 | /* Set proper policy_cpu */ | 819 | /* Set proper policy_cpu */ |
803 | unlock_policy_rwsem_write(cpu); | 820 | unlock_policy_rwsem_write(cpu); |
804 | per_cpu(policy_cpu, cpu) = managed_policy->cpu; | 821 | per_cpu(cpufreq_policy_cpu, cpu) = managed_policy->cpu; |
805 | 822 | ||
806 | if (lock_policy_rwsem_write(cpu) < 0) { | 823 | if (lock_policy_rwsem_write(cpu) < 0) { |
807 | /* Should not go through policy unlock path */ | 824 | /* Should not go through policy unlock path */ |
@@ -842,7 +859,8 @@ int cpufreq_add_dev_policy(unsigned int cpu, struct cpufreq_policy *policy, | |||
842 | 859 | ||
843 | 860 | ||
844 | /* symlink affected CPUs */ | 861 | /* symlink affected CPUs */ |
845 | int cpufreq_add_dev_symlink(unsigned int cpu, struct cpufreq_policy *policy) | 862 | static int cpufreq_add_dev_symlink(unsigned int cpu, |
863 | struct cpufreq_policy *policy) | ||
846 | { | 864 | { |
847 | unsigned int j; | 865 | unsigned int j; |
848 | int ret = 0; | 866 | int ret = 0; |
@@ -869,8 +887,9 @@ int cpufreq_add_dev_symlink(unsigned int cpu, struct cpufreq_policy *policy) | |||
869 | return ret; | 887 | return ret; |
870 | } | 888 | } |
871 | 889 | ||
872 | int cpufreq_add_dev_interface(unsigned int cpu, struct cpufreq_policy *policy, | 890 | static int cpufreq_add_dev_interface(unsigned int cpu, |
873 | struct sys_device *sys_dev) | 891 | struct cpufreq_policy *policy, |
892 | struct sys_device *sys_dev) | ||
874 | { | 893 | { |
875 | struct cpufreq_policy new_policy; | 894 | struct cpufreq_policy new_policy; |
876 | struct freq_attr **drv_attr; | 895 | struct freq_attr **drv_attr; |
@@ -902,13 +921,18 @@ int cpufreq_add_dev_interface(unsigned int cpu, struct cpufreq_policy *policy, | |||
902 | if (ret) | 921 | if (ret) |
903 | goto err_out_kobj_put; | 922 | goto err_out_kobj_put; |
904 | } | 923 | } |
924 | if (cpufreq_driver->bios_limit) { | ||
925 | ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); | ||
926 | if (ret) | ||
927 | goto err_out_kobj_put; | ||
928 | } | ||
905 | 929 | ||
906 | spin_lock_irqsave(&cpufreq_driver_lock, flags); | 930 | spin_lock_irqsave(&cpufreq_driver_lock, flags); |
907 | for_each_cpu(j, policy->cpus) { | 931 | for_each_cpu(j, policy->cpus) { |
908 | if (!cpu_online(j)) | 932 | if (!cpu_online(j)) |
909 | continue; | 933 | continue; |
910 | per_cpu(cpufreq_cpu_data, j) = policy; | 934 | per_cpu(cpufreq_cpu_data, j) = policy; |
911 | per_cpu(policy_cpu, j) = policy->cpu; | 935 | per_cpu(cpufreq_policy_cpu, j) = policy->cpu; |
912 | } | 936 | } |
913 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 937 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
914 | 938 | ||
@@ -996,7 +1020,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
996 | cpumask_copy(policy->cpus, cpumask_of(cpu)); | 1020 | cpumask_copy(policy->cpus, cpumask_of(cpu)); |
997 | 1021 | ||
998 | /* Initially set CPU itself as the policy_cpu */ | 1022 | /* Initially set CPU itself as the policy_cpu */ |
999 | per_cpu(policy_cpu, cpu) = cpu; | 1023 | per_cpu(cpufreq_policy_cpu, cpu) = cpu; |
1000 | ret = (lock_policy_rwsem_write(cpu) < 0); | 1024 | ret = (lock_policy_rwsem_write(cpu) < 0); |
1001 | WARN_ON(ret); | 1025 | WARN_ON(ret); |
1002 | 1026 | ||
@@ -1089,6 +1113,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
1089 | unsigned int cpu = sys_dev->id; | 1113 | unsigned int cpu = sys_dev->id; |
1090 | unsigned long flags; | 1114 | unsigned long flags; |
1091 | struct cpufreq_policy *data; | 1115 | struct cpufreq_policy *data; |
1116 | struct kobject *kobj; | ||
1117 | struct completion *cmp; | ||
1092 | #ifdef CONFIG_SMP | 1118 | #ifdef CONFIG_SMP |
1093 | struct sys_device *cpu_sys_dev; | 1119 | struct sys_device *cpu_sys_dev; |
1094 | unsigned int j; | 1120 | unsigned int j; |
@@ -1117,10 +1143,11 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
1117 | dprintk("removing link\n"); | 1143 | dprintk("removing link\n"); |
1118 | cpumask_clear_cpu(cpu, data->cpus); | 1144 | cpumask_clear_cpu(cpu, data->cpus); |
1119 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1145 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
1120 | sysfs_remove_link(&sys_dev->kobj, "cpufreq"); | 1146 | kobj = &sys_dev->kobj; |
1121 | cpufreq_cpu_put(data); | 1147 | cpufreq_cpu_put(data); |
1122 | cpufreq_debug_enable_ratelimit(); | 1148 | cpufreq_debug_enable_ratelimit(); |
1123 | unlock_policy_rwsem_write(cpu); | 1149 | unlock_policy_rwsem_write(cpu); |
1150 | sysfs_remove_link(kobj, "cpufreq"); | ||
1124 | return 0; | 1151 | return 0; |
1125 | } | 1152 | } |
1126 | #endif | 1153 | #endif |
@@ -1157,7 +1184,10 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
1157 | data->governor->name, CPUFREQ_NAME_LEN); | 1184 | data->governor->name, CPUFREQ_NAME_LEN); |
1158 | #endif | 1185 | #endif |
1159 | cpu_sys_dev = get_cpu_sysdev(j); | 1186 | cpu_sys_dev = get_cpu_sysdev(j); |
1160 | sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); | 1187 | kobj = &cpu_sys_dev->kobj; |
1188 | unlock_policy_rwsem_write(cpu); | ||
1189 | sysfs_remove_link(kobj, "cpufreq"); | ||
1190 | lock_policy_rwsem_write(cpu); | ||
1161 | cpufreq_cpu_put(data); | 1191 | cpufreq_cpu_put(data); |
1162 | } | 1192 | } |
1163 | } | 1193 | } |
@@ -1168,19 +1198,22 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
1168 | if (cpufreq_driver->target) | 1198 | if (cpufreq_driver->target) |
1169 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 1199 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
1170 | 1200 | ||
1171 | kobject_put(&data->kobj); | 1201 | kobj = &data->kobj; |
1202 | cmp = &data->kobj_unregister; | ||
1203 | unlock_policy_rwsem_write(cpu); | ||
1204 | kobject_put(kobj); | ||
1172 | 1205 | ||
1173 | /* we need to make sure that the underlying kobj is actually | 1206 | /* we need to make sure that the underlying kobj is actually |
1174 | * not referenced anymore by anybody before we proceed with | 1207 | * not referenced anymore by anybody before we proceed with |
1175 | * unloading. | 1208 | * unloading. |
1176 | */ | 1209 | */ |
1177 | dprintk("waiting for dropping of refcount\n"); | 1210 | dprintk("waiting for dropping of refcount\n"); |
1178 | wait_for_completion(&data->kobj_unregister); | 1211 | wait_for_completion(cmp); |
1179 | dprintk("wait complete\n"); | 1212 | dprintk("wait complete\n"); |
1180 | 1213 | ||
1214 | lock_policy_rwsem_write(cpu); | ||
1181 | if (cpufreq_driver->exit) | 1215 | if (cpufreq_driver->exit) |
1182 | cpufreq_driver->exit(data); | 1216 | cpufreq_driver->exit(data); |
1183 | |||
1184 | unlock_policy_rwsem_write(cpu); | 1217 | unlock_policy_rwsem_write(cpu); |
1185 | 1218 | ||
1186 | free_cpumask_var(data->related_cpus); | 1219 | free_cpumask_var(data->related_cpus); |
@@ -1978,7 +2011,7 @@ static int __init cpufreq_core_init(void) | |||
1978 | int cpu; | 2011 | int cpu; |
1979 | 2012 | ||
1980 | for_each_possible_cpu(cpu) { | 2013 | for_each_possible_cpu(cpu) { |
1981 | per_cpu(policy_cpu, cpu) = -1; | 2014 | per_cpu(cpufreq_policy_cpu, cpu) = -1; |
1982 | init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); | 2015 | init_rwsem(&per_cpu(cpu_policy_rwsem, cpu)); |
1983 | } | 2016 | } |
1984 | 2017 | ||