1 2 /* 3 * linux/drivers/cpufreq/cpufreq_userspace.c 4 * 5 * Copyright (C) 2001 Russell King 6 * (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16 #include <linux/cpufreq.h> 17 #include <linux/init.h> 18 #include <linux/module.h> 19 #include <linux/mutex.h> 20 21 static DEFINE_PER_CPU(unsigned int, cpu_is_managed); 22 static DEFINE_MUTEX(userspace_mutex); 23 24 /** 25 * cpufreq_set - set the CPU frequency 26 * @policy: pointer to policy struct where freq is being set 27 * @freq: target frequency in kHz 28 * 29 * Sets the CPU frequency to freq. 30 */ 31 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) 32 { 33 int ret = -EINVAL; 34 35 pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); 36 37 mutex_lock(&userspace_mutex); 38 if (!per_cpu(cpu_is_managed, policy->cpu)) 39 goto err; 40 41 /* 42 * We're safe from concurrent calls to ->target() here 43 * as we hold the userspace_mutex lock. If we were calling 44 * cpufreq_driver_target, a deadlock situation might occur: 45 * A: cpufreq_set (lock userspace_mutex) -> 46 * cpufreq_driver_target(lock policy->lock) 47 * B: cpufreq_set_policy(lock policy->lock) -> 48 * __cpufreq_governor -> 49 * cpufreq_governor_userspace (lock userspace_mutex) 50 */ 51 ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); 52 53 err: 54 mutex_unlock(&userspace_mutex); 55 return ret; 56 } 57 58 static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) 59 { 60 return sprintf(buf, "%u\n", policy->cur); 61 } 62 63 static int cpufreq_governor_userspace(struct cpufreq_policy *policy, 64 unsigned int event) 65 { 66 unsigned int cpu = policy->cpu; 67 int rc = 0; 68 69 switch (event) { 70 case CPUFREQ_GOV_START: 71 BUG_ON(!policy->cur); 72 pr_debug("started managing cpu %u\n", cpu); 73 74 mutex_lock(&userspace_mutex); 75 per_cpu(cpu_is_managed, cpu) = 1; 76 mutex_unlock(&userspace_mutex); 77 break; 78 case CPUFREQ_GOV_STOP: 79 pr_debug("managing cpu %u stopped\n", cpu); 80 81 mutex_lock(&userspace_mutex); 82 per_cpu(cpu_is_managed, cpu) = 0; 83 mutex_unlock(&userspace_mutex); 84 break; 85 case CPUFREQ_GOV_LIMITS: 86 mutex_lock(&userspace_mutex); 87 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz\n", 88 cpu, policy->min, policy->max, 89 policy->cur); 90 91 if (policy->max < policy->cur) 92 __cpufreq_driver_target(policy, policy->max, 93 CPUFREQ_RELATION_H); 94 else if (policy->min > policy->cur) 95 __cpufreq_driver_target(policy, policy->min, 96 CPUFREQ_RELATION_L); 97 mutex_unlock(&userspace_mutex); 98 break; 99 } 100 return rc; 101 } 102 103 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE 104 static 105 #endif 106 struct cpufreq_governor cpufreq_gov_userspace = { 107 .name = "userspace", 108 .governor = cpufreq_governor_userspace, 109 .store_setspeed = cpufreq_set, 110 .show_setspeed = show_speed, 111 .owner = THIS_MODULE, 112 }; 113 114 static int __init cpufreq_gov_userspace_init(void) 115 { 116 return cpufreq_register_governor(&cpufreq_gov_userspace); 117 } 118 119 static void __exit cpufreq_gov_userspace_exit(void) 120 { 121 cpufreq_unregister_governor(&cpufreq_gov_userspace); 122 } 123 124 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, " 125 "Russell King <rmk@arm.linux.org.uk>"); 126 MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); 127 MODULE_LICENSE("GPL"); 128 129 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE 130 fs_initcall(cpufreq_gov_userspace_init); 131 #else 132 module_init(cpufreq_gov_userspace_init); 133 #endif 134 module_exit(cpufreq_gov_userspace_exit); 135