Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / cpufreq / cpufreq_userspace.c
index d32bf35..071ee4f 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  *  linux/drivers/cpufreq/cpufreq_userspace.c
  *
@@ -21,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/sysfs.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 
@@ -33,14 +35,13 @@ static unsigned int cpu_min_freq[NR_CPUS];
 static unsigned int    cpu_cur_freq[NR_CPUS]; /* current CPU freq */
 static unsigned int    cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
 static unsigned int    cpu_is_managed[NR_CPUS];
-static struct cpufreq_policy current_policy[NR_CPUS];
 
-static DECLARE_MUTEX   (userspace_sem); 
+static DEFINE_MUTEX    (userspace_mutex);
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
 
 /* keep track of frequency transitions */
-static int 
+static int
 userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
                        void *data)
 {
@@ -57,42 +58,41 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
 };
 
 
-/** 
+/**
  * cpufreq_set - set the CPU frequency
  * @freq: target frequency in kHz
  * @cpu: CPU for which the frequency is to be set
  *
  * Sets the CPU frequency to freq.
  */
-static int cpufreq_set(unsigned int freq, unsigned int cpu)
+static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
 {
        int ret = -EINVAL;
 
-       dprintk("cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq);
+       dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
-       down(&userspace_sem);
-       if (!cpu_is_managed[cpu])
+       mutex_lock(&userspace_mutex);
+       if (!cpu_is_managed[policy->cpu])
                goto err;
 
-       cpu_set_freq[cpu] = freq;
+       cpu_set_freq[policy->cpu] = freq;
 
-       if (freq < cpu_min_freq[cpu])
-               freq = cpu_min_freq[cpu];
-       if (freq > cpu_max_freq[cpu])
-               freq = cpu_max_freq[cpu];
+       if (freq < cpu_min_freq[policy->cpu])
+               freq = cpu_min_freq[policy->cpu];
+       if (freq > cpu_max_freq[policy->cpu])
+               freq = cpu_max_freq[policy->cpu];
 
        /*
         * We're safe from concurrent calls to ->target() here
-        * as we hold the userspace_sem lock. If we were calling
+        * as we hold the userspace_mutex lock. If we were calling
         * cpufreq_driver_target, a deadlock situation might occur:
-        * A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock)
-        * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem)
+        * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock)
+        * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex)
         */
-       ret = __cpufreq_driver_target(&current_policy[cpu], freq, 
-             CPUFREQ_RELATION_L);
+       ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
 
  err:
-       up(&userspace_sem);
+       mutex_unlock(&userspace_mutex);
        return ret;
 }
 
@@ -103,8 +103,8 @@ static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
        return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
 }
 
-static ssize_t 
-store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) 
+static ssize_t
+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
 {
        unsigned int freq = 0;
        unsigned int ret;
@@ -113,12 +113,12 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
        if (ret != 1)
                return -EINVAL;
 
-       cpufreq_set(freq, policy->cpu);
+       cpufreq_set(freq, policy);
 
        return count;
 }
 
-static struct freq_attr freq_attr_scaling_setspeed = 
+static struct freq_attr freq_attr_scaling_setspeed =
 {
        .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
        .show = show_speed,
@@ -134,44 +134,48 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
                if (!cpu_online(cpu))
                        return -EINVAL;
                BUG_ON(!policy->cur);
-               down(&userspace_sem);
-               cpu_is_managed[cpu] = 1;                
+               mutex_lock(&userspace_mutex);
+               cpu_is_managed[cpu] = 1;
                cpu_min_freq[cpu] = policy->min;
                cpu_max_freq[cpu] = policy->max;
                cpu_cur_freq[cpu] = policy->cur;
                cpu_set_freq[cpu] = policy->cur;
                sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
-               memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
                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]);
-               up(&userspace_sem);
+               mutex_unlock(&userspace_mutex);
                break;
        case CPUFREQ_GOV_STOP:
-               down(&userspace_sem);
+               mutex_lock(&userspace_mutex);
                cpu_is_managed[cpu] = 0;
                cpu_min_freq[cpu] = 0;
                cpu_max_freq[cpu] = 0;
                cpu_set_freq[cpu] = 0;
                sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
                dprintk("managing cpu %u stopped\n", cpu);
-               up(&userspace_sem);
+               mutex_unlock(&userspace_mutex);
                break;
        case CPUFREQ_GOV_LIMITS:
-               down(&userspace_sem);
-               cpu_min_freq[cpu] = policy->min;
-               cpu_max_freq[cpu] = policy->max;
-               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]);
+               mutex_lock(&userspace_mutex);
+               dprintk("limit event for cpu %u: %u - %u kHz,"
+                       "currently %u kHz, last set to %u kHz\n",
+                       cpu, policy->min, policy->max,
+                       cpu_cur_freq[cpu], cpu_set_freq[cpu]);
                if (policy->max < cpu_set_freq[cpu]) {
-                       __cpufreq_driver_target(&current_policy[cpu], policy->max, 
-                             CPUFREQ_RELATION_H);
-               } else if (policy->min > cpu_set_freq[cpu]) {
-                       __cpufreq_driver_target(&current_policy[cpu], policy->min, 
-                             CPUFREQ_RELATION_L);
-               } else {
-                       __cpufreq_driver_target(&current_policy[cpu], cpu_set_freq[cpu],
-                             CPUFREQ_RELATION_L);
+                       __cpufreq_driver_target(policy, policy->max,
+                                               CPUFREQ_RELATION_H);
+               }
+               else if (policy->min > cpu_set_freq[cpu]) {
+                       __cpufreq_driver_target(policy, policy->min,
+                                               CPUFREQ_RELATION_L);
                }
-               memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
-               up(&userspace_sem);
+               else {
+                       __cpufreq_driver_target(policy, cpu_set_freq[cpu],
+                                               CPUFREQ_RELATION_L);
+               }
+               cpu_min_freq[cpu] = policy->min;
+               cpu_max_freq[cpu] = policy->max;
+               cpu_cur_freq[cpu] = policy->cur;
+               mutex_unlock(&userspace_mutex);
                break;
        }
        return 0;