blob: 480c49c71afec6661ab9ddb7e3729e54f8af8fd7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/cpufreq/cpufreq.c
3 *
4 * Copyright (C) 2001 Russell King
5 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
6 *
Ashok Rajc32b6b82005-10-30 14:59:54 -08007 * Oct 2005 - Ashok Raj <ashok.raj@intel.com>
Dave Jones32ee8c32006-02-28 00:43:23 -05008 * Added handling for CPU hotplug
Dave Jones8ff69732006-03-05 03:37:23 -05009 * Feb 2006 - Jacob Shin <jacob.shin@amd.com>
10 * Fix handling for CPU hotplug -- affected CPUs
Ashok Rajc32b6b82005-10-30 14:59:54 -080011 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
Viresh Kumardb701152012-10-23 01:29:03 +020018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/notifier.h>
24#include <linux/cpufreq.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/spinlock.h>
28#include <linux/device.h>
29#include <linux/slab.h>
30#include <linux/cpu.h>
31#include <linux/completion.h>
akpm@osdl.org3fc54d32006-01-13 15:54:22 -080032#include <linux/mutex.h>
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +010033#include <linux/syscore_ops.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Thomas Renninger6f4f2722010-04-20 13:17:36 +020035#include <trace/events/power.h>
36
Linus Torvalds1da177e2005-04-16 15:20:36 -070037/**
Dave Jonescd878472006-08-11 17:59:28 -040038 * The "cpufreq driver" - the arch- or hardware-dependent low
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 * level driver of CPUFreq support, and its spinlock. This lock
40 * also protects the cpufreq_cpu_data array.
41 */
Dave Jones7d5e3502006-02-02 17:03:42 -050042static struct cpufreq_driver *cpufreq_driver;
Mike Travis7a6aedf2008-03-25 15:06:53 -070043static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
Thomas Renninger084f3492007-07-09 11:35:28 -070044#ifdef CONFIG_HOTPLUG_CPU
45/* This one keeps track of the previously set governor of a removed CPU */
Dmitry Monakhove77b89f2009-10-05 00:38:55 +040046static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
Thomas Renninger084f3492007-07-09 11:35:28 -070047#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070048static DEFINE_SPINLOCK(cpufreq_driver_lock);
49
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080050/*
51 * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
52 * all cpufreq/hotplug/workqueue/etc related lock issues.
53 *
54 * The rules for this semaphore:
55 * - Any routine that wants to read from the policy structure will
56 * do a down_read on this semaphore.
57 * - Any routine that will write to the policy structure and/or may take away
58 * the policy altogether (eg. CPU hotplug), will hold this lock in write
59 * mode before doing so.
60 *
61 * Additional rules:
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080062 * - Governor routines that can be called in cpufreq hotplug path should not
63 * take this sem as top level hotplug notifier handler takes this.
Mathieu Desnoyers395913d2009-06-08 13:17:31 -040064 * - Lock should not be held across
65 * __cpufreq_governor(data, CPUFREQ_GOV_STOP);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080066 */
Tejun Heof1625062009-10-29 22:34:13 +090067static DEFINE_PER_CPU(int, cpufreq_policy_cpu);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080068static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
69
70#define lock_policy_rwsem(mode, cpu) \
Viresh Kumarfa1d8af2013-02-07 15:38:42 +053071static int lock_policy_rwsem_##mode(int cpu) \
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080072{ \
Tejun Heof1625062009-10-29 22:34:13 +090073 int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080074 BUG_ON(policy_cpu == -1); \
75 down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080076 \
77 return 0; \
78}
79
80lock_policy_rwsem(read, cpu);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080081lock_policy_rwsem(write, cpu);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080082
Viresh Kumarfa1d8af2013-02-07 15:38:42 +053083#define unlock_policy_rwsem(mode, cpu) \
84static void unlock_policy_rwsem_##mode(int cpu) \
85{ \
86 int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu); \
87 BUG_ON(policy_cpu == -1); \
88 up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu)); \
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080089}
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080090
Viresh Kumarfa1d8af2013-02-07 15:38:42 +053091unlock_policy_rwsem(read, cpu);
92unlock_policy_rwsem(write, cpu);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080093
Linus Torvalds1da177e2005-04-16 15:20:36 -070094/* internal prototypes */
Dave Jones29464f22009-01-18 01:37:11 -050095static int __cpufreq_governor(struct cpufreq_policy *policy,
96 unsigned int event);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -080097static unsigned int __cpufreq_get(unsigned int cpu);
David Howells65f27f32006-11-22 14:55:48 +000098static void handle_update(struct work_struct *work);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100/**
Dave Jones32ee8c32006-02-28 00:43:23 -0500101 * Two notifier lists: the "policy" list is involved in the
102 * validation process for a new CPU frequency policy; the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 * "transition" list for kernel code that needs to handle
104 * changes to devices when the CPU clock speed changes.
105 * The mutex locks both lists.
106 */
Alan Sterne041c682006-03-27 01:16:30 -0800107static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
Alan Sternb4dfdbb2006-10-04 02:17:06 -0700108static struct srcu_notifier_head cpufreq_transition_notifier_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Cesar Eduardo Barros74212ca2008-02-16 08:41:24 -0200110static bool init_cpufreq_transition_notifier_list_called;
Alan Sternb4dfdbb2006-10-04 02:17:06 -0700111static int __init init_cpufreq_transition_notifier_list(void)
112{
113 srcu_init_notifier_head(&cpufreq_transition_notifier_list);
Cesar Eduardo Barros74212ca2008-02-16 08:41:24 -0200114 init_cpufreq_transition_notifier_list_called = true;
Alan Sternb4dfdbb2006-10-04 02:17:06 -0700115 return 0;
116}
Linus Torvaldsb3438f82006-11-20 11:47:18 -0800117pure_initcall(init_cpufreq_transition_notifier_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -0400119static int off __read_mostly;
Viresh Kumarda584452012-10-26 00:51:32 +0200120static int cpufreq_disabled(void)
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -0400121{
122 return off;
123}
124void disable_cpufreq(void)
125{
126 off = 1;
127}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128static LIST_HEAD(cpufreq_governor_list);
Dave Jones29464f22009-01-18 01:37:11 -0500129static DEFINE_MUTEX(cpufreq_governor_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Stephen Boyda9144432012-07-20 18:14:38 +0000131static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132{
133 struct cpufreq_policy *data;
134 unsigned long flags;
135
Mike Travis7a6aedf2008-03-25 15:06:53 -0700136 if (cpu >= nr_cpu_ids)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 goto err_out;
138
139 /* get the cpufreq driver */
140 spin_lock_irqsave(&cpufreq_driver_lock, flags);
141
142 if (!cpufreq_driver)
143 goto err_out_unlock;
144
145 if (!try_module_get(cpufreq_driver->owner))
146 goto err_out_unlock;
147
148
149 /* get the CPU */
Mike Travis7a6aedf2008-03-25 15:06:53 -0700150 data = per_cpu(cpufreq_cpu_data, cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152 if (!data)
153 goto err_out_put_module;
154
Stephen Boyda9144432012-07-20 18:14:38 +0000155 if (!sysfs && !kobject_get(&data->kobj))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 goto err_out_put_module;
157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 return data;
160
Dave Jones7d5e3502006-02-02 17:03:42 -0500161err_out_put_module:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 module_put(cpufreq_driver->owner);
Dave Jones7d5e3502006-02-02 17:03:42 -0500163err_out_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Dave Jones7d5e3502006-02-02 17:03:42 -0500165err_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 return NULL;
167}
Stephen Boyda9144432012-07-20 18:14:38 +0000168
169struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
170{
Dirk Brandewied5aaffa2013-01-17 16:22:21 +0000171 if (cpufreq_disabled())
172 return NULL;
173
Stephen Boyda9144432012-07-20 18:14:38 +0000174 return __cpufreq_cpu_get(cpu, false);
175}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
177
Stephen Boyda9144432012-07-20 18:14:38 +0000178static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
179{
180 return __cpufreq_cpu_get(cpu, true);
181}
182
183static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
184{
185 if (!sysfs)
186 kobject_put(&data->kobj);
187 module_put(cpufreq_driver->owner);
188}
Dave Jones7d5e3502006-02-02 17:03:42 -0500189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190void cpufreq_cpu_put(struct cpufreq_policy *data)
191{
Dirk Brandewied5aaffa2013-01-17 16:22:21 +0000192 if (cpufreq_disabled())
193 return;
194
Stephen Boyda9144432012-07-20 18:14:38 +0000195 __cpufreq_cpu_put(data, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196}
197EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
198
Stephen Boyda9144432012-07-20 18:14:38 +0000199static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
200{
201 __cpufreq_cpu_put(data, true);
202}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204/*********************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 * EXTERNALLY AFFECTING FREQUENCY CHANGES *
206 *********************************************************************/
207
208/**
209 * adjust_jiffies - adjust the system "loops_per_jiffy"
210 *
211 * This function alters the system "loops_per_jiffy" for the clock
212 * speed change. Note that loops_per_jiffy cannot be updated on SMP
Dave Jones32ee8c32006-02-28 00:43:23 -0500213 * systems as each CPU might be scaled differently. So, use the arch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 * per-CPU loops_per_jiffy value wherever possible.
215 */
216#ifndef CONFIG_SMP
217static unsigned long l_p_j_ref;
218static unsigned int l_p_j_ref_freq;
219
Arjan van de Ven858119e2006-01-14 13:20:43 -0800220static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 if (ci->flags & CPUFREQ_CONST_LOOPS)
223 return;
224
225 if (!l_p_j_ref_freq) {
226 l_p_j_ref = loops_per_jiffy;
227 l_p_j_ref_freq = ci->old;
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200228 pr_debug("saving %lu as reference value for loops_per_jiffy; "
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530229 "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 }
Afzal Mohammedd08de0c12012-01-04 10:52:46 +0530231 if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -0700232 (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530233 loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
234 ci->new);
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200235 pr_debug("scaling loops_per_jiffy to %lu "
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530236 "for frequency %u kHz\n", loops_per_jiffy, ci->new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
238}
239#else
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530240static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
241{
242 return;
243}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244#endif
245
246
247/**
Dave Jonese4472cb2006-01-31 15:53:55 -0800248 * cpufreq_notify_transition - call notifier chain and adjust_jiffies
249 * on frequency transition.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 *
Dave Jonese4472cb2006-01-31 15:53:55 -0800251 * This function calls the transition notifiers and the "adjust_jiffies"
252 * function. It is called twice on all CPU frequency changes that have
Dave Jones32ee8c32006-02-28 00:43:23 -0500253 * external effects.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 */
255void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
256{
Dave Jonese4472cb2006-01-31 15:53:55 -0800257 struct cpufreq_policy *policy;
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530258 unsigned long flags;
Dave Jonese4472cb2006-01-31 15:53:55 -0800259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 BUG_ON(irqs_disabled());
261
Dirk Brandewied5aaffa2013-01-17 16:22:21 +0000262 if (cpufreq_disabled())
263 return;
264
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 freqs->flags = cpufreq_driver->flags;
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200266 pr_debug("notification %u of frequency transition to %u kHz\n",
Dave Jonese4472cb2006-01-31 15:53:55 -0800267 state, freqs->new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530269 spin_lock_irqsave(&cpufreq_driver_lock, flags);
Mike Travis7a6aedf2008-03-25 15:06:53 -0700270 policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530271 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 switch (state) {
Dave Jonese4472cb2006-01-31 15:53:55 -0800274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 case CPUFREQ_PRECHANGE:
Dave Jones32ee8c32006-02-28 00:43:23 -0500276 /* detect if the driver reported a value as "old frequency"
Dave Jonese4472cb2006-01-31 15:53:55 -0800277 * which is not equal to what the cpufreq core thinks is
278 * "old frequency".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 */
280 if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
Dave Jonese4472cb2006-01-31 15:53:55 -0800281 if ((policy) && (policy->cpu == freqs->cpu) &&
282 (policy->cur) && (policy->cur != freqs->old)) {
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200283 pr_debug("Warning: CPU frequency is"
Dave Jonese4472cb2006-01-31 15:53:55 -0800284 " %u, cpufreq assumed %u kHz.\n",
285 freqs->old, policy->cur);
286 freqs->old = policy->cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 }
288 }
Alan Sternb4dfdbb2006-10-04 02:17:06 -0700289 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
Alan Sterne041c682006-03-27 01:16:30 -0800290 CPUFREQ_PRECHANGE, freqs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
292 break;
Dave Jonese4472cb2006-01-31 15:53:55 -0800293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 case CPUFREQ_POSTCHANGE:
295 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200296 pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
Thomas Renninger6f4f2722010-04-20 13:17:36 +0200297 (unsigned long)freqs->cpu);
298 trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
Thomas Renninger25e41932011-01-03 17:50:44 +0100299 trace_cpu_frequency(freqs->new, freqs->cpu);
Alan Sternb4dfdbb2006-10-04 02:17:06 -0700300 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
Alan Sterne041c682006-03-27 01:16:30 -0800301 CPUFREQ_POSTCHANGE, freqs);
Dave Jonese4472cb2006-01-31 15:53:55 -0800302 if (likely(policy) && likely(policy->cpu == freqs->cpu))
303 policy->cur = freqs->new;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 break;
305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306}
307EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
308
309
310
311/*********************************************************************
312 * SYSFS INTERFACE *
313 *********************************************************************/
314
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700315static struct cpufreq_governor *__find_governor(const char *str_governor)
316{
317 struct cpufreq_governor *t;
318
319 list_for_each_entry(t, &cpufreq_governor_list, governor_list)
Dave Jones29464f22009-01-18 01:37:11 -0500320 if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN))
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700321 return t;
322
323 return NULL;
324}
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326/**
327 * cpufreq_parse_governor - parse a governor string
328 */
Dave Jones905d77c2008-03-05 14:28:32 -0500329static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 struct cpufreq_governor **governor)
331{
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700332 int err = -EINVAL;
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if (!cpufreq_driver)
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700335 goto out;
336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 if (cpufreq_driver->setpolicy) {
338 if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
339 *policy = CPUFREQ_POLICY_PERFORMANCE;
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700340 err = 0;
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530341 } else if (!strnicmp(str_governor, "powersave",
342 CPUFREQ_NAME_LEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 *policy = CPUFREQ_POLICY_POWERSAVE;
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700344 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 }
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700346 } else if (cpufreq_driver->target) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 struct cpufreq_governor *t;
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700348
akpm@osdl.org3fc54d32006-01-13 15:54:22 -0800349 mutex_lock(&cpufreq_governor_mutex);
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700350
351 t = __find_governor(str_governor);
352
Jeremy Fitzhardingeea714972006-07-06 12:32:01 -0700353 if (t == NULL) {
Kees Cook1a8e1462011-05-04 08:38:56 -0700354 int ret;
Jeremy Fitzhardingeea714972006-07-06 12:32:01 -0700355
Kees Cook1a8e1462011-05-04 08:38:56 -0700356 mutex_unlock(&cpufreq_governor_mutex);
357 ret = request_module("cpufreq_%s", str_governor);
358 mutex_lock(&cpufreq_governor_mutex);
Jeremy Fitzhardingeea714972006-07-06 12:32:01 -0700359
Kees Cook1a8e1462011-05-04 08:38:56 -0700360 if (ret == 0)
361 t = __find_governor(str_governor);
Jeremy Fitzhardingeea714972006-07-06 12:32:01 -0700362 }
363
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700364 if (t != NULL) {
365 *governor = t;
366 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700368
akpm@osdl.org3fc54d32006-01-13 15:54:22 -0800369 mutex_unlock(&cpufreq_governor_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 }
Dave Jones29464f22009-01-18 01:37:11 -0500371out:
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -0700372 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
375
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376/**
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530377 * cpufreq_per_cpu_attr_read() / show_##file_name() -
378 * print out cpufreq information
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 *
380 * Write out information from cpufreq_driver->policy[cpu]; object must be
381 * "unsigned int".
382 */
383
Dave Jones32ee8c32006-02-28 00:43:23 -0500384#define show_one(file_name, object) \
385static ssize_t show_##file_name \
Dave Jones905d77c2008-03-05 14:28:32 -0500386(struct cpufreq_policy *policy, char *buf) \
Dave Jones32ee8c32006-02-28 00:43:23 -0500387{ \
Dave Jones29464f22009-01-18 01:37:11 -0500388 return sprintf(buf, "%u\n", policy->object); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389}
390
391show_one(cpuinfo_min_freq, cpuinfo.min_freq);
392show_one(cpuinfo_max_freq, cpuinfo.max_freq);
Thomas Renningered129782009-02-04 01:17:41 +0100393show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394show_one(scaling_min_freq, min);
395show_one(scaling_max_freq, max);
396show_one(scaling_cur_freq, cur);
397
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530398static int __cpufreq_set_policy(struct cpufreq_policy *data,
399 struct cpufreq_policy *policy);
Thomas Renninger7970e082006-04-13 15:14:04 +0200400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401/**
402 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
403 */
404#define store_one(file_name, object) \
405static ssize_t store_##file_name \
Dave Jones905d77c2008-03-05 14:28:32 -0500406(struct cpufreq_policy *policy, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{ \
Jingoo Hanf55c9c22012-10-31 05:49:13 +0000408 unsigned int ret; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 struct cpufreq_policy new_policy; \
410 \
411 ret = cpufreq_get_policy(&new_policy, policy->cpu); \
412 if (ret) \
413 return -EINVAL; \
414 \
Dave Jones29464f22009-01-18 01:37:11 -0500415 ret = sscanf(buf, "%u", &new_policy.object); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (ret != 1) \
417 return -EINVAL; \
418 \
Thomas Renninger7970e082006-04-13 15:14:04 +0200419 ret = __cpufreq_set_policy(policy, &new_policy); \
420 policy->user_policy.object = policy->object; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 \
422 return ret ? ret : count; \
423}
424
Dave Jones29464f22009-01-18 01:37:11 -0500425store_one(scaling_min_freq, min);
426store_one(scaling_max_freq, max);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428/**
429 * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
430 */
Dave Jones905d77c2008-03-05 14:28:32 -0500431static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
432 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800434 unsigned int cur_freq = __cpufreq_get(policy->cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 if (!cur_freq)
436 return sprintf(buf, "<unknown>");
437 return sprintf(buf, "%u\n", cur_freq);
438}
439
440
441/**
442 * show_scaling_governor - show the current policy for the specified CPU
443 */
Dave Jones905d77c2008-03-05 14:28:32 -0500444static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Dave Jones29464f22009-01-18 01:37:11 -0500446 if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return sprintf(buf, "powersave\n");
448 else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
449 return sprintf(buf, "performance\n");
450 else if (policy->governor)
viresh kumar4b972f02012-10-23 01:23:43 +0200451 return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
Dave Jones29464f22009-01-18 01:37:11 -0500452 policy->governor->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 return -EINVAL;
454}
455
456
457/**
458 * store_scaling_governor - store policy for the specified CPU
459 */
Dave Jones905d77c2008-03-05 14:28:32 -0500460static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
461 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
Jingoo Hanf55c9c22012-10-31 05:49:13 +0000463 unsigned int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 char str_governor[16];
465 struct cpufreq_policy new_policy;
466
467 ret = cpufreq_get_policy(&new_policy, policy->cpu);
468 if (ret)
469 return ret;
470
Dave Jones29464f22009-01-18 01:37:11 -0500471 ret = sscanf(buf, "%15s", str_governor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 if (ret != 1)
473 return -EINVAL;
474
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530475 if (cpufreq_parse_governor(str_governor, &new_policy.policy,
476 &new_policy.governor))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 return -EINVAL;
478
Thomas Renninger7970e082006-04-13 15:14:04 +0200479 /* Do not use cpufreq_set_policy here or the user_policy.max
480 will be wrongly overridden */
Thomas Renninger7970e082006-04-13 15:14:04 +0200481 ret = __cpufreq_set_policy(policy, &new_policy);
482
483 policy->user_policy.policy = policy->policy;
484 policy->user_policy.governor = policy->governor;
Thomas Renninger7970e082006-04-13 15:14:04 +0200485
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530486 if (ret)
487 return ret;
488 else
489 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490}
491
492/**
493 * show_scaling_driver - show the cpufreq driver currently loaded
494 */
Dave Jones905d77c2008-03-05 14:28:32 -0500495static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
viresh kumar4b972f02012-10-23 01:23:43 +0200497 return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498}
499
500/**
501 * show_scaling_available_governors - show the available CPUfreq governors
502 */
Dave Jones905d77c2008-03-05 14:28:32 -0500503static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
504 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
506 ssize_t i = 0;
507 struct cpufreq_governor *t;
508
509 if (!cpufreq_driver->target) {
510 i += sprintf(buf, "performance powersave");
511 goto out;
512 }
513
514 list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
Dave Jones29464f22009-01-18 01:37:11 -0500515 if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
516 - (CPUFREQ_NAME_LEN + 2)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 goto out;
viresh kumar4b972f02012-10-23 01:23:43 +0200518 i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
Dave Jones7d5e3502006-02-02 17:03:42 -0500520out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 i += sprintf(&buf[i], "\n");
522 return i;
523}
Darrick J. Wonge8628dd2008-04-18 13:31:12 -0700524
Rusty Russell835481d2009-01-04 05:18:06 -0800525static ssize_t show_cpus(const struct cpumask *mask, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 ssize_t i = 0;
528 unsigned int cpu;
529
Rusty Russell835481d2009-01-04 05:18:06 -0800530 for_each_cpu(cpu, mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (i)
532 i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
533 i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
534 if (i >= (PAGE_SIZE - 5))
Dave Jones29464f22009-01-18 01:37:11 -0500535 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 }
537 i += sprintf(&buf[i], "\n");
538 return i;
539}
540
Darrick J. Wonge8628dd2008-04-18 13:31:12 -0700541/**
542 * show_related_cpus - show the CPUs affected by each transition even if
543 * hw coordination is in use
544 */
545static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
546{
Darrick J. Wonge8628dd2008-04-18 13:31:12 -0700547 return show_cpus(policy->related_cpus, buf);
548}
549
550/**
551 * show_affected_cpus - show the CPUs affected by each transition
552 */
553static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
554{
555 return show_cpus(policy->cpus, buf);
556}
557
Venki Pallipadi9e769882007-10-26 10:18:21 -0700558static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
Dave Jones905d77c2008-03-05 14:28:32 -0500559 const char *buf, size_t count)
Venki Pallipadi9e769882007-10-26 10:18:21 -0700560{
561 unsigned int freq = 0;
562 unsigned int ret;
563
CHIKAMA masaki879000f2008-06-05 22:46:33 -0700564 if (!policy->governor || !policy->governor->store_setspeed)
Venki Pallipadi9e769882007-10-26 10:18:21 -0700565 return -EINVAL;
566
567 ret = sscanf(buf, "%u", &freq);
568 if (ret != 1)
569 return -EINVAL;
570
571 policy->governor->store_setspeed(policy, freq);
572
573 return count;
574}
575
576static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
577{
CHIKAMA masaki879000f2008-06-05 22:46:33 -0700578 if (!policy->governor || !policy->governor->show_setspeed)
Venki Pallipadi9e769882007-10-26 10:18:21 -0700579 return sprintf(buf, "<unsupported>\n");
580
581 return policy->governor->show_setspeed(policy, buf);
582}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Thomas Renningere2f74f32009-11-19 12:31:01 +0100584/**
viresh kumar8bf1ac722012-10-23 01:23:33 +0200585 * show_bios_limit - show the current cpufreq HW/BIOS limitation
Thomas Renningere2f74f32009-11-19 12:31:01 +0100586 */
587static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
588{
589 unsigned int limit;
590 int ret;
591 if (cpufreq_driver->bios_limit) {
592 ret = cpufreq_driver->bios_limit(policy->cpu, &limit);
593 if (!ret)
594 return sprintf(buf, "%u\n", limit);
595 }
596 return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
597}
598
Borislav Petkov6dad2a22010-03-31 21:56:46 +0200599cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
600cpufreq_freq_attr_ro(cpuinfo_min_freq);
601cpufreq_freq_attr_ro(cpuinfo_max_freq);
602cpufreq_freq_attr_ro(cpuinfo_transition_latency);
603cpufreq_freq_attr_ro(scaling_available_governors);
604cpufreq_freq_attr_ro(scaling_driver);
605cpufreq_freq_attr_ro(scaling_cur_freq);
606cpufreq_freq_attr_ro(bios_limit);
607cpufreq_freq_attr_ro(related_cpus);
608cpufreq_freq_attr_ro(affected_cpus);
609cpufreq_freq_attr_rw(scaling_min_freq);
610cpufreq_freq_attr_rw(scaling_max_freq);
611cpufreq_freq_attr_rw(scaling_governor);
612cpufreq_freq_attr_rw(scaling_setspeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Dave Jones905d77c2008-03-05 14:28:32 -0500614static struct attribute *default_attrs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 &cpuinfo_min_freq.attr,
616 &cpuinfo_max_freq.attr,
Thomas Renningered129782009-02-04 01:17:41 +0100617 &cpuinfo_transition_latency.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 &scaling_min_freq.attr,
619 &scaling_max_freq.attr,
620 &affected_cpus.attr,
Darrick J. Wonge8628dd2008-04-18 13:31:12 -0700621 &related_cpus.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 &scaling_governor.attr,
623 &scaling_driver.attr,
624 &scaling_available_governors.attr,
Venki Pallipadi9e769882007-10-26 10:18:21 -0700625 &scaling_setspeed.attr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 NULL
627};
628
Thomas Renninger8aa84ad2009-07-24 15:25:05 +0200629struct kobject *cpufreq_global_kobject;
630EXPORT_SYMBOL(cpufreq_global_kobject);
631
Dave Jones29464f22009-01-18 01:37:11 -0500632#define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
633#define to_attr(a) container_of(a, struct freq_attr, attr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Dave Jones29464f22009-01-18 01:37:11 -0500635static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
Dave Jones905d77c2008-03-05 14:28:32 -0500637 struct cpufreq_policy *policy = to_policy(kobj);
638 struct freq_attr *fattr = to_attr(attr);
Dave Jones0db4a8a2008-03-05 14:20:57 -0500639 ssize_t ret = -EINVAL;
Stephen Boyda9144432012-07-20 18:14:38 +0000640 policy = cpufreq_cpu_get_sysfs(policy->cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 if (!policy)
Dave Jones0db4a8a2008-03-05 14:20:57 -0500642 goto no_policy;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800643
644 if (lock_policy_rwsem_read(policy->cpu) < 0)
Dave Jones0db4a8a2008-03-05 14:20:57 -0500645 goto fail;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800646
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530647 if (fattr->show)
648 ret = fattr->show(policy, buf);
649 else
650 ret = -EIO;
651
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800652 unlock_policy_rwsem_read(policy->cpu);
Dave Jones0db4a8a2008-03-05 14:20:57 -0500653fail:
Stephen Boyda9144432012-07-20 18:14:38 +0000654 cpufreq_cpu_put_sysfs(policy);
Dave Jones0db4a8a2008-03-05 14:20:57 -0500655no_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return ret;
657}
658
Dave Jones905d77c2008-03-05 14:28:32 -0500659static ssize_t store(struct kobject *kobj, struct attribute *attr,
660 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661{
Dave Jones905d77c2008-03-05 14:28:32 -0500662 struct cpufreq_policy *policy = to_policy(kobj);
663 struct freq_attr *fattr = to_attr(attr);
Dave Jonesa07530b2008-03-05 14:22:25 -0500664 ssize_t ret = -EINVAL;
Stephen Boyda9144432012-07-20 18:14:38 +0000665 policy = cpufreq_cpu_get_sysfs(policy->cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 if (!policy)
Dave Jonesa07530b2008-03-05 14:22:25 -0500667 goto no_policy;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800668
669 if (lock_policy_rwsem_write(policy->cpu) < 0)
Dave Jonesa07530b2008-03-05 14:22:25 -0500670 goto fail;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800671
Gautham R Shenoye08f5f52006-10-26 16:20:58 +0530672 if (fattr->store)
673 ret = fattr->store(policy, buf, count);
674 else
675 ret = -EIO;
676
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800677 unlock_policy_rwsem_write(policy->cpu);
Dave Jonesa07530b2008-03-05 14:22:25 -0500678fail:
Stephen Boyda9144432012-07-20 18:14:38 +0000679 cpufreq_cpu_put_sysfs(policy);
Dave Jonesa07530b2008-03-05 14:22:25 -0500680no_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 return ret;
682}
683
Dave Jones905d77c2008-03-05 14:28:32 -0500684static void cpufreq_sysfs_release(struct kobject *kobj)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Dave Jones905d77c2008-03-05 14:28:32 -0500686 struct cpufreq_policy *policy = to_policy(kobj);
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200687 pr_debug("last reference is dropped\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 complete(&policy->kobj_unregister);
689}
690
Emese Revfy52cf25d2010-01-19 02:58:23 +0100691static const struct sysfs_ops sysfs_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 .show = show,
693 .store = store,
694};
695
696static struct kobj_type ktype_cpufreq = {
697 .sysfs_ops = &sysfs_ops,
698 .default_attrs = default_attrs,
699 .release = cpufreq_sysfs_release,
700};
701
Dave Jones19d6f7e2009-07-08 17:35:39 -0400702/* symlink affected CPUs */
Alex Chiangcf3289d02009-11-17 20:27:08 -0700703static int cpufreq_add_dev_symlink(unsigned int cpu,
704 struct cpufreq_policy *policy)
Dave Jones19d6f7e2009-07-08 17:35:39 -0400705{
706 unsigned int j;
707 int ret = 0;
708
709 for_each_cpu(j, policy->cpus) {
710 struct cpufreq_policy *managed_policy;
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800711 struct device *cpu_dev;
Dave Jones19d6f7e2009-07-08 17:35:39 -0400712
713 if (j == cpu)
714 continue;
Dave Jones19d6f7e2009-07-08 17:35:39 -0400715
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200716 pr_debug("CPU %u already managed, adding link\n", j);
Dave Jones19d6f7e2009-07-08 17:35:39 -0400717 managed_policy = cpufreq_cpu_get(cpu);
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800718 cpu_dev = get_cpu_device(j);
719 ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
Dave Jones19d6f7e2009-07-08 17:35:39 -0400720 "cpufreq");
721 if (ret) {
722 cpufreq_cpu_put(managed_policy);
723 return ret;
724 }
725 }
726 return ret;
727}
728
Alex Chiangcf3289d02009-11-17 20:27:08 -0700729static int cpufreq_add_dev_interface(unsigned int cpu,
730 struct cpufreq_policy *policy,
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800731 struct device *dev)
Dave Jones909a6942009-07-08 18:05:42 -0400732{
Dave Jonesecf7e462009-07-08 18:48:47 -0400733 struct cpufreq_policy new_policy;
Dave Jones909a6942009-07-08 18:05:42 -0400734 struct freq_attr **drv_attr;
735 unsigned long flags;
736 int ret = 0;
737 unsigned int j;
738
739 /* prepare interface data */
740 ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800741 &dev->kobj, "cpufreq");
Dave Jones909a6942009-07-08 18:05:42 -0400742 if (ret)
743 return ret;
744
745 /* set up files for this cpu device */
746 drv_attr = cpufreq_driver->attr;
747 while ((drv_attr) && (*drv_attr)) {
748 ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
749 if (ret)
750 goto err_out_kobj_put;
751 drv_attr++;
752 }
753 if (cpufreq_driver->get) {
754 ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
755 if (ret)
756 goto err_out_kobj_put;
757 }
758 if (cpufreq_driver->target) {
759 ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
760 if (ret)
761 goto err_out_kobj_put;
762 }
Thomas Renningere2f74f32009-11-19 12:31:01 +0100763 if (cpufreq_driver->bios_limit) {
764 ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
765 if (ret)
766 goto err_out_kobj_put;
767 }
Dave Jones909a6942009-07-08 18:05:42 -0400768
769 spin_lock_irqsave(&cpufreq_driver_lock, flags);
770 for_each_cpu(j, policy->cpus) {
Dave Jones909a6942009-07-08 18:05:42 -0400771 per_cpu(cpufreq_cpu_data, j) = policy;
Tejun Heof1625062009-10-29 22:34:13 +0900772 per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
Dave Jones909a6942009-07-08 18:05:42 -0400773 }
774 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
775
776 ret = cpufreq_add_dev_symlink(cpu, policy);
Dave Jonesecf7e462009-07-08 18:48:47 -0400777 if (ret)
778 goto err_out_kobj_put;
779
780 memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
781 /* assure that the starting sequence is run in __cpufreq_set_policy */
782 policy->governor = NULL;
783
784 /* set default policy */
785 ret = __cpufreq_set_policy(policy, &new_policy);
786 policy->user_policy.policy = policy->policy;
787 policy->user_policy.governor = policy->governor;
788
789 if (ret) {
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200790 pr_debug("setting policy failed\n");
Dave Jonesecf7e462009-07-08 18:48:47 -0400791 if (cpufreq_driver->exit)
792 cpufreq_driver->exit(policy);
793 }
Dave Jones909a6942009-07-08 18:05:42 -0400794 return ret;
795
796err_out_kobj_put:
797 kobject_put(&policy->kobj);
798 wait_for_completion(&policy->kobj_unregister);
799 return ret;
800}
801
Viresh Kumarfcf80582013-01-29 14:39:08 +0000802#ifdef CONFIG_HOTPLUG_CPU
803static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
804 struct device *dev)
805{
806 struct cpufreq_policy *policy;
807 int ret = 0;
808 unsigned long flags;
809
810 policy = cpufreq_cpu_get(sibling);
811 WARN_ON(!policy);
812
Viresh Kumarfcf80582013-01-29 14:39:08 +0000813 __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
814
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530815 lock_policy_rwsem_write(sibling);
816
Viresh Kumarfcf80582013-01-29 14:39:08 +0000817 spin_lock_irqsave(&cpufreq_driver_lock, flags);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530818
Viresh Kumarfcf80582013-01-29 14:39:08 +0000819 cpumask_set_cpu(cpu, policy->cpus);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530820 per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu;
Viresh Kumarfcf80582013-01-29 14:39:08 +0000821 per_cpu(cpufreq_cpu_data, cpu) = policy;
822 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
823
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530824 unlock_policy_rwsem_write(sibling);
825
Viresh Kumarfcf80582013-01-29 14:39:08 +0000826 __cpufreq_governor(policy, CPUFREQ_GOV_START);
827 __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
828
Viresh Kumarfcf80582013-01-29 14:39:08 +0000829 ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
830 if (ret) {
831 cpufreq_cpu_put(policy);
832 return ret;
833 }
834
835 return 0;
836}
837#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839/**
840 * cpufreq_add_dev - add a CPU device
841 *
Dave Jones32ee8c32006-02-28 00:43:23 -0500842 * Adds the cpufreq interface for a CPU device.
Mathieu Desnoyers3f4a7822009-07-03 11:25:16 -0400843 *
844 * The Oracle says: try running cpufreq registration/unregistration concurrently
845 * with with cpu hotplugging and all hell will break loose. Tried to clean this
846 * mess up, but more thorough testing is needed. - Mathieu
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 */
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800848static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849{
Viresh Kumarfcf80582013-01-29 14:39:08 +0000850 unsigned int j, cpu = dev->id;
Viresh Kumar65922462013-02-07 10:56:03 +0530851 int ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 struct cpufreq_policy *policy;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 unsigned long flags;
Prarit Bhargava90e41ba2009-11-12 09:18:46 -0500854#ifdef CONFIG_HOTPLUG_CPU
Viresh Kumarfcf80582013-01-29 14:39:08 +0000855 struct cpufreq_governor *gov;
Prarit Bhargava90e41ba2009-11-12 09:18:46 -0500856 int sibling;
857#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
Ashok Rajc32b6b82005-10-30 14:59:54 -0800859 if (cpu_is_offline(cpu))
860 return 0;
861
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200862 pr_debug("adding CPU %u\n", cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864#ifdef CONFIG_SMP
865 /* check whether a different CPU already registered this
866 * CPU because it is in the same boat. */
867 policy = cpufreq_cpu_get(cpu);
868 if (unlikely(policy)) {
Dave Jones8ff69732006-03-05 03:37:23 -0500869 cpufreq_cpu_put(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return 0;
871 }
Viresh Kumarfcf80582013-01-29 14:39:08 +0000872
873#ifdef CONFIG_HOTPLUG_CPU
874 /* Check if this cpu was hot-unplugged earlier and has siblings */
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530875 spin_lock_irqsave(&cpufreq_driver_lock, flags);
Viresh Kumarfcf80582013-01-29 14:39:08 +0000876 for_each_online_cpu(sibling) {
877 struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530878 if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
879 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Viresh Kumarfcf80582013-01-29 14:39:08 +0000880 return cpufreq_add_policy_cpu(cpu, sibling, dev);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530881 }
Viresh Kumarfcf80582013-01-29 14:39:08 +0000882 }
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530883 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Viresh Kumarfcf80582013-01-29 14:39:08 +0000884#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885#endif
886
887 if (!try_module_get(cpufreq_driver->owner)) {
888 ret = -EINVAL;
889 goto module_out;
890 }
891
Dave Jonese98df502005-10-20 15:17:43 -0700892 policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
Dave Jones059019a2009-07-08 16:30:03 -0400893 if (!policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 goto nomem_out;
Dave Jones059019a2009-07-08 16:30:03 -0400895
896 if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
Mathieu Desnoyers3f4a7822009-07-03 11:25:16 -0400897 goto err_free_policy;
Dave Jones059019a2009-07-08 16:30:03 -0400898
899 if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
Mathieu Desnoyers3f4a7822009-07-03 11:25:16 -0400900 goto err_free_cpumask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 policy->cpu = cpu;
Viresh Kumar65922462013-02-07 10:56:03 +0530903 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
Rusty Russell835481d2009-01-04 05:18:06 -0800904 cpumask_copy(policy->cpus, cpumask_of(cpu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800906 /* Initially set CPU itself as the policy_cpu */
Tejun Heof1625062009-10-29 22:34:13 +0900907 per_cpu(cpufreq_policy_cpu, cpu) = cpu;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 init_completion(&policy->kobj_unregister);
David Howells65f27f32006-11-22 14:55:48 +0000910 INIT_WORK(&policy->update, handle_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
912 /* call driver. From then on the cpufreq must be able
913 * to accept all calls to ->verify and ->setpolicy for this CPU
914 */
915 ret = cpufreq_driver->init(policy);
916 if (ret) {
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200917 pr_debug("initialization failed\n");
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530918 goto err_set_policy_cpu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
Viresh Kumar643ae6e2013-01-12 05:14:38 +0000920
Viresh Kumarfcf80582013-01-29 14:39:08 +0000921 /* related cpus should atleast have policy->cpus */
922 cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
923
Viresh Kumar643ae6e2013-01-12 05:14:38 +0000924 /*
925 * affected cpus must always be the one, which are online. We aren't
926 * managing offline cpus here.
927 */
928 cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
929
Mike Chan187d9f42008-12-04 12:19:17 -0800930 policy->user_policy.min = policy->min;
931 policy->user_policy.max = policy->max;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
Thomas Renningera1531ac2008-07-29 22:32:58 -0700933 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
934 CPUFREQ_START, policy);
935
Viresh Kumarfcf80582013-01-29 14:39:08 +0000936#ifdef CONFIG_HOTPLUG_CPU
937 gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
938 if (gov) {
939 policy->governor = gov;
940 pr_debug("Restoring governor %s for cpu %d\n",
941 policy->governor->name, cpu);
Thomas Renninger4bfa0422009-07-24 15:25:03 +0200942 }
Viresh Kumarfcf80582013-01-29 14:39:08 +0000943#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Kay Sievers8a25a2f2011-12-21 14:29:42 -0800945 ret = cpufreq_add_dev_interface(cpu, policy, dev);
Dave Jones19d6f7e2009-07-08 17:35:39 -0400946 if (ret)
947 goto err_out_unregister;
Dave Jones8ff69732006-03-05 03:37:23 -0500948
Greg Kroah-Hartman038c5b32007-12-17 15:54:39 -0400949 kobject_uevent(&policy->kobj, KOBJ_ADD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 module_put(cpufreq_driver->owner);
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +0200951 pr_debug("initialization complete\n");
Dave Jones87c32272006-03-29 01:48:37 -0500952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return 0;
954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955err_out_unregister:
956 spin_lock_irqsave(&cpufreq_driver_lock, flags);
Rusty Russell835481d2009-01-04 05:18:06 -0800957 for_each_cpu(j, policy->cpus)
Mike Travis7a6aedf2008-03-25 15:06:53 -0700958 per_cpu(cpufreq_cpu_data, j) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
960
Greg Kroah-Hartmanc10997f2007-12-20 08:13:05 -0800961 kobject_put(&policy->kobj);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 wait_for_completion(&policy->kobj_unregister);
963
Viresh Kumar2eaa3e22013-02-07 10:55:00 +0530964err_set_policy_cpu:
965 per_cpu(cpufreq_policy_cpu, cpu) = -1;
Xiaotian Fengcad70a62010-07-20 20:11:02 +0800966 free_cpumask_var(policy->related_cpus);
Mathieu Desnoyers3f4a7822009-07-03 11:25:16 -0400967err_free_cpumask:
968 free_cpumask_var(policy->cpus);
969err_free_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 kfree(policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971nomem_out:
972 module_put(cpufreq_driver->owner);
Ashok Rajc32b6b82005-10-30 14:59:54 -0800973module_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 return ret;
975}
976
Viresh Kumarb8eed8a2013-01-14 13:23:03 +0000977static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
978{
979 int j;
980
981 policy->last_cpu = policy->cpu;
982 policy->cpu = cpu;
983
Viresh Kumar3361b7b2013-02-04 11:38:51 +0000984 for_each_cpu(j, policy->cpus)
Viresh Kumarb8eed8a2013-01-14 13:23:03 +0000985 per_cpu(cpufreq_policy_cpu, j) = cpu;
Viresh Kumarb8eed8a2013-01-14 13:23:03 +0000986
987#ifdef CONFIG_CPU_FREQ_TABLE
988 cpufreq_frequency_table_update_policy_cpu(policy);
989#endif
990 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
991 CPUFREQ_UPDATE_POLICY_CPU, policy);
992}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994/**
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800995 * __cpufreq_remove_dev - remove a CPU device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 *
997 * Removes the cpufreq interface for a CPU device.
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -0800998 * Caller should already have policy_rwsem in write mode for this CPU.
999 * This routine frees the rwsem before returning.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 */
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001001static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002{
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001003 unsigned int cpu = dev->id, ret, cpus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 unsigned long flags;
1005 struct cpufreq_policy *data;
Amerigo Wang499bca92010-03-04 03:23:46 -05001006 struct kobject *kobj;
1007 struct completion *cmp;
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001008 struct device *cpu_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001010 pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012 spin_lock_irqsave(&cpufreq_driver_lock, flags);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301013
Mike Travis7a6aedf2008-03-25 15:06:53 -07001014 data = per_cpu(cpufreq_cpu_data, cpu);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301015 per_cpu(cpufreq_cpu_data, cpu) = NULL;
1016
1017 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 if (!data) {
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001020 pr_debug("%s: No cpu_data found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return -EINVAL;
1022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001024 if (cpufreq_driver->target)
Viresh Kumarf6a74092013-01-12 05:14:39 +00001025 __cpufreq_governor(data, CPUFREQ_GOV_STOP);
Thomas Renninger084f3492007-07-09 11:35:28 -07001026
1027#ifdef CONFIG_HOTPLUG_CPU
Dmitry Monakhove77b89f2009-10-05 00:38:55 +04001028 strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name,
1029 CPUFREQ_NAME_LEN);
Thomas Renninger084f3492007-07-09 11:35:28 -07001030#endif
1031
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301032 WARN_ON(lock_policy_rwsem_write(cpu));
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001033 cpus = cpumask_weight(data->cpus);
1034 cpumask_clear_cpu(cpu, data->cpus);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301035 unlock_policy_rwsem_write(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Viresh Kumar73bf0fc2013-02-05 22:21:14 +01001037 if (cpu != data->cpu) {
1038 sysfs_remove_link(&dev->kobj, "cpufreq");
1039 } else if (cpus > 1) {
Jacob Shin27ecddc2011-04-27 13:32:11 -05001040 /* first sibling now owns the new sysfs dir */
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001041 cpu_dev = get_cpu_device(cpumask_first(data->cpus));
1042 sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1043 ret = kobject_move(&data->kobj, &cpu_dev->kobj);
1044 if (ret) {
1045 pr_err("%s: Failed to move kobj: %d", __func__, ret);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301046
1047 WARN_ON(lock_policy_rwsem_write(cpu));
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001048 cpumask_set_cpu(cpu, data->cpus);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301049
1050 spin_lock_irqsave(&cpufreq_driver_lock, flags);
1051 per_cpu(cpufreq_cpu_data, cpu) = data;
1052 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
1053
1054 unlock_policy_rwsem_write(cpu);
1055
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001056 ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj,
1057 "cpufreq");
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001058 return -EINVAL;
1059 }
Jacob Shin27ecddc2011-04-27 13:32:11 -05001060
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301061 WARN_ON(lock_policy_rwsem_write(cpu));
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001062 update_policy_cpu(data, cpu_dev->id);
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301063 unlock_policy_rwsem_write(cpu);
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001064 pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
1065 __func__, cpu_dev->id, cpu);
Jacob Shin27ecddc2011-04-27 13:32:11 -05001066 }
Jacob Shin27ecddc2011-04-27 13:32:11 -05001067
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001068 pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
1069 cpufreq_cpu_put(data);
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001070
1071 /* If cpu is last user of policy, free policy */
1072 if (cpus == 1) {
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301073 lock_policy_rwsem_read(cpu);
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001074 kobj = &data->kobj;
1075 cmp = &data->kobj_unregister;
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301076 unlock_policy_rwsem_read(cpu);
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001077 kobject_put(kobj);
1078
1079 /* we need to make sure that the underlying kobj is actually
1080 * not referenced anymore by anybody before we proceed with
1081 * unloading.
1082 */
1083 pr_debug("waiting for dropping of refcount\n");
1084 wait_for_completion(cmp);
1085 pr_debug("wait complete\n");
1086
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001087 if (cpufreq_driver->exit)
1088 cpufreq_driver->exit(data);
Viresh Kumarb8eed8a2013-01-14 13:23:03 +00001089
1090 free_cpumask_var(data->related_cpus);
1091 free_cpumask_var(data->cpus);
1092 kfree(data);
1093 } else if (cpufreq_driver->target) {
1094 __cpufreq_governor(data, CPUFREQ_GOV_START);
1095 __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
1096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Viresh Kumar2eaa3e22013-02-07 10:55:00 +05301098 per_cpu(cpufreq_policy_cpu, cpu) = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 return 0;
1100}
1101
1102
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001103static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001104{
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001105 unsigned int cpu = dev->id;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001106 int retval;
Venki Pallipadiec282972007-03-26 12:03:19 -07001107
1108 if (cpu_is_offline(cpu))
1109 return 0;
1110
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001111 retval = __cpufreq_remove_dev(dev, sif);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001112 return retval;
1113}
1114
1115
David Howells65f27f32006-11-22 14:55:48 +00001116static void handle_update(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117{
David Howells65f27f32006-11-22 14:55:48 +00001118 struct cpufreq_policy *policy =
1119 container_of(work, struct cpufreq_policy, update);
1120 unsigned int cpu = policy->cpu;
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001121 pr_debug("handle_update for cpu %u called\n", cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 cpufreq_update_policy(cpu);
1123}
1124
1125/**
1126 * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're in deep trouble.
1127 * @cpu: cpu number
1128 * @old_freq: CPU frequency the kernel thinks the CPU runs at
1129 * @new_freq: CPU frequency the CPU actually runs at
1130 *
Dave Jones29464f22009-01-18 01:37:11 -05001131 * We adjust to current frequency first, and need to clean up later.
1132 * So either call to cpufreq_update_policy() or schedule handle_update()).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 */
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301134static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
1135 unsigned int new_freq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 struct cpufreq_freqs freqs;
1138
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001139 pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
1141
1142 freqs.cpu = cpu;
1143 freqs.old = old_freq;
1144 freqs.new = new_freq;
1145 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
1146 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
1147}
1148
1149
Dave Jones32ee8c32006-02-28 00:43:23 -05001150/**
Dhaval Giani4ab70df2006-12-13 14:49:15 +05301151 * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001152 * @cpu: CPU number
1153 *
1154 * This is the last known freq, without actually getting it from the driver.
1155 * Return value will be same as what is shown in scaling_cur_freq in sysfs.
1156 */
1157unsigned int cpufreq_quick_get(unsigned int cpu)
1158{
Dirk Brandewie9e21ba82013-02-06 09:02:08 -08001159 struct cpufreq_policy *policy;
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301160 unsigned int ret_freq = 0;
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001161
Dirk Brandewie9e21ba82013-02-06 09:02:08 -08001162 if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
1163 return cpufreq_driver->get(cpu);
1164
1165 policy = cpufreq_cpu_get(cpu);
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001166 if (policy) {
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301167 ret_freq = policy->cur;
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001168 cpufreq_cpu_put(policy);
1169 }
1170
Dave Jones4d34a672008-02-07 16:33:49 -05001171 return ret_freq;
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001172}
1173EXPORT_SYMBOL(cpufreq_quick_get);
1174
Jesse Barnes3d737102011-06-28 10:59:12 -07001175/**
1176 * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
1177 * @cpu: CPU number
1178 *
1179 * Just return the max possible frequency for a given CPU.
1180 */
1181unsigned int cpufreq_quick_get_max(unsigned int cpu)
1182{
1183 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
1184 unsigned int ret_freq = 0;
1185
1186 if (policy) {
1187 ret_freq = policy->max;
1188 cpufreq_cpu_put(policy);
1189 }
1190
1191 return ret_freq;
1192}
1193EXPORT_SYMBOL(cpufreq_quick_get_max);
1194
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001195
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001196static unsigned int __cpufreq_get(unsigned int cpu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197{
Mike Travis7a6aedf2008-03-25 15:06:53 -07001198 struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301199 unsigned int ret_freq = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 if (!cpufreq_driver->get)
Dave Jones4d34a672008-02-07 16:33:49 -05001202 return ret_freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301204 ret_freq = cpufreq_driver->get(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301206 if (ret_freq && policy->cur &&
1207 !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
1208 /* verify no discrepancy between actual and
1209 saved value exists */
1210 if (unlikely(ret_freq != policy->cur)) {
1211 cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 schedule_work(&policy->update);
1213 }
1214 }
1215
Dave Jones4d34a672008-02-07 16:33:49 -05001216 return ret_freq;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001217}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001219/**
1220 * cpufreq_get - get the current CPU frequency (in kHz)
1221 * @cpu: CPU number
1222 *
1223 * Get the CPU current (static) CPU frequency
1224 */
1225unsigned int cpufreq_get(unsigned int cpu)
1226{
1227 unsigned int ret_freq = 0;
1228 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
1229
1230 if (!policy)
1231 goto out;
1232
1233 if (unlikely(lock_policy_rwsem_read(cpu)))
1234 goto out_policy;
1235
1236 ret_freq = __cpufreq_get(cpu);
1237
1238 unlock_policy_rwsem_read(cpu);
1239
1240out_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 cpufreq_cpu_put(policy);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001242out:
Dave Jones4d34a672008-02-07 16:33:49 -05001243 return ret_freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245EXPORT_SYMBOL(cpufreq_get);
1246
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001247static struct subsys_interface cpufreq_interface = {
1248 .name = "cpufreq",
1249 .subsys = &cpu_subsys,
1250 .add_dev = cpufreq_add_dev,
1251 .remove_dev = cpufreq_remove_dev,
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001252};
1253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
1255/**
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001256 * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
1257 *
1258 * This function is only executed for the boot processor. The other CPUs
1259 * have been put offline by means of CPU hotplug.
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001260 */
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001261static int cpufreq_bp_suspend(void)
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001262{
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301263 int ret = 0;
Dave Jones4bc5d342009-08-04 14:03:25 -04001264
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001265 int cpu = smp_processor_id();
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001266 struct cpufreq_policy *cpu_policy;
1267
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001268 pr_debug("suspending cpu %u\n", cpu);
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001269
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001270 /* If there's no policy for the boot CPU, we have nothing to do. */
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001271 cpu_policy = cpufreq_cpu_get(cpu);
1272 if (!cpu_policy)
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001273 return 0;
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001274
1275 if (cpufreq_driver->suspend) {
Rafael J. Wysocki7ca64e22011-03-10 21:13:05 +01001276 ret = cpufreq_driver->suspend(cpu_policy);
Dominik Brodowskice6c3992009-08-07 22:58:51 +02001277 if (ret)
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001278 printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
1279 "step on CPU %u\n", cpu_policy->cpu);
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001280 }
1281
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001282 cpufreq_cpu_put(cpu_policy);
Dave Jonesc9060492008-02-07 16:32:18 -05001283 return ret;
Benjamin Herrenschmidt42d4dc32005-04-29 07:40:12 -07001284}
1285
1286/**
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001287 * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 *
1289 * 1.) resume CPUfreq hardware support (cpufreq_driver->resume())
Dominik Brodowskice6c3992009-08-07 22:58:51 +02001290 * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
1291 * restored. It will verify that the current freq is in sync with
1292 * what we believe it to be. This is a bit later than when it
1293 * should be, but nonethteless it's better than calling
1294 * cpufreq_driver->get() here which might re-enable interrupts...
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001295 *
1296 * This function is only executed for the boot CPU. The other CPUs have not
1297 * been turned on yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 */
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001299static void cpufreq_bp_resume(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300{
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301301 int ret = 0;
Dave Jones4bc5d342009-08-04 14:03:25 -04001302
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001303 int cpu = smp_processor_id();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 struct cpufreq_policy *cpu_policy;
1305
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001306 pr_debug("resuming cpu %u\n", cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001308 /* If there's no policy for the boot CPU, we have nothing to do. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 cpu_policy = cpufreq_cpu_get(cpu);
1310 if (!cpu_policy)
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001311 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 if (cpufreq_driver->resume) {
1314 ret = cpufreq_driver->resume(cpu_policy);
1315 if (ret) {
1316 printk(KERN_ERR "cpufreq: resume failed in ->resume "
1317 "step on CPU %u\n", cpu_policy->cpu);
Dave Jonesc9060492008-02-07 16:32:18 -05001318 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 }
1320 }
1321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 schedule_work(&cpu_policy->update);
Dominik Brodowskice6c3992009-08-07 22:58:51 +02001323
Dave Jonesc9060492008-02-07 16:32:18 -05001324fail:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 cpufreq_cpu_put(cpu_policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326}
1327
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001328static struct syscore_ops cpufreq_syscore_ops = {
1329 .suspend = cpufreq_bp_suspend,
1330 .resume = cpufreq_bp_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331};
1332
Borislav Petkov9d950462013-01-20 10:24:28 +00001333/**
1334 * cpufreq_get_current_driver - return current driver's name
1335 *
1336 * Return the name string of the currently loaded cpufreq driver
1337 * or NULL, if none.
1338 */
1339const char *cpufreq_get_current_driver(void)
1340{
1341 if (cpufreq_driver)
1342 return cpufreq_driver->name;
1343
1344 return NULL;
1345}
1346EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
1348/*********************************************************************
1349 * NOTIFIER LISTS INTERFACE *
1350 *********************************************************************/
1351
1352/**
1353 * cpufreq_register_notifier - register a driver with cpufreq
1354 * @nb: notifier function to register
1355 * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
1356 *
Dave Jones32ee8c32006-02-28 00:43:23 -05001357 * Add a driver to one of two lists: either a list of drivers that
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 * are notified about clock rate changes (once before and once after
1359 * the transition), or a list of drivers that are notified about
1360 * changes in cpufreq policy.
1361 *
1362 * This function may sleep, and has the same return conditions as
Alan Sterne041c682006-03-27 01:16:30 -08001363 * blocking_notifier_chain_register.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 */
1365int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
1366{
1367 int ret;
1368
Dirk Brandewied5aaffa2013-01-17 16:22:21 +00001369 if (cpufreq_disabled())
1370 return -EINVAL;
1371
Cesar Eduardo Barros74212ca2008-02-16 08:41:24 -02001372 WARN_ON(!init_cpufreq_transition_notifier_list_called);
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 switch (list) {
1375 case CPUFREQ_TRANSITION_NOTIFIER:
Alan Sternb4dfdbb2006-10-04 02:17:06 -07001376 ret = srcu_notifier_chain_register(
Alan Sterne041c682006-03-27 01:16:30 -08001377 &cpufreq_transition_notifier_list, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 break;
1379 case CPUFREQ_POLICY_NOTIFIER:
Alan Sterne041c682006-03-27 01:16:30 -08001380 ret = blocking_notifier_chain_register(
1381 &cpufreq_policy_notifier_list, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 break;
1383 default:
1384 ret = -EINVAL;
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 return ret;
1388}
1389EXPORT_SYMBOL(cpufreq_register_notifier);
1390
1391
1392/**
1393 * cpufreq_unregister_notifier - unregister a driver with cpufreq
1394 * @nb: notifier block to be unregistered
1395 * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
1396 *
1397 * Remove a driver from the CPU frequency notifier list.
1398 *
1399 * This function may sleep, and has the same return conditions as
Alan Sterne041c682006-03-27 01:16:30 -08001400 * blocking_notifier_chain_unregister.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 */
1402int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
1403{
1404 int ret;
1405
Dirk Brandewied5aaffa2013-01-17 16:22:21 +00001406 if (cpufreq_disabled())
1407 return -EINVAL;
1408
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 switch (list) {
1410 case CPUFREQ_TRANSITION_NOTIFIER:
Alan Sternb4dfdbb2006-10-04 02:17:06 -07001411 ret = srcu_notifier_chain_unregister(
Alan Sterne041c682006-03-27 01:16:30 -08001412 &cpufreq_transition_notifier_list, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 break;
1414 case CPUFREQ_POLICY_NOTIFIER:
Alan Sterne041c682006-03-27 01:16:30 -08001415 ret = blocking_notifier_chain_unregister(
1416 &cpufreq_policy_notifier_list, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 break;
1418 default:
1419 ret = -EINVAL;
1420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
1422 return ret;
1423}
1424EXPORT_SYMBOL(cpufreq_unregister_notifier);
1425
1426
1427/*********************************************************************
1428 * GOVERNORS *
1429 *********************************************************************/
1430
1431
1432int __cpufreq_driver_target(struct cpufreq_policy *policy,
1433 unsigned int target_freq,
1434 unsigned int relation)
1435{
1436 int retval = -EINVAL;
Viresh Kumar72499242012-10-31 01:28:21 +01001437 unsigned int old_target_freq = target_freq;
Ashok Rajc32b6b82005-10-30 14:59:54 -08001438
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -04001439 if (cpufreq_disabled())
1440 return -ENODEV;
1441
Viresh Kumar72499242012-10-31 01:28:21 +01001442 /* Make sure that target_freq is within supported range */
1443 if (target_freq > policy->max)
1444 target_freq = policy->max;
1445 if (target_freq < policy->min)
1446 target_freq = policy->min;
1447
1448 pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
1449 policy->cpu, target_freq, relation, old_target_freq);
Viresh Kumar5a1c0222012-10-31 01:28:15 +01001450
1451 if (target_freq == policy->cur)
1452 return 0;
1453
Viresh Kumar3361b7b2013-02-04 11:38:51 +00001454 if (cpufreq_driver->target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 retval = cpufreq_driver->target(policy, target_freq, relation);
Ashok Raj90d45d12005-11-08 21:34:24 -08001456
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 return retval;
1458}
1459EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461int cpufreq_driver_target(struct cpufreq_policy *policy,
1462 unsigned int target_freq,
1463 unsigned int relation)
1464{
Julia Lawallf1829e42008-07-25 22:44:53 +02001465 int ret = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 policy = cpufreq_cpu_get(policy->cpu);
1468 if (!policy)
Julia Lawallf1829e42008-07-25 22:44:53 +02001469 goto no_policy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001471 if (unlikely(lock_policy_rwsem_write(policy->cpu)))
Julia Lawallf1829e42008-07-25 22:44:53 +02001472 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 ret = __cpufreq_driver_target(policy, target_freq, relation);
1475
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001476 unlock_policy_rwsem_write(policy->cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Julia Lawallf1829e42008-07-25 22:44:53 +02001478fail:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 cpufreq_cpu_put(policy);
Julia Lawallf1829e42008-07-25 22:44:53 +02001480no_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 return ret;
1482}
1483EXPORT_SYMBOL_GPL(cpufreq_driver_target);
1484
venkatesh.pallipadi@intel.combf0b90e2008-08-04 11:59:07 -07001485int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
Venkatesh Pallipadidfde5d62006-10-03 12:38:45 -07001486{
1487 int ret = 0;
1488
Dirk Brandewied5aaffa2013-01-17 16:22:21 +00001489 if (cpufreq_disabled())
1490 return ret;
1491
Viresh Kumar3361b7b2013-02-04 11:38:51 +00001492 if (!cpufreq_driver->getavg)
Viresh Kumar0676f7f2012-10-24 23:39:48 +02001493 return 0;
1494
Venkatesh Pallipadidfde5d62006-10-03 12:38:45 -07001495 policy = cpufreq_cpu_get(policy->cpu);
1496 if (!policy)
1497 return -EINVAL;
1498
Viresh Kumar0676f7f2012-10-24 23:39:48 +02001499 ret = cpufreq_driver->getavg(policy, cpu);
Venkatesh Pallipadidfde5d62006-10-03 12:38:45 -07001500
Venkatesh Pallipadidfde5d62006-10-03 12:38:45 -07001501 cpufreq_cpu_put(policy);
1502 return ret;
1503}
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001504EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
Venkatesh Pallipadidfde5d62006-10-03 12:38:45 -07001505
Arjan van de Ven153d7f32006-07-26 15:40:07 +02001506/*
Arjan van de Ven153d7f32006-07-26 15:40:07 +02001507 * when "event" is CPUFREQ_GOV_LIMITS
1508 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301510static int __cpufreq_governor(struct cpufreq_policy *policy,
1511 unsigned int event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
Dave Jonescc993ca2005-07-28 09:43:56 -07001513 int ret;
Thomas Renninger6afde102007-10-02 13:28:13 -07001514
1515 /* Only must be defined when default governor is known to have latency
1516 restrictions, like e.g. conservative or ondemand.
1517 That this is the case is already ensured in Kconfig
1518 */
1519#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
1520 struct cpufreq_governor *gov = &cpufreq_gov_performance;
1521#else
1522 struct cpufreq_governor *gov = NULL;
1523#endif
Thomas Renninger1c256242007-10-02 13:28:12 -07001524
1525 if (policy->governor->max_transition_latency &&
1526 policy->cpuinfo.transition_latency >
1527 policy->governor->max_transition_latency) {
Thomas Renninger6afde102007-10-02 13:28:13 -07001528 if (!gov)
1529 return -EINVAL;
1530 else {
1531 printk(KERN_WARNING "%s governor failed, too long"
1532 " transition latency of HW, fallback"
1533 " to %s governor\n",
1534 policy->governor->name,
1535 gov->name);
1536 policy->governor = gov;
1537 }
Thomas Renninger1c256242007-10-02 13:28:12 -07001538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
1540 if (!try_module_get(policy->governor->owner))
1541 return -EINVAL;
1542
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001543 pr_debug("__cpufreq_governor for CPU %u, event %u\n",
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301544 policy->cpu, event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 ret = policy->governor->governor(policy, event);
1546
Viresh Kumar8e536952013-02-07 12:51:27 +05301547 if (event == CPUFREQ_GOV_START)
1548 policy->governor->initialized++;
1549 else if (event == CPUFREQ_GOV_STOP)
1550 policy->governor->initialized--;
Viresh Kumarb3940582013-02-01 05:42:58 +00001551
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301552 /* we keep one module reference alive for
1553 each CPU governed by this CPU */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 if ((event != CPUFREQ_GOV_START) || ret)
1555 module_put(policy->governor->owner);
1556 if ((event == CPUFREQ_GOV_STOP) && !ret)
1557 module_put(policy->governor->owner);
1558
1559 return ret;
1560}
1561
1562
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563int cpufreq_register_governor(struct cpufreq_governor *governor)
1564{
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -07001565 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 if (!governor)
1568 return -EINVAL;
1569
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -04001570 if (cpufreq_disabled())
1571 return -ENODEV;
1572
akpm@osdl.org3fc54d32006-01-13 15:54:22 -08001573 mutex_lock(&cpufreq_governor_mutex);
Dave Jones32ee8c32006-02-28 00:43:23 -05001574
Viresh Kumarb3940582013-02-01 05:42:58 +00001575 governor->initialized = 0;
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -07001576 err = -EBUSY;
1577 if (__find_governor(governor->name) == NULL) {
1578 err = 0;
1579 list_add(&governor->governor_list, &cpufreq_governor_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Dave Jones32ee8c32006-02-28 00:43:23 -05001582 mutex_unlock(&cpufreq_governor_mutex);
Jeremy Fitzhardinge3bcb09a2006-07-06 12:30:26 -07001583 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585EXPORT_SYMBOL_GPL(cpufreq_register_governor);
1586
1587
1588void cpufreq_unregister_governor(struct cpufreq_governor *governor)
1589{
Prarit Bhargava90e41ba2009-11-12 09:18:46 -05001590#ifdef CONFIG_HOTPLUG_CPU
1591 int cpu;
1592#endif
1593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 if (!governor)
1595 return;
1596
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -04001597 if (cpufreq_disabled())
1598 return;
1599
Prarit Bhargava90e41ba2009-11-12 09:18:46 -05001600#ifdef CONFIG_HOTPLUG_CPU
1601 for_each_present_cpu(cpu) {
1602 if (cpu_online(cpu))
1603 continue;
1604 if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
1605 strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
1606 }
1607#endif
1608
akpm@osdl.org3fc54d32006-01-13 15:54:22 -08001609 mutex_lock(&cpufreq_governor_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 list_del(&governor->governor_list);
akpm@osdl.org3fc54d32006-01-13 15:54:22 -08001611 mutex_unlock(&cpufreq_governor_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 return;
1613}
1614EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
1615
1616
1617
1618/*********************************************************************
1619 * POLICY INTERFACE *
1620 *********************************************************************/
1621
1622/**
1623 * cpufreq_get_policy - get the current cpufreq_policy
Dave Jones29464f22009-01-18 01:37:11 -05001624 * @policy: struct cpufreq_policy into which the current cpufreq_policy
1625 * is written
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 *
1627 * Reads the current cpufreq policy.
1628 */
1629int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
1630{
1631 struct cpufreq_policy *cpu_policy;
1632 if (!policy)
1633 return -EINVAL;
1634
1635 cpu_policy = cpufreq_cpu_get(cpu);
1636 if (!cpu_policy)
1637 return -EINVAL;
1638
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 cpufreq_cpu_put(cpu_policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 return 0;
1643}
1644EXPORT_SYMBOL(cpufreq_get_policy);
1645
1646
Arjan van de Ven153d7f32006-07-26 15:40:07 +02001647/*
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301648 * data : current policy.
1649 * policy : policy to be set.
Arjan van de Ven153d7f32006-07-26 15:40:07 +02001650 */
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301651static int __cpufreq_set_policy(struct cpufreq_policy *data,
1652 struct cpufreq_policy *policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653{
1654 int ret = 0;
1655
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001656 pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 policy->min, policy->max);
1658
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301659 memcpy(&policy->cpuinfo, &data->cpuinfo,
1660 sizeof(struct cpufreq_cpuinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
Yi Yang53391fa2008-01-30 13:33:34 +01001662 if (policy->min > data->max || policy->max < data->min) {
Mattia Dongili9c9a43e2006-07-05 23:12:20 +02001663 ret = -EINVAL;
1664 goto error_out;
1665 }
1666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 /* verify the cpu speed can be set within this limit */
1668 ret = cpufreq_driver->verify(policy);
1669 if (ret)
1670 goto error_out;
1671
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 /* adjust if necessary - all reasons */
Alan Sterne041c682006-03-27 01:16:30 -08001673 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1674 CPUFREQ_ADJUST, policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
1676 /* adjust if necessary - hardware incompatibility*/
Alan Sterne041c682006-03-27 01:16:30 -08001677 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1678 CPUFREQ_INCOMPATIBLE, policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
1680 /* verify the cpu speed can be set within this limit,
1681 which might be different to the first one */
1682 ret = cpufreq_driver->verify(policy);
Alan Sterne041c682006-03-27 01:16:30 -08001683 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 goto error_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 /* notification of the new policy */
Alan Sterne041c682006-03-27 01:16:30 -08001687 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1688 CPUFREQ_NOTIFY, policy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
Dave Jones7d5e3502006-02-02 17:03:42 -05001690 data->min = policy->min;
1691 data->max = policy->max;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001693 pr_debug("new min and max freqs are %u - %u kHz\n",
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301694 data->min, data->max);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 if (cpufreq_driver->setpolicy) {
1697 data->policy = policy->policy;
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001698 pr_debug("setting range\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 ret = cpufreq_driver->setpolicy(policy);
1700 } else {
1701 if (policy->governor != data->governor) {
1702 /* save old, working values */
1703 struct cpufreq_governor *old_gov = data->governor;
1704
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001705 pr_debug("governor switch\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 /* end old governor */
Andrej Gelenbergffe62752010-05-14 15:15:58 -07001708 if (data->governor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 __cpufreq_governor(data, CPUFREQ_GOV_STOP);
1710
1711 /* start new governor */
1712 data->governor = policy->governor;
1713 if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
1714 /* new governor failed, so re-start old one */
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001715 pr_debug("starting governor %s failed\n",
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301716 data->governor->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 if (old_gov) {
1718 data->governor = old_gov;
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301719 __cpufreq_governor(data,
1720 CPUFREQ_GOV_START);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 }
1722 ret = -EINVAL;
1723 goto error_out;
1724 }
1725 /* might be a policy change, too, so fall through */
1726 }
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001727 pr_debug("governor: change or update limits\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
1729 }
1730
Dave Jones7d5e3502006-02-02 17:03:42 -05001731error_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 return ret;
1733}
1734
1735/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 * cpufreq_update_policy - re-evaluate an existing cpufreq policy
1737 * @cpu: CPU which shall be re-evaluated
1738 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001739 * Useful for policy notifiers which have different necessities
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 * at different times.
1741 */
1742int cpufreq_update_policy(unsigned int cpu)
1743{
1744 struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
1745 struct cpufreq_policy policy;
Julia Lawallf1829e42008-07-25 22:44:53 +02001746 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
Julia Lawallf1829e42008-07-25 22:44:53 +02001748 if (!data) {
1749 ret = -ENODEV;
1750 goto no_policy;
1751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
Julia Lawallf1829e42008-07-25 22:44:53 +02001753 if (unlikely(lock_policy_rwsem_write(cpu))) {
1754 ret = -EINVAL;
1755 goto fail;
1756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001758 pr_debug("updating policy for CPU %u\n", cpu);
Dave Jones7d5e3502006-02-02 17:03:42 -05001759 memcpy(&policy, data, sizeof(struct cpufreq_policy));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 policy.min = data->user_policy.min;
1761 policy.max = data->user_policy.max;
1762 policy.policy = data->user_policy.policy;
1763 policy.governor = data->user_policy.governor;
1764
Thomas Renninger0961dd02006-01-26 18:46:33 +01001765 /* BIOS might change freq behind our back
1766 -> ask driver for current freq and notify governors about a change */
1767 if (cpufreq_driver->get) {
1768 policy.cur = cpufreq_driver->get(cpu);
Thomas Renningera85f7bd2006-02-01 11:36:04 +01001769 if (!data->cur) {
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001770 pr_debug("Driver did not initialize current freq");
Thomas Renningera85f7bd2006-02-01 11:36:04 +01001771 data->cur = policy.cur;
1772 } else {
Dirk Brandewief6b05152013-02-06 09:02:09 -08001773 if (data->cur != policy.cur && cpufreq_driver->target)
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301774 cpufreq_out_of_sync(cpu, data->cur,
1775 policy.cur);
Thomas Renningera85f7bd2006-02-01 11:36:04 +01001776 }
Thomas Renninger0961dd02006-01-26 18:46:33 +01001777 }
1778
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 ret = __cpufreq_set_policy(data, &policy);
1780
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001781 unlock_policy_rwsem_write(cpu);
1782
Julia Lawallf1829e42008-07-25 22:44:53 +02001783fail:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 cpufreq_cpu_put(data);
Julia Lawallf1829e42008-07-25 22:44:53 +02001785no_policy:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 return ret;
1787}
1788EXPORT_SYMBOL(cpufreq_update_policy);
1789
Satyam Sharmadd184a02007-10-02 13:28:14 -07001790static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
Ashok Rajc32b6b82005-10-30 14:59:54 -08001791 unsigned long action, void *hcpu)
1792{
1793 unsigned int cpu = (unsigned long)hcpu;
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001794 struct device *dev;
Ashok Rajc32b6b82005-10-30 14:59:54 -08001795
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001796 dev = get_cpu_device(cpu);
1797 if (dev) {
Ashok Rajc32b6b82005-10-30 14:59:54 -08001798 switch (action) {
1799 case CPU_ONLINE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -07001800 case CPU_ONLINE_FROZEN:
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001801 cpufreq_add_dev(dev, NULL);
Ashok Rajc32b6b82005-10-30 14:59:54 -08001802 break;
1803 case CPU_DOWN_PREPARE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -07001804 case CPU_DOWN_PREPARE_FROZEN:
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001805 __cpufreq_remove_dev(dev, NULL);
Ashok Rajc32b6b82005-10-30 14:59:54 -08001806 break;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001807 case CPU_DOWN_FAILED:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -07001808 case CPU_DOWN_FAILED_FROZEN:
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001809 cpufreq_add_dev(dev, NULL);
Ashok Rajc32b6b82005-10-30 14:59:54 -08001810 break;
1811 }
1812 }
1813 return NOTIFY_OK;
1814}
1815
Neal Buckendahl9c36f742010-06-22 22:02:44 -05001816static struct notifier_block __refdata cpufreq_cpu_notifier = {
Ashok Rajc32b6b82005-10-30 14:59:54 -08001817 .notifier_call = cpufreq_cpu_callback,
1818};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
1820/*********************************************************************
1821 * REGISTER / UNREGISTER CPUFREQ DRIVER *
1822 *********************************************************************/
1823
1824/**
1825 * cpufreq_register_driver - register a CPU Frequency driver
1826 * @driver_data: A struct cpufreq_driver containing the values#
1827 * submitted by the CPU Frequency driver.
1828 *
Dave Jones32ee8c32006-02-28 00:43:23 -05001829 * Registers a CPU Frequency driver to this core code. This code
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 * returns zero on success, -EBUSY when another driver got here first
Dave Jones32ee8c32006-02-28 00:43:23 -05001831 * (and isn't unregistered in the meantime).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 *
1833 */
Linus Torvalds221dee22007-02-26 14:55:48 -08001834int cpufreq_register_driver(struct cpufreq_driver *driver_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835{
1836 unsigned long flags;
1837 int ret;
1838
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -04001839 if (cpufreq_disabled())
1840 return -ENODEV;
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 if (!driver_data || !driver_data->verify || !driver_data->init ||
1843 ((!driver_data->setpolicy) && (!driver_data->target)))
1844 return -EINVAL;
1845
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001846 pr_debug("trying to register driver %s\n", driver_data->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848 if (driver_data->setpolicy)
1849 driver_data->flags |= CPUFREQ_CONST_LOOPS;
1850
1851 spin_lock_irqsave(&cpufreq_driver_lock, flags);
1852 if (cpufreq_driver) {
1853 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
1854 return -EBUSY;
1855 }
1856 cpufreq_driver = driver_data;
1857 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
1858
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001859 ret = subsys_interface_register(&cpufreq_interface);
Jiri Slaby8f5bc2a2011-03-01 17:41:10 +01001860 if (ret)
1861 goto err_null_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Jiri Slaby8f5bc2a2011-03-01 17:41:10 +01001863 if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 int i;
1865 ret = -ENODEV;
1866
1867 /* check for at least one working CPU */
Mike Travis7a6aedf2008-03-25 15:06:53 -07001868 for (i = 0; i < nr_cpu_ids; i++)
1869 if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 ret = 0;
Mike Travis7a6aedf2008-03-25 15:06:53 -07001871 break;
1872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
1874 /* if all ->init() calls failed, unregister */
1875 if (ret) {
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001876 pr_debug("no CPU initialized for driver %s\n",
Gautham R Shenoye08f5f52006-10-26 16:20:58 +05301877 driver_data->name);
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001878 goto err_if_unreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
1880 }
1881
Jiri Slaby8f5bc2a2011-03-01 17:41:10 +01001882 register_hotcpu_notifier(&cpufreq_cpu_notifier);
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001883 pr_debug("driver %s up and running\n", driver_data->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Jiri Slaby8f5bc2a2011-03-01 17:41:10 +01001885 return 0;
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001886err_if_unreg:
1887 subsys_interface_unregister(&cpufreq_interface);
Jiri Slaby8f5bc2a2011-03-01 17:41:10 +01001888err_null_driver:
1889 spin_lock_irqsave(&cpufreq_driver_lock, flags);
1890 cpufreq_driver = NULL;
1891 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
Dave Jones4d34a672008-02-07 16:33:49 -05001892 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893}
1894EXPORT_SYMBOL_GPL(cpufreq_register_driver);
1895
1896
1897/**
1898 * cpufreq_unregister_driver - unregister the current CPUFreq driver
1899 *
Dave Jones32ee8c32006-02-28 00:43:23 -05001900 * Unregister the current CPUFreq driver. Only call this if you have
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 * the right to do so, i.e. if you have succeeded in initialising before!
1902 * Returns zero if successful, and -EINVAL if the cpufreq_driver is
1903 * currently not initialised.
1904 */
Linus Torvalds221dee22007-02-26 14:55:48 -08001905int cpufreq_unregister_driver(struct cpufreq_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906{
1907 unsigned long flags;
1908
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001909 if (!cpufreq_driver || (driver != cpufreq_driver))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
Dominik Brodowski2d06d8c2011-03-27 15:04:46 +02001912 pr_debug("unregistering driver %s\n", driver->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001914 subsys_interface_unregister(&cpufreq_interface);
Chandra Seetharaman65edc682006-06-27 02:54:08 -07001915 unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 spin_lock_irqsave(&cpufreq_driver_lock, flags);
1918 cpufreq_driver = NULL;
1919 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
1920
1921 return 0;
1922}
1923EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001924
1925static int __init cpufreq_core_init(void)
1926{
1927 int cpu;
1928
Konrad Rzeszutek Wilka7b422c2012-03-13 19:18:39 -04001929 if (cpufreq_disabled())
1930 return -ENODEV;
1931
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001932 for_each_possible_cpu(cpu) {
Tejun Heof1625062009-10-29 22:34:13 +09001933 per_cpu(cpufreq_policy_cpu, cpu) = -1;
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001934 init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
1935 }
Thomas Renninger8aa84ad2009-07-24 15:25:05 +02001936
Kay Sievers8a25a2f2011-12-21 14:29:42 -08001937 cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
Thomas Renninger8aa84ad2009-07-24 15:25:05 +02001938 BUG_ON(!cpufreq_global_kobject);
Rafael J. Wysockie00e56d2011-03-23 22:16:32 +01001939 register_syscore_ops(&cpufreq_syscore_ops);
Thomas Renninger8aa84ad2009-07-24 15:25:05 +02001940
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001941 return 0;
1942}
Venkatesh Pallipadi5a01f2e2007-02-05 16:12:44 -08001943core_initcall(cpufreq_core_init);