aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_userspace.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq_userspace.c')
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index d32bf3593cd3..92a0be22a2a9 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -1,3 +1,4 @@
1
1/* 2/*
2 * linux/drivers/cpufreq/cpufreq_userspace.c 3 * linux/drivers/cpufreq/cpufreq_userspace.c
3 * 4 *
@@ -21,6 +22,7 @@
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/fs.h> 23#include <linux/fs.h>
23#include <linux/sysfs.h> 24#include <linux/sysfs.h>
25#include <linux/mutex.h>
24 26
25#include <asm/uaccess.h> 27#include <asm/uaccess.h>
26 28
@@ -33,9 +35,8 @@ static unsigned int cpu_min_freq[NR_CPUS];
33static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */ 35static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */
34static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */ 36static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
35static unsigned int cpu_is_managed[NR_CPUS]; 37static unsigned int cpu_is_managed[NR_CPUS];
36static struct cpufreq_policy current_policy[NR_CPUS];
37 38
38static DECLARE_MUTEX (userspace_sem); 39static DEFINE_MUTEX (userspace_mutex);
39 40
40#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg) 41#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
41 42
@@ -64,35 +65,34 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
64 * 65 *
65 * Sets the CPU frequency to freq. 66 * Sets the CPU frequency to freq.
66 */ 67 */
67static int cpufreq_set(unsigned int freq, unsigned int cpu) 68static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
68{ 69{
69 int ret = -EINVAL; 70 int ret = -EINVAL;
70 71
71 dprintk("cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq); 72 dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
72 73
73 down(&userspace_sem); 74 mutex_lock(&userspace_mutex);
74 if (!cpu_is_managed[cpu]) 75 if (!cpu_is_managed[policy->cpu])
75 goto err; 76 goto err;
76 77
77 cpu_set_freq[cpu] = freq; 78 cpu_set_freq[policy->cpu] = freq;
78 79
79 if (freq < cpu_min_freq[cpu]) 80 if (freq < cpu_min_freq[policy->cpu])
80 freq = cpu_min_freq[cpu]; 81 freq = cpu_min_freq[policy->cpu];
81 if (freq > cpu_max_freq[cpu]) 82 if (freq > cpu_max_freq[policy->cpu])
82 freq = cpu_max_freq[cpu]; 83 freq = cpu_max_freq[policy->cpu];
83 84
84 /* 85 /*
85 * We're safe from concurrent calls to ->target() here 86 * We're safe from concurrent calls to ->target() here
86 * as we hold the userspace_sem lock. If we were calling 87 * as we hold the userspace_mutex lock. If we were calling
87 * cpufreq_driver_target, a deadlock situation might occur: 88 * cpufreq_driver_target, a deadlock situation might occur:
88 * A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock) 89 * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock)
89 * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem) 90 * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex)
90 */ 91 */
91 ret = __cpufreq_driver_target(&current_policy[cpu], freq, 92 ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
92 CPUFREQ_RELATION_L);
93 93
94 err: 94 err:
95 up(&userspace_sem); 95 mutex_unlock(&userspace_mutex);
96 return ret; 96 return ret;
97} 97}
98 98
@@ -113,7 +113,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
113 if (ret != 1) 113 if (ret != 1)
114 return -EINVAL; 114 return -EINVAL;
115 115
116 cpufreq_set(freq, policy->cpu); 116 cpufreq_set(freq, policy);
117 117
118 return count; 118 return count;
119} 119}
@@ -134,44 +134,48 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
134 if (!cpu_online(cpu)) 134 if (!cpu_online(cpu))
135 return -EINVAL; 135 return -EINVAL;
136 BUG_ON(!policy->cur); 136 BUG_ON(!policy->cur);
137 down(&userspace_sem); 137 mutex_lock(&userspace_mutex);
138 cpu_is_managed[cpu] = 1; 138 cpu_is_managed[cpu] = 1;
139 cpu_min_freq[cpu] = policy->min; 139 cpu_min_freq[cpu] = policy->min;
140 cpu_max_freq[cpu] = policy->max; 140 cpu_max_freq[cpu] = policy->max;
141 cpu_cur_freq[cpu] = policy->cur; 141 cpu_cur_freq[cpu] = policy->cur;
142 cpu_set_freq[cpu] = policy->cur; 142 cpu_set_freq[cpu] = policy->cur;
143 sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); 143 sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
144 memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
145 dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]); 144 dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
146 up(&userspace_sem); 145 mutex_unlock(&userspace_mutex);
147 break; 146 break;
148 case CPUFREQ_GOV_STOP: 147 case CPUFREQ_GOV_STOP:
149 down(&userspace_sem); 148 mutex_lock(&userspace_mutex);
150 cpu_is_managed[cpu] = 0; 149 cpu_is_managed[cpu] = 0;
151 cpu_min_freq[cpu] = 0; 150 cpu_min_freq[cpu] = 0;
152 cpu_max_freq[cpu] = 0; 151 cpu_max_freq[cpu] = 0;
153 cpu_set_freq[cpu] = 0; 152 cpu_set_freq[cpu] = 0;
154 sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); 153 sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
155 dprintk("managing cpu %u stopped\n", cpu); 154 dprintk("managing cpu %u stopped\n", cpu);
156 up(&userspace_sem); 155 mutex_unlock(&userspace_mutex);
157 break; 156 break;
158 case CPUFREQ_GOV_LIMITS: 157 case CPUFREQ_GOV_LIMITS:
159 down(&userspace_sem); 158 mutex_lock(&userspace_mutex);
160 cpu_min_freq[cpu] = policy->min; 159 dprintk("limit event for cpu %u: %u - %u kHz,"
161 cpu_max_freq[cpu] = policy->max; 160 "currently %u kHz, last set to %u kHz\n",
162 dprintk("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu], cpu_set_freq[cpu]); 161 cpu, policy->min, policy->max,
162 cpu_cur_freq[cpu], cpu_set_freq[cpu]);
163 if (policy->max < cpu_set_freq[cpu]) { 163 if (policy->max < cpu_set_freq[cpu]) {
164 __cpufreq_driver_target(&current_policy[cpu], policy->max, 164 __cpufreq_driver_target(policy, policy->max,
165 CPUFREQ_RELATION_H); 165 CPUFREQ_RELATION_H);
166 } else if (policy->min > cpu_set_freq[cpu]) { 166 }
167 __cpufreq_driver_target(&current_policy[cpu], policy->min, 167 else if (policy->min > cpu_set_freq[cpu]) {
168 CPUFREQ_RELATION_L); 168 __cpufreq_driver_target(policy, policy->min,
169 } else { 169 CPUFREQ_RELATION_L);
170 __cpufreq_driver_target(&current_policy[cpu], cpu_set_freq[cpu],
171 CPUFREQ_RELATION_L);
172 } 170 }
173 memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy)); 171 else {
174 up(&userspace_sem); 172 __cpufreq_driver_target(policy, cpu_set_freq[cpu],
173 CPUFREQ_RELATION_L);
174 }
175 cpu_min_freq[cpu] = policy->min;
176 cpu_max_freq[cpu] = policy->max;
177 cpu_cur_freq[cpu] = policy->cur;
178 mutex_unlock(&userspace_mutex);
175 break; 179 break;
176 } 180 }
177 return 0; 181 return 0;