xref: /openbmc/linux/drivers/cpufreq/cpufreq.c (revision 820c6ca293e99ae225dc9dd7e0e689c444b08f92)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/drivers/cpufreq/cpufreq.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 2001 Russell King
51da177e4SLinus Torvalds  *            (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
61da177e4SLinus Torvalds  *
7c32b6b8eSAshok Raj  *  Oct 2005 - Ashok Raj <ashok.raj@intel.com>
8c32b6b8eSAshok Raj  *	Added handling for CPU hotplug
98ff69732SDave Jones  *  Feb 2006 - Jacob Shin <jacob.shin@amd.com>
108ff69732SDave Jones  *	Fix handling for CPU hotplug -- affected CPUs
11c32b6b8eSAshok Raj  *
121da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
131da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
141da177e4SLinus Torvalds  * published by the Free Software Foundation.
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds 
18db701151SViresh Kumar #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19db701151SViresh Kumar 
201da177e4SLinus Torvalds #include <linux/kernel.h>
211da177e4SLinus Torvalds #include <linux/module.h>
221da177e4SLinus Torvalds #include <linux/init.h>
231da177e4SLinus Torvalds #include <linux/notifier.h>
241da177e4SLinus Torvalds #include <linux/cpufreq.h>
251da177e4SLinus Torvalds #include <linux/delay.h>
261da177e4SLinus Torvalds #include <linux/interrupt.h>
271da177e4SLinus Torvalds #include <linux/spinlock.h>
281da177e4SLinus Torvalds #include <linux/device.h>
291da177e4SLinus Torvalds #include <linux/slab.h>
301da177e4SLinus Torvalds #include <linux/cpu.h>
311da177e4SLinus Torvalds #include <linux/completion.h>
323fc54d37Sakpm@osdl.org #include <linux/mutex.h>
33e00e56dfSRafael J. Wysocki #include <linux/syscore_ops.h>
341da177e4SLinus Torvalds 
356f4f2723SThomas Renninger #include <trace/events/power.h>
366f4f2723SThomas Renninger 
371da177e4SLinus Torvalds /**
38cd878479SDave Jones  * The "cpufreq driver" - the arch- or hardware-dependent low
391da177e4SLinus Torvalds  * level driver of CPUFreq support, and its spinlock. This lock
401da177e4SLinus Torvalds  * also protects the cpufreq_cpu_data array.
411da177e4SLinus Torvalds  */
425800043bSNathan Zimmer static struct cpufreq_driver __rcu *cpufreq_driver;
437a6aedfaSMike Travis static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
44084f3493SThomas Renninger #ifdef CONFIG_HOTPLUG_CPU
45084f3493SThomas Renninger /* This one keeps track of the previously set governor of a removed CPU */
46e77b89f1SDmitry Monakhov static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
47084f3493SThomas Renninger #endif
480d1857a1SNathan Zimmer static DEFINE_RWLOCK(cpufreq_driver_lock);
491da177e4SLinus Torvalds 
505a01f2e8SVenkatesh Pallipadi /*
515a01f2e8SVenkatesh Pallipadi  * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
525a01f2e8SVenkatesh Pallipadi  * all cpufreq/hotplug/workqueue/etc related lock issues.
535a01f2e8SVenkatesh Pallipadi  *
545a01f2e8SVenkatesh Pallipadi  * The rules for this semaphore:
555a01f2e8SVenkatesh Pallipadi  * - Any routine that wants to read from the policy structure will
565a01f2e8SVenkatesh Pallipadi  *   do a down_read on this semaphore.
575a01f2e8SVenkatesh Pallipadi  * - Any routine that will write to the policy structure and/or may take away
585a01f2e8SVenkatesh Pallipadi  *   the policy altogether (eg. CPU hotplug), will hold this lock in write
595a01f2e8SVenkatesh Pallipadi  *   mode before doing so.
605a01f2e8SVenkatesh Pallipadi  *
615a01f2e8SVenkatesh Pallipadi  * Additional rules:
625a01f2e8SVenkatesh Pallipadi  * - Governor routines that can be called in cpufreq hotplug path should not
635a01f2e8SVenkatesh Pallipadi  *   take this sem as top level hotplug notifier handler takes this.
64395913d0SMathieu Desnoyers  * - Lock should not be held across
65395913d0SMathieu Desnoyers  *     __cpufreq_governor(data, CPUFREQ_GOV_STOP);
665a01f2e8SVenkatesh Pallipadi  */
67f1625066STejun Heo static DEFINE_PER_CPU(int, cpufreq_policy_cpu);
685a01f2e8SVenkatesh Pallipadi static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
695a01f2e8SVenkatesh Pallipadi 
705a01f2e8SVenkatesh Pallipadi #define lock_policy_rwsem(mode, cpu)					\
71fa1d8af4SViresh Kumar static int lock_policy_rwsem_##mode(int cpu)				\
725a01f2e8SVenkatesh Pallipadi {									\
73f1625066STejun Heo 	int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);		\
745a01f2e8SVenkatesh Pallipadi 	BUG_ON(policy_cpu == -1);					\
755a01f2e8SVenkatesh Pallipadi 	down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
765a01f2e8SVenkatesh Pallipadi 									\
775a01f2e8SVenkatesh Pallipadi 	return 0;							\
785a01f2e8SVenkatesh Pallipadi }
795a01f2e8SVenkatesh Pallipadi 
805a01f2e8SVenkatesh Pallipadi lock_policy_rwsem(read, cpu);
815a01f2e8SVenkatesh Pallipadi lock_policy_rwsem(write, cpu);
825a01f2e8SVenkatesh Pallipadi 
83fa1d8af4SViresh Kumar #define unlock_policy_rwsem(mode, cpu)					\
84fa1d8af4SViresh Kumar static void unlock_policy_rwsem_##mode(int cpu)				\
85fa1d8af4SViresh Kumar {									\
86fa1d8af4SViresh Kumar 	int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);		\
87fa1d8af4SViresh Kumar 	BUG_ON(policy_cpu == -1);					\
88fa1d8af4SViresh Kumar 	up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
895a01f2e8SVenkatesh Pallipadi }
905a01f2e8SVenkatesh Pallipadi 
91fa1d8af4SViresh Kumar unlock_policy_rwsem(read, cpu);
92fa1d8af4SViresh Kumar unlock_policy_rwsem(write, cpu);
935a01f2e8SVenkatesh Pallipadi 
941da177e4SLinus Torvalds /* internal prototypes */
9529464f28SDave Jones static int __cpufreq_governor(struct cpufreq_policy *policy,
9629464f28SDave Jones 		unsigned int event);
975a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu);
9865f27f38SDavid Howells static void handle_update(struct work_struct *work);
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds /**
1011da177e4SLinus Torvalds  * Two notifier lists: the "policy" list is involved in the
1021da177e4SLinus Torvalds  * validation process for a new CPU frequency policy; the
1031da177e4SLinus Torvalds  * "transition" list for kernel code that needs to handle
1041da177e4SLinus Torvalds  * changes to devices when the CPU clock speed changes.
1051da177e4SLinus Torvalds  * The mutex locks both lists.
1061da177e4SLinus Torvalds  */
107e041c683SAlan Stern static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
108b4dfdbb3SAlan Stern static struct srcu_notifier_head cpufreq_transition_notifier_list;
1091da177e4SLinus Torvalds 
11074212ca4SCesar Eduardo Barros static bool init_cpufreq_transition_notifier_list_called;
111b4dfdbb3SAlan Stern static int __init init_cpufreq_transition_notifier_list(void)
112b4dfdbb3SAlan Stern {
113b4dfdbb3SAlan Stern 	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
11474212ca4SCesar Eduardo Barros 	init_cpufreq_transition_notifier_list_called = true;
115b4dfdbb3SAlan Stern 	return 0;
116b4dfdbb3SAlan Stern }
117b3438f82SLinus Torvalds pure_initcall(init_cpufreq_transition_notifier_list);
1181da177e4SLinus Torvalds 
119a7b422cdSKonrad Rzeszutek Wilk static int off __read_mostly;
120da584455SViresh Kumar static int cpufreq_disabled(void)
121a7b422cdSKonrad Rzeszutek Wilk {
122a7b422cdSKonrad Rzeszutek Wilk 	return off;
123a7b422cdSKonrad Rzeszutek Wilk }
124a7b422cdSKonrad Rzeszutek Wilk void disable_cpufreq(void)
125a7b422cdSKonrad Rzeszutek Wilk {
126a7b422cdSKonrad Rzeszutek Wilk 	off = 1;
127a7b422cdSKonrad Rzeszutek Wilk }
1281da177e4SLinus Torvalds static LIST_HEAD(cpufreq_governor_list);
1293fc54d37Sakpm@osdl.org static DEFINE_MUTEX(cpufreq_governor_mutex);
1301da177e4SLinus Torvalds 
1314d5dcc42SViresh Kumar bool have_governor_per_policy(void)
1324d5dcc42SViresh Kumar {
1335800043bSNathan Zimmer 	bool have_governor_per_policy;
1345800043bSNathan Zimmer 	rcu_read_lock();
1355800043bSNathan Zimmer 	have_governor_per_policy =
1365800043bSNathan Zimmer 		rcu_dereference(cpufreq_driver)->have_governor_per_policy;
1375800043bSNathan Zimmer 	rcu_read_unlock();
1385800043bSNathan Zimmer 	return have_governor_per_policy;
1394d5dcc42SViresh Kumar }
1404d5dcc42SViresh Kumar 
141a9144436SStephen Boyd static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds 	struct cpufreq_policy *data;
1445800043bSNathan Zimmer 	struct cpufreq_driver *driver;
1451da177e4SLinus Torvalds 	unsigned long flags;
1461da177e4SLinus Torvalds 
1477a6aedfaSMike Travis 	if (cpu >= nr_cpu_ids)
1481da177e4SLinus Torvalds 		goto err_out;
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 	/* get the cpufreq driver */
1515800043bSNathan Zimmer 	rcu_read_lock();
1525800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
1535800043bSNathan Zimmer 
1545800043bSNathan Zimmer 	if (!driver)
1555800043bSNathan Zimmer 		goto err_out_unlock;
1565800043bSNathan Zimmer 
1575800043bSNathan Zimmer 	if (!try_module_get(driver->owner))
1585800043bSNathan Zimmer 		goto err_out_unlock;
1595800043bSNathan Zimmer 
1600d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds 	/* get the CPU */
1637a6aedfaSMike Travis 	data = per_cpu(cpufreq_cpu_data, cpu);
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds 	if (!data)
1661da177e4SLinus Torvalds 		goto err_out_put_module;
1671da177e4SLinus Torvalds 
168a9144436SStephen Boyd 	if (!sysfs && !kobject_get(&data->kobj))
1691da177e4SLinus Torvalds 		goto err_out_put_module;
1701da177e4SLinus Torvalds 
1710d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1725800043bSNathan Zimmer 	rcu_read_unlock();
1731da177e4SLinus Torvalds 	return data;
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds err_out_put_module:
1765800043bSNathan Zimmer 	module_put(driver->owner);
1770d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1785800043bSNathan Zimmer err_out_unlock:
1795800043bSNathan Zimmer 	rcu_read_unlock();
1801da177e4SLinus Torvalds err_out:
1811da177e4SLinus Torvalds 	return NULL;
1821da177e4SLinus Torvalds }
183a9144436SStephen Boyd 
184a9144436SStephen Boyd struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
185a9144436SStephen Boyd {
186d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
187d5aaffa9SDirk Brandewie 		return NULL;
188d5aaffa9SDirk Brandewie 
189a9144436SStephen Boyd 	return __cpufreq_cpu_get(cpu, false);
190a9144436SStephen Boyd }
1911da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
1921da177e4SLinus Torvalds 
193a9144436SStephen Boyd static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
1941da177e4SLinus Torvalds {
195a9144436SStephen Boyd 	return __cpufreq_cpu_get(cpu, true);
196a9144436SStephen Boyd }
197a9144436SStephen Boyd 
198a9144436SStephen Boyd static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
199a9144436SStephen Boyd {
200a9144436SStephen Boyd 	if (!sysfs)
2011da177e4SLinus Torvalds 		kobject_put(&data->kobj);
2025800043bSNathan Zimmer 	rcu_read_lock();
2035800043bSNathan Zimmer 	module_put(rcu_dereference(cpufreq_driver)->owner);
2045800043bSNathan Zimmer 	rcu_read_unlock();
2051da177e4SLinus Torvalds }
206a9144436SStephen Boyd 
207a9144436SStephen Boyd void cpufreq_cpu_put(struct cpufreq_policy *data)
208a9144436SStephen Boyd {
209d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
210d5aaffa9SDirk Brandewie 		return;
211d5aaffa9SDirk Brandewie 
212a9144436SStephen Boyd 	__cpufreq_cpu_put(data, false);
213a9144436SStephen Boyd }
2141da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
2151da177e4SLinus Torvalds 
216a9144436SStephen Boyd static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
217a9144436SStephen Boyd {
218a9144436SStephen Boyd 	__cpufreq_cpu_put(data, true);
219a9144436SStephen Boyd }
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds /*********************************************************************
2221da177e4SLinus Torvalds  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
2231da177e4SLinus Torvalds  *********************************************************************/
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds /**
2261da177e4SLinus Torvalds  * adjust_jiffies - adjust the system "loops_per_jiffy"
2271da177e4SLinus Torvalds  *
2281da177e4SLinus Torvalds  * This function alters the system "loops_per_jiffy" for the clock
2291da177e4SLinus Torvalds  * speed change. Note that loops_per_jiffy cannot be updated on SMP
2301da177e4SLinus Torvalds  * systems as each CPU might be scaled differently. So, use the arch
2311da177e4SLinus Torvalds  * per-CPU loops_per_jiffy value wherever possible.
2321da177e4SLinus Torvalds  */
2331da177e4SLinus Torvalds #ifndef CONFIG_SMP
2341da177e4SLinus Torvalds static unsigned long l_p_j_ref;
2351da177e4SLinus Torvalds static unsigned int  l_p_j_ref_freq;
2361da177e4SLinus Torvalds 
237858119e1SArjan van de Ven static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
2381da177e4SLinus Torvalds {
2391da177e4SLinus Torvalds 	if (ci->flags & CPUFREQ_CONST_LOOPS)
2401da177e4SLinus Torvalds 		return;
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds 	if (!l_p_j_ref_freq) {
2431da177e4SLinus Torvalds 		l_p_j_ref = loops_per_jiffy;
2441da177e4SLinus Torvalds 		l_p_j_ref_freq = ci->old;
2452d06d8c4SDominik Brodowski 		pr_debug("saving %lu as reference value for loops_per_jiffy; "
246e08f5f5bSGautham R Shenoy 			"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
2471da177e4SLinus Torvalds 	}
248d08de0c1SAfzal Mohammed 	if ((val == CPUFREQ_POSTCHANGE  && ci->old != ci->new) ||
24942d4dc3fSBenjamin Herrenschmidt 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
250e08f5f5bSGautham R Shenoy 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
251e08f5f5bSGautham R Shenoy 								ci->new);
2522d06d8c4SDominik Brodowski 		pr_debug("scaling loops_per_jiffy to %lu "
253e08f5f5bSGautham R Shenoy 			"for frequency %u kHz\n", loops_per_jiffy, ci->new);
2541da177e4SLinus Torvalds 	}
2551da177e4SLinus Torvalds }
2561da177e4SLinus Torvalds #else
257e08f5f5bSGautham R Shenoy static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
258e08f5f5bSGautham R Shenoy {
259e08f5f5bSGautham R Shenoy 	return;
260e08f5f5bSGautham R Shenoy }
2611da177e4SLinus Torvalds #endif
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 
264b43a7ffbSViresh Kumar void __cpufreq_notify_transition(struct cpufreq_policy *policy,
265b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
2661da177e4SLinus Torvalds {
2671da177e4SLinus Torvalds 	BUG_ON(irqs_disabled());
2681da177e4SLinus Torvalds 
269d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
270d5aaffa9SDirk Brandewie 		return;
271d5aaffa9SDirk Brandewie 
2725800043bSNathan Zimmer 	rcu_read_lock();
2735800043bSNathan Zimmer 	freqs->flags = rcu_dereference(cpufreq_driver)->flags;
2745800043bSNathan Zimmer 	rcu_read_unlock();
2752d06d8c4SDominik Brodowski 	pr_debug("notification %u of frequency transition to %u kHz\n",
276e4472cb3SDave Jones 		state, freqs->new);
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 	switch (state) {
279e4472cb3SDave Jones 
2801da177e4SLinus Torvalds 	case CPUFREQ_PRECHANGE:
281e4472cb3SDave Jones 		/* detect if the driver reported a value as "old frequency"
282e4472cb3SDave Jones 		 * which is not equal to what the cpufreq core thinks is
283e4472cb3SDave Jones 		 * "old frequency".
2841da177e4SLinus Torvalds 		 */
2855800043bSNathan Zimmer 		if (!(freqs->flags & CPUFREQ_CONST_LOOPS)) {
286e4472cb3SDave Jones 			if ((policy) && (policy->cpu == freqs->cpu) &&
287e4472cb3SDave Jones 			    (policy->cur) && (policy->cur != freqs->old)) {
2882d06d8c4SDominik Brodowski 				pr_debug("Warning: CPU frequency is"
289e4472cb3SDave Jones 					" %u, cpufreq assumed %u kHz.\n",
290e4472cb3SDave Jones 					freqs->old, policy->cur);
291e4472cb3SDave Jones 				freqs->old = policy->cur;
2921da177e4SLinus Torvalds 			}
2931da177e4SLinus Torvalds 		}
294b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
295e4472cb3SDave Jones 				CPUFREQ_PRECHANGE, freqs);
2961da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
2971da177e4SLinus Torvalds 		break;
298e4472cb3SDave Jones 
2991da177e4SLinus Torvalds 	case CPUFREQ_POSTCHANGE:
3001da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
3012d06d8c4SDominik Brodowski 		pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
3026f4f2723SThomas Renninger 			(unsigned long)freqs->cpu);
30325e41933SThomas Renninger 		trace_cpu_frequency(freqs->new, freqs->cpu);
304b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
305e4472cb3SDave Jones 				CPUFREQ_POSTCHANGE, freqs);
306e4472cb3SDave Jones 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
307e4472cb3SDave Jones 			policy->cur = freqs->new;
3081da177e4SLinus Torvalds 		break;
3091da177e4SLinus Torvalds 	}
3101da177e4SLinus Torvalds }
311b43a7ffbSViresh Kumar /**
312b43a7ffbSViresh Kumar  * cpufreq_notify_transition - call notifier chain and adjust_jiffies
313b43a7ffbSViresh Kumar  * on frequency transition.
314b43a7ffbSViresh Kumar  *
315b43a7ffbSViresh Kumar  * This function calls the transition notifiers and the "adjust_jiffies"
316b43a7ffbSViresh Kumar  * function. It is called twice on all CPU frequency changes that have
317b43a7ffbSViresh Kumar  * external effects.
318b43a7ffbSViresh Kumar  */
319b43a7ffbSViresh Kumar void cpufreq_notify_transition(struct cpufreq_policy *policy,
320b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
321b43a7ffbSViresh Kumar {
322b43a7ffbSViresh Kumar 	for_each_cpu(freqs->cpu, policy->cpus)
323b43a7ffbSViresh Kumar 		__cpufreq_notify_transition(policy, freqs, state);
324b43a7ffbSViresh Kumar }
3251da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
3261da177e4SLinus Torvalds 
3271da177e4SLinus Torvalds 
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds /*********************************************************************
3301da177e4SLinus Torvalds  *                          SYSFS INTERFACE                          *
3311da177e4SLinus Torvalds  *********************************************************************/
3321da177e4SLinus Torvalds 
3333bcb09a3SJeremy Fitzhardinge static struct cpufreq_governor *__find_governor(const char *str_governor)
3343bcb09a3SJeremy Fitzhardinge {
3353bcb09a3SJeremy Fitzhardinge 	struct cpufreq_governor *t;
3363bcb09a3SJeremy Fitzhardinge 
3373bcb09a3SJeremy Fitzhardinge 	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
3383bcb09a3SJeremy Fitzhardinge 		if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN))
3393bcb09a3SJeremy Fitzhardinge 			return t;
3403bcb09a3SJeremy Fitzhardinge 
3413bcb09a3SJeremy Fitzhardinge 	return NULL;
3423bcb09a3SJeremy Fitzhardinge }
3433bcb09a3SJeremy Fitzhardinge 
3441da177e4SLinus Torvalds /**
3451da177e4SLinus Torvalds  * cpufreq_parse_governor - parse a governor string
3461da177e4SLinus Torvalds  */
3471da177e4SLinus Torvalds static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
3481da177e4SLinus Torvalds 				struct cpufreq_governor **governor)
3491da177e4SLinus Torvalds {
3503bcb09a3SJeremy Fitzhardinge 	int err = -EINVAL;
3515800043bSNathan Zimmer 	struct cpufreq_driver *driver;
3525800043bSNathan Zimmer 	bool has_setpolicy;
3535800043bSNathan Zimmer 	bool has_target;
3543bcb09a3SJeremy Fitzhardinge 
3555800043bSNathan Zimmer 	rcu_read_lock();
3565800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
3575800043bSNathan Zimmer 	if (!driver) {
3585800043bSNathan Zimmer 		rcu_read_unlock();
3593bcb09a3SJeremy Fitzhardinge 		goto out;
3605800043bSNathan Zimmer 	}
3615800043bSNathan Zimmer 	has_setpolicy = driver->setpolicy ? true : false;
3625800043bSNathan Zimmer 	has_target = driver->target ? true : false;
3635800043bSNathan Zimmer 	rcu_read_unlock();
3643bcb09a3SJeremy Fitzhardinge 
3655800043bSNathan Zimmer 	if (has_setpolicy) {
3661da177e4SLinus Torvalds 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
3671da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_PERFORMANCE;
3683bcb09a3SJeremy Fitzhardinge 			err = 0;
369e08f5f5bSGautham R Shenoy 		} else if (!strnicmp(str_governor, "powersave",
370e08f5f5bSGautham R Shenoy 						CPUFREQ_NAME_LEN)) {
3711da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_POWERSAVE;
3723bcb09a3SJeremy Fitzhardinge 			err = 0;
3731da177e4SLinus Torvalds 		}
3745800043bSNathan Zimmer 	} else if (has_target) {
3751da177e4SLinus Torvalds 		struct cpufreq_governor *t;
3763bcb09a3SJeremy Fitzhardinge 
3773fc54d37Sakpm@osdl.org 		mutex_lock(&cpufreq_governor_mutex);
3783bcb09a3SJeremy Fitzhardinge 
3793bcb09a3SJeremy Fitzhardinge 		t = __find_governor(str_governor);
3803bcb09a3SJeremy Fitzhardinge 
381ea714970SJeremy Fitzhardinge 		if (t == NULL) {
382ea714970SJeremy Fitzhardinge 			int ret;
383ea714970SJeremy Fitzhardinge 
384ea714970SJeremy Fitzhardinge 			mutex_unlock(&cpufreq_governor_mutex);
3851a8e1463SKees Cook 			ret = request_module("cpufreq_%s", str_governor);
386ea714970SJeremy Fitzhardinge 			mutex_lock(&cpufreq_governor_mutex);
387ea714970SJeremy Fitzhardinge 
388ea714970SJeremy Fitzhardinge 			if (ret == 0)
389ea714970SJeremy Fitzhardinge 				t = __find_governor(str_governor);
390ea714970SJeremy Fitzhardinge 		}
391ea714970SJeremy Fitzhardinge 
3923bcb09a3SJeremy Fitzhardinge 		if (t != NULL) {
3931da177e4SLinus Torvalds 			*governor = t;
3943bcb09a3SJeremy Fitzhardinge 			err = 0;
3951da177e4SLinus Torvalds 		}
3963bcb09a3SJeremy Fitzhardinge 
3973bcb09a3SJeremy Fitzhardinge 		mutex_unlock(&cpufreq_governor_mutex);
3981da177e4SLinus Torvalds 	}
3991da177e4SLinus Torvalds out:
4003bcb09a3SJeremy Fitzhardinge 	return err;
4011da177e4SLinus Torvalds }
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds /**
405e08f5f5bSGautham R Shenoy  * cpufreq_per_cpu_attr_read() / show_##file_name() -
406e08f5f5bSGautham R Shenoy  * print out cpufreq information
4071da177e4SLinus Torvalds  *
4081da177e4SLinus Torvalds  * Write out information from cpufreq_driver->policy[cpu]; object must be
4091da177e4SLinus Torvalds  * "unsigned int".
4101da177e4SLinus Torvalds  */
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds #define show_one(file_name, object)			\
4131da177e4SLinus Torvalds static ssize_t show_##file_name				\
4141da177e4SLinus Torvalds (struct cpufreq_policy *policy, char *buf)		\
4151da177e4SLinus Torvalds {							\
4161da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", policy->object);	\
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds show_one(cpuinfo_min_freq, cpuinfo.min_freq);
4201da177e4SLinus Torvalds show_one(cpuinfo_max_freq, cpuinfo.max_freq);
421ed129784SThomas Renninger show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
4221da177e4SLinus Torvalds show_one(scaling_min_freq, min);
4231da177e4SLinus Torvalds show_one(scaling_max_freq, max);
4241da177e4SLinus Torvalds show_one(scaling_cur_freq, cur);
4251da177e4SLinus Torvalds 
426e08f5f5bSGautham R Shenoy static int __cpufreq_set_policy(struct cpufreq_policy *data,
427e08f5f5bSGautham R Shenoy 				struct cpufreq_policy *policy);
4287970e08bSThomas Renninger 
4291da177e4SLinus Torvalds /**
4301da177e4SLinus Torvalds  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
4311da177e4SLinus Torvalds  */
4321da177e4SLinus Torvalds #define store_one(file_name, object)			\
4331da177e4SLinus Torvalds static ssize_t store_##file_name					\
4341da177e4SLinus Torvalds (struct cpufreq_policy *policy, const char *buf, size_t count)		\
4351da177e4SLinus Torvalds {									\
436f55c9c26SJingoo Han 	unsigned int ret;						\
4371da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;				\
4381da177e4SLinus Torvalds 									\
4391da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
4401da177e4SLinus Torvalds 	if (ret)							\
4411da177e4SLinus Torvalds 		return -EINVAL;						\
4421da177e4SLinus Torvalds 									\
4431da177e4SLinus Torvalds 	ret = sscanf(buf, "%u", &new_policy.object);			\
4441da177e4SLinus Torvalds 	if (ret != 1)							\
4451da177e4SLinus Torvalds 		return -EINVAL;						\
4461da177e4SLinus Torvalds 									\
4477970e08bSThomas Renninger 	ret = __cpufreq_set_policy(policy, &new_policy);		\
4487970e08bSThomas Renninger 	policy->user_policy.object = policy->object;			\
4491da177e4SLinus Torvalds 									\
4501da177e4SLinus Torvalds 	return ret ? ret : count;					\
4511da177e4SLinus Torvalds }
4521da177e4SLinus Torvalds 
4531da177e4SLinus Torvalds store_one(scaling_min_freq, min);
4541da177e4SLinus Torvalds store_one(scaling_max_freq, max);
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds /**
4571da177e4SLinus Torvalds  * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
4581da177e4SLinus Torvalds  */
459e08f5f5bSGautham R Shenoy static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
460e08f5f5bSGautham R Shenoy 					char *buf)
4611da177e4SLinus Torvalds {
4625a01f2e8SVenkatesh Pallipadi 	unsigned int cur_freq = __cpufreq_get(policy->cpu);
4631da177e4SLinus Torvalds 	if (!cur_freq)
4641da177e4SLinus Torvalds 		return sprintf(buf, "<unknown>");
4651da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", cur_freq);
4661da177e4SLinus Torvalds }
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds /**
4701da177e4SLinus Torvalds  * show_scaling_governor - show the current policy for the specified CPU
4711da177e4SLinus Torvalds  */
472905d77cdSDave Jones static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
4731da177e4SLinus Torvalds {
4741da177e4SLinus Torvalds 	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
4751da177e4SLinus Torvalds 		return sprintf(buf, "powersave\n");
4761da177e4SLinus Torvalds 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
4771da177e4SLinus Torvalds 		return sprintf(buf, "performance\n");
4781da177e4SLinus Torvalds 	else if (policy->governor)
4794b972f0bSviresh kumar 		return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
48029464f28SDave Jones 				policy->governor->name);
4811da177e4SLinus Torvalds 	return -EINVAL;
4821da177e4SLinus Torvalds }
4831da177e4SLinus Torvalds 
4841da177e4SLinus Torvalds 
4851da177e4SLinus Torvalds /**
4861da177e4SLinus Torvalds  * store_scaling_governor - store policy for the specified CPU
4871da177e4SLinus Torvalds  */
4881da177e4SLinus Torvalds static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
4891da177e4SLinus Torvalds 					const char *buf, size_t count)
4901da177e4SLinus Torvalds {
491f55c9c26SJingoo Han 	unsigned int ret;
4921da177e4SLinus Torvalds 	char	str_governor[16];
4931da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);
4961da177e4SLinus Torvalds 	if (ret)
4971da177e4SLinus Torvalds 		return ret;
4981da177e4SLinus Torvalds 
4991da177e4SLinus Torvalds 	ret = sscanf(buf, "%15s", str_governor);
5001da177e4SLinus Torvalds 	if (ret != 1)
5011da177e4SLinus Torvalds 		return -EINVAL;
5021da177e4SLinus Torvalds 
503e08f5f5bSGautham R Shenoy 	if (cpufreq_parse_governor(str_governor, &new_policy.policy,
504e08f5f5bSGautham R Shenoy 						&new_policy.governor))
5051da177e4SLinus Torvalds 		return -EINVAL;
5061da177e4SLinus Torvalds 
5077970e08bSThomas Renninger 	/* Do not use cpufreq_set_policy here or the user_policy.max
5087970e08bSThomas Renninger 	   will be wrongly overridden */
5097970e08bSThomas Renninger 	ret = __cpufreq_set_policy(policy, &new_policy);
5107970e08bSThomas Renninger 
5117970e08bSThomas Renninger 	policy->user_policy.policy = policy->policy;
5127970e08bSThomas Renninger 	policy->user_policy.governor = policy->governor;
5137970e08bSThomas Renninger 
514e08f5f5bSGautham R Shenoy 	if (ret)
515e08f5f5bSGautham R Shenoy 		return ret;
516e08f5f5bSGautham R Shenoy 	else
517e08f5f5bSGautham R Shenoy 		return count;
5181da177e4SLinus Torvalds }
5191da177e4SLinus Torvalds 
5201da177e4SLinus Torvalds /**
5211da177e4SLinus Torvalds  * show_scaling_driver - show the cpufreq driver currently loaded
5221da177e4SLinus Torvalds  */
5231da177e4SLinus Torvalds static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
5241da177e4SLinus Torvalds {
5255800043bSNathan Zimmer 	ssize_t size;
5265800043bSNathan Zimmer 	rcu_read_lock();
5275800043bSNathan Zimmer 	size = scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
5285800043bSNathan Zimmer 		rcu_dereference(cpufreq_driver)->name);
5295800043bSNathan Zimmer 	rcu_read_unlock();
5305800043bSNathan Zimmer 	return size;
5311da177e4SLinus Torvalds }
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds /**
5341da177e4SLinus Torvalds  * show_scaling_available_governors - show the available CPUfreq governors
5351da177e4SLinus Torvalds  */
5361da177e4SLinus Torvalds static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
5371da177e4SLinus Torvalds 						char *buf)
5381da177e4SLinus Torvalds {
5391da177e4SLinus Torvalds 	ssize_t i = 0;
5401da177e4SLinus Torvalds 	struct cpufreq_governor *t;
5411da177e4SLinus Torvalds 
5425800043bSNathan Zimmer 	rcu_read_lock();
5435800043bSNathan Zimmer 	if (!rcu_dereference(cpufreq_driver)->target) {
5445800043bSNathan Zimmer 		rcu_read_unlock();
5451da177e4SLinus Torvalds 		i += sprintf(buf, "performance powersave");
5461da177e4SLinus Torvalds 		goto out;
5471da177e4SLinus Torvalds 	}
5485800043bSNathan Zimmer 	rcu_read_unlock();
5491da177e4SLinus Torvalds 
5501da177e4SLinus Torvalds 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
55129464f28SDave Jones 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
55229464f28SDave Jones 		    - (CPUFREQ_NAME_LEN + 2)))
5531da177e4SLinus Torvalds 			goto out;
5544b972f0bSviresh kumar 		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
5551da177e4SLinus Torvalds 	}
5561da177e4SLinus Torvalds out:
5571da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
5581da177e4SLinus Torvalds 	return i;
5591da177e4SLinus Torvalds }
560e8628dd0SDarrick J. Wong 
561835481d9SRusty Russell static ssize_t show_cpus(const struct cpumask *mask, char *buf)
5621da177e4SLinus Torvalds {
5631da177e4SLinus Torvalds 	ssize_t i = 0;
5641da177e4SLinus Torvalds 	unsigned int cpu;
5651da177e4SLinus Torvalds 
566835481d9SRusty Russell 	for_each_cpu(cpu, mask) {
5671da177e4SLinus Torvalds 		if (i)
5681da177e4SLinus Torvalds 			i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
5691da177e4SLinus Torvalds 		i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
5701da177e4SLinus Torvalds 		if (i >= (PAGE_SIZE - 5))
5711da177e4SLinus Torvalds 			break;
5721da177e4SLinus Torvalds 	}
5731da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
5741da177e4SLinus Torvalds 	return i;
5751da177e4SLinus Torvalds }
5761da177e4SLinus Torvalds 
577e8628dd0SDarrick J. Wong /**
578e8628dd0SDarrick J. Wong  * show_related_cpus - show the CPUs affected by each transition even if
579e8628dd0SDarrick J. Wong  * hw coordination is in use
580e8628dd0SDarrick J. Wong  */
581e8628dd0SDarrick J. Wong static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
582e8628dd0SDarrick J. Wong {
583e8628dd0SDarrick J. Wong 	return show_cpus(policy->related_cpus, buf);
584e8628dd0SDarrick J. Wong }
585e8628dd0SDarrick J. Wong 
586e8628dd0SDarrick J. Wong /**
587e8628dd0SDarrick J. Wong  * show_affected_cpus - show the CPUs affected by each transition
588e8628dd0SDarrick J. Wong  */
589e8628dd0SDarrick J. Wong static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
590e8628dd0SDarrick J. Wong {
591e8628dd0SDarrick J. Wong 	return show_cpus(policy->cpus, buf);
592e8628dd0SDarrick J. Wong }
593e8628dd0SDarrick J. Wong 
5949e76988eSVenki Pallipadi static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
5959e76988eSVenki Pallipadi 					const char *buf, size_t count)
5969e76988eSVenki Pallipadi {
5979e76988eSVenki Pallipadi 	unsigned int freq = 0;
5989e76988eSVenki Pallipadi 	unsigned int ret;
5999e76988eSVenki Pallipadi 
600879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->store_setspeed)
6019e76988eSVenki Pallipadi 		return -EINVAL;
6029e76988eSVenki Pallipadi 
6039e76988eSVenki Pallipadi 	ret = sscanf(buf, "%u", &freq);
6049e76988eSVenki Pallipadi 	if (ret != 1)
6059e76988eSVenki Pallipadi 		return -EINVAL;
6069e76988eSVenki Pallipadi 
6079e76988eSVenki Pallipadi 	policy->governor->store_setspeed(policy, freq);
6089e76988eSVenki Pallipadi 
6099e76988eSVenki Pallipadi 	return count;
6109e76988eSVenki Pallipadi }
6119e76988eSVenki Pallipadi 
6129e76988eSVenki Pallipadi static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
6139e76988eSVenki Pallipadi {
614879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->show_setspeed)
6159e76988eSVenki Pallipadi 		return sprintf(buf, "<unsupported>\n");
6169e76988eSVenki Pallipadi 
6179e76988eSVenki Pallipadi 	return policy->governor->show_setspeed(policy, buf);
6189e76988eSVenki Pallipadi }
6191da177e4SLinus Torvalds 
620e2f74f35SThomas Renninger /**
6218bf1ac72Sviresh kumar  * show_bios_limit - show the current cpufreq HW/BIOS limitation
622e2f74f35SThomas Renninger  */
623e2f74f35SThomas Renninger static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
624e2f74f35SThomas Renninger {
625e2f74f35SThomas Renninger 	unsigned int limit;
6265800043bSNathan Zimmer 	int (*bios_limit)(int cpu, unsigned int *limit);
627e2f74f35SThomas Renninger 	int ret;
6285800043bSNathan Zimmer 
6295800043bSNathan Zimmer 	rcu_read_lock();
6305800043bSNathan Zimmer 	bios_limit = rcu_dereference(cpufreq_driver)->bios_limit;
6315800043bSNathan Zimmer 	rcu_read_unlock();
6325800043bSNathan Zimmer 
6335800043bSNathan Zimmer 	if (bios_limit) {
6345800043bSNathan Zimmer 		ret = bios_limit(policy->cpu, &limit);
635e2f74f35SThomas Renninger 		if (!ret)
636e2f74f35SThomas Renninger 			return sprintf(buf, "%u\n", limit);
637e2f74f35SThomas Renninger 	}
638e2f74f35SThomas Renninger 	return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
639e2f74f35SThomas Renninger }
640e2f74f35SThomas Renninger 
6416dad2a29SBorislav Petkov cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
6426dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_min_freq);
6436dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_max_freq);
6446dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_transition_latency);
6456dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_available_governors);
6466dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_driver);
6476dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_cur_freq);
6486dad2a29SBorislav Petkov cpufreq_freq_attr_ro(bios_limit);
6496dad2a29SBorislav Petkov cpufreq_freq_attr_ro(related_cpus);
6506dad2a29SBorislav Petkov cpufreq_freq_attr_ro(affected_cpus);
6516dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_min_freq);
6526dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_max_freq);
6536dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_governor);
6546dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_setspeed);
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds static struct attribute *default_attrs[] = {
6571da177e4SLinus Torvalds 	&cpuinfo_min_freq.attr,
6581da177e4SLinus Torvalds 	&cpuinfo_max_freq.attr,
659ed129784SThomas Renninger 	&cpuinfo_transition_latency.attr,
6601da177e4SLinus Torvalds 	&scaling_min_freq.attr,
6611da177e4SLinus Torvalds 	&scaling_max_freq.attr,
6621da177e4SLinus Torvalds 	&affected_cpus.attr,
663e8628dd0SDarrick J. Wong 	&related_cpus.attr,
6641da177e4SLinus Torvalds 	&scaling_governor.attr,
6651da177e4SLinus Torvalds 	&scaling_driver.attr,
6661da177e4SLinus Torvalds 	&scaling_available_governors.attr,
6679e76988eSVenki Pallipadi 	&scaling_setspeed.attr,
6681da177e4SLinus Torvalds 	NULL
6691da177e4SLinus Torvalds };
6701da177e4SLinus Torvalds 
6718aa84ad8SThomas Renninger struct kobject *cpufreq_global_kobject;
6728aa84ad8SThomas Renninger EXPORT_SYMBOL(cpufreq_global_kobject);
6738aa84ad8SThomas Renninger 
6741da177e4SLinus Torvalds #define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
6751da177e4SLinus Torvalds #define to_attr(a) container_of(a, struct freq_attr, attr)
6761da177e4SLinus Torvalds 
6771da177e4SLinus Torvalds static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
6781da177e4SLinus Torvalds {
6791da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
6801da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
6810db4a8a9SDave Jones 	ssize_t ret = -EINVAL;
682a9144436SStephen Boyd 	policy = cpufreq_cpu_get_sysfs(policy->cpu);
6831da177e4SLinus Torvalds 	if (!policy)
6840db4a8a9SDave Jones 		goto no_policy;
6855a01f2e8SVenkatesh Pallipadi 
6865a01f2e8SVenkatesh Pallipadi 	if (lock_policy_rwsem_read(policy->cpu) < 0)
6870db4a8a9SDave Jones 		goto fail;
6885a01f2e8SVenkatesh Pallipadi 
689e08f5f5bSGautham R Shenoy 	if (fattr->show)
690e08f5f5bSGautham R Shenoy 		ret = fattr->show(policy, buf);
691e08f5f5bSGautham R Shenoy 	else
692e08f5f5bSGautham R Shenoy 		ret = -EIO;
693e08f5f5bSGautham R Shenoy 
6945a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_read(policy->cpu);
6950db4a8a9SDave Jones fail:
696a9144436SStephen Boyd 	cpufreq_cpu_put_sysfs(policy);
6970db4a8a9SDave Jones no_policy:
6981da177e4SLinus Torvalds 	return ret;
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds static ssize_t store(struct kobject *kobj, struct attribute *attr,
7021da177e4SLinus Torvalds 		     const char *buf, size_t count)
7031da177e4SLinus Torvalds {
7041da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7051da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
706a07530b4SDave Jones 	ssize_t ret = -EINVAL;
707a9144436SStephen Boyd 	policy = cpufreq_cpu_get_sysfs(policy->cpu);
7081da177e4SLinus Torvalds 	if (!policy)
709a07530b4SDave Jones 		goto no_policy;
7105a01f2e8SVenkatesh Pallipadi 
7115a01f2e8SVenkatesh Pallipadi 	if (lock_policy_rwsem_write(policy->cpu) < 0)
712a07530b4SDave Jones 		goto fail;
7135a01f2e8SVenkatesh Pallipadi 
714e08f5f5bSGautham R Shenoy 	if (fattr->store)
715e08f5f5bSGautham R Shenoy 		ret = fattr->store(policy, buf, count);
716e08f5f5bSGautham R Shenoy 	else
717e08f5f5bSGautham R Shenoy 		ret = -EIO;
718e08f5f5bSGautham R Shenoy 
7195a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(policy->cpu);
720a07530b4SDave Jones fail:
721a9144436SStephen Boyd 	cpufreq_cpu_put_sysfs(policy);
722a07530b4SDave Jones no_policy:
7231da177e4SLinus Torvalds 	return ret;
7241da177e4SLinus Torvalds }
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds static void cpufreq_sysfs_release(struct kobject *kobj)
7271da177e4SLinus Torvalds {
7281da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7292d06d8c4SDominik Brodowski 	pr_debug("last reference is dropped\n");
7301da177e4SLinus Torvalds 	complete(&policy->kobj_unregister);
7311da177e4SLinus Torvalds }
7321da177e4SLinus Torvalds 
73352cf25d0SEmese Revfy static const struct sysfs_ops sysfs_ops = {
7341da177e4SLinus Torvalds 	.show	= show,
7351da177e4SLinus Torvalds 	.store	= store,
7361da177e4SLinus Torvalds };
7371da177e4SLinus Torvalds 
7381da177e4SLinus Torvalds static struct kobj_type ktype_cpufreq = {
7391da177e4SLinus Torvalds 	.sysfs_ops	= &sysfs_ops,
7401da177e4SLinus Torvalds 	.default_attrs	= default_attrs,
7411da177e4SLinus Torvalds 	.release	= cpufreq_sysfs_release,
7421da177e4SLinus Torvalds };
7431da177e4SLinus Torvalds 
74419d6f7ecSDave Jones /* symlink affected CPUs */
745cf3289d0SAlex Chiang static int cpufreq_add_dev_symlink(unsigned int cpu,
746cf3289d0SAlex Chiang 				   struct cpufreq_policy *policy)
74719d6f7ecSDave Jones {
74819d6f7ecSDave Jones 	unsigned int j;
74919d6f7ecSDave Jones 	int ret = 0;
75019d6f7ecSDave Jones 
75119d6f7ecSDave Jones 	for_each_cpu(j, policy->cpus) {
75219d6f7ecSDave Jones 		struct cpufreq_policy *managed_policy;
7538a25a2fdSKay Sievers 		struct device *cpu_dev;
75419d6f7ecSDave Jones 
75519d6f7ecSDave Jones 		if (j == cpu)
75619d6f7ecSDave Jones 			continue;
75719d6f7ecSDave Jones 
7582d06d8c4SDominik Brodowski 		pr_debug("CPU %u already managed, adding link\n", j);
75919d6f7ecSDave Jones 		managed_policy = cpufreq_cpu_get(cpu);
7608a25a2fdSKay Sievers 		cpu_dev = get_cpu_device(j);
7618a25a2fdSKay Sievers 		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
76219d6f7ecSDave Jones 					"cpufreq");
76319d6f7ecSDave Jones 		if (ret) {
76419d6f7ecSDave Jones 			cpufreq_cpu_put(managed_policy);
76519d6f7ecSDave Jones 			return ret;
76619d6f7ecSDave Jones 		}
76719d6f7ecSDave Jones 	}
76819d6f7ecSDave Jones 	return ret;
76919d6f7ecSDave Jones }
77019d6f7ecSDave Jones 
771cf3289d0SAlex Chiang static int cpufreq_add_dev_interface(unsigned int cpu,
772cf3289d0SAlex Chiang 				     struct cpufreq_policy *policy,
7738a25a2fdSKay Sievers 				     struct device *dev)
774909a694eSDave Jones {
775ecf7e461SDave Jones 	struct cpufreq_policy new_policy;
776909a694eSDave Jones 	struct freq_attr **drv_attr;
7775800043bSNathan Zimmer 	struct cpufreq_driver *driver;
778909a694eSDave Jones 	unsigned long flags;
779909a694eSDave Jones 	int ret = 0;
780909a694eSDave Jones 	unsigned int j;
781909a694eSDave Jones 
782909a694eSDave Jones 	/* prepare interface data */
783909a694eSDave Jones 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
7848a25a2fdSKay Sievers 				   &dev->kobj, "cpufreq");
785909a694eSDave Jones 	if (ret)
786909a694eSDave Jones 		return ret;
787909a694eSDave Jones 
788909a694eSDave Jones 	/* set up files for this cpu device */
7895800043bSNathan Zimmer 	rcu_read_lock();
7905800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
7915800043bSNathan Zimmer 	drv_attr = driver->attr;
792909a694eSDave Jones 	while ((drv_attr) && (*drv_attr)) {
793909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
794909a694eSDave Jones 		if (ret)
7955800043bSNathan Zimmer 			goto err_out_unlock;
796909a694eSDave Jones 		drv_attr++;
797909a694eSDave Jones 	}
7985800043bSNathan Zimmer 	if (driver->get) {
799909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
800909a694eSDave Jones 		if (ret)
8015800043bSNathan Zimmer 			goto err_out_unlock;
802909a694eSDave Jones 	}
8035800043bSNathan Zimmer 	if (driver->target) {
804909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
805909a694eSDave Jones 		if (ret)
8065800043bSNathan Zimmer 			goto err_out_unlock;
807909a694eSDave Jones 	}
8085800043bSNathan Zimmer 	if (driver->bios_limit) {
809e2f74f35SThomas Renninger 		ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
810e2f74f35SThomas Renninger 		if (ret)
8115800043bSNathan Zimmer 			goto err_out_unlock;
812e2f74f35SThomas Renninger 	}
8135800043bSNathan Zimmer 	rcu_read_unlock();
814909a694eSDave Jones 
8150d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
816909a694eSDave Jones 	for_each_cpu(j, policy->cpus) {
817909a694eSDave Jones 		per_cpu(cpufreq_cpu_data, j) = policy;
818f1625066STejun Heo 		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
819909a694eSDave Jones 	}
8200d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
821909a694eSDave Jones 
822909a694eSDave Jones 	ret = cpufreq_add_dev_symlink(cpu, policy);
823ecf7e461SDave Jones 	if (ret)
824ecf7e461SDave Jones 		goto err_out_kobj_put;
825ecf7e461SDave Jones 
826ecf7e461SDave Jones 	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
827ecf7e461SDave Jones 	/* assure that the starting sequence is run in __cpufreq_set_policy */
828ecf7e461SDave Jones 	policy->governor = NULL;
829ecf7e461SDave Jones 
830ecf7e461SDave Jones 	/* set default policy */
831ecf7e461SDave Jones 	ret = __cpufreq_set_policy(policy, &new_policy);
832ecf7e461SDave Jones 	policy->user_policy.policy = policy->policy;
833ecf7e461SDave Jones 	policy->user_policy.governor = policy->governor;
834ecf7e461SDave Jones 
835ecf7e461SDave Jones 	if (ret) {
8365800043bSNathan Zimmer 		int (*exit)(struct cpufreq_policy *policy);
8375800043bSNathan Zimmer 
8382d06d8c4SDominik Brodowski 		pr_debug("setting policy failed\n");
8395800043bSNathan Zimmer 		rcu_read_lock();
8405800043bSNathan Zimmer 		exit = rcu_dereference(cpufreq_driver)->exit;
8415800043bSNathan Zimmer 		rcu_read_unlock();
8425800043bSNathan Zimmer 		if (exit)
8435800043bSNathan Zimmer 			exit(policy);
8445800043bSNathan Zimmer 
845ecf7e461SDave Jones 	}
846909a694eSDave Jones 	return ret;
847909a694eSDave Jones 
8485800043bSNathan Zimmer err_out_unlock:
8495800043bSNathan Zimmer 	rcu_read_unlock();
850909a694eSDave Jones err_out_kobj_put:
851909a694eSDave Jones 	kobject_put(&policy->kobj);
852909a694eSDave Jones 	wait_for_completion(&policy->kobj_unregister);
853909a694eSDave Jones 	return ret;
854909a694eSDave Jones }
855909a694eSDave Jones 
856fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
857fcf80582SViresh Kumar static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
858fcf80582SViresh Kumar 				  struct device *dev)
859fcf80582SViresh Kumar {
860fcf80582SViresh Kumar 	struct cpufreq_policy *policy;
861*820c6ca2SViresh Kumar 	int ret = 0, has_target = 0;
862fcf80582SViresh Kumar 	unsigned long flags;
863fcf80582SViresh Kumar 
864fcf80582SViresh Kumar 	policy = cpufreq_cpu_get(sibling);
865fcf80582SViresh Kumar 	WARN_ON(!policy);
866fcf80582SViresh Kumar 
867*820c6ca2SViresh Kumar 	rcu_read_lock();
868*820c6ca2SViresh Kumar 	has_target = !!rcu_dereference(cpufreq_driver)->target;
869*820c6ca2SViresh Kumar 	rcu_read_unlock();
870*820c6ca2SViresh Kumar 
871*820c6ca2SViresh Kumar 	if (has_target)
872fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
873fcf80582SViresh Kumar 
8742eaa3e2dSViresh Kumar 	lock_policy_rwsem_write(sibling);
8752eaa3e2dSViresh Kumar 
8760d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
8772eaa3e2dSViresh Kumar 
878fcf80582SViresh Kumar 	cpumask_set_cpu(cpu, policy->cpus);
8792eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu;
880fcf80582SViresh Kumar 	per_cpu(cpufreq_cpu_data, cpu) = policy;
8810d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
882fcf80582SViresh Kumar 
8832eaa3e2dSViresh Kumar 	unlock_policy_rwsem_write(sibling);
8842eaa3e2dSViresh Kumar 
885*820c6ca2SViresh Kumar 	if (has_target) {
886fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_START);
887fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
888*820c6ca2SViresh Kumar 	}
889fcf80582SViresh Kumar 
890fcf80582SViresh Kumar 	ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
891fcf80582SViresh Kumar 	if (ret) {
892fcf80582SViresh Kumar 		cpufreq_cpu_put(policy);
893fcf80582SViresh Kumar 		return ret;
894fcf80582SViresh Kumar 	}
895fcf80582SViresh Kumar 
896fcf80582SViresh Kumar 	return 0;
897fcf80582SViresh Kumar }
898fcf80582SViresh Kumar #endif
8991da177e4SLinus Torvalds 
9001da177e4SLinus Torvalds /**
9011da177e4SLinus Torvalds  * cpufreq_add_dev - add a CPU device
9021da177e4SLinus Torvalds  *
9031da177e4SLinus Torvalds  * Adds the cpufreq interface for a CPU device.
9043f4a782bSMathieu Desnoyers  *
9053f4a782bSMathieu Desnoyers  * The Oracle says: try running cpufreq registration/unregistration concurrently
9063f4a782bSMathieu Desnoyers  * with with cpu hotplugging and all hell will break loose. Tried to clean this
9073f4a782bSMathieu Desnoyers  * mess up, but more thorough testing is needed. - Mathieu
9081da177e4SLinus Torvalds  */
9098a25a2fdSKay Sievers static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
9101da177e4SLinus Torvalds {
911fcf80582SViresh Kumar 	unsigned int j, cpu = dev->id;
91265922465SViresh Kumar 	int ret = -ENOMEM;
9131da177e4SLinus Torvalds 	struct cpufreq_policy *policy;
9145800043bSNathan Zimmer 	struct cpufreq_driver *driver;
9155800043bSNathan Zimmer 	int (*init)(struct cpufreq_policy *policy);
9161da177e4SLinus Torvalds 	unsigned long flags;
91790e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
918fcf80582SViresh Kumar 	struct cpufreq_governor *gov;
91990e41bacSPrarit Bhargava 	int sibling;
92090e41bacSPrarit Bhargava #endif
9211da177e4SLinus Torvalds 
922c32b6b8eSAshok Raj 	if (cpu_is_offline(cpu))
923c32b6b8eSAshok Raj 		return 0;
924c32b6b8eSAshok Raj 
9252d06d8c4SDominik Brodowski 	pr_debug("adding CPU %u\n", cpu);
9261da177e4SLinus Torvalds 
9271da177e4SLinus Torvalds #ifdef CONFIG_SMP
9281da177e4SLinus Torvalds 	/* check whether a different CPU already registered this
9291da177e4SLinus Torvalds 	 * CPU because it is in the same boat. */
9301da177e4SLinus Torvalds 	policy = cpufreq_cpu_get(cpu);
9311da177e4SLinus Torvalds 	if (unlikely(policy)) {
9328ff69732SDave Jones 		cpufreq_cpu_put(policy);
9331da177e4SLinus Torvalds 		return 0;
9341da177e4SLinus Torvalds 	}
935fcf80582SViresh Kumar 
936fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
937fcf80582SViresh Kumar 	/* Check if this cpu was hot-unplugged earlier and has siblings */
9380d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
939fcf80582SViresh Kumar 	for_each_online_cpu(sibling) {
940fcf80582SViresh Kumar 		struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
9412eaa3e2dSViresh Kumar 		if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
9420d1857a1SNathan Zimmer 			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
943fcf80582SViresh Kumar 			return cpufreq_add_policy_cpu(cpu, sibling, dev);
944fcf80582SViresh Kumar 		}
9452eaa3e2dSViresh Kumar 	}
9460d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
947fcf80582SViresh Kumar #endif
9481da177e4SLinus Torvalds #endif
9491da177e4SLinus Torvalds 
9505800043bSNathan Zimmer 	rcu_read_lock();
9515800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
9525800043bSNathan Zimmer 	if (!try_module_get(driver->owner)) {
9535800043bSNathan Zimmer 		rcu_read_unlock();
9541da177e4SLinus Torvalds 		ret = -EINVAL;
9551da177e4SLinus Torvalds 		goto module_out;
9561da177e4SLinus Torvalds 	}
9575800043bSNathan Zimmer 	init = driver->init;
9585800043bSNathan Zimmer 	rcu_read_unlock();
9591da177e4SLinus Torvalds 
960e98df50cSDave Jones 	policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
961059019a3SDave Jones 	if (!policy)
9621da177e4SLinus Torvalds 		goto nomem_out;
963059019a3SDave Jones 
964059019a3SDave Jones 	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
9653f4a782bSMathieu Desnoyers 		goto err_free_policy;
966059019a3SDave Jones 
967059019a3SDave Jones 	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
9683f4a782bSMathieu Desnoyers 		goto err_free_cpumask;
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds 	policy->cpu = cpu;
97165922465SViresh Kumar 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
972835481d9SRusty Russell 	cpumask_copy(policy->cpus, cpumask_of(cpu));
9731da177e4SLinus Torvalds 
9745a01f2e8SVenkatesh Pallipadi 	/* Initially set CPU itself as the policy_cpu */
975f1625066STejun Heo 	per_cpu(cpufreq_policy_cpu, cpu) = cpu;
9765a01f2e8SVenkatesh Pallipadi 
9771da177e4SLinus Torvalds 	init_completion(&policy->kobj_unregister);
97865f27f38SDavid Howells 	INIT_WORK(&policy->update, handle_update);
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	/* call driver. From then on the cpufreq must be able
9811da177e4SLinus Torvalds 	 * to accept all calls to ->verify and ->setpolicy for this CPU
9821da177e4SLinus Torvalds 	 */
9835800043bSNathan Zimmer 	ret = init(policy);
9841da177e4SLinus Torvalds 	if (ret) {
9852d06d8c4SDominik Brodowski 		pr_debug("initialization failed\n");
9862eaa3e2dSViresh Kumar 		goto err_set_policy_cpu;
9871da177e4SLinus Torvalds 	}
988643ae6e8SViresh Kumar 
989fcf80582SViresh Kumar 	/* related cpus should atleast have policy->cpus */
990fcf80582SViresh Kumar 	cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
991fcf80582SViresh Kumar 
992643ae6e8SViresh Kumar 	/*
993643ae6e8SViresh Kumar 	 * affected cpus must always be the one, which are online. We aren't
994643ae6e8SViresh Kumar 	 * managing offline cpus here.
995643ae6e8SViresh Kumar 	 */
996643ae6e8SViresh Kumar 	cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
997643ae6e8SViresh Kumar 
998187d9f4eSMike Chan 	policy->user_policy.min = policy->min;
999187d9f4eSMike Chan 	policy->user_policy.max = policy->max;
10001da177e4SLinus Torvalds 
1001a1531acdSThomas Renninger 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1002a1531acdSThomas Renninger 				     CPUFREQ_START, policy);
1003a1531acdSThomas Renninger 
1004fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
1005fcf80582SViresh Kumar 	gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
1006fcf80582SViresh Kumar 	if (gov) {
1007fcf80582SViresh Kumar 		policy->governor = gov;
1008fcf80582SViresh Kumar 		pr_debug("Restoring governor %s for cpu %d\n",
1009fcf80582SViresh Kumar 		       policy->governor->name, cpu);
10104bfa042cSThomas Renninger 	}
1011fcf80582SViresh Kumar #endif
10121da177e4SLinus Torvalds 
10138a25a2fdSKay Sievers 	ret = cpufreq_add_dev_interface(cpu, policy, dev);
101419d6f7ecSDave Jones 	if (ret)
10150142f9dcSAhmed S. Darwish 		goto err_out_unregister;
10168ff69732SDave Jones 
1017038c5b3eSGreg Kroah-Hartman 	kobject_uevent(&policy->kobj, KOBJ_ADD);
10185800043bSNathan Zimmer 	rcu_read_lock();
10195800043bSNathan Zimmer 	module_put(rcu_dereference(cpufreq_driver)->owner);
10205800043bSNathan Zimmer 	rcu_read_unlock();
10212d06d8c4SDominik Brodowski 	pr_debug("initialization complete\n");
10221da177e4SLinus Torvalds 
10231da177e4SLinus Torvalds 	return 0;
10241da177e4SLinus Torvalds 
10251da177e4SLinus Torvalds err_out_unregister:
10260d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1027835481d9SRusty Russell 	for_each_cpu(j, policy->cpus)
10287a6aedfaSMike Travis 		per_cpu(cpufreq_cpu_data, j) = NULL;
10290d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
10301da177e4SLinus Torvalds 
1031c10997f6SGreg Kroah-Hartman 	kobject_put(&policy->kobj);
10321da177e4SLinus Torvalds 	wait_for_completion(&policy->kobj_unregister);
10331da177e4SLinus Torvalds 
10342eaa3e2dSViresh Kumar err_set_policy_cpu:
10352eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = -1;
1036cad70a6aSXiaotian Feng 	free_cpumask_var(policy->related_cpus);
10373f4a782bSMathieu Desnoyers err_free_cpumask:
10383f4a782bSMathieu Desnoyers 	free_cpumask_var(policy->cpus);
10393f4a782bSMathieu Desnoyers err_free_policy:
10401da177e4SLinus Torvalds 	kfree(policy);
10411da177e4SLinus Torvalds nomem_out:
10425800043bSNathan Zimmer 	rcu_read_lock();
10435800043bSNathan Zimmer 	module_put(rcu_dereference(cpufreq_driver)->owner);
10445800043bSNathan Zimmer 	rcu_read_unlock();
10451da177e4SLinus Torvalds module_out:
10461da177e4SLinus Torvalds 	return ret;
10471da177e4SLinus Torvalds }
10481da177e4SLinus Torvalds 
1049b8eed8afSViresh Kumar static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
1050b8eed8afSViresh Kumar {
1051b8eed8afSViresh Kumar 	int j;
1052b8eed8afSViresh Kumar 
1053b8eed8afSViresh Kumar 	policy->last_cpu = policy->cpu;
1054b8eed8afSViresh Kumar 	policy->cpu = cpu;
1055b8eed8afSViresh Kumar 
10563361b7b1SViresh Kumar 	for_each_cpu(j, policy->cpus)
1057b8eed8afSViresh Kumar 		per_cpu(cpufreq_policy_cpu, j) = cpu;
1058b8eed8afSViresh Kumar 
1059b8eed8afSViresh Kumar #ifdef CONFIG_CPU_FREQ_TABLE
1060b8eed8afSViresh Kumar 	cpufreq_frequency_table_update_policy_cpu(policy);
1061b8eed8afSViresh Kumar #endif
1062b8eed8afSViresh Kumar 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1063b8eed8afSViresh Kumar 			CPUFREQ_UPDATE_POLICY_CPU, policy);
1064b8eed8afSViresh Kumar }
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds /**
10675a01f2e8SVenkatesh Pallipadi  * __cpufreq_remove_dev - remove a CPU device
10681da177e4SLinus Torvalds  *
10691da177e4SLinus Torvalds  * Removes the cpufreq interface for a CPU device.
10705a01f2e8SVenkatesh Pallipadi  * Caller should already have policy_rwsem in write mode for this CPU.
10715a01f2e8SVenkatesh Pallipadi  * This routine frees the rwsem before returning.
10721da177e4SLinus Torvalds  */
10738a25a2fdSKay Sievers static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
10741da177e4SLinus Torvalds {
1075b8eed8afSViresh Kumar 	unsigned int cpu = dev->id, ret, cpus;
10761da177e4SLinus Torvalds 	unsigned long flags;
10771da177e4SLinus Torvalds 	struct cpufreq_policy *data;
10785800043bSNathan Zimmer 	struct cpufreq_driver *driver;
1079499bca9bSAmerigo Wang 	struct kobject *kobj;
1080499bca9bSAmerigo Wang 	struct completion *cmp;
10818a25a2fdSKay Sievers 	struct device *cpu_dev;
10825800043bSNathan Zimmer 	bool has_target;
10835800043bSNathan Zimmer 	int (*exit)(struct cpufreq_policy *policy);
10841da177e4SLinus Torvalds 
1085b8eed8afSViresh Kumar 	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
10861da177e4SLinus Torvalds 
10870d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
10881da177e4SLinus Torvalds 
10891da177e4SLinus Torvalds 	data = per_cpu(cpufreq_cpu_data, cpu);
10907a6aedfaSMike Travis 	per_cpu(cpufreq_cpu_data, cpu) = NULL;
10911da177e4SLinus Torvalds 
10920d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds 	if (!data) {
1095b8eed8afSViresh Kumar 		pr_debug("%s: No cpu_data found\n", __func__);
10961da177e4SLinus Torvalds 		return -EINVAL;
10971da177e4SLinus Torvalds 	}
10981da177e4SLinus Torvalds 
10995800043bSNathan Zimmer 	rcu_read_lock();
11005800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
11015800043bSNathan Zimmer 	has_target = driver->target ? true : false;
11025800043bSNathan Zimmer 	exit = driver->exit;
11035800043bSNathan Zimmer 	if (has_target)
11041da177e4SLinus Torvalds 		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
11055a01f2e8SVenkatesh Pallipadi 
11061da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG_CPU
11075800043bSNathan Zimmer 	if (!driver->setpolicy)
1108fa69e33fSDirk Brandewie 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
1109fa69e33fSDirk Brandewie 			data->governor->name, CPUFREQ_NAME_LEN);
11101da177e4SLinus Torvalds #endif
11115800043bSNathan Zimmer 	rcu_read_unlock();
11121da177e4SLinus Torvalds 
11132eaa3e2dSViresh Kumar 	WARN_ON(lock_policy_rwsem_write(cpu));
1114b8eed8afSViresh Kumar 	cpus = cpumask_weight(data->cpus);
1115e4969ebaSViresh Kumar 
1116e4969ebaSViresh Kumar 	if (cpus > 1)
1117b8eed8afSViresh Kumar 		cpumask_clear_cpu(cpu, data->cpus);
11182eaa3e2dSViresh Kumar 	unlock_policy_rwsem_write(cpu);
11191da177e4SLinus Torvalds 
112073bf0fc2SViresh Kumar 	if (cpu != data->cpu) {
112173bf0fc2SViresh Kumar 		sysfs_remove_link(&dev->kobj, "cpufreq");
112273bf0fc2SViresh Kumar 	} else if (cpus > 1) {
1123b8eed8afSViresh Kumar 		/* first sibling now owns the new sysfs dir */
1124b8eed8afSViresh Kumar 		cpu_dev = get_cpu_device(cpumask_first(data->cpus));
1125b8eed8afSViresh Kumar 		sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1126b8eed8afSViresh Kumar 		ret = kobject_move(&data->kobj, &cpu_dev->kobj);
1127b8eed8afSViresh Kumar 		if (ret) {
1128b8eed8afSViresh Kumar 			pr_err("%s: Failed to move kobj: %d", __func__, ret);
11292eaa3e2dSViresh Kumar 
11302eaa3e2dSViresh Kumar 			WARN_ON(lock_policy_rwsem_write(cpu));
1131b8eed8afSViresh Kumar 			cpumask_set_cpu(cpu, data->cpus);
11322eaa3e2dSViresh Kumar 
11330d1857a1SNathan Zimmer 			write_lock_irqsave(&cpufreq_driver_lock, flags);
11342eaa3e2dSViresh Kumar 			per_cpu(cpufreq_cpu_data, cpu) = data;
11350d1857a1SNathan Zimmer 			write_unlock_irqrestore(&cpufreq_driver_lock, flags);
11362eaa3e2dSViresh Kumar 
11372eaa3e2dSViresh Kumar 			unlock_policy_rwsem_write(cpu);
11382eaa3e2dSViresh Kumar 
1139b8eed8afSViresh Kumar 			ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj,
1140b8eed8afSViresh Kumar 					"cpufreq");
1141b8eed8afSViresh Kumar 			return -EINVAL;
11421da177e4SLinus Torvalds 		}
1143b8eed8afSViresh Kumar 
11442eaa3e2dSViresh Kumar 		WARN_ON(lock_policy_rwsem_write(cpu));
1145b8eed8afSViresh Kumar 		update_policy_cpu(data, cpu_dev->id);
11462eaa3e2dSViresh Kumar 		unlock_policy_rwsem_write(cpu);
1147b8eed8afSViresh Kumar 		pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
1148b8eed8afSViresh Kumar 				__func__, cpu_dev->id, cpu);
11491da177e4SLinus Torvalds 	}
1150b8eed8afSViresh Kumar 
1151b8eed8afSViresh Kumar 	pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
1152b8eed8afSViresh Kumar 	cpufreq_cpu_put(data);
11535a01f2e8SVenkatesh Pallipadi 
1154b8eed8afSViresh Kumar 	/* If cpu is last user of policy, free policy */
1155b8eed8afSViresh Kumar 	if (cpus == 1) {
1156*820c6ca2SViresh Kumar 		if (has_target)
11577bd353a9SViresh Kumar 			__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
11587bd353a9SViresh Kumar 
11592eaa3e2dSViresh Kumar 		lock_policy_rwsem_read(cpu);
1160499bca9bSAmerigo Wang 		kobj = &data->kobj;
1161499bca9bSAmerigo Wang 		cmp = &data->kobj_unregister;
11622eaa3e2dSViresh Kumar 		unlock_policy_rwsem_read(cpu);
1163499bca9bSAmerigo Wang 		kobject_put(kobj);
11641da177e4SLinus Torvalds 
11651da177e4SLinus Torvalds 		/* we need to make sure that the underlying kobj is actually
11661da177e4SLinus Torvalds 		 * not referenced anymore by anybody before we proceed with
11671da177e4SLinus Torvalds 		 * unloading.
11681da177e4SLinus Torvalds 		 */
11692d06d8c4SDominik Brodowski 		pr_debug("waiting for dropping of refcount\n");
1170499bca9bSAmerigo Wang 		wait_for_completion(cmp);
11712d06d8c4SDominik Brodowski 		pr_debug("wait complete\n");
11721da177e4SLinus Torvalds 
11735800043bSNathan Zimmer 		if (exit)
11745800043bSNathan Zimmer 			exit(data);
117527ecddc2SJacob Shin 
1176835481d9SRusty Russell 		free_cpumask_var(data->related_cpus);
1177835481d9SRusty Russell 		free_cpumask_var(data->cpus);
11781da177e4SLinus Torvalds 		kfree(data);
11795800043bSNathan Zimmer 	} else if (has_target) {
1180b8eed8afSViresh Kumar 		__cpufreq_governor(data, CPUFREQ_GOV_START);
1181b8eed8afSViresh Kumar 		__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
1182b8eed8afSViresh Kumar 	}
11831da177e4SLinus Torvalds 
11842eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = -1;
11851da177e4SLinus Torvalds 	return 0;
11861da177e4SLinus Torvalds }
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds 
11898a25a2fdSKay Sievers static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
11905a01f2e8SVenkatesh Pallipadi {
11918a25a2fdSKay Sievers 	unsigned int cpu = dev->id;
11925a01f2e8SVenkatesh Pallipadi 	int retval;
1193ec28297aSVenki Pallipadi 
1194ec28297aSVenki Pallipadi 	if (cpu_is_offline(cpu))
1195ec28297aSVenki Pallipadi 		return 0;
1196ec28297aSVenki Pallipadi 
11978a25a2fdSKay Sievers 	retval = __cpufreq_remove_dev(dev, sif);
11985a01f2e8SVenkatesh Pallipadi 	return retval;
11995a01f2e8SVenkatesh Pallipadi }
12005a01f2e8SVenkatesh Pallipadi 
12015a01f2e8SVenkatesh Pallipadi 
120265f27f38SDavid Howells static void handle_update(struct work_struct *work)
12031da177e4SLinus Torvalds {
120465f27f38SDavid Howells 	struct cpufreq_policy *policy =
120565f27f38SDavid Howells 		container_of(work, struct cpufreq_policy, update);
120665f27f38SDavid Howells 	unsigned int cpu = policy->cpu;
12072d06d8c4SDominik Brodowski 	pr_debug("handle_update for cpu %u called\n", cpu);
12081da177e4SLinus Torvalds 	cpufreq_update_policy(cpu);
12091da177e4SLinus Torvalds }
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds /**
12121da177e4SLinus Torvalds  *	cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're in deep trouble.
12131da177e4SLinus Torvalds  *	@cpu: cpu number
12141da177e4SLinus Torvalds  *	@old_freq: CPU frequency the kernel thinks the CPU runs at
12151da177e4SLinus Torvalds  *	@new_freq: CPU frequency the CPU actually runs at
12161da177e4SLinus Torvalds  *
121729464f28SDave Jones  *	We adjust to current frequency first, and need to clean up later.
121829464f28SDave Jones  *	So either call to cpufreq_update_policy() or schedule handle_update()).
12191da177e4SLinus Torvalds  */
1220e08f5f5bSGautham R Shenoy static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
1221e08f5f5bSGautham R Shenoy 				unsigned int new_freq)
12221da177e4SLinus Torvalds {
1223b43a7ffbSViresh Kumar 	struct cpufreq_policy *policy;
12241da177e4SLinus Torvalds 	struct cpufreq_freqs freqs;
1225b43a7ffbSViresh Kumar 	unsigned long flags;
1226b43a7ffbSViresh Kumar 
12271da177e4SLinus Torvalds 
12282d06d8c4SDominik Brodowski 	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
12291da177e4SLinus Torvalds 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds 	freqs.old = old_freq;
12321da177e4SLinus Torvalds 	freqs.new = new_freq;
1233b43a7ffbSViresh Kumar 
1234b43a7ffbSViresh Kumar 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1235b43a7ffbSViresh Kumar 	policy = per_cpu(cpufreq_cpu_data, cpu);
1236b43a7ffbSViresh Kumar 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1237b43a7ffbSViresh Kumar 
1238b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
1239b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
12401da177e4SLinus Torvalds }
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds /**
12444ab70df4SDhaval Giani  * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
124595235ca2SVenkatesh Pallipadi  * @cpu: CPU number
124695235ca2SVenkatesh Pallipadi  *
124795235ca2SVenkatesh Pallipadi  * This is the last known freq, without actually getting it from the driver.
124895235ca2SVenkatesh Pallipadi  * Return value will be same as what is shown in scaling_cur_freq in sysfs.
124995235ca2SVenkatesh Pallipadi  */
125095235ca2SVenkatesh Pallipadi unsigned int cpufreq_quick_get(unsigned int cpu)
125195235ca2SVenkatesh Pallipadi {
12529e21ba8bSDirk Brandewie 	struct cpufreq_policy *policy;
12535800043bSNathan Zimmer 	struct cpufreq_driver *driver;
12545800043bSNathan Zimmer 	unsigned int (*get)(unsigned int cpu);
1255e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
125695235ca2SVenkatesh Pallipadi 
12575800043bSNathan Zimmer 	rcu_read_lock();
12585800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
12595800043bSNathan Zimmer 	if (driver && driver->setpolicy && driver->get) {
12605800043bSNathan Zimmer 		get = driver->get;
12615800043bSNathan Zimmer 		rcu_read_unlock();
12625800043bSNathan Zimmer 		return get(cpu);
12635800043bSNathan Zimmer 	}
12645800043bSNathan Zimmer 	rcu_read_unlock();
12659e21ba8bSDirk Brandewie 
12669e21ba8bSDirk Brandewie 	policy = cpufreq_cpu_get(cpu);
126795235ca2SVenkatesh Pallipadi 	if (policy) {
1268e08f5f5bSGautham R Shenoy 		ret_freq = policy->cur;
126995235ca2SVenkatesh Pallipadi 		cpufreq_cpu_put(policy);
127095235ca2SVenkatesh Pallipadi 	}
127195235ca2SVenkatesh Pallipadi 
12724d34a67dSDave Jones 	return ret_freq;
127395235ca2SVenkatesh Pallipadi }
127495235ca2SVenkatesh Pallipadi EXPORT_SYMBOL(cpufreq_quick_get);
127595235ca2SVenkatesh Pallipadi 
12763d737108SJesse Barnes /**
12773d737108SJesse Barnes  * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
12783d737108SJesse Barnes  * @cpu: CPU number
12793d737108SJesse Barnes  *
12803d737108SJesse Barnes  * Just return the max possible frequency for a given CPU.
12813d737108SJesse Barnes  */
12823d737108SJesse Barnes unsigned int cpufreq_quick_get_max(unsigned int cpu)
12833d737108SJesse Barnes {
12843d737108SJesse Barnes 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
12853d737108SJesse Barnes 	unsigned int ret_freq = 0;
12863d737108SJesse Barnes 
12873d737108SJesse Barnes 	if (policy) {
12883d737108SJesse Barnes 		ret_freq = policy->max;
12893d737108SJesse Barnes 		cpufreq_cpu_put(policy);
12903d737108SJesse Barnes 	}
12913d737108SJesse Barnes 
12923d737108SJesse Barnes 	return ret_freq;
12933d737108SJesse Barnes }
12943d737108SJesse Barnes EXPORT_SYMBOL(cpufreq_quick_get_max);
12953d737108SJesse Barnes 
129695235ca2SVenkatesh Pallipadi 
12975a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu)
12981da177e4SLinus Torvalds {
12997a6aedfaSMike Travis 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
13005800043bSNathan Zimmer 	struct cpufreq_driver *driver;
13015800043bSNathan Zimmer 	unsigned int (*get)(unsigned int cpu);
1302e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
13035800043bSNathan Zimmer 	u8 flags;
13041da177e4SLinus Torvalds 
13055800043bSNathan Zimmer 
13065800043bSNathan Zimmer 	rcu_read_lock();
13075800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
13085800043bSNathan Zimmer 	if (!driver->get) {
13095800043bSNathan Zimmer 		rcu_read_unlock();
13104d34a67dSDave Jones 		return ret_freq;
13115800043bSNathan Zimmer 	}
13125800043bSNathan Zimmer 	flags = driver->flags;
13135800043bSNathan Zimmer 	get = driver->get;
13145800043bSNathan Zimmer 	rcu_read_unlock();
13151da177e4SLinus Torvalds 
13165800043bSNathan Zimmer 	ret_freq = get(cpu);
13171da177e4SLinus Torvalds 
1318e08f5f5bSGautham R Shenoy 	if (ret_freq && policy->cur &&
13195800043bSNathan Zimmer 		!(flags & CPUFREQ_CONST_LOOPS)) {
1320e08f5f5bSGautham R Shenoy 		/* verify no discrepancy between actual and
1321e08f5f5bSGautham R Shenoy 					saved value exists */
1322e08f5f5bSGautham R Shenoy 		if (unlikely(ret_freq != policy->cur)) {
1323e08f5f5bSGautham R Shenoy 			cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
13241da177e4SLinus Torvalds 			schedule_work(&policy->update);
13251da177e4SLinus Torvalds 		}
13261da177e4SLinus Torvalds 	}
13271da177e4SLinus Torvalds 
13284d34a67dSDave Jones 	return ret_freq;
13295a01f2e8SVenkatesh Pallipadi }
13301da177e4SLinus Torvalds 
13315a01f2e8SVenkatesh Pallipadi /**
13325a01f2e8SVenkatesh Pallipadi  * cpufreq_get - get the current CPU frequency (in kHz)
13335a01f2e8SVenkatesh Pallipadi  * @cpu: CPU number
13345a01f2e8SVenkatesh Pallipadi  *
13355a01f2e8SVenkatesh Pallipadi  * Get the CPU current (static) CPU frequency
13365a01f2e8SVenkatesh Pallipadi  */
13375a01f2e8SVenkatesh Pallipadi unsigned int cpufreq_get(unsigned int cpu)
13385a01f2e8SVenkatesh Pallipadi {
13395a01f2e8SVenkatesh Pallipadi 	unsigned int ret_freq = 0;
13405a01f2e8SVenkatesh Pallipadi 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
13415a01f2e8SVenkatesh Pallipadi 
13425a01f2e8SVenkatesh Pallipadi 	if (!policy)
13435a01f2e8SVenkatesh Pallipadi 		goto out;
13445a01f2e8SVenkatesh Pallipadi 
13455a01f2e8SVenkatesh Pallipadi 	if (unlikely(lock_policy_rwsem_read(cpu)))
13465a01f2e8SVenkatesh Pallipadi 		goto out_policy;
13475a01f2e8SVenkatesh Pallipadi 
13485a01f2e8SVenkatesh Pallipadi 	ret_freq = __cpufreq_get(cpu);
13495a01f2e8SVenkatesh Pallipadi 
13505a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_read(cpu);
13515a01f2e8SVenkatesh Pallipadi 
13525a01f2e8SVenkatesh Pallipadi out_policy:
13531da177e4SLinus Torvalds 	cpufreq_cpu_put(policy);
13545a01f2e8SVenkatesh Pallipadi out:
13554d34a67dSDave Jones 	return ret_freq;
13561da177e4SLinus Torvalds }
13571da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get);
13581da177e4SLinus Torvalds 
13598a25a2fdSKay Sievers static struct subsys_interface cpufreq_interface = {
13608a25a2fdSKay Sievers 	.name		= "cpufreq",
13618a25a2fdSKay Sievers 	.subsys		= &cpu_subsys,
13628a25a2fdSKay Sievers 	.add_dev	= cpufreq_add_dev,
13638a25a2fdSKay Sievers 	.remove_dev	= cpufreq_remove_dev,
1364e00e56dfSRafael J. Wysocki };
1365e00e56dfSRafael J. Wysocki 
13661da177e4SLinus Torvalds 
13671da177e4SLinus Torvalds /**
1368e00e56dfSRafael J. Wysocki  * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
1369e00e56dfSRafael J. Wysocki  *
1370e00e56dfSRafael J. Wysocki  * This function is only executed for the boot processor.  The other CPUs
1371e00e56dfSRafael J. Wysocki  * have been put offline by means of CPU hotplug.
137242d4dc3fSBenjamin Herrenschmidt  */
1373e00e56dfSRafael J. Wysocki static int cpufreq_bp_suspend(void)
137442d4dc3fSBenjamin Herrenschmidt {
13755800043bSNathan Zimmer 	int (*suspend)(struct cpufreq_policy *policy);
1376e08f5f5bSGautham R Shenoy 	int ret = 0;
13774bc5d341SDave Jones 
1378e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
137942d4dc3fSBenjamin Herrenschmidt 	struct cpufreq_policy *cpu_policy;
138042d4dc3fSBenjamin Herrenschmidt 
13812d06d8c4SDominik Brodowski 	pr_debug("suspending cpu %u\n", cpu);
138242d4dc3fSBenjamin Herrenschmidt 
1383e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
138442d4dc3fSBenjamin Herrenschmidt 	cpu_policy = cpufreq_cpu_get(cpu);
138542d4dc3fSBenjamin Herrenschmidt 	if (!cpu_policy)
1386e00e56dfSRafael J. Wysocki 		return 0;
138742d4dc3fSBenjamin Herrenschmidt 
13885800043bSNathan Zimmer 	rcu_read_lock();
13895800043bSNathan Zimmer 	suspend = rcu_dereference(cpufreq_driver)->suspend;
13905800043bSNathan Zimmer 	rcu_read_unlock();
13915800043bSNathan Zimmer 	if (suspend) {
13925800043bSNathan Zimmer 		ret = suspend(cpu_policy);
1393ce6c3997SDominik Brodowski 		if (ret)
139442d4dc3fSBenjamin Herrenschmidt 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
139542d4dc3fSBenjamin Herrenschmidt 					"step on CPU %u\n", cpu_policy->cpu);
139642d4dc3fSBenjamin Herrenschmidt 	}
139742d4dc3fSBenjamin Herrenschmidt 
139842d4dc3fSBenjamin Herrenschmidt 	cpufreq_cpu_put(cpu_policy);
1399c9060494SDave Jones 	return ret;
140042d4dc3fSBenjamin Herrenschmidt }
140142d4dc3fSBenjamin Herrenschmidt 
140242d4dc3fSBenjamin Herrenschmidt /**
1403e00e56dfSRafael J. Wysocki  * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
14041da177e4SLinus Torvalds  *
14051da177e4SLinus Torvalds  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
1406ce6c3997SDominik Brodowski  *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
1407ce6c3997SDominik Brodowski  *	    restored. It will verify that the current freq is in sync with
1408ce6c3997SDominik Brodowski  *	    what we believe it to be. This is a bit later than when it
1409ce6c3997SDominik Brodowski  *	    should be, but nonethteless it's better than calling
1410ce6c3997SDominik Brodowski  *	    cpufreq_driver->get() here which might re-enable interrupts...
1411e00e56dfSRafael J. Wysocki  *
1412e00e56dfSRafael J. Wysocki  * This function is only executed for the boot CPU.  The other CPUs have not
1413e00e56dfSRafael J. Wysocki  * been turned on yet.
14141da177e4SLinus Torvalds  */
1415e00e56dfSRafael J. Wysocki static void cpufreq_bp_resume(void)
14161da177e4SLinus Torvalds {
1417e08f5f5bSGautham R Shenoy 	int ret = 0;
14185800043bSNathan Zimmer 	int (*resume)(struct cpufreq_policy *policy);
14194bc5d341SDave Jones 
1420e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
14211da177e4SLinus Torvalds 	struct cpufreq_policy *cpu_policy;
14221da177e4SLinus Torvalds 
14232d06d8c4SDominik Brodowski 	pr_debug("resuming cpu %u\n", cpu);
14241da177e4SLinus Torvalds 
1425e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
14261da177e4SLinus Torvalds 	cpu_policy = cpufreq_cpu_get(cpu);
14271da177e4SLinus Torvalds 	if (!cpu_policy)
1428e00e56dfSRafael J. Wysocki 		return;
14291da177e4SLinus Torvalds 
14305800043bSNathan Zimmer 	rcu_read_lock();
14315800043bSNathan Zimmer 	resume = rcu_dereference(cpufreq_driver)->resume;
14325800043bSNathan Zimmer 	rcu_read_unlock();
14335800043bSNathan Zimmer 
14345800043bSNathan Zimmer 	if (resume) {
14355800043bSNathan Zimmer 		ret = resume(cpu_policy);
14361da177e4SLinus Torvalds 		if (ret) {
14371da177e4SLinus Torvalds 			printk(KERN_ERR "cpufreq: resume failed in ->resume "
14381da177e4SLinus Torvalds 					"step on CPU %u\n", cpu_policy->cpu);
1439c9060494SDave Jones 			goto fail;
14401da177e4SLinus Torvalds 		}
14411da177e4SLinus Torvalds 	}
14421da177e4SLinus Torvalds 
14431da177e4SLinus Torvalds 	schedule_work(&cpu_policy->update);
1444ce6c3997SDominik Brodowski 
1445c9060494SDave Jones fail:
14461da177e4SLinus Torvalds 	cpufreq_cpu_put(cpu_policy);
14471da177e4SLinus Torvalds }
14481da177e4SLinus Torvalds 
1449e00e56dfSRafael J. Wysocki static struct syscore_ops cpufreq_syscore_ops = {
1450e00e56dfSRafael J. Wysocki 	.suspend	= cpufreq_bp_suspend,
1451e00e56dfSRafael J. Wysocki 	.resume		= cpufreq_bp_resume,
14521da177e4SLinus Torvalds };
14531da177e4SLinus Torvalds 
14549d95046eSBorislav Petkov /**
14559d95046eSBorislav Petkov  *	cpufreq_get_current_driver - return current driver's name
14569d95046eSBorislav Petkov  *
14579d95046eSBorislav Petkov  *	Return the name string of the currently loaded cpufreq driver
14589d95046eSBorislav Petkov  *	or NULL, if none.
14599d95046eSBorislav Petkov  */
14609d95046eSBorislav Petkov const char *cpufreq_get_current_driver(void)
14619d95046eSBorislav Petkov {
14625800043bSNathan Zimmer 	struct cpufreq_driver *driver;
14635800043bSNathan Zimmer 	const char *name = NULL;
14645800043bSNathan Zimmer 	rcu_read_lock();
14655800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
14665800043bSNathan Zimmer 	if (driver)
14675800043bSNathan Zimmer 		name = driver->name;
14685800043bSNathan Zimmer 	rcu_read_unlock();
14695800043bSNathan Zimmer 	return name;
14709d95046eSBorislav Petkov }
14719d95046eSBorislav Petkov EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
14721da177e4SLinus Torvalds 
14731da177e4SLinus Torvalds /*********************************************************************
14741da177e4SLinus Torvalds  *                     NOTIFIER LISTS INTERFACE                      *
14751da177e4SLinus Torvalds  *********************************************************************/
14761da177e4SLinus Torvalds 
14771da177e4SLinus Torvalds /**
14781da177e4SLinus Torvalds  *	cpufreq_register_notifier - register a driver with cpufreq
14791da177e4SLinus Torvalds  *	@nb: notifier function to register
14801da177e4SLinus Torvalds  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
14811da177e4SLinus Torvalds  *
14821da177e4SLinus Torvalds  *	Add a driver to one of two lists: either a list of drivers that
14831da177e4SLinus Torvalds  *      are notified about clock rate changes (once before and once after
14841da177e4SLinus Torvalds  *      the transition), or a list of drivers that are notified about
14851da177e4SLinus Torvalds  *      changes in cpufreq policy.
14861da177e4SLinus Torvalds  *
14871da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1488e041c683SAlan Stern  *	blocking_notifier_chain_register.
14891da177e4SLinus Torvalds  */
14901da177e4SLinus Torvalds int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
14911da177e4SLinus Torvalds {
14921da177e4SLinus Torvalds 	int ret;
14931da177e4SLinus Torvalds 
1494d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1495d5aaffa9SDirk Brandewie 		return -EINVAL;
1496d5aaffa9SDirk Brandewie 
149774212ca4SCesar Eduardo Barros 	WARN_ON(!init_cpufreq_transition_notifier_list_called);
149874212ca4SCesar Eduardo Barros 
14991da177e4SLinus Torvalds 	switch (list) {
15001da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1501b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_register(
1502e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
15031da177e4SLinus Torvalds 		break;
15041da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1505e041c683SAlan Stern 		ret = blocking_notifier_chain_register(
1506e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
15071da177e4SLinus Torvalds 		break;
15081da177e4SLinus Torvalds 	default:
15091da177e4SLinus Torvalds 		ret = -EINVAL;
15101da177e4SLinus Torvalds 	}
15111da177e4SLinus Torvalds 
15121da177e4SLinus Torvalds 	return ret;
15131da177e4SLinus Torvalds }
15141da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_register_notifier);
15151da177e4SLinus Torvalds 
15161da177e4SLinus Torvalds 
15171da177e4SLinus Torvalds /**
15181da177e4SLinus Torvalds  *	cpufreq_unregister_notifier - unregister a driver with cpufreq
15191da177e4SLinus Torvalds  *	@nb: notifier block to be unregistered
15201da177e4SLinus Torvalds  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
15211da177e4SLinus Torvalds  *
15221da177e4SLinus Torvalds  *	Remove a driver from the CPU frequency notifier list.
15231da177e4SLinus Torvalds  *
15241da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1525e041c683SAlan Stern  *	blocking_notifier_chain_unregister.
15261da177e4SLinus Torvalds  */
15271da177e4SLinus Torvalds int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
15281da177e4SLinus Torvalds {
15291da177e4SLinus Torvalds 	int ret;
15301da177e4SLinus Torvalds 
1531d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1532d5aaffa9SDirk Brandewie 		return -EINVAL;
1533d5aaffa9SDirk Brandewie 
15341da177e4SLinus Torvalds 	switch (list) {
15351da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1536b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_unregister(
1537e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
15381da177e4SLinus Torvalds 		break;
15391da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1540e041c683SAlan Stern 		ret = blocking_notifier_chain_unregister(
1541e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
15421da177e4SLinus Torvalds 		break;
15431da177e4SLinus Torvalds 	default:
15441da177e4SLinus Torvalds 		ret = -EINVAL;
15451da177e4SLinus Torvalds 	}
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 	return ret;
15481da177e4SLinus Torvalds }
15491da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_unregister_notifier);
15501da177e4SLinus Torvalds 
15511da177e4SLinus Torvalds 
15521da177e4SLinus Torvalds /*********************************************************************
15531da177e4SLinus Torvalds  *                              GOVERNORS                            *
15541da177e4SLinus Torvalds  *********************************************************************/
15551da177e4SLinus Torvalds 
15561da177e4SLinus Torvalds 
15571da177e4SLinus Torvalds int __cpufreq_driver_target(struct cpufreq_policy *policy,
15581da177e4SLinus Torvalds 			    unsigned int target_freq,
15591da177e4SLinus Torvalds 			    unsigned int relation)
15601da177e4SLinus Torvalds {
15611da177e4SLinus Torvalds 	int retval = -EINVAL;
15627249924eSViresh Kumar 	unsigned int old_target_freq = target_freq;
15635800043bSNathan Zimmer 	int (*target)(struct cpufreq_policy *policy,
15645800043bSNathan Zimmer 		      unsigned int target_freq,
15655800043bSNathan Zimmer 		      unsigned int relation);
1566c32b6b8eSAshok Raj 
1567a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1568a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
1569a7b422cdSKonrad Rzeszutek Wilk 
15707249924eSViresh Kumar 	/* Make sure that target_freq is within supported range */
15717249924eSViresh Kumar 	if (target_freq > policy->max)
15727249924eSViresh Kumar 		target_freq = policy->max;
15737249924eSViresh Kumar 	if (target_freq < policy->min)
15747249924eSViresh Kumar 		target_freq = policy->min;
15757249924eSViresh Kumar 
15767249924eSViresh Kumar 	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
15777249924eSViresh Kumar 			policy->cpu, target_freq, relation, old_target_freq);
15785a1c0228SViresh Kumar 
15795a1c0228SViresh Kumar 	if (target_freq == policy->cur)
15805a1c0228SViresh Kumar 		return 0;
15815a1c0228SViresh Kumar 
15825800043bSNathan Zimmer 	rcu_read_lock();
15835800043bSNathan Zimmer 	target = rcu_dereference(cpufreq_driver)->target;
15845800043bSNathan Zimmer 	rcu_read_unlock();
15855800043bSNathan Zimmer 	if (target)
15865800043bSNathan Zimmer 		retval = target(policy, target_freq, relation);
158790d45d17SAshok Raj 
15881da177e4SLinus Torvalds 	return retval;
15891da177e4SLinus Torvalds }
15901da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds int cpufreq_driver_target(struct cpufreq_policy *policy,
15931da177e4SLinus Torvalds 			  unsigned int target_freq,
15941da177e4SLinus Torvalds 			  unsigned int relation)
15951da177e4SLinus Torvalds {
1596f1829e4aSJulia Lawall 	int ret = -EINVAL;
15971da177e4SLinus Torvalds 
15981da177e4SLinus Torvalds 	policy = cpufreq_cpu_get(policy->cpu);
15991da177e4SLinus Torvalds 	if (!policy)
1600f1829e4aSJulia Lawall 		goto no_policy;
16011da177e4SLinus Torvalds 
16025a01f2e8SVenkatesh Pallipadi 	if (unlikely(lock_policy_rwsem_write(policy->cpu)))
1603f1829e4aSJulia Lawall 		goto fail;
16041da177e4SLinus Torvalds 
16051da177e4SLinus Torvalds 	ret = __cpufreq_driver_target(policy, target_freq, relation);
16061da177e4SLinus Torvalds 
16075a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(policy->cpu);
16081da177e4SLinus Torvalds 
1609f1829e4aSJulia Lawall fail:
16101da177e4SLinus Torvalds 	cpufreq_cpu_put(policy);
1611f1829e4aSJulia Lawall no_policy:
16121da177e4SLinus Torvalds 	return ret;
16131da177e4SLinus Torvalds }
16141da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_driver_target);
16151da177e4SLinus Torvalds 
1616bf0b90e3Svenkatesh.pallipadi@intel.com int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
1617dfde5d62SVenkatesh Pallipadi {
1618dfde5d62SVenkatesh Pallipadi 	int ret = 0;
16195800043bSNathan Zimmer 	unsigned int (*getavg)(struct cpufreq_policy *policy,
16205800043bSNathan Zimmer 			       unsigned int cpu);
1621dfde5d62SVenkatesh Pallipadi 
1622d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1623d5aaffa9SDirk Brandewie 		return ret;
1624d5aaffa9SDirk Brandewie 
16255800043bSNathan Zimmer 	rcu_read_lock();
16265800043bSNathan Zimmer 	getavg = rcu_dereference(cpufreq_driver)->getavg;
16275800043bSNathan Zimmer 	rcu_read_unlock();
16285800043bSNathan Zimmer 
16295800043bSNathan Zimmer 	if (!getavg)
16300676f7f2SViresh Kumar 		return 0;
16310676f7f2SViresh Kumar 
1632dfde5d62SVenkatesh Pallipadi 	policy = cpufreq_cpu_get(policy->cpu);
1633dfde5d62SVenkatesh Pallipadi 	if (!policy)
1634dfde5d62SVenkatesh Pallipadi 		return -EINVAL;
1635dfde5d62SVenkatesh Pallipadi 
16365800043bSNathan Zimmer 	ret = getavg(policy, cpu);
1637dfde5d62SVenkatesh Pallipadi 
1638dfde5d62SVenkatesh Pallipadi 	cpufreq_cpu_put(policy);
1639dfde5d62SVenkatesh Pallipadi 	return ret;
1640dfde5d62SVenkatesh Pallipadi }
16415a01f2e8SVenkatesh Pallipadi EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
1642dfde5d62SVenkatesh Pallipadi 
1643153d7f3fSArjan van de Ven /*
1644153d7f3fSArjan van de Ven  * when "event" is CPUFREQ_GOV_LIMITS
1645153d7f3fSArjan van de Ven  */
16461da177e4SLinus Torvalds 
1647e08f5f5bSGautham R Shenoy static int __cpufreq_governor(struct cpufreq_policy *policy,
1648e08f5f5bSGautham R Shenoy 					unsigned int event)
16491da177e4SLinus Torvalds {
1650cc993cabSDave Jones 	int ret;
16516afde10cSThomas Renninger 
16526afde10cSThomas Renninger 	/* Only must be defined when default governor is known to have latency
16536afde10cSThomas Renninger 	   restrictions, like e.g. conservative or ondemand.
16546afde10cSThomas Renninger 	   That this is the case is already ensured in Kconfig
16556afde10cSThomas Renninger 	*/
16566afde10cSThomas Renninger #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
16576afde10cSThomas Renninger 	struct cpufreq_governor *gov = &cpufreq_gov_performance;
16586afde10cSThomas Renninger #else
16596afde10cSThomas Renninger 	struct cpufreq_governor *gov = NULL;
16606afde10cSThomas Renninger #endif
16611c256245SThomas Renninger 
16621c256245SThomas Renninger 	if (policy->governor->max_transition_latency &&
16631c256245SThomas Renninger 	    policy->cpuinfo.transition_latency >
16641c256245SThomas Renninger 	    policy->governor->max_transition_latency) {
16656afde10cSThomas Renninger 		if (!gov)
16666afde10cSThomas Renninger 			return -EINVAL;
16676afde10cSThomas Renninger 		else {
16681c256245SThomas Renninger 			printk(KERN_WARNING "%s governor failed, too long"
16691c256245SThomas Renninger 			       " transition latency of HW, fallback"
16701c256245SThomas Renninger 			       " to %s governor\n",
16711c256245SThomas Renninger 			       policy->governor->name,
16721c256245SThomas Renninger 			       gov->name);
16731c256245SThomas Renninger 			policy->governor = gov;
16741c256245SThomas Renninger 		}
16756afde10cSThomas Renninger 	}
16761da177e4SLinus Torvalds 
16771da177e4SLinus Torvalds 	if (!try_module_get(policy->governor->owner))
16781da177e4SLinus Torvalds 		return -EINVAL;
16791da177e4SLinus Torvalds 
16802d06d8c4SDominik Brodowski 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
1681e08f5f5bSGautham R Shenoy 						policy->cpu, event);
16821da177e4SLinus Torvalds 	ret = policy->governor->governor(policy, event);
16831da177e4SLinus Torvalds 
16844d5dcc42SViresh Kumar 	if (!ret) {
16854d5dcc42SViresh Kumar 		if (event == CPUFREQ_GOV_POLICY_INIT)
16868e53695fSViresh Kumar 			policy->governor->initialized++;
16874d5dcc42SViresh Kumar 		else if (event == CPUFREQ_GOV_POLICY_EXIT)
16888e53695fSViresh Kumar 			policy->governor->initialized--;
16894d5dcc42SViresh Kumar 	}
1690b394058fSViresh Kumar 
1691e08f5f5bSGautham R Shenoy 	/* we keep one module reference alive for
1692e08f5f5bSGautham R Shenoy 			each CPU governed by this CPU */
16931da177e4SLinus Torvalds 	if ((event != CPUFREQ_GOV_START) || ret)
16941da177e4SLinus Torvalds 		module_put(policy->governor->owner);
16951da177e4SLinus Torvalds 	if ((event == CPUFREQ_GOV_STOP) && !ret)
16961da177e4SLinus Torvalds 		module_put(policy->governor->owner);
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 	return ret;
16991da177e4SLinus Torvalds }
17001da177e4SLinus Torvalds 
17011da177e4SLinus Torvalds 
17021da177e4SLinus Torvalds int cpufreq_register_governor(struct cpufreq_governor *governor)
17031da177e4SLinus Torvalds {
17043bcb09a3SJeremy Fitzhardinge 	int err;
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds 	if (!governor)
17071da177e4SLinus Torvalds 		return -EINVAL;
17081da177e4SLinus Torvalds 
1709a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1710a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
1711a7b422cdSKonrad Rzeszutek Wilk 
17123fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
17131da177e4SLinus Torvalds 
1714b394058fSViresh Kumar 	governor->initialized = 0;
17153bcb09a3SJeremy Fitzhardinge 	err = -EBUSY;
17163bcb09a3SJeremy Fitzhardinge 	if (__find_governor(governor->name) == NULL) {
17173bcb09a3SJeremy Fitzhardinge 		err = 0;
17181da177e4SLinus Torvalds 		list_add(&governor->governor_list, &cpufreq_governor_list);
17193bcb09a3SJeremy Fitzhardinge 	}
17201da177e4SLinus Torvalds 
17213fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
17223bcb09a3SJeremy Fitzhardinge 	return err;
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_governor);
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds void cpufreq_unregister_governor(struct cpufreq_governor *governor)
17281da177e4SLinus Torvalds {
172990e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
173090e41bacSPrarit Bhargava 	int cpu;
173190e41bacSPrarit Bhargava #endif
173290e41bacSPrarit Bhargava 
17331da177e4SLinus Torvalds 	if (!governor)
17341da177e4SLinus Torvalds 		return;
17351da177e4SLinus Torvalds 
1736a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1737a7b422cdSKonrad Rzeszutek Wilk 		return;
1738a7b422cdSKonrad Rzeszutek Wilk 
173990e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
174090e41bacSPrarit Bhargava 	for_each_present_cpu(cpu) {
174190e41bacSPrarit Bhargava 		if (cpu_online(cpu))
174290e41bacSPrarit Bhargava 			continue;
174390e41bacSPrarit Bhargava 		if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
174490e41bacSPrarit Bhargava 			strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
174590e41bacSPrarit Bhargava 	}
174690e41bacSPrarit Bhargava #endif
174790e41bacSPrarit Bhargava 
17483fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
17491da177e4SLinus Torvalds 	list_del(&governor->governor_list);
17503fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
17511da177e4SLinus Torvalds 	return;
17521da177e4SLinus Torvalds }
17531da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds 
17571da177e4SLinus Torvalds /*********************************************************************
17581da177e4SLinus Torvalds  *                          POLICY INTERFACE                         *
17591da177e4SLinus Torvalds  *********************************************************************/
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds /**
17621da177e4SLinus Torvalds  * cpufreq_get_policy - get the current cpufreq_policy
176329464f28SDave Jones  * @policy: struct cpufreq_policy into which the current cpufreq_policy
176429464f28SDave Jones  *	is written
17651da177e4SLinus Torvalds  *
17661da177e4SLinus Torvalds  * Reads the current cpufreq policy.
17671da177e4SLinus Torvalds  */
17681da177e4SLinus Torvalds int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
17691da177e4SLinus Torvalds {
17701da177e4SLinus Torvalds 	struct cpufreq_policy *cpu_policy;
17711da177e4SLinus Torvalds 	if (!policy)
17721da177e4SLinus Torvalds 		return -EINVAL;
17731da177e4SLinus Torvalds 
17741da177e4SLinus Torvalds 	cpu_policy = cpufreq_cpu_get(cpu);
17751da177e4SLinus Torvalds 	if (!cpu_policy)
17761da177e4SLinus Torvalds 		return -EINVAL;
17771da177e4SLinus Torvalds 
17781da177e4SLinus Torvalds 	memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
17791da177e4SLinus Torvalds 
17801da177e4SLinus Torvalds 	cpufreq_cpu_put(cpu_policy);
17811da177e4SLinus Torvalds 	return 0;
17821da177e4SLinus Torvalds }
17831da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get_policy);
17841da177e4SLinus Torvalds 
17851da177e4SLinus Torvalds 
1786153d7f3fSArjan van de Ven /*
1787e08f5f5bSGautham R Shenoy  * data   : current policy.
1788e08f5f5bSGautham R Shenoy  * policy : policy to be set.
1789153d7f3fSArjan van de Ven  */
1790e08f5f5bSGautham R Shenoy static int __cpufreq_set_policy(struct cpufreq_policy *data,
1791e08f5f5bSGautham R Shenoy 				struct cpufreq_policy *policy)
17921da177e4SLinus Torvalds {
17937bd353a9SViresh Kumar 	int ret = 0, failed = 1;
17945800043bSNathan Zimmer 	struct cpufreq_driver *driver;
17955800043bSNathan Zimmer 	int (*verify)(struct cpufreq_policy *policy);
17965800043bSNathan Zimmer 	int (*setpolicy)(struct cpufreq_policy *policy);
17971da177e4SLinus Torvalds 
17982d06d8c4SDominik Brodowski 	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
17991da177e4SLinus Torvalds 		policy->min, policy->max);
18001da177e4SLinus Torvalds 
1801e08f5f5bSGautham R Shenoy 	memcpy(&policy->cpuinfo, &data->cpuinfo,
1802e08f5f5bSGautham R Shenoy 				sizeof(struct cpufreq_cpuinfo));
18031da177e4SLinus Torvalds 
180453391fa2SYi Yang 	if (policy->min > data->max || policy->max < data->min) {
18059c9a43edSMattia Dongili 		ret = -EINVAL;
18069c9a43edSMattia Dongili 		goto error_out;
18079c9a43edSMattia Dongili 	}
18089c9a43edSMattia Dongili 
18091da177e4SLinus Torvalds 	/* verify the cpu speed can be set within this limit */
18105800043bSNathan Zimmer 	rcu_read_lock();
18115800043bSNathan Zimmer 	driver = rcu_dereference(cpufreq_driver);
18125800043bSNathan Zimmer 	verify = driver->verify;
18135800043bSNathan Zimmer 	setpolicy = driver->setpolicy;
18145800043bSNathan Zimmer 	rcu_read_unlock();
18155800043bSNathan Zimmer 
18165800043bSNathan Zimmer 	ret = verify(policy);
18171da177e4SLinus Torvalds 	if (ret)
18181da177e4SLinus Torvalds 		goto error_out;
18191da177e4SLinus Torvalds 
18201da177e4SLinus Torvalds 	/* adjust if necessary - all reasons */
1821e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1822e041c683SAlan Stern 			CPUFREQ_ADJUST, policy);
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds 	/* adjust if necessary - hardware incompatibility*/
1825e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1826e041c683SAlan Stern 			CPUFREQ_INCOMPATIBLE, policy);
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds 	/* verify the cpu speed can be set within this limit,
18291da177e4SLinus Torvalds 	   which might be different to the first one */
18305800043bSNathan Zimmer 	ret = verify(policy);
1831e041c683SAlan Stern 	if (ret)
18321da177e4SLinus Torvalds 		goto error_out;
18331da177e4SLinus Torvalds 
18341da177e4SLinus Torvalds 	/* notification of the new policy */
1835e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1836e041c683SAlan Stern 			CPUFREQ_NOTIFY, policy);
18371da177e4SLinus Torvalds 
18381da177e4SLinus Torvalds 	data->min = policy->min;
18391da177e4SLinus Torvalds 	data->max = policy->max;
18401da177e4SLinus Torvalds 
18412d06d8c4SDominik Brodowski 	pr_debug("new min and max freqs are %u - %u kHz\n",
1842e08f5f5bSGautham R Shenoy 					data->min, data->max);
18431da177e4SLinus Torvalds 
18445800043bSNathan Zimmer 	if (setpolicy) {
18451da177e4SLinus Torvalds 		data->policy = policy->policy;
18462d06d8c4SDominik Brodowski 		pr_debug("setting range\n");
18475800043bSNathan Zimmer 		ret = setpolicy(policy);
18481da177e4SLinus Torvalds 	} else {
18491da177e4SLinus Torvalds 		if (policy->governor != data->governor) {
18501da177e4SLinus Torvalds 			/* save old, working values */
18511da177e4SLinus Torvalds 			struct cpufreq_governor *old_gov = data->governor;
18521da177e4SLinus Torvalds 
18532d06d8c4SDominik Brodowski 			pr_debug("governor switch\n");
18541da177e4SLinus Torvalds 
18551da177e4SLinus Torvalds 			/* end old governor */
18567bd353a9SViresh Kumar 			if (data->governor) {
18571da177e4SLinus Torvalds 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
18587bd353a9SViresh Kumar 				__cpufreq_governor(data,
18597bd353a9SViresh Kumar 						CPUFREQ_GOV_POLICY_EXIT);
18607bd353a9SViresh Kumar 			}
18611da177e4SLinus Torvalds 
18621da177e4SLinus Torvalds 			/* start new governor */
18631da177e4SLinus Torvalds 			data->governor = policy->governor;
18647bd353a9SViresh Kumar 			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
18657bd353a9SViresh Kumar 				if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
18667bd353a9SViresh Kumar 					failed = 0;
18677bd353a9SViresh Kumar 				else
18687bd353a9SViresh Kumar 					__cpufreq_governor(data,
18697bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_EXIT);
18707bd353a9SViresh Kumar 			}
18717bd353a9SViresh Kumar 
18727bd353a9SViresh Kumar 			if (failed) {
18731da177e4SLinus Torvalds 				/* new governor failed, so re-start old one */
18742d06d8c4SDominik Brodowski 				pr_debug("starting governor %s failed\n",
1875e08f5f5bSGautham R Shenoy 							data->governor->name);
18761da177e4SLinus Torvalds 				if (old_gov) {
18771da177e4SLinus Torvalds 					data->governor = old_gov;
1878e08f5f5bSGautham R Shenoy 					__cpufreq_governor(data,
18797bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_INIT);
18807bd353a9SViresh Kumar 					__cpufreq_governor(data,
1881e08f5f5bSGautham R Shenoy 							   CPUFREQ_GOV_START);
18821da177e4SLinus Torvalds 				}
18831da177e4SLinus Torvalds 				ret = -EINVAL;
18841da177e4SLinus Torvalds 				goto error_out;
18851da177e4SLinus Torvalds 			}
18861da177e4SLinus Torvalds 			/* might be a policy change, too, so fall through */
18871da177e4SLinus Torvalds 		}
18882d06d8c4SDominik Brodowski 		pr_debug("governor: change or update limits\n");
18891da177e4SLinus Torvalds 		__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
18901da177e4SLinus Torvalds 	}
18911da177e4SLinus Torvalds 
18921da177e4SLinus Torvalds error_out:
18931da177e4SLinus Torvalds 	return ret;
18941da177e4SLinus Torvalds }
18951da177e4SLinus Torvalds 
18961da177e4SLinus Torvalds /**
18971da177e4SLinus Torvalds  *	cpufreq_update_policy - re-evaluate an existing cpufreq policy
18981da177e4SLinus Torvalds  *	@cpu: CPU which shall be re-evaluated
18991da177e4SLinus Torvalds  *
190025985edcSLucas De Marchi  *	Useful for policy notifiers which have different necessities
19011da177e4SLinus Torvalds  *	at different times.
19021da177e4SLinus Torvalds  */
19031da177e4SLinus Torvalds int cpufreq_update_policy(unsigned int cpu)
19041da177e4SLinus Torvalds {
19051da177e4SLinus Torvalds 	struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
19061da177e4SLinus Torvalds 	struct cpufreq_policy policy;
19075800043bSNathan Zimmer 	struct cpufreq_driver *driver;
19085800043bSNathan Zimmer 	unsigned int (*get)(unsigned int cpu);
19095800043bSNathan Zimmer 	int (*target)(struct cpufreq_policy *policy,
19105800043bSNathan Zimmer 		      unsigned int target_freq,
19115800043bSNathan Zimmer 		      unsigned int relation);
1912f1829e4aSJulia Lawall 	int ret;
19131da177e4SLinus Torvalds 
1914f1829e4aSJulia Lawall 	if (!data) {
1915f1829e4aSJulia Lawall 		ret = -ENODEV;
1916f1829e4aSJulia Lawall 		goto no_policy;
1917f1829e4aSJulia Lawall 	}
19181da177e4SLinus Torvalds 
1919f1829e4aSJulia Lawall 	if (unlikely(lock_policy_rwsem_write(cpu))) {
1920f1829e4aSJulia Lawall 		ret = -EINVAL;
1921f1829e4aSJulia Lawall 		goto fail;
1922f1829e4aSJulia Lawall 	}
19231da177e4SLinus Torvalds 
19242d06d8c4SDominik Brodowski 	pr_debug("updating policy for CPU %u\n", cpu);
19257d5e350fSDave Jones 	memcpy(&policy, data, sizeof(struct cpufreq_policy));
19261da177e4SLinus Torvalds 	policy.min = data->user_policy.min;
19271da177e4SLinus Torvalds 	policy.max = data->user_policy.max;
19281da177e4SLinus Torvalds 	policy.policy = data->user_policy.policy;
19291da177e4SLinus Torvalds 	policy.governor = data->user_policy.governor;
19301da177e4SLinus Torvalds 
19310961dd0dSThomas Renninger 	/* BIOS might change freq behind our back
19320961dd0dSThomas Renninger 	  -> ask driver for current freq and notify governors about a change */
19335800043bSNathan Zimmer 	rcu_read_lock();
19345800043bSNathan Zimmer 	driver = rcu_access_pointer(cpufreq_driver);
19355800043bSNathan Zimmer 	get = driver->get;
19365800043bSNathan Zimmer 	target = driver->target;
19375800043bSNathan Zimmer 	rcu_read_unlock();
19385800043bSNathan Zimmer 	if (get) {
19395800043bSNathan Zimmer 		policy.cur = get(cpu);
1940a85f7bd3SThomas Renninger 		if (!data->cur) {
19412d06d8c4SDominik Brodowski 			pr_debug("Driver did not initialize current freq");
1942a85f7bd3SThomas Renninger 			data->cur = policy.cur;
1943a85f7bd3SThomas Renninger 		} else {
19445800043bSNathan Zimmer 			if (data->cur != policy.cur && target)
1945e08f5f5bSGautham R Shenoy 				cpufreq_out_of_sync(cpu, data->cur,
1946e08f5f5bSGautham R Shenoy 								policy.cur);
19470961dd0dSThomas Renninger 		}
1948a85f7bd3SThomas Renninger 	}
19490961dd0dSThomas Renninger 
19501da177e4SLinus Torvalds 	ret = __cpufreq_set_policy(data, &policy);
19511da177e4SLinus Torvalds 
19525a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(cpu);
19535a01f2e8SVenkatesh Pallipadi 
1954f1829e4aSJulia Lawall fail:
19551da177e4SLinus Torvalds 	cpufreq_cpu_put(data);
1956f1829e4aSJulia Lawall no_policy:
19571da177e4SLinus Torvalds 	return ret;
19581da177e4SLinus Torvalds }
19591da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_update_policy);
19601da177e4SLinus Torvalds 
1961dd184a01SSatyam Sharma static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
1962c32b6b8eSAshok Raj 					unsigned long action, void *hcpu)
1963c32b6b8eSAshok Raj {
1964c32b6b8eSAshok Raj 	unsigned int cpu = (unsigned long)hcpu;
19658a25a2fdSKay Sievers 	struct device *dev;
1966c32b6b8eSAshok Raj 
19678a25a2fdSKay Sievers 	dev = get_cpu_device(cpu);
19688a25a2fdSKay Sievers 	if (dev) {
1969c32b6b8eSAshok Raj 		switch (action) {
1970c32b6b8eSAshok Raj 		case CPU_ONLINE:
19718bb78442SRafael J. Wysocki 		case CPU_ONLINE_FROZEN:
19728a25a2fdSKay Sievers 			cpufreq_add_dev(dev, NULL);
1973c32b6b8eSAshok Raj 			break;
1974c32b6b8eSAshok Raj 		case CPU_DOWN_PREPARE:
19758bb78442SRafael J. Wysocki 		case CPU_DOWN_PREPARE_FROZEN:
19768a25a2fdSKay Sievers 			__cpufreq_remove_dev(dev, NULL);
1977c32b6b8eSAshok Raj 			break;
19785a01f2e8SVenkatesh Pallipadi 		case CPU_DOWN_FAILED:
19798bb78442SRafael J. Wysocki 		case CPU_DOWN_FAILED_FROZEN:
19808a25a2fdSKay Sievers 			cpufreq_add_dev(dev, NULL);
1981c32b6b8eSAshok Raj 			break;
1982c32b6b8eSAshok Raj 		}
1983c32b6b8eSAshok Raj 	}
1984c32b6b8eSAshok Raj 	return NOTIFY_OK;
1985c32b6b8eSAshok Raj }
1986c32b6b8eSAshok Raj 
19879c36f746SNeal Buckendahl static struct notifier_block __refdata cpufreq_cpu_notifier = {
1988c32b6b8eSAshok Raj     .notifier_call = cpufreq_cpu_callback,
1989c32b6b8eSAshok Raj };
19901da177e4SLinus Torvalds 
19911da177e4SLinus Torvalds /*********************************************************************
19921da177e4SLinus Torvalds  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
19931da177e4SLinus Torvalds  *********************************************************************/
19941da177e4SLinus Torvalds 
19951da177e4SLinus Torvalds /**
19961da177e4SLinus Torvalds  * cpufreq_register_driver - register a CPU Frequency driver
19971da177e4SLinus Torvalds  * @driver_data: A struct cpufreq_driver containing the values#
19981da177e4SLinus Torvalds  * submitted by the CPU Frequency driver.
19991da177e4SLinus Torvalds  *
20001da177e4SLinus Torvalds  *   Registers a CPU Frequency driver to this core code. This code
20011da177e4SLinus Torvalds  * returns zero on success, -EBUSY when another driver got here first
20021da177e4SLinus Torvalds  * (and isn't unregistered in the meantime).
20031da177e4SLinus Torvalds  *
20041da177e4SLinus Torvalds  */
2005221dee28SLinus Torvalds int cpufreq_register_driver(struct cpufreq_driver *driver_data)
20061da177e4SLinus Torvalds {
20071da177e4SLinus Torvalds 	unsigned long flags;
20081da177e4SLinus Torvalds 	int ret;
20091da177e4SLinus Torvalds 
2010a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2011a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2012a7b422cdSKonrad Rzeszutek Wilk 
20131da177e4SLinus Torvalds 	if (!driver_data || !driver_data->verify || !driver_data->init ||
20141da177e4SLinus Torvalds 	    ((!driver_data->setpolicy) && (!driver_data->target)))
20151da177e4SLinus Torvalds 		return -EINVAL;
20161da177e4SLinus Torvalds 
20172d06d8c4SDominik Brodowski 	pr_debug("trying to register driver %s\n", driver_data->name);
20181da177e4SLinus Torvalds 
20191da177e4SLinus Torvalds 	if (driver_data->setpolicy)
20201da177e4SLinus Torvalds 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
20211da177e4SLinus Torvalds 
20220d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
20235800043bSNathan Zimmer 	if (rcu_access_pointer(cpufreq_driver)) {
20240d1857a1SNathan Zimmer 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20251da177e4SLinus Torvalds 		return -EBUSY;
20261da177e4SLinus Torvalds 	}
20275800043bSNathan Zimmer 	rcu_assign_pointer(cpufreq_driver, driver_data);
20280d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20295800043bSNathan Zimmer 	synchronize_rcu();
20301da177e4SLinus Torvalds 
20318a25a2fdSKay Sievers 	ret = subsys_interface_register(&cpufreq_interface);
20328f5bc2abSJiri Slaby 	if (ret)
20338f5bc2abSJiri Slaby 		goto err_null_driver;
20341da177e4SLinus Torvalds 
20355800043bSNathan Zimmer 	if (!(driver_data->flags & CPUFREQ_STICKY)) {
20361da177e4SLinus Torvalds 		int i;
20371da177e4SLinus Torvalds 		ret = -ENODEV;
20381da177e4SLinus Torvalds 
20391da177e4SLinus Torvalds 		/* check for at least one working CPU */
20407a6aedfaSMike Travis 		for (i = 0; i < nr_cpu_ids; i++)
20417a6aedfaSMike Travis 			if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
20421da177e4SLinus Torvalds 				ret = 0;
20437a6aedfaSMike Travis 				break;
20447a6aedfaSMike Travis 			}
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 		/* if all ->init() calls failed, unregister */
20471da177e4SLinus Torvalds 		if (ret) {
20482d06d8c4SDominik Brodowski 			pr_debug("no CPU initialized for driver %s\n",
2049e08f5f5bSGautham R Shenoy 							driver_data->name);
20508a25a2fdSKay Sievers 			goto err_if_unreg;
20511da177e4SLinus Torvalds 		}
20521da177e4SLinus Torvalds 	}
20531da177e4SLinus Torvalds 
205465edc68cSChandra Seetharaman 	register_hotcpu_notifier(&cpufreq_cpu_notifier);
20552d06d8c4SDominik Brodowski 	pr_debug("driver %s up and running\n", driver_data->name);
20561da177e4SLinus Torvalds 
20578f5bc2abSJiri Slaby 	return 0;
20588a25a2fdSKay Sievers err_if_unreg:
20598a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
20608f5bc2abSJiri Slaby err_null_driver:
20610d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
20625800043bSNathan Zimmer 	rcu_assign_pointer(cpufreq_driver, NULL);
20630d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20645800043bSNathan Zimmer 	synchronize_rcu();
20654d34a67dSDave Jones 	return ret;
20661da177e4SLinus Torvalds }
20671da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_driver);
20681da177e4SLinus Torvalds 
20691da177e4SLinus Torvalds 
20701da177e4SLinus Torvalds /**
20711da177e4SLinus Torvalds  * cpufreq_unregister_driver - unregister the current CPUFreq driver
20721da177e4SLinus Torvalds  *
20731da177e4SLinus Torvalds  *    Unregister the current CPUFreq driver. Only call this if you have
20741da177e4SLinus Torvalds  * the right to do so, i.e. if you have succeeded in initialising before!
20751da177e4SLinus Torvalds  * Returns zero if successful, and -EINVAL if the cpufreq_driver is
20761da177e4SLinus Torvalds  * currently not initialised.
20771da177e4SLinus Torvalds  */
2078221dee28SLinus Torvalds int cpufreq_unregister_driver(struct cpufreq_driver *driver)
20791da177e4SLinus Torvalds {
20801da177e4SLinus Torvalds 	unsigned long flags;
20815800043bSNathan Zimmer 	struct cpufreq_driver *old_driver;
20821da177e4SLinus Torvalds 
20835800043bSNathan Zimmer 	rcu_read_lock();
20845800043bSNathan Zimmer 	old_driver = rcu_access_pointer(cpufreq_driver);
20855800043bSNathan Zimmer 	if (!old_driver || (driver != old_driver)) {
20865800043bSNathan Zimmer 		rcu_read_unlock();
20871da177e4SLinus Torvalds 		return -EINVAL;
20885800043bSNathan Zimmer 	}
20895800043bSNathan Zimmer 	rcu_read_unlock();
20901da177e4SLinus Torvalds 
20912d06d8c4SDominik Brodowski 	pr_debug("unregistering driver %s\n", driver->name);
20921da177e4SLinus Torvalds 
20938a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
209465edc68cSChandra Seetharaman 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
20951da177e4SLinus Torvalds 
20960d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
20975800043bSNathan Zimmer 	rcu_assign_pointer(cpufreq_driver, NULL);
20980d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20995800043bSNathan Zimmer 	synchronize_rcu();
21001da177e4SLinus Torvalds 
21011da177e4SLinus Torvalds 	return 0;
21021da177e4SLinus Torvalds }
21031da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
21045a01f2e8SVenkatesh Pallipadi 
21055a01f2e8SVenkatesh Pallipadi static int __init cpufreq_core_init(void)
21065a01f2e8SVenkatesh Pallipadi {
21075a01f2e8SVenkatesh Pallipadi 	int cpu;
21085a01f2e8SVenkatesh Pallipadi 
2109a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2110a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2111a7b422cdSKonrad Rzeszutek Wilk 
21125a01f2e8SVenkatesh Pallipadi 	for_each_possible_cpu(cpu) {
2113f1625066STejun Heo 		per_cpu(cpufreq_policy_cpu, cpu) = -1;
21145a01f2e8SVenkatesh Pallipadi 		init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
21155a01f2e8SVenkatesh Pallipadi 	}
21168aa84ad8SThomas Renninger 
21178a25a2fdSKay Sievers 	cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
21188aa84ad8SThomas Renninger 	BUG_ON(!cpufreq_global_kobject);
2119e00e56dfSRafael J. Wysocki 	register_syscore_ops(&cpufreq_syscore_ops);
21208aa84ad8SThomas Renninger 
21215a01f2e8SVenkatesh Pallipadi 	return 0;
21225a01f2e8SVenkatesh Pallipadi }
21235a01f2e8SVenkatesh Pallipadi core_initcall(cpufreq_core_init);
2124