1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/drivers/cpufreq/cpufreq.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 2001 Russell King 5*1da177e4SLinus Torvalds * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 8*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 9*1da177e4SLinus Torvalds * published by the Free Software Foundation. 10*1da177e4SLinus Torvalds * 11*1da177e4SLinus Torvalds */ 12*1da177e4SLinus Torvalds 13*1da177e4SLinus Torvalds #include <linux/config.h> 14*1da177e4SLinus Torvalds #include <linux/kernel.h> 15*1da177e4SLinus Torvalds #include <linux/module.h> 16*1da177e4SLinus Torvalds #include <linux/init.h> 17*1da177e4SLinus Torvalds #include <linux/notifier.h> 18*1da177e4SLinus Torvalds #include <linux/cpufreq.h> 19*1da177e4SLinus Torvalds #include <linux/delay.h> 20*1da177e4SLinus Torvalds #include <linux/interrupt.h> 21*1da177e4SLinus Torvalds #include <linux/spinlock.h> 22*1da177e4SLinus Torvalds #include <linux/device.h> 23*1da177e4SLinus Torvalds #include <linux/slab.h> 24*1da177e4SLinus Torvalds #include <linux/cpu.h> 25*1da177e4SLinus Torvalds #include <linux/completion.h> 26*1da177e4SLinus Torvalds 27*1da177e4SLinus Torvalds #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds /** 30*1da177e4SLinus Torvalds * The "cpufreq driver" - the arch- or hardware-dependend low 31*1da177e4SLinus Torvalds * level driver of CPUFreq support, and its spinlock. This lock 32*1da177e4SLinus Torvalds * also protects the cpufreq_cpu_data array. 33*1da177e4SLinus Torvalds */ 34*1da177e4SLinus Torvalds static struct cpufreq_driver *cpufreq_driver; 35*1da177e4SLinus Torvalds static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; 36*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(cpufreq_driver_lock); 37*1da177e4SLinus Torvalds 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds /* we keep a copy of all ->add'ed CPU's struct sys_device here; 40*1da177e4SLinus Torvalds * as it is only accessed in ->add and ->remove, no lock or reference 41*1da177e4SLinus Torvalds * count is necessary. 42*1da177e4SLinus Torvalds */ 43*1da177e4SLinus Torvalds static struct sys_device *cpu_sys_devices[NR_CPUS]; 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds /* internal prototypes */ 47*1da177e4SLinus Torvalds static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); 48*1da177e4SLinus Torvalds static void handle_update(void *data); 49*1da177e4SLinus Torvalds static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci); 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds /** 52*1da177e4SLinus Torvalds * Two notifier lists: the "policy" list is involved in the 53*1da177e4SLinus Torvalds * validation process for a new CPU frequency policy; the 54*1da177e4SLinus Torvalds * "transition" list for kernel code that needs to handle 55*1da177e4SLinus Torvalds * changes to devices when the CPU clock speed changes. 56*1da177e4SLinus Torvalds * The mutex locks both lists. 57*1da177e4SLinus Torvalds */ 58*1da177e4SLinus Torvalds static struct notifier_block *cpufreq_policy_notifier_list; 59*1da177e4SLinus Torvalds static struct notifier_block *cpufreq_transition_notifier_list; 60*1da177e4SLinus Torvalds static DECLARE_RWSEM (cpufreq_notifier_rwsem); 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds static LIST_HEAD(cpufreq_governor_list); 64*1da177e4SLinus Torvalds static DECLARE_MUTEX (cpufreq_governor_sem); 65*1da177e4SLinus Torvalds 66*1da177e4SLinus Torvalds struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) 67*1da177e4SLinus Torvalds { 68*1da177e4SLinus Torvalds struct cpufreq_policy *data; 69*1da177e4SLinus Torvalds unsigned long flags; 70*1da177e4SLinus Torvalds 71*1da177e4SLinus Torvalds if (cpu >= NR_CPUS) 72*1da177e4SLinus Torvalds goto err_out; 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds /* get the cpufreq driver */ 75*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds if (!cpufreq_driver) 78*1da177e4SLinus Torvalds goto err_out_unlock; 79*1da177e4SLinus Torvalds 80*1da177e4SLinus Torvalds if (!try_module_get(cpufreq_driver->owner)) 81*1da177e4SLinus Torvalds goto err_out_unlock; 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds /* get the CPU */ 85*1da177e4SLinus Torvalds data = cpufreq_cpu_data[cpu]; 86*1da177e4SLinus Torvalds 87*1da177e4SLinus Torvalds if (!data) 88*1da177e4SLinus Torvalds goto err_out_put_module; 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds if (!kobject_get(&data->kobj)) 91*1da177e4SLinus Torvalds goto err_out_put_module; 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 95*1da177e4SLinus Torvalds 96*1da177e4SLinus Torvalds return data; 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds err_out_put_module: 99*1da177e4SLinus Torvalds module_put(cpufreq_driver->owner); 100*1da177e4SLinus Torvalds err_out_unlock: 101*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 102*1da177e4SLinus Torvalds err_out: 103*1da177e4SLinus Torvalds return NULL; 104*1da177e4SLinus Torvalds } 105*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_get); 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds void cpufreq_cpu_put(struct cpufreq_policy *data) 108*1da177e4SLinus Torvalds { 109*1da177e4SLinus Torvalds kobject_put(&data->kobj); 110*1da177e4SLinus Torvalds module_put(cpufreq_driver->owner); 111*1da177e4SLinus Torvalds } 112*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_put); 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds 115*1da177e4SLinus Torvalds /********************************************************************* 116*1da177e4SLinus Torvalds * UNIFIED DEBUG HELPERS * 117*1da177e4SLinus Torvalds *********************************************************************/ 118*1da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ_DEBUG 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds /* what part(s) of the CPUfreq subsystem are debugged? */ 121*1da177e4SLinus Torvalds static unsigned int debug; 122*1da177e4SLinus Torvalds 123*1da177e4SLinus Torvalds /* is the debug output ratelimit'ed using printk_ratelimit? User can 124*1da177e4SLinus Torvalds * set or modify this value. 125*1da177e4SLinus Torvalds */ 126*1da177e4SLinus Torvalds static unsigned int debug_ratelimit = 1; 127*1da177e4SLinus Torvalds 128*1da177e4SLinus Torvalds /* is the printk_ratelimit'ing enabled? It's enabled after a successful 129*1da177e4SLinus Torvalds * loading of a cpufreq driver, temporarily disabled when a new policy 130*1da177e4SLinus Torvalds * is set, and disabled upon cpufreq driver removal 131*1da177e4SLinus Torvalds */ 132*1da177e4SLinus Torvalds static unsigned int disable_ratelimit = 1; 133*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(disable_ratelimit_lock); 134*1da177e4SLinus Torvalds 135*1da177e4SLinus Torvalds static inline void cpufreq_debug_enable_ratelimit(void) 136*1da177e4SLinus Torvalds { 137*1da177e4SLinus Torvalds unsigned long flags; 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds spin_lock_irqsave(&disable_ratelimit_lock, flags); 140*1da177e4SLinus Torvalds if (disable_ratelimit) 141*1da177e4SLinus Torvalds disable_ratelimit--; 142*1da177e4SLinus Torvalds spin_unlock_irqrestore(&disable_ratelimit_lock, flags); 143*1da177e4SLinus Torvalds } 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds static inline void cpufreq_debug_disable_ratelimit(void) 146*1da177e4SLinus Torvalds { 147*1da177e4SLinus Torvalds unsigned long flags; 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds spin_lock_irqsave(&disable_ratelimit_lock, flags); 150*1da177e4SLinus Torvalds disable_ratelimit++; 151*1da177e4SLinus Torvalds spin_unlock_irqrestore(&disable_ratelimit_lock, flags); 152*1da177e4SLinus Torvalds } 153*1da177e4SLinus Torvalds 154*1da177e4SLinus Torvalds void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...) 155*1da177e4SLinus Torvalds { 156*1da177e4SLinus Torvalds char s[256]; 157*1da177e4SLinus Torvalds va_list args; 158*1da177e4SLinus Torvalds unsigned int len; 159*1da177e4SLinus Torvalds unsigned long flags; 160*1da177e4SLinus Torvalds 161*1da177e4SLinus Torvalds WARN_ON(!prefix); 162*1da177e4SLinus Torvalds if (type & debug) { 163*1da177e4SLinus Torvalds spin_lock_irqsave(&disable_ratelimit_lock, flags); 164*1da177e4SLinus Torvalds if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) { 165*1da177e4SLinus Torvalds spin_unlock_irqrestore(&disable_ratelimit_lock, flags); 166*1da177e4SLinus Torvalds return; 167*1da177e4SLinus Torvalds } 168*1da177e4SLinus Torvalds spin_unlock_irqrestore(&disable_ratelimit_lock, flags); 169*1da177e4SLinus Torvalds 170*1da177e4SLinus Torvalds len = snprintf(s, 256, KERN_DEBUG "%s: ", prefix); 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds va_start(args, fmt); 173*1da177e4SLinus Torvalds len += vsnprintf(&s[len], (256 - len), fmt, args); 174*1da177e4SLinus Torvalds va_end(args); 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds printk(s); 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds WARN_ON(len < 5); 179*1da177e4SLinus Torvalds } 180*1da177e4SLinus Torvalds } 181*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_debug_printk); 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds module_param(debug, uint, 0644); 185*1da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors."); 186*1da177e4SLinus Torvalds 187*1da177e4SLinus Torvalds module_param(debug_ratelimit, uint, 0644); 188*1da177e4SLinus Torvalds MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting."); 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds #else /* !CONFIG_CPU_FREQ_DEBUG */ 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds static inline void cpufreq_debug_enable_ratelimit(void) { return; } 193*1da177e4SLinus Torvalds static inline void cpufreq_debug_disable_ratelimit(void) { return; } 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds #endif /* CONFIG_CPU_FREQ_DEBUG */ 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds /********************************************************************* 199*1da177e4SLinus Torvalds * EXTERNALLY AFFECTING FREQUENCY CHANGES * 200*1da177e4SLinus Torvalds *********************************************************************/ 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds /** 203*1da177e4SLinus Torvalds * adjust_jiffies - adjust the system "loops_per_jiffy" 204*1da177e4SLinus Torvalds * 205*1da177e4SLinus Torvalds * This function alters the system "loops_per_jiffy" for the clock 206*1da177e4SLinus Torvalds * speed change. Note that loops_per_jiffy cannot be updated on SMP 207*1da177e4SLinus Torvalds * systems as each CPU might be scaled differently. So, use the arch 208*1da177e4SLinus Torvalds * per-CPU loops_per_jiffy value wherever possible. 209*1da177e4SLinus Torvalds */ 210*1da177e4SLinus Torvalds #ifndef CONFIG_SMP 211*1da177e4SLinus Torvalds static unsigned long l_p_j_ref; 212*1da177e4SLinus Torvalds static unsigned int l_p_j_ref_freq; 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) 215*1da177e4SLinus Torvalds { 216*1da177e4SLinus Torvalds if (ci->flags & CPUFREQ_CONST_LOOPS) 217*1da177e4SLinus Torvalds return; 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds if (!l_p_j_ref_freq) { 220*1da177e4SLinus Torvalds l_p_j_ref = loops_per_jiffy; 221*1da177e4SLinus Torvalds l_p_j_ref_freq = ci->old; 222*1da177e4SLinus Torvalds dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); 223*1da177e4SLinus Torvalds } 224*1da177e4SLinus Torvalds if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || 225*1da177e4SLinus Torvalds (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || 226*1da177e4SLinus Torvalds (val == CPUFREQ_RESUMECHANGE)) { 227*1da177e4SLinus Torvalds loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); 228*1da177e4SLinus Torvalds dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new); 229*1da177e4SLinus Torvalds } 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds #else 232*1da177e4SLinus Torvalds static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; } 233*1da177e4SLinus Torvalds #endif 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds /** 237*1da177e4SLinus Torvalds * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition 238*1da177e4SLinus Torvalds * 239*1da177e4SLinus Torvalds * This function calls the transition notifiers and the "adjust_jiffies" function. It is called 240*1da177e4SLinus Torvalds * twice on all CPU frequency changes that have external effects. 241*1da177e4SLinus Torvalds */ 242*1da177e4SLinus Torvalds void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) 243*1da177e4SLinus Torvalds { 244*1da177e4SLinus Torvalds BUG_ON(irqs_disabled()); 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds freqs->flags = cpufreq_driver->flags; 247*1da177e4SLinus Torvalds dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); 248*1da177e4SLinus Torvalds 249*1da177e4SLinus Torvalds down_read(&cpufreq_notifier_rwsem); 250*1da177e4SLinus Torvalds switch (state) { 251*1da177e4SLinus Torvalds case CPUFREQ_PRECHANGE: 252*1da177e4SLinus Torvalds /* detect if the driver reported a value as "old frequency" which 253*1da177e4SLinus Torvalds * is not equal to what the cpufreq core thinks is "old frequency". 254*1da177e4SLinus Torvalds */ 255*1da177e4SLinus Torvalds if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { 256*1da177e4SLinus Torvalds if ((likely(cpufreq_cpu_data[freqs->cpu])) && 257*1da177e4SLinus Torvalds (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && 258*1da177e4SLinus Torvalds (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && 259*1da177e4SLinus Torvalds (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) 260*1da177e4SLinus Torvalds { 261*1da177e4SLinus Torvalds printk(KERN_WARNING "Warning: CPU frequency is %u, " 262*1da177e4SLinus Torvalds "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); 263*1da177e4SLinus Torvalds freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; 264*1da177e4SLinus Torvalds } 265*1da177e4SLinus Torvalds } 266*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); 267*1da177e4SLinus Torvalds adjust_jiffies(CPUFREQ_PRECHANGE, freqs); 268*1da177e4SLinus Torvalds break; 269*1da177e4SLinus Torvalds case CPUFREQ_POSTCHANGE: 270*1da177e4SLinus Torvalds adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); 271*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); 272*1da177e4SLinus Torvalds if ((likely(cpufreq_cpu_data[freqs->cpu])) && 273*1da177e4SLinus Torvalds (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) 274*1da177e4SLinus Torvalds cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; 275*1da177e4SLinus Torvalds break; 276*1da177e4SLinus Torvalds } 277*1da177e4SLinus Torvalds up_read(&cpufreq_notifier_rwsem); 278*1da177e4SLinus Torvalds } 279*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_notify_transition); 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds /********************************************************************* 284*1da177e4SLinus Torvalds * SYSFS INTERFACE * 285*1da177e4SLinus Torvalds *********************************************************************/ 286*1da177e4SLinus Torvalds 287*1da177e4SLinus Torvalds /** 288*1da177e4SLinus Torvalds * cpufreq_parse_governor - parse a governor string 289*1da177e4SLinus Torvalds */ 290*1da177e4SLinus Torvalds static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, 291*1da177e4SLinus Torvalds struct cpufreq_governor **governor) 292*1da177e4SLinus Torvalds { 293*1da177e4SLinus Torvalds if (!cpufreq_driver) 294*1da177e4SLinus Torvalds return -EINVAL; 295*1da177e4SLinus Torvalds if (cpufreq_driver->setpolicy) { 296*1da177e4SLinus Torvalds if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { 297*1da177e4SLinus Torvalds *policy = CPUFREQ_POLICY_PERFORMANCE; 298*1da177e4SLinus Torvalds return 0; 299*1da177e4SLinus Torvalds } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { 300*1da177e4SLinus Torvalds *policy = CPUFREQ_POLICY_POWERSAVE; 301*1da177e4SLinus Torvalds return 0; 302*1da177e4SLinus Torvalds } 303*1da177e4SLinus Torvalds return -EINVAL; 304*1da177e4SLinus Torvalds } else { 305*1da177e4SLinus Torvalds struct cpufreq_governor *t; 306*1da177e4SLinus Torvalds down(&cpufreq_governor_sem); 307*1da177e4SLinus Torvalds if (!cpufreq_driver || !cpufreq_driver->target) 308*1da177e4SLinus Torvalds goto out; 309*1da177e4SLinus Torvalds list_for_each_entry(t, &cpufreq_governor_list, governor_list) { 310*1da177e4SLinus Torvalds if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { 311*1da177e4SLinus Torvalds *governor = t; 312*1da177e4SLinus Torvalds up(&cpufreq_governor_sem); 313*1da177e4SLinus Torvalds return 0; 314*1da177e4SLinus Torvalds } 315*1da177e4SLinus Torvalds } 316*1da177e4SLinus Torvalds out: 317*1da177e4SLinus Torvalds up(&cpufreq_governor_sem); 318*1da177e4SLinus Torvalds } 319*1da177e4SLinus Torvalds return -EINVAL; 320*1da177e4SLinus Torvalds } 321*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_parse_governor); 322*1da177e4SLinus Torvalds 323*1da177e4SLinus Torvalds 324*1da177e4SLinus Torvalds /* drivers/base/cpu.c */ 325*1da177e4SLinus Torvalds extern struct sysdev_class cpu_sysdev_class; 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds 328*1da177e4SLinus Torvalds /** 329*1da177e4SLinus Torvalds * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information 330*1da177e4SLinus Torvalds * 331*1da177e4SLinus Torvalds * Write out information from cpufreq_driver->policy[cpu]; object must be 332*1da177e4SLinus Torvalds * "unsigned int". 333*1da177e4SLinus Torvalds */ 334*1da177e4SLinus Torvalds 335*1da177e4SLinus Torvalds #define show_one(file_name, object) \ 336*1da177e4SLinus Torvalds static ssize_t show_##file_name \ 337*1da177e4SLinus Torvalds (struct cpufreq_policy * policy, char *buf) \ 338*1da177e4SLinus Torvalds { \ 339*1da177e4SLinus Torvalds return sprintf (buf, "%u\n", policy->object); \ 340*1da177e4SLinus Torvalds } 341*1da177e4SLinus Torvalds 342*1da177e4SLinus Torvalds show_one(cpuinfo_min_freq, cpuinfo.min_freq); 343*1da177e4SLinus Torvalds show_one(cpuinfo_max_freq, cpuinfo.max_freq); 344*1da177e4SLinus Torvalds show_one(scaling_min_freq, min); 345*1da177e4SLinus Torvalds show_one(scaling_max_freq, max); 346*1da177e4SLinus Torvalds show_one(scaling_cur_freq, cur); 347*1da177e4SLinus Torvalds 348*1da177e4SLinus Torvalds /** 349*1da177e4SLinus Torvalds * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access 350*1da177e4SLinus Torvalds */ 351*1da177e4SLinus Torvalds #define store_one(file_name, object) \ 352*1da177e4SLinus Torvalds static ssize_t store_##file_name \ 353*1da177e4SLinus Torvalds (struct cpufreq_policy * policy, const char *buf, size_t count) \ 354*1da177e4SLinus Torvalds { \ 355*1da177e4SLinus Torvalds unsigned int ret = -EINVAL; \ 356*1da177e4SLinus Torvalds struct cpufreq_policy new_policy; \ 357*1da177e4SLinus Torvalds \ 358*1da177e4SLinus Torvalds ret = cpufreq_get_policy(&new_policy, policy->cpu); \ 359*1da177e4SLinus Torvalds if (ret) \ 360*1da177e4SLinus Torvalds return -EINVAL; \ 361*1da177e4SLinus Torvalds \ 362*1da177e4SLinus Torvalds ret = sscanf (buf, "%u", &new_policy.object); \ 363*1da177e4SLinus Torvalds if (ret != 1) \ 364*1da177e4SLinus Torvalds return -EINVAL; \ 365*1da177e4SLinus Torvalds \ 366*1da177e4SLinus Torvalds ret = cpufreq_set_policy(&new_policy); \ 367*1da177e4SLinus Torvalds \ 368*1da177e4SLinus Torvalds return ret ? ret : count; \ 369*1da177e4SLinus Torvalds } 370*1da177e4SLinus Torvalds 371*1da177e4SLinus Torvalds store_one(scaling_min_freq,min); 372*1da177e4SLinus Torvalds store_one(scaling_max_freq,max); 373*1da177e4SLinus Torvalds 374*1da177e4SLinus Torvalds /** 375*1da177e4SLinus Torvalds * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware 376*1da177e4SLinus Torvalds */ 377*1da177e4SLinus Torvalds static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf) 378*1da177e4SLinus Torvalds { 379*1da177e4SLinus Torvalds unsigned int cur_freq = cpufreq_get(policy->cpu); 380*1da177e4SLinus Torvalds if (!cur_freq) 381*1da177e4SLinus Torvalds return sprintf(buf, "<unknown>"); 382*1da177e4SLinus Torvalds return sprintf(buf, "%u\n", cur_freq); 383*1da177e4SLinus Torvalds } 384*1da177e4SLinus Torvalds 385*1da177e4SLinus Torvalds 386*1da177e4SLinus Torvalds /** 387*1da177e4SLinus Torvalds * show_scaling_governor - show the current policy for the specified CPU 388*1da177e4SLinus Torvalds */ 389*1da177e4SLinus Torvalds static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) 390*1da177e4SLinus Torvalds { 391*1da177e4SLinus Torvalds if(policy->policy == CPUFREQ_POLICY_POWERSAVE) 392*1da177e4SLinus Torvalds return sprintf(buf, "powersave\n"); 393*1da177e4SLinus Torvalds else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) 394*1da177e4SLinus Torvalds return sprintf(buf, "performance\n"); 395*1da177e4SLinus Torvalds else if (policy->governor) 396*1da177e4SLinus Torvalds return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); 397*1da177e4SLinus Torvalds return -EINVAL; 398*1da177e4SLinus Torvalds } 399*1da177e4SLinus Torvalds 400*1da177e4SLinus Torvalds 401*1da177e4SLinus Torvalds /** 402*1da177e4SLinus Torvalds * store_scaling_governor - store policy for the specified CPU 403*1da177e4SLinus Torvalds */ 404*1da177e4SLinus Torvalds static ssize_t store_scaling_governor (struct cpufreq_policy * policy, 405*1da177e4SLinus Torvalds const char *buf, size_t count) 406*1da177e4SLinus Torvalds { 407*1da177e4SLinus Torvalds unsigned int ret = -EINVAL; 408*1da177e4SLinus Torvalds char str_governor[16]; 409*1da177e4SLinus Torvalds struct cpufreq_policy new_policy; 410*1da177e4SLinus Torvalds 411*1da177e4SLinus Torvalds ret = cpufreq_get_policy(&new_policy, policy->cpu); 412*1da177e4SLinus Torvalds if (ret) 413*1da177e4SLinus Torvalds return ret; 414*1da177e4SLinus Torvalds 415*1da177e4SLinus Torvalds ret = sscanf (buf, "%15s", str_governor); 416*1da177e4SLinus Torvalds if (ret != 1) 417*1da177e4SLinus Torvalds return -EINVAL; 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor)) 420*1da177e4SLinus Torvalds return -EINVAL; 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds ret = cpufreq_set_policy(&new_policy); 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds return ret ? ret : count; 425*1da177e4SLinus Torvalds } 426*1da177e4SLinus Torvalds 427*1da177e4SLinus Torvalds /** 428*1da177e4SLinus Torvalds * show_scaling_driver - show the cpufreq driver currently loaded 429*1da177e4SLinus Torvalds */ 430*1da177e4SLinus Torvalds static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) 431*1da177e4SLinus Torvalds { 432*1da177e4SLinus Torvalds return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); 433*1da177e4SLinus Torvalds } 434*1da177e4SLinus Torvalds 435*1da177e4SLinus Torvalds /** 436*1da177e4SLinus Torvalds * show_scaling_available_governors - show the available CPUfreq governors 437*1da177e4SLinus Torvalds */ 438*1da177e4SLinus Torvalds static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, 439*1da177e4SLinus Torvalds char *buf) 440*1da177e4SLinus Torvalds { 441*1da177e4SLinus Torvalds ssize_t i = 0; 442*1da177e4SLinus Torvalds struct cpufreq_governor *t; 443*1da177e4SLinus Torvalds 444*1da177e4SLinus Torvalds if (!cpufreq_driver->target) { 445*1da177e4SLinus Torvalds i += sprintf(buf, "performance powersave"); 446*1da177e4SLinus Torvalds goto out; 447*1da177e4SLinus Torvalds } 448*1da177e4SLinus Torvalds 449*1da177e4SLinus Torvalds list_for_each_entry(t, &cpufreq_governor_list, governor_list) { 450*1da177e4SLinus Torvalds if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) 451*1da177e4SLinus Torvalds goto out; 452*1da177e4SLinus Torvalds i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); 453*1da177e4SLinus Torvalds } 454*1da177e4SLinus Torvalds out: 455*1da177e4SLinus Torvalds i += sprintf(&buf[i], "\n"); 456*1da177e4SLinus Torvalds return i; 457*1da177e4SLinus Torvalds } 458*1da177e4SLinus Torvalds /** 459*1da177e4SLinus Torvalds * show_affected_cpus - show the CPUs affected by each transition 460*1da177e4SLinus Torvalds */ 461*1da177e4SLinus Torvalds static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf) 462*1da177e4SLinus Torvalds { 463*1da177e4SLinus Torvalds ssize_t i = 0; 464*1da177e4SLinus Torvalds unsigned int cpu; 465*1da177e4SLinus Torvalds 466*1da177e4SLinus Torvalds for_each_cpu_mask(cpu, policy->cpus) { 467*1da177e4SLinus Torvalds if (i) 468*1da177e4SLinus Torvalds i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " "); 469*1da177e4SLinus Torvalds i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu); 470*1da177e4SLinus Torvalds if (i >= (PAGE_SIZE - 5)) 471*1da177e4SLinus Torvalds break; 472*1da177e4SLinus Torvalds } 473*1da177e4SLinus Torvalds i += sprintf(&buf[i], "\n"); 474*1da177e4SLinus Torvalds return i; 475*1da177e4SLinus Torvalds } 476*1da177e4SLinus Torvalds 477*1da177e4SLinus Torvalds 478*1da177e4SLinus Torvalds #define define_one_ro(_name) \ 479*1da177e4SLinus Torvalds static struct freq_attr _name = \ 480*1da177e4SLinus Torvalds __ATTR(_name, 0444, show_##_name, NULL) 481*1da177e4SLinus Torvalds 482*1da177e4SLinus Torvalds #define define_one_ro0400(_name) \ 483*1da177e4SLinus Torvalds static struct freq_attr _name = \ 484*1da177e4SLinus Torvalds __ATTR(_name, 0400, show_##_name, NULL) 485*1da177e4SLinus Torvalds 486*1da177e4SLinus Torvalds #define define_one_rw(_name) \ 487*1da177e4SLinus Torvalds static struct freq_attr _name = \ 488*1da177e4SLinus Torvalds __ATTR(_name, 0644, show_##_name, store_##_name) 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds define_one_ro0400(cpuinfo_cur_freq); 491*1da177e4SLinus Torvalds define_one_ro(cpuinfo_min_freq); 492*1da177e4SLinus Torvalds define_one_ro(cpuinfo_max_freq); 493*1da177e4SLinus Torvalds define_one_ro(scaling_available_governors); 494*1da177e4SLinus Torvalds define_one_ro(scaling_driver); 495*1da177e4SLinus Torvalds define_one_ro(scaling_cur_freq); 496*1da177e4SLinus Torvalds define_one_ro(affected_cpus); 497*1da177e4SLinus Torvalds define_one_rw(scaling_min_freq); 498*1da177e4SLinus Torvalds define_one_rw(scaling_max_freq); 499*1da177e4SLinus Torvalds define_one_rw(scaling_governor); 500*1da177e4SLinus Torvalds 501*1da177e4SLinus Torvalds static struct attribute * default_attrs[] = { 502*1da177e4SLinus Torvalds &cpuinfo_min_freq.attr, 503*1da177e4SLinus Torvalds &cpuinfo_max_freq.attr, 504*1da177e4SLinus Torvalds &scaling_min_freq.attr, 505*1da177e4SLinus Torvalds &scaling_max_freq.attr, 506*1da177e4SLinus Torvalds &affected_cpus.attr, 507*1da177e4SLinus Torvalds &scaling_governor.attr, 508*1da177e4SLinus Torvalds &scaling_driver.attr, 509*1da177e4SLinus Torvalds &scaling_available_governors.attr, 510*1da177e4SLinus Torvalds NULL 511*1da177e4SLinus Torvalds }; 512*1da177e4SLinus Torvalds 513*1da177e4SLinus Torvalds #define to_policy(k) container_of(k,struct cpufreq_policy,kobj) 514*1da177e4SLinus Torvalds #define to_attr(a) container_of(a,struct freq_attr,attr) 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) 517*1da177e4SLinus Torvalds { 518*1da177e4SLinus Torvalds struct cpufreq_policy * policy = to_policy(kobj); 519*1da177e4SLinus Torvalds struct freq_attr * fattr = to_attr(attr); 520*1da177e4SLinus Torvalds ssize_t ret; 521*1da177e4SLinus Torvalds policy = cpufreq_cpu_get(policy->cpu); 522*1da177e4SLinus Torvalds if (!policy) 523*1da177e4SLinus Torvalds return -EINVAL; 524*1da177e4SLinus Torvalds ret = fattr->show ? fattr->show(policy,buf) : 0; 525*1da177e4SLinus Torvalds cpufreq_cpu_put(policy); 526*1da177e4SLinus Torvalds return ret; 527*1da177e4SLinus Torvalds } 528*1da177e4SLinus Torvalds 529*1da177e4SLinus Torvalds static ssize_t store(struct kobject * kobj, struct attribute * attr, 530*1da177e4SLinus Torvalds const char * buf, size_t count) 531*1da177e4SLinus Torvalds { 532*1da177e4SLinus Torvalds struct cpufreq_policy * policy = to_policy(kobj); 533*1da177e4SLinus Torvalds struct freq_attr * fattr = to_attr(attr); 534*1da177e4SLinus Torvalds ssize_t ret; 535*1da177e4SLinus Torvalds policy = cpufreq_cpu_get(policy->cpu); 536*1da177e4SLinus Torvalds if (!policy) 537*1da177e4SLinus Torvalds return -EINVAL; 538*1da177e4SLinus Torvalds ret = fattr->store ? fattr->store(policy,buf,count) : 0; 539*1da177e4SLinus Torvalds cpufreq_cpu_put(policy); 540*1da177e4SLinus Torvalds return ret; 541*1da177e4SLinus Torvalds } 542*1da177e4SLinus Torvalds 543*1da177e4SLinus Torvalds static void cpufreq_sysfs_release(struct kobject * kobj) 544*1da177e4SLinus Torvalds { 545*1da177e4SLinus Torvalds struct cpufreq_policy * policy = to_policy(kobj); 546*1da177e4SLinus Torvalds dprintk("last reference is dropped\n"); 547*1da177e4SLinus Torvalds complete(&policy->kobj_unregister); 548*1da177e4SLinus Torvalds } 549*1da177e4SLinus Torvalds 550*1da177e4SLinus Torvalds static struct sysfs_ops sysfs_ops = { 551*1da177e4SLinus Torvalds .show = show, 552*1da177e4SLinus Torvalds .store = store, 553*1da177e4SLinus Torvalds }; 554*1da177e4SLinus Torvalds 555*1da177e4SLinus Torvalds static struct kobj_type ktype_cpufreq = { 556*1da177e4SLinus Torvalds .sysfs_ops = &sysfs_ops, 557*1da177e4SLinus Torvalds .default_attrs = default_attrs, 558*1da177e4SLinus Torvalds .release = cpufreq_sysfs_release, 559*1da177e4SLinus Torvalds }; 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds 562*1da177e4SLinus Torvalds /** 563*1da177e4SLinus Torvalds * cpufreq_add_dev - add a CPU device 564*1da177e4SLinus Torvalds * 565*1da177e4SLinus Torvalds * Adds the cpufreq interface for a CPU device. 566*1da177e4SLinus Torvalds */ 567*1da177e4SLinus Torvalds static int cpufreq_add_dev (struct sys_device * sys_dev) 568*1da177e4SLinus Torvalds { 569*1da177e4SLinus Torvalds unsigned int cpu = sys_dev->id; 570*1da177e4SLinus Torvalds int ret = 0; 571*1da177e4SLinus Torvalds struct cpufreq_policy new_policy; 572*1da177e4SLinus Torvalds struct cpufreq_policy *policy; 573*1da177e4SLinus Torvalds struct freq_attr **drv_attr; 574*1da177e4SLinus Torvalds unsigned long flags; 575*1da177e4SLinus Torvalds unsigned int j; 576*1da177e4SLinus Torvalds 577*1da177e4SLinus Torvalds cpufreq_debug_disable_ratelimit(); 578*1da177e4SLinus Torvalds dprintk("adding CPU %u\n", cpu); 579*1da177e4SLinus Torvalds 580*1da177e4SLinus Torvalds #ifdef CONFIG_SMP 581*1da177e4SLinus Torvalds /* check whether a different CPU already registered this 582*1da177e4SLinus Torvalds * CPU because it is in the same boat. */ 583*1da177e4SLinus Torvalds policy = cpufreq_cpu_get(cpu); 584*1da177e4SLinus Torvalds if (unlikely(policy)) { 585*1da177e4SLinus Torvalds cpu_sys_devices[cpu] = sys_dev; 586*1da177e4SLinus Torvalds dprintk("CPU already managed, adding link\n"); 587*1da177e4SLinus Torvalds sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq"); 588*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 589*1da177e4SLinus Torvalds return 0; 590*1da177e4SLinus Torvalds } 591*1da177e4SLinus Torvalds #endif 592*1da177e4SLinus Torvalds 593*1da177e4SLinus Torvalds if (!try_module_get(cpufreq_driver->owner)) { 594*1da177e4SLinus Torvalds ret = -EINVAL; 595*1da177e4SLinus Torvalds goto module_out; 596*1da177e4SLinus Torvalds } 597*1da177e4SLinus Torvalds 598*1da177e4SLinus Torvalds policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); 599*1da177e4SLinus Torvalds if (!policy) { 600*1da177e4SLinus Torvalds ret = -ENOMEM; 601*1da177e4SLinus Torvalds goto nomem_out; 602*1da177e4SLinus Torvalds } 603*1da177e4SLinus Torvalds memset(policy, 0, sizeof(struct cpufreq_policy)); 604*1da177e4SLinus Torvalds 605*1da177e4SLinus Torvalds policy->cpu = cpu; 606*1da177e4SLinus Torvalds policy->cpus = cpumask_of_cpu(cpu); 607*1da177e4SLinus Torvalds 608*1da177e4SLinus Torvalds init_MUTEX_LOCKED(&policy->lock); 609*1da177e4SLinus Torvalds init_completion(&policy->kobj_unregister); 610*1da177e4SLinus Torvalds INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); 611*1da177e4SLinus Torvalds 612*1da177e4SLinus Torvalds /* call driver. From then on the cpufreq must be able 613*1da177e4SLinus Torvalds * to accept all calls to ->verify and ->setpolicy for this CPU 614*1da177e4SLinus Torvalds */ 615*1da177e4SLinus Torvalds ret = cpufreq_driver->init(policy); 616*1da177e4SLinus Torvalds if (ret) { 617*1da177e4SLinus Torvalds dprintk("initialization failed\n"); 618*1da177e4SLinus Torvalds goto err_out; 619*1da177e4SLinus Torvalds } 620*1da177e4SLinus Torvalds 621*1da177e4SLinus Torvalds memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); 622*1da177e4SLinus Torvalds 623*1da177e4SLinus Torvalds /* prepare interface data */ 624*1da177e4SLinus Torvalds policy->kobj.parent = &sys_dev->kobj; 625*1da177e4SLinus Torvalds policy->kobj.ktype = &ktype_cpufreq; 626*1da177e4SLinus Torvalds strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); 627*1da177e4SLinus Torvalds 628*1da177e4SLinus Torvalds ret = kobject_register(&policy->kobj); 629*1da177e4SLinus Torvalds if (ret) 630*1da177e4SLinus Torvalds goto err_out; 631*1da177e4SLinus Torvalds 632*1da177e4SLinus Torvalds /* set up files for this cpu device */ 633*1da177e4SLinus Torvalds drv_attr = cpufreq_driver->attr; 634*1da177e4SLinus Torvalds while ((drv_attr) && (*drv_attr)) { 635*1da177e4SLinus Torvalds sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); 636*1da177e4SLinus Torvalds drv_attr++; 637*1da177e4SLinus Torvalds } 638*1da177e4SLinus Torvalds if (cpufreq_driver->get) 639*1da177e4SLinus Torvalds sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); 640*1da177e4SLinus Torvalds if (cpufreq_driver->target) 641*1da177e4SLinus Torvalds sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); 642*1da177e4SLinus Torvalds 643*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 644*1da177e4SLinus Torvalds for_each_cpu_mask(j, policy->cpus) 645*1da177e4SLinus Torvalds cpufreq_cpu_data[j] = policy; 646*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 647*1da177e4SLinus Torvalds policy->governor = NULL; /* to assure that the starting sequence is 648*1da177e4SLinus Torvalds * run in cpufreq_set_policy */ 649*1da177e4SLinus Torvalds up(&policy->lock); 650*1da177e4SLinus Torvalds 651*1da177e4SLinus Torvalds /* set default policy */ 652*1da177e4SLinus Torvalds 653*1da177e4SLinus Torvalds ret = cpufreq_set_policy(&new_policy); 654*1da177e4SLinus Torvalds if (ret) { 655*1da177e4SLinus Torvalds dprintk("setting policy failed\n"); 656*1da177e4SLinus Torvalds goto err_out_unregister; 657*1da177e4SLinus Torvalds } 658*1da177e4SLinus Torvalds 659*1da177e4SLinus Torvalds module_put(cpufreq_driver->owner); 660*1da177e4SLinus Torvalds cpu_sys_devices[cpu] = sys_dev; 661*1da177e4SLinus Torvalds dprintk("initialization complete\n"); 662*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 663*1da177e4SLinus Torvalds 664*1da177e4SLinus Torvalds return 0; 665*1da177e4SLinus Torvalds 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvalds err_out_unregister: 668*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 669*1da177e4SLinus Torvalds for_each_cpu_mask(j, policy->cpus) 670*1da177e4SLinus Torvalds cpufreq_cpu_data[j] = NULL; 671*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 672*1da177e4SLinus Torvalds 673*1da177e4SLinus Torvalds kobject_unregister(&policy->kobj); 674*1da177e4SLinus Torvalds wait_for_completion(&policy->kobj_unregister); 675*1da177e4SLinus Torvalds 676*1da177e4SLinus Torvalds err_out: 677*1da177e4SLinus Torvalds kfree(policy); 678*1da177e4SLinus Torvalds 679*1da177e4SLinus Torvalds nomem_out: 680*1da177e4SLinus Torvalds module_put(cpufreq_driver->owner); 681*1da177e4SLinus Torvalds module_out: 682*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 683*1da177e4SLinus Torvalds return ret; 684*1da177e4SLinus Torvalds } 685*1da177e4SLinus Torvalds 686*1da177e4SLinus Torvalds 687*1da177e4SLinus Torvalds /** 688*1da177e4SLinus Torvalds * cpufreq_remove_dev - remove a CPU device 689*1da177e4SLinus Torvalds * 690*1da177e4SLinus Torvalds * Removes the cpufreq interface for a CPU device. 691*1da177e4SLinus Torvalds */ 692*1da177e4SLinus Torvalds static int cpufreq_remove_dev (struct sys_device * sys_dev) 693*1da177e4SLinus Torvalds { 694*1da177e4SLinus Torvalds unsigned int cpu = sys_dev->id; 695*1da177e4SLinus Torvalds unsigned long flags; 696*1da177e4SLinus Torvalds struct cpufreq_policy *data; 697*1da177e4SLinus Torvalds #ifdef CONFIG_SMP 698*1da177e4SLinus Torvalds unsigned int j; 699*1da177e4SLinus Torvalds #endif 700*1da177e4SLinus Torvalds 701*1da177e4SLinus Torvalds cpufreq_debug_disable_ratelimit(); 702*1da177e4SLinus Torvalds dprintk("unregistering CPU %u\n", cpu); 703*1da177e4SLinus Torvalds 704*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 705*1da177e4SLinus Torvalds data = cpufreq_cpu_data[cpu]; 706*1da177e4SLinus Torvalds 707*1da177e4SLinus Torvalds if (!data) { 708*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 709*1da177e4SLinus Torvalds cpu_sys_devices[cpu] = NULL; 710*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 711*1da177e4SLinus Torvalds return -EINVAL; 712*1da177e4SLinus Torvalds } 713*1da177e4SLinus Torvalds cpufreq_cpu_data[cpu] = NULL; 714*1da177e4SLinus Torvalds 715*1da177e4SLinus Torvalds 716*1da177e4SLinus Torvalds #ifdef CONFIG_SMP 717*1da177e4SLinus Torvalds /* if this isn't the CPU which is the parent of the kobj, we 718*1da177e4SLinus Torvalds * only need to unlink, put and exit 719*1da177e4SLinus Torvalds */ 720*1da177e4SLinus Torvalds if (unlikely(cpu != data->cpu)) { 721*1da177e4SLinus Torvalds dprintk("removing link\n"); 722*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 723*1da177e4SLinus Torvalds sysfs_remove_link(&sys_dev->kobj, "cpufreq"); 724*1da177e4SLinus Torvalds cpu_sys_devices[cpu] = NULL; 725*1da177e4SLinus Torvalds cpufreq_cpu_put(data); 726*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 727*1da177e4SLinus Torvalds return 0; 728*1da177e4SLinus Torvalds } 729*1da177e4SLinus Torvalds #endif 730*1da177e4SLinus Torvalds 731*1da177e4SLinus Torvalds cpu_sys_devices[cpu] = NULL; 732*1da177e4SLinus Torvalds 733*1da177e4SLinus Torvalds if (!kobject_get(&data->kobj)) { 734*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 735*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 736*1da177e4SLinus Torvalds return -EFAULT; 737*1da177e4SLinus Torvalds } 738*1da177e4SLinus Torvalds 739*1da177e4SLinus Torvalds #ifdef CONFIG_SMP 740*1da177e4SLinus Torvalds /* if we have other CPUs still registered, we need to unlink them, 741*1da177e4SLinus Torvalds * or else wait_for_completion below will lock up. Clean the 742*1da177e4SLinus Torvalds * cpufreq_cpu_data[] while holding the lock, and remove the sysfs 743*1da177e4SLinus Torvalds * links afterwards. 744*1da177e4SLinus Torvalds */ 745*1da177e4SLinus Torvalds if (unlikely(cpus_weight(data->cpus) > 1)) { 746*1da177e4SLinus Torvalds for_each_cpu_mask(j, data->cpus) { 747*1da177e4SLinus Torvalds if (j == cpu) 748*1da177e4SLinus Torvalds continue; 749*1da177e4SLinus Torvalds cpufreq_cpu_data[j] = NULL; 750*1da177e4SLinus Torvalds } 751*1da177e4SLinus Torvalds } 752*1da177e4SLinus Torvalds 753*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 754*1da177e4SLinus Torvalds 755*1da177e4SLinus Torvalds if (unlikely(cpus_weight(data->cpus) > 1)) { 756*1da177e4SLinus Torvalds for_each_cpu_mask(j, data->cpus) { 757*1da177e4SLinus Torvalds if (j == cpu) 758*1da177e4SLinus Torvalds continue; 759*1da177e4SLinus Torvalds dprintk("removing link for cpu %u\n", j); 760*1da177e4SLinus Torvalds sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq"); 761*1da177e4SLinus Torvalds cpufreq_cpu_put(data); 762*1da177e4SLinus Torvalds } 763*1da177e4SLinus Torvalds } 764*1da177e4SLinus Torvalds #else 765*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 766*1da177e4SLinus Torvalds #endif 767*1da177e4SLinus Torvalds 768*1da177e4SLinus Torvalds down(&data->lock); 769*1da177e4SLinus Torvalds if (cpufreq_driver->target) 770*1da177e4SLinus Torvalds __cpufreq_governor(data, CPUFREQ_GOV_STOP); 771*1da177e4SLinus Torvalds cpufreq_driver->target = NULL; 772*1da177e4SLinus Torvalds up(&data->lock); 773*1da177e4SLinus Torvalds 774*1da177e4SLinus Torvalds kobject_unregister(&data->kobj); 775*1da177e4SLinus Torvalds 776*1da177e4SLinus Torvalds kobject_put(&data->kobj); 777*1da177e4SLinus Torvalds 778*1da177e4SLinus Torvalds /* we need to make sure that the underlying kobj is actually 779*1da177e4SLinus Torvalds * not referenced anymore by anybody before we proceed with 780*1da177e4SLinus Torvalds * unloading. 781*1da177e4SLinus Torvalds */ 782*1da177e4SLinus Torvalds dprintk("waiting for dropping of refcount\n"); 783*1da177e4SLinus Torvalds wait_for_completion(&data->kobj_unregister); 784*1da177e4SLinus Torvalds dprintk("wait complete\n"); 785*1da177e4SLinus Torvalds 786*1da177e4SLinus Torvalds if (cpufreq_driver->exit) 787*1da177e4SLinus Torvalds cpufreq_driver->exit(data); 788*1da177e4SLinus Torvalds 789*1da177e4SLinus Torvalds kfree(data); 790*1da177e4SLinus Torvalds 791*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 792*1da177e4SLinus Torvalds 793*1da177e4SLinus Torvalds return 0; 794*1da177e4SLinus Torvalds } 795*1da177e4SLinus Torvalds 796*1da177e4SLinus Torvalds 797*1da177e4SLinus Torvalds static void handle_update(void *data) 798*1da177e4SLinus Torvalds { 799*1da177e4SLinus Torvalds unsigned int cpu = (unsigned int)(long)data; 800*1da177e4SLinus Torvalds dprintk("handle_update for cpu %u called\n", cpu); 801*1da177e4SLinus Torvalds cpufreq_update_policy(cpu); 802*1da177e4SLinus Torvalds } 803*1da177e4SLinus Torvalds 804*1da177e4SLinus Torvalds /** 805*1da177e4SLinus Torvalds * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're in deep trouble. 806*1da177e4SLinus Torvalds * @cpu: cpu number 807*1da177e4SLinus Torvalds * @old_freq: CPU frequency the kernel thinks the CPU runs at 808*1da177e4SLinus Torvalds * @new_freq: CPU frequency the CPU actually runs at 809*1da177e4SLinus Torvalds * 810*1da177e4SLinus Torvalds * We adjust to current frequency first, and need to clean up later. So either call 811*1da177e4SLinus Torvalds * to cpufreq_update_policy() or schedule handle_update()). 812*1da177e4SLinus Torvalds */ 813*1da177e4SLinus Torvalds static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq) 814*1da177e4SLinus Torvalds { 815*1da177e4SLinus Torvalds struct cpufreq_freqs freqs; 816*1da177e4SLinus Torvalds 817*1da177e4SLinus Torvalds printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " 818*1da177e4SLinus Torvalds "core thinks of %u, is %u kHz.\n", old_freq, new_freq); 819*1da177e4SLinus Torvalds 820*1da177e4SLinus Torvalds freqs.cpu = cpu; 821*1da177e4SLinus Torvalds freqs.old = old_freq; 822*1da177e4SLinus Torvalds freqs.new = new_freq; 823*1da177e4SLinus Torvalds cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 824*1da177e4SLinus Torvalds cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 825*1da177e4SLinus Torvalds } 826*1da177e4SLinus Torvalds 827*1da177e4SLinus Torvalds 828*1da177e4SLinus Torvalds /** 829*1da177e4SLinus Torvalds * cpufreq_get - get the current CPU frequency (in kHz) 830*1da177e4SLinus Torvalds * @cpu: CPU number 831*1da177e4SLinus Torvalds * 832*1da177e4SLinus Torvalds * Get the CPU current (static) CPU frequency 833*1da177e4SLinus Torvalds */ 834*1da177e4SLinus Torvalds unsigned int cpufreq_get(unsigned int cpu) 835*1da177e4SLinus Torvalds { 836*1da177e4SLinus Torvalds struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 837*1da177e4SLinus Torvalds unsigned int ret = 0; 838*1da177e4SLinus Torvalds 839*1da177e4SLinus Torvalds if (!policy) 840*1da177e4SLinus Torvalds return 0; 841*1da177e4SLinus Torvalds 842*1da177e4SLinus Torvalds if (!cpufreq_driver->get) 843*1da177e4SLinus Torvalds goto out; 844*1da177e4SLinus Torvalds 845*1da177e4SLinus Torvalds down(&policy->lock); 846*1da177e4SLinus Torvalds 847*1da177e4SLinus Torvalds ret = cpufreq_driver->get(cpu); 848*1da177e4SLinus Torvalds 849*1da177e4SLinus Torvalds if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) 850*1da177e4SLinus Torvalds { 851*1da177e4SLinus Torvalds /* verify no discrepancy between actual and saved value exists */ 852*1da177e4SLinus Torvalds if (unlikely(ret != policy->cur)) { 853*1da177e4SLinus Torvalds cpufreq_out_of_sync(cpu, policy->cur, ret); 854*1da177e4SLinus Torvalds schedule_work(&policy->update); 855*1da177e4SLinus Torvalds } 856*1da177e4SLinus Torvalds } 857*1da177e4SLinus Torvalds 858*1da177e4SLinus Torvalds up(&policy->lock); 859*1da177e4SLinus Torvalds 860*1da177e4SLinus Torvalds out: 861*1da177e4SLinus Torvalds cpufreq_cpu_put(policy); 862*1da177e4SLinus Torvalds 863*1da177e4SLinus Torvalds return (ret); 864*1da177e4SLinus Torvalds } 865*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get); 866*1da177e4SLinus Torvalds 867*1da177e4SLinus Torvalds 868*1da177e4SLinus Torvalds /** 869*1da177e4SLinus Torvalds * cpufreq_resume - restore proper CPU frequency handling after resume 870*1da177e4SLinus Torvalds * 871*1da177e4SLinus Torvalds * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) 872*1da177e4SLinus Torvalds * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync 873*1da177e4SLinus Torvalds * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are restored. 874*1da177e4SLinus Torvalds */ 875*1da177e4SLinus Torvalds static int cpufreq_resume(struct sys_device * sysdev) 876*1da177e4SLinus Torvalds { 877*1da177e4SLinus Torvalds int cpu = sysdev->id; 878*1da177e4SLinus Torvalds unsigned int ret = 0; 879*1da177e4SLinus Torvalds struct cpufreq_policy *cpu_policy; 880*1da177e4SLinus Torvalds 881*1da177e4SLinus Torvalds dprintk("resuming cpu %u\n", cpu); 882*1da177e4SLinus Torvalds 883*1da177e4SLinus Torvalds if (!cpu_online(cpu)) 884*1da177e4SLinus Torvalds return 0; 885*1da177e4SLinus Torvalds 886*1da177e4SLinus Torvalds /* we may be lax here as interrupts are off. Nonetheless 887*1da177e4SLinus Torvalds * we need to grab the correct cpu policy, as to check 888*1da177e4SLinus Torvalds * whether we really run on this CPU. 889*1da177e4SLinus Torvalds */ 890*1da177e4SLinus Torvalds 891*1da177e4SLinus Torvalds cpu_policy = cpufreq_cpu_get(cpu); 892*1da177e4SLinus Torvalds if (!cpu_policy) 893*1da177e4SLinus Torvalds return -EINVAL; 894*1da177e4SLinus Torvalds 895*1da177e4SLinus Torvalds /* only handle each CPU group once */ 896*1da177e4SLinus Torvalds if (unlikely(cpu_policy->cpu != cpu)) { 897*1da177e4SLinus Torvalds cpufreq_cpu_put(cpu_policy); 898*1da177e4SLinus Torvalds return 0; 899*1da177e4SLinus Torvalds } 900*1da177e4SLinus Torvalds 901*1da177e4SLinus Torvalds if (cpufreq_driver->resume) { 902*1da177e4SLinus Torvalds ret = cpufreq_driver->resume(cpu_policy); 903*1da177e4SLinus Torvalds if (ret) { 904*1da177e4SLinus Torvalds printk(KERN_ERR "cpufreq: resume failed in ->resume " 905*1da177e4SLinus Torvalds "step on CPU %u\n", cpu_policy->cpu); 906*1da177e4SLinus Torvalds cpufreq_cpu_put(cpu_policy); 907*1da177e4SLinus Torvalds return ret; 908*1da177e4SLinus Torvalds } 909*1da177e4SLinus Torvalds } 910*1da177e4SLinus Torvalds 911*1da177e4SLinus Torvalds if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { 912*1da177e4SLinus Torvalds unsigned int cur_freq = 0; 913*1da177e4SLinus Torvalds 914*1da177e4SLinus Torvalds if (cpufreq_driver->get) 915*1da177e4SLinus Torvalds cur_freq = cpufreq_driver->get(cpu_policy->cpu); 916*1da177e4SLinus Torvalds 917*1da177e4SLinus Torvalds if (!cur_freq || !cpu_policy->cur) { 918*1da177e4SLinus Torvalds printk(KERN_ERR "cpufreq: resume failed to assert current frequency is what timing core thinks it is.\n"); 919*1da177e4SLinus Torvalds goto out; 920*1da177e4SLinus Torvalds } 921*1da177e4SLinus Torvalds 922*1da177e4SLinus Torvalds if (unlikely(cur_freq != cpu_policy->cur)) { 923*1da177e4SLinus Torvalds struct cpufreq_freqs freqs; 924*1da177e4SLinus Torvalds 925*1da177e4SLinus Torvalds printk(KERN_WARNING "Warning: CPU frequency is %u, " 926*1da177e4SLinus Torvalds "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); 927*1da177e4SLinus Torvalds 928*1da177e4SLinus Torvalds freqs.cpu = cpu; 929*1da177e4SLinus Torvalds freqs.old = cpu_policy->cur; 930*1da177e4SLinus Torvalds freqs.new = cur_freq; 931*1da177e4SLinus Torvalds 932*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); 933*1da177e4SLinus Torvalds adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); 934*1da177e4SLinus Torvalds 935*1da177e4SLinus Torvalds cpu_policy->cur = cur_freq; 936*1da177e4SLinus Torvalds } 937*1da177e4SLinus Torvalds } 938*1da177e4SLinus Torvalds 939*1da177e4SLinus Torvalds out: 940*1da177e4SLinus Torvalds schedule_work(&cpu_policy->update); 941*1da177e4SLinus Torvalds cpufreq_cpu_put(cpu_policy); 942*1da177e4SLinus Torvalds return ret; 943*1da177e4SLinus Torvalds } 944*1da177e4SLinus Torvalds 945*1da177e4SLinus Torvalds static struct sysdev_driver cpufreq_sysdev_driver = { 946*1da177e4SLinus Torvalds .add = cpufreq_add_dev, 947*1da177e4SLinus Torvalds .remove = cpufreq_remove_dev, 948*1da177e4SLinus Torvalds .resume = cpufreq_resume, 949*1da177e4SLinus Torvalds }; 950*1da177e4SLinus Torvalds 951*1da177e4SLinus Torvalds 952*1da177e4SLinus Torvalds /********************************************************************* 953*1da177e4SLinus Torvalds * NOTIFIER LISTS INTERFACE * 954*1da177e4SLinus Torvalds *********************************************************************/ 955*1da177e4SLinus Torvalds 956*1da177e4SLinus Torvalds /** 957*1da177e4SLinus Torvalds * cpufreq_register_notifier - register a driver with cpufreq 958*1da177e4SLinus Torvalds * @nb: notifier function to register 959*1da177e4SLinus Torvalds * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 960*1da177e4SLinus Torvalds * 961*1da177e4SLinus Torvalds * Add a driver to one of two lists: either a list of drivers that 962*1da177e4SLinus Torvalds * are notified about clock rate changes (once before and once after 963*1da177e4SLinus Torvalds * the transition), or a list of drivers that are notified about 964*1da177e4SLinus Torvalds * changes in cpufreq policy. 965*1da177e4SLinus Torvalds * 966*1da177e4SLinus Torvalds * This function may sleep, and has the same return conditions as 967*1da177e4SLinus Torvalds * notifier_chain_register. 968*1da177e4SLinus Torvalds */ 969*1da177e4SLinus Torvalds int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) 970*1da177e4SLinus Torvalds { 971*1da177e4SLinus Torvalds int ret; 972*1da177e4SLinus Torvalds 973*1da177e4SLinus Torvalds down_write(&cpufreq_notifier_rwsem); 974*1da177e4SLinus Torvalds switch (list) { 975*1da177e4SLinus Torvalds case CPUFREQ_TRANSITION_NOTIFIER: 976*1da177e4SLinus Torvalds ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); 977*1da177e4SLinus Torvalds break; 978*1da177e4SLinus Torvalds case CPUFREQ_POLICY_NOTIFIER: 979*1da177e4SLinus Torvalds ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); 980*1da177e4SLinus Torvalds break; 981*1da177e4SLinus Torvalds default: 982*1da177e4SLinus Torvalds ret = -EINVAL; 983*1da177e4SLinus Torvalds } 984*1da177e4SLinus Torvalds up_write(&cpufreq_notifier_rwsem); 985*1da177e4SLinus Torvalds 986*1da177e4SLinus Torvalds return ret; 987*1da177e4SLinus Torvalds } 988*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_register_notifier); 989*1da177e4SLinus Torvalds 990*1da177e4SLinus Torvalds 991*1da177e4SLinus Torvalds /** 992*1da177e4SLinus Torvalds * cpufreq_unregister_notifier - unregister a driver with cpufreq 993*1da177e4SLinus Torvalds * @nb: notifier block to be unregistered 994*1da177e4SLinus Torvalds * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 995*1da177e4SLinus Torvalds * 996*1da177e4SLinus Torvalds * Remove a driver from the CPU frequency notifier list. 997*1da177e4SLinus Torvalds * 998*1da177e4SLinus Torvalds * This function may sleep, and has the same return conditions as 999*1da177e4SLinus Torvalds * notifier_chain_unregister. 1000*1da177e4SLinus Torvalds */ 1001*1da177e4SLinus Torvalds int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) 1002*1da177e4SLinus Torvalds { 1003*1da177e4SLinus Torvalds int ret; 1004*1da177e4SLinus Torvalds 1005*1da177e4SLinus Torvalds down_write(&cpufreq_notifier_rwsem); 1006*1da177e4SLinus Torvalds switch (list) { 1007*1da177e4SLinus Torvalds case CPUFREQ_TRANSITION_NOTIFIER: 1008*1da177e4SLinus Torvalds ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); 1009*1da177e4SLinus Torvalds break; 1010*1da177e4SLinus Torvalds case CPUFREQ_POLICY_NOTIFIER: 1011*1da177e4SLinus Torvalds ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); 1012*1da177e4SLinus Torvalds break; 1013*1da177e4SLinus Torvalds default: 1014*1da177e4SLinus Torvalds ret = -EINVAL; 1015*1da177e4SLinus Torvalds } 1016*1da177e4SLinus Torvalds up_write(&cpufreq_notifier_rwsem); 1017*1da177e4SLinus Torvalds 1018*1da177e4SLinus Torvalds return ret; 1019*1da177e4SLinus Torvalds } 1020*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_unregister_notifier); 1021*1da177e4SLinus Torvalds 1022*1da177e4SLinus Torvalds 1023*1da177e4SLinus Torvalds /********************************************************************* 1024*1da177e4SLinus Torvalds * GOVERNORS * 1025*1da177e4SLinus Torvalds *********************************************************************/ 1026*1da177e4SLinus Torvalds 1027*1da177e4SLinus Torvalds 1028*1da177e4SLinus Torvalds int __cpufreq_driver_target(struct cpufreq_policy *policy, 1029*1da177e4SLinus Torvalds unsigned int target_freq, 1030*1da177e4SLinus Torvalds unsigned int relation) 1031*1da177e4SLinus Torvalds { 1032*1da177e4SLinus Torvalds int retval = -EINVAL; 1033*1da177e4SLinus Torvalds lock_cpu_hotplug(); 1034*1da177e4SLinus Torvalds dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, 1035*1da177e4SLinus Torvalds target_freq, relation); 1036*1da177e4SLinus Torvalds if (cpu_online(policy->cpu) && cpufreq_driver->target) 1037*1da177e4SLinus Torvalds retval = cpufreq_driver->target(policy, target_freq, relation); 1038*1da177e4SLinus Torvalds unlock_cpu_hotplug(); 1039*1da177e4SLinus Torvalds return retval; 1040*1da177e4SLinus Torvalds } 1041*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(__cpufreq_driver_target); 1042*1da177e4SLinus Torvalds 1043*1da177e4SLinus Torvalds 1044*1da177e4SLinus Torvalds int cpufreq_driver_target(struct cpufreq_policy *policy, 1045*1da177e4SLinus Torvalds unsigned int target_freq, 1046*1da177e4SLinus Torvalds unsigned int relation) 1047*1da177e4SLinus Torvalds { 1048*1da177e4SLinus Torvalds unsigned int ret; 1049*1da177e4SLinus Torvalds 1050*1da177e4SLinus Torvalds policy = cpufreq_cpu_get(policy->cpu); 1051*1da177e4SLinus Torvalds if (!policy) 1052*1da177e4SLinus Torvalds return -EINVAL; 1053*1da177e4SLinus Torvalds 1054*1da177e4SLinus Torvalds down(&policy->lock); 1055*1da177e4SLinus Torvalds 1056*1da177e4SLinus Torvalds ret = __cpufreq_driver_target(policy, target_freq, relation); 1057*1da177e4SLinus Torvalds 1058*1da177e4SLinus Torvalds up(&policy->lock); 1059*1da177e4SLinus Torvalds 1060*1da177e4SLinus Torvalds cpufreq_cpu_put(policy); 1061*1da177e4SLinus Torvalds 1062*1da177e4SLinus Torvalds return ret; 1063*1da177e4SLinus Torvalds } 1064*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_driver_target); 1065*1da177e4SLinus Torvalds 1066*1da177e4SLinus Torvalds 1067*1da177e4SLinus Torvalds static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) 1068*1da177e4SLinus Torvalds { 1069*1da177e4SLinus Torvalds int ret = -EINVAL; 1070*1da177e4SLinus Torvalds 1071*1da177e4SLinus Torvalds if (!try_module_get(policy->governor->owner)) 1072*1da177e4SLinus Torvalds return -EINVAL; 1073*1da177e4SLinus Torvalds 1074*1da177e4SLinus Torvalds dprintk("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event); 1075*1da177e4SLinus Torvalds ret = policy->governor->governor(policy, event); 1076*1da177e4SLinus Torvalds 1077*1da177e4SLinus Torvalds /* we keep one module reference alive for each CPU governed by this CPU */ 1078*1da177e4SLinus Torvalds if ((event != CPUFREQ_GOV_START) || ret) 1079*1da177e4SLinus Torvalds module_put(policy->governor->owner); 1080*1da177e4SLinus Torvalds if ((event == CPUFREQ_GOV_STOP) && !ret) 1081*1da177e4SLinus Torvalds module_put(policy->governor->owner); 1082*1da177e4SLinus Torvalds 1083*1da177e4SLinus Torvalds return ret; 1084*1da177e4SLinus Torvalds } 1085*1da177e4SLinus Torvalds 1086*1da177e4SLinus Torvalds 1087*1da177e4SLinus Torvalds int cpufreq_governor(unsigned int cpu, unsigned int event) 1088*1da177e4SLinus Torvalds { 1089*1da177e4SLinus Torvalds int ret = 0; 1090*1da177e4SLinus Torvalds struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 1091*1da177e4SLinus Torvalds 1092*1da177e4SLinus Torvalds if (!policy) 1093*1da177e4SLinus Torvalds return -EINVAL; 1094*1da177e4SLinus Torvalds 1095*1da177e4SLinus Torvalds down(&policy->lock); 1096*1da177e4SLinus Torvalds ret = __cpufreq_governor(policy, event); 1097*1da177e4SLinus Torvalds up(&policy->lock); 1098*1da177e4SLinus Torvalds 1099*1da177e4SLinus Torvalds cpufreq_cpu_put(policy); 1100*1da177e4SLinus Torvalds 1101*1da177e4SLinus Torvalds return ret; 1102*1da177e4SLinus Torvalds } 1103*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_governor); 1104*1da177e4SLinus Torvalds 1105*1da177e4SLinus Torvalds 1106*1da177e4SLinus Torvalds int cpufreq_register_governor(struct cpufreq_governor *governor) 1107*1da177e4SLinus Torvalds { 1108*1da177e4SLinus Torvalds struct cpufreq_governor *t; 1109*1da177e4SLinus Torvalds 1110*1da177e4SLinus Torvalds if (!governor) 1111*1da177e4SLinus Torvalds return -EINVAL; 1112*1da177e4SLinus Torvalds 1113*1da177e4SLinus Torvalds down(&cpufreq_governor_sem); 1114*1da177e4SLinus Torvalds 1115*1da177e4SLinus Torvalds list_for_each_entry(t, &cpufreq_governor_list, governor_list) { 1116*1da177e4SLinus Torvalds if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { 1117*1da177e4SLinus Torvalds up(&cpufreq_governor_sem); 1118*1da177e4SLinus Torvalds return -EBUSY; 1119*1da177e4SLinus Torvalds } 1120*1da177e4SLinus Torvalds } 1121*1da177e4SLinus Torvalds list_add(&governor->governor_list, &cpufreq_governor_list); 1122*1da177e4SLinus Torvalds 1123*1da177e4SLinus Torvalds up(&cpufreq_governor_sem); 1124*1da177e4SLinus Torvalds 1125*1da177e4SLinus Torvalds return 0; 1126*1da177e4SLinus Torvalds } 1127*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_governor); 1128*1da177e4SLinus Torvalds 1129*1da177e4SLinus Torvalds 1130*1da177e4SLinus Torvalds void cpufreq_unregister_governor(struct cpufreq_governor *governor) 1131*1da177e4SLinus Torvalds { 1132*1da177e4SLinus Torvalds if (!governor) 1133*1da177e4SLinus Torvalds return; 1134*1da177e4SLinus Torvalds 1135*1da177e4SLinus Torvalds down(&cpufreq_governor_sem); 1136*1da177e4SLinus Torvalds list_del(&governor->governor_list); 1137*1da177e4SLinus Torvalds up(&cpufreq_governor_sem); 1138*1da177e4SLinus Torvalds return; 1139*1da177e4SLinus Torvalds } 1140*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); 1141*1da177e4SLinus Torvalds 1142*1da177e4SLinus Torvalds 1143*1da177e4SLinus Torvalds 1144*1da177e4SLinus Torvalds /********************************************************************* 1145*1da177e4SLinus Torvalds * POLICY INTERFACE * 1146*1da177e4SLinus Torvalds *********************************************************************/ 1147*1da177e4SLinus Torvalds 1148*1da177e4SLinus Torvalds /** 1149*1da177e4SLinus Torvalds * cpufreq_get_policy - get the current cpufreq_policy 1150*1da177e4SLinus Torvalds * @policy: struct cpufreq_policy into which the current cpufreq_policy is written 1151*1da177e4SLinus Torvalds * 1152*1da177e4SLinus Torvalds * Reads the current cpufreq policy. 1153*1da177e4SLinus Torvalds */ 1154*1da177e4SLinus Torvalds int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) 1155*1da177e4SLinus Torvalds { 1156*1da177e4SLinus Torvalds struct cpufreq_policy *cpu_policy; 1157*1da177e4SLinus Torvalds if (!policy) 1158*1da177e4SLinus Torvalds return -EINVAL; 1159*1da177e4SLinus Torvalds 1160*1da177e4SLinus Torvalds cpu_policy = cpufreq_cpu_get(cpu); 1161*1da177e4SLinus Torvalds if (!cpu_policy) 1162*1da177e4SLinus Torvalds return -EINVAL; 1163*1da177e4SLinus Torvalds 1164*1da177e4SLinus Torvalds down(&cpu_policy->lock); 1165*1da177e4SLinus Torvalds memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); 1166*1da177e4SLinus Torvalds up(&cpu_policy->lock); 1167*1da177e4SLinus Torvalds 1168*1da177e4SLinus Torvalds cpufreq_cpu_put(cpu_policy); 1169*1da177e4SLinus Torvalds 1170*1da177e4SLinus Torvalds return 0; 1171*1da177e4SLinus Torvalds } 1172*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get_policy); 1173*1da177e4SLinus Torvalds 1174*1da177e4SLinus Torvalds 1175*1da177e4SLinus Torvalds static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) 1176*1da177e4SLinus Torvalds { 1177*1da177e4SLinus Torvalds int ret = 0; 1178*1da177e4SLinus Torvalds 1179*1da177e4SLinus Torvalds cpufreq_debug_disable_ratelimit(); 1180*1da177e4SLinus Torvalds dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, 1181*1da177e4SLinus Torvalds policy->min, policy->max); 1182*1da177e4SLinus Torvalds 1183*1da177e4SLinus Torvalds memcpy(&policy->cpuinfo, 1184*1da177e4SLinus Torvalds &data->cpuinfo, 1185*1da177e4SLinus Torvalds sizeof(struct cpufreq_cpuinfo)); 1186*1da177e4SLinus Torvalds 1187*1da177e4SLinus Torvalds /* verify the cpu speed can be set within this limit */ 1188*1da177e4SLinus Torvalds ret = cpufreq_driver->verify(policy); 1189*1da177e4SLinus Torvalds if (ret) 1190*1da177e4SLinus Torvalds goto error_out; 1191*1da177e4SLinus Torvalds 1192*1da177e4SLinus Torvalds down_read(&cpufreq_notifier_rwsem); 1193*1da177e4SLinus Torvalds 1194*1da177e4SLinus Torvalds /* adjust if necessary - all reasons */ 1195*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, 1196*1da177e4SLinus Torvalds policy); 1197*1da177e4SLinus Torvalds 1198*1da177e4SLinus Torvalds /* adjust if necessary - hardware incompatibility*/ 1199*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, 1200*1da177e4SLinus Torvalds policy); 1201*1da177e4SLinus Torvalds 1202*1da177e4SLinus Torvalds /* verify the cpu speed can be set within this limit, 1203*1da177e4SLinus Torvalds which might be different to the first one */ 1204*1da177e4SLinus Torvalds ret = cpufreq_driver->verify(policy); 1205*1da177e4SLinus Torvalds if (ret) { 1206*1da177e4SLinus Torvalds up_read(&cpufreq_notifier_rwsem); 1207*1da177e4SLinus Torvalds goto error_out; 1208*1da177e4SLinus Torvalds } 1209*1da177e4SLinus Torvalds 1210*1da177e4SLinus Torvalds /* notification of the new policy */ 1211*1da177e4SLinus Torvalds notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, 1212*1da177e4SLinus Torvalds policy); 1213*1da177e4SLinus Torvalds 1214*1da177e4SLinus Torvalds up_read(&cpufreq_notifier_rwsem); 1215*1da177e4SLinus Torvalds 1216*1da177e4SLinus Torvalds data->min = policy->min; 1217*1da177e4SLinus Torvalds data->max = policy->max; 1218*1da177e4SLinus Torvalds 1219*1da177e4SLinus Torvalds dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); 1220*1da177e4SLinus Torvalds 1221*1da177e4SLinus Torvalds if (cpufreq_driver->setpolicy) { 1222*1da177e4SLinus Torvalds data->policy = policy->policy; 1223*1da177e4SLinus Torvalds dprintk("setting range\n"); 1224*1da177e4SLinus Torvalds ret = cpufreq_driver->setpolicy(policy); 1225*1da177e4SLinus Torvalds } else { 1226*1da177e4SLinus Torvalds if (policy->governor != data->governor) { 1227*1da177e4SLinus Torvalds /* save old, working values */ 1228*1da177e4SLinus Torvalds struct cpufreq_governor *old_gov = data->governor; 1229*1da177e4SLinus Torvalds 1230*1da177e4SLinus Torvalds dprintk("governor switch\n"); 1231*1da177e4SLinus Torvalds 1232*1da177e4SLinus Torvalds /* end old governor */ 1233*1da177e4SLinus Torvalds if (data->governor) 1234*1da177e4SLinus Torvalds __cpufreq_governor(data, CPUFREQ_GOV_STOP); 1235*1da177e4SLinus Torvalds 1236*1da177e4SLinus Torvalds /* start new governor */ 1237*1da177e4SLinus Torvalds data->governor = policy->governor; 1238*1da177e4SLinus Torvalds if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { 1239*1da177e4SLinus Torvalds /* new governor failed, so re-start old one */ 1240*1da177e4SLinus Torvalds dprintk("starting governor %s failed\n", data->governor->name); 1241*1da177e4SLinus Torvalds if (old_gov) { 1242*1da177e4SLinus Torvalds data->governor = old_gov; 1243*1da177e4SLinus Torvalds __cpufreq_governor(data, CPUFREQ_GOV_START); 1244*1da177e4SLinus Torvalds } 1245*1da177e4SLinus Torvalds ret = -EINVAL; 1246*1da177e4SLinus Torvalds goto error_out; 1247*1da177e4SLinus Torvalds } 1248*1da177e4SLinus Torvalds /* might be a policy change, too, so fall through */ 1249*1da177e4SLinus Torvalds } 1250*1da177e4SLinus Torvalds dprintk("governor: change or update limits\n"); 1251*1da177e4SLinus Torvalds __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); 1252*1da177e4SLinus Torvalds } 1253*1da177e4SLinus Torvalds 1254*1da177e4SLinus Torvalds error_out: 1255*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 1256*1da177e4SLinus Torvalds return ret; 1257*1da177e4SLinus Torvalds } 1258*1da177e4SLinus Torvalds 1259*1da177e4SLinus Torvalds /** 1260*1da177e4SLinus Torvalds * cpufreq_set_policy - set a new CPUFreq policy 1261*1da177e4SLinus Torvalds * @policy: policy to be set. 1262*1da177e4SLinus Torvalds * 1263*1da177e4SLinus Torvalds * Sets a new CPU frequency and voltage scaling policy. 1264*1da177e4SLinus Torvalds */ 1265*1da177e4SLinus Torvalds int cpufreq_set_policy(struct cpufreq_policy *policy) 1266*1da177e4SLinus Torvalds { 1267*1da177e4SLinus Torvalds int ret = 0; 1268*1da177e4SLinus Torvalds struct cpufreq_policy *data; 1269*1da177e4SLinus Torvalds 1270*1da177e4SLinus Torvalds if (!policy) 1271*1da177e4SLinus Torvalds return -EINVAL; 1272*1da177e4SLinus Torvalds 1273*1da177e4SLinus Torvalds data = cpufreq_cpu_get(policy->cpu); 1274*1da177e4SLinus Torvalds if (!data) 1275*1da177e4SLinus Torvalds return -EINVAL; 1276*1da177e4SLinus Torvalds 1277*1da177e4SLinus Torvalds /* lock this CPU */ 1278*1da177e4SLinus Torvalds down(&data->lock); 1279*1da177e4SLinus Torvalds 1280*1da177e4SLinus Torvalds ret = __cpufreq_set_policy(data, policy); 1281*1da177e4SLinus Torvalds data->user_policy.min = data->min; 1282*1da177e4SLinus Torvalds data->user_policy.max = data->max; 1283*1da177e4SLinus Torvalds data->user_policy.policy = data->policy; 1284*1da177e4SLinus Torvalds data->user_policy.governor = data->governor; 1285*1da177e4SLinus Torvalds 1286*1da177e4SLinus Torvalds up(&data->lock); 1287*1da177e4SLinus Torvalds cpufreq_cpu_put(data); 1288*1da177e4SLinus Torvalds 1289*1da177e4SLinus Torvalds return ret; 1290*1da177e4SLinus Torvalds } 1291*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_set_policy); 1292*1da177e4SLinus Torvalds 1293*1da177e4SLinus Torvalds 1294*1da177e4SLinus Torvalds /** 1295*1da177e4SLinus Torvalds * cpufreq_update_policy - re-evaluate an existing cpufreq policy 1296*1da177e4SLinus Torvalds * @cpu: CPU which shall be re-evaluated 1297*1da177e4SLinus Torvalds * 1298*1da177e4SLinus Torvalds * Usefull for policy notifiers which have different necessities 1299*1da177e4SLinus Torvalds * at different times. 1300*1da177e4SLinus Torvalds */ 1301*1da177e4SLinus Torvalds int cpufreq_update_policy(unsigned int cpu) 1302*1da177e4SLinus Torvalds { 1303*1da177e4SLinus Torvalds struct cpufreq_policy *data = cpufreq_cpu_get(cpu); 1304*1da177e4SLinus Torvalds struct cpufreq_policy policy; 1305*1da177e4SLinus Torvalds int ret = 0; 1306*1da177e4SLinus Torvalds 1307*1da177e4SLinus Torvalds if (!data) 1308*1da177e4SLinus Torvalds return -ENODEV; 1309*1da177e4SLinus Torvalds 1310*1da177e4SLinus Torvalds down(&data->lock); 1311*1da177e4SLinus Torvalds 1312*1da177e4SLinus Torvalds dprintk("updating policy for CPU %u\n", cpu); 1313*1da177e4SLinus Torvalds memcpy(&policy, 1314*1da177e4SLinus Torvalds data, 1315*1da177e4SLinus Torvalds sizeof(struct cpufreq_policy)); 1316*1da177e4SLinus Torvalds policy.min = data->user_policy.min; 1317*1da177e4SLinus Torvalds policy.max = data->user_policy.max; 1318*1da177e4SLinus Torvalds policy.policy = data->user_policy.policy; 1319*1da177e4SLinus Torvalds policy.governor = data->user_policy.governor; 1320*1da177e4SLinus Torvalds 1321*1da177e4SLinus Torvalds ret = __cpufreq_set_policy(data, &policy); 1322*1da177e4SLinus Torvalds 1323*1da177e4SLinus Torvalds up(&data->lock); 1324*1da177e4SLinus Torvalds 1325*1da177e4SLinus Torvalds cpufreq_cpu_put(data); 1326*1da177e4SLinus Torvalds return ret; 1327*1da177e4SLinus Torvalds } 1328*1da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_update_policy); 1329*1da177e4SLinus Torvalds 1330*1da177e4SLinus Torvalds 1331*1da177e4SLinus Torvalds /********************************************************************* 1332*1da177e4SLinus Torvalds * REGISTER / UNREGISTER CPUFREQ DRIVER * 1333*1da177e4SLinus Torvalds *********************************************************************/ 1334*1da177e4SLinus Torvalds 1335*1da177e4SLinus Torvalds /** 1336*1da177e4SLinus Torvalds * cpufreq_register_driver - register a CPU Frequency driver 1337*1da177e4SLinus Torvalds * @driver_data: A struct cpufreq_driver containing the values# 1338*1da177e4SLinus Torvalds * submitted by the CPU Frequency driver. 1339*1da177e4SLinus Torvalds * 1340*1da177e4SLinus Torvalds * Registers a CPU Frequency driver to this core code. This code 1341*1da177e4SLinus Torvalds * returns zero on success, -EBUSY when another driver got here first 1342*1da177e4SLinus Torvalds * (and isn't unregistered in the meantime). 1343*1da177e4SLinus Torvalds * 1344*1da177e4SLinus Torvalds */ 1345*1da177e4SLinus Torvalds int cpufreq_register_driver(struct cpufreq_driver *driver_data) 1346*1da177e4SLinus Torvalds { 1347*1da177e4SLinus Torvalds unsigned long flags; 1348*1da177e4SLinus Torvalds int ret; 1349*1da177e4SLinus Torvalds 1350*1da177e4SLinus Torvalds if (!driver_data || !driver_data->verify || !driver_data->init || 1351*1da177e4SLinus Torvalds ((!driver_data->setpolicy) && (!driver_data->target))) 1352*1da177e4SLinus Torvalds return -EINVAL; 1353*1da177e4SLinus Torvalds 1354*1da177e4SLinus Torvalds dprintk("trying to register driver %s\n", driver_data->name); 1355*1da177e4SLinus Torvalds 1356*1da177e4SLinus Torvalds if (driver_data->setpolicy) 1357*1da177e4SLinus Torvalds driver_data->flags |= CPUFREQ_CONST_LOOPS; 1358*1da177e4SLinus Torvalds 1359*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 1360*1da177e4SLinus Torvalds if (cpufreq_driver) { 1361*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1362*1da177e4SLinus Torvalds return -EBUSY; 1363*1da177e4SLinus Torvalds } 1364*1da177e4SLinus Torvalds cpufreq_driver = driver_data; 1365*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1366*1da177e4SLinus Torvalds 1367*1da177e4SLinus Torvalds ret = sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver); 1368*1da177e4SLinus Torvalds 1369*1da177e4SLinus Torvalds if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) { 1370*1da177e4SLinus Torvalds int i; 1371*1da177e4SLinus Torvalds ret = -ENODEV; 1372*1da177e4SLinus Torvalds 1373*1da177e4SLinus Torvalds /* check for at least one working CPU */ 1374*1da177e4SLinus Torvalds for (i=0; i<NR_CPUS; i++) 1375*1da177e4SLinus Torvalds if (cpufreq_cpu_data[i]) 1376*1da177e4SLinus Torvalds ret = 0; 1377*1da177e4SLinus Torvalds 1378*1da177e4SLinus Torvalds /* if all ->init() calls failed, unregister */ 1379*1da177e4SLinus Torvalds if (ret) { 1380*1da177e4SLinus Torvalds dprintk("no CPU initialized for driver %s\n", driver_data->name); 1381*1da177e4SLinus Torvalds sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); 1382*1da177e4SLinus Torvalds 1383*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 1384*1da177e4SLinus Torvalds cpufreq_driver = NULL; 1385*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1386*1da177e4SLinus Torvalds } 1387*1da177e4SLinus Torvalds } 1388*1da177e4SLinus Torvalds 1389*1da177e4SLinus Torvalds if (!ret) { 1390*1da177e4SLinus Torvalds dprintk("driver %s up and running\n", driver_data->name); 1391*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 1392*1da177e4SLinus Torvalds } 1393*1da177e4SLinus Torvalds 1394*1da177e4SLinus Torvalds return (ret); 1395*1da177e4SLinus Torvalds } 1396*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_driver); 1397*1da177e4SLinus Torvalds 1398*1da177e4SLinus Torvalds 1399*1da177e4SLinus Torvalds /** 1400*1da177e4SLinus Torvalds * cpufreq_unregister_driver - unregister the current CPUFreq driver 1401*1da177e4SLinus Torvalds * 1402*1da177e4SLinus Torvalds * Unregister the current CPUFreq driver. Only call this if you have 1403*1da177e4SLinus Torvalds * the right to do so, i.e. if you have succeeded in initialising before! 1404*1da177e4SLinus Torvalds * Returns zero if successful, and -EINVAL if the cpufreq_driver is 1405*1da177e4SLinus Torvalds * currently not initialised. 1406*1da177e4SLinus Torvalds */ 1407*1da177e4SLinus Torvalds int cpufreq_unregister_driver(struct cpufreq_driver *driver) 1408*1da177e4SLinus Torvalds { 1409*1da177e4SLinus Torvalds unsigned long flags; 1410*1da177e4SLinus Torvalds 1411*1da177e4SLinus Torvalds cpufreq_debug_disable_ratelimit(); 1412*1da177e4SLinus Torvalds 1413*1da177e4SLinus Torvalds if (!cpufreq_driver || (driver != cpufreq_driver)) { 1414*1da177e4SLinus Torvalds cpufreq_debug_enable_ratelimit(); 1415*1da177e4SLinus Torvalds return -EINVAL; 1416*1da177e4SLinus Torvalds } 1417*1da177e4SLinus Torvalds 1418*1da177e4SLinus Torvalds dprintk("unregistering driver %s\n", driver->name); 1419*1da177e4SLinus Torvalds 1420*1da177e4SLinus Torvalds sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); 1421*1da177e4SLinus Torvalds 1422*1da177e4SLinus Torvalds spin_lock_irqsave(&cpufreq_driver_lock, flags); 1423*1da177e4SLinus Torvalds cpufreq_driver = NULL; 1424*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1425*1da177e4SLinus Torvalds 1426*1da177e4SLinus Torvalds return 0; 1427*1da177e4SLinus Torvalds } 1428*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); 1429