xref: /openbmc/linux/drivers/cpufreq/cpufreq.c (revision fcd7af917abba798cd954419030142e95139359f)
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>
6bb176f7dSViresh Kumar  *            (C) 2013 Viresh Kumar <viresh.kumar@linaro.org>
71da177e4SLinus Torvalds  *
8c32b6b8eSAshok Raj  *  Oct 2005 - Ashok Raj <ashok.raj@intel.com>
9c32b6b8eSAshok Raj  *	Added handling for CPU hotplug
108ff69732SDave Jones  *  Feb 2006 - Jacob Shin <jacob.shin@amd.com>
118ff69732SDave Jones  *	Fix handling for CPU hotplug -- affected CPUs
12c32b6b8eSAshok Raj  *
131da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
141da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
151da177e4SLinus Torvalds  * published by the Free Software Foundation.
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds 
18db701151SViresh Kumar #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19db701151SViresh Kumar 
205ff0a268SViresh Kumar #include <linux/cpu.h>
211da177e4SLinus Torvalds #include <linux/cpufreq.h>
221da177e4SLinus Torvalds #include <linux/delay.h>
231da177e4SLinus Torvalds #include <linux/device.h>
245ff0a268SViresh Kumar #include <linux/init.h>
255ff0a268SViresh Kumar #include <linux/kernel_stat.h>
265ff0a268SViresh Kumar #include <linux/module.h>
273fc54d37Sakpm@osdl.org #include <linux/mutex.h>
285ff0a268SViresh Kumar #include <linux/slab.h>
29e00e56dfSRafael J. Wysocki #include <linux/syscore_ops.h>
305ff0a268SViresh Kumar #include <linux/tick.h>
316f4f2723SThomas Renninger #include <trace/events/power.h>
326f4f2723SThomas Renninger 
331da177e4SLinus Torvalds /**
34cd878479SDave Jones  * The "cpufreq driver" - the arch- or hardware-dependent low
351da177e4SLinus Torvalds  * level driver of CPUFreq support, and its spinlock. This lock
361da177e4SLinus Torvalds  * also protects the cpufreq_cpu_data array.
371da177e4SLinus Torvalds  */
381c3d85ddSRafael J. Wysocki static struct cpufreq_driver *cpufreq_driver;
397a6aedfaSMike Travis static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
408414809cSSrivatsa S. Bhat static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
41bb176f7dSViresh Kumar static DEFINE_RWLOCK(cpufreq_driver_lock);
426f1e4efdSJane Li DEFINE_MUTEX(cpufreq_governor_lock);
43c88a1f8bSLukasz Majewski static LIST_HEAD(cpufreq_policy_list);
44bb176f7dSViresh Kumar 
45084f3493SThomas Renninger #ifdef CONFIG_HOTPLUG_CPU
46084f3493SThomas Renninger /* This one keeps track of the previously set governor of a removed CPU */
47e77b89f1SDmitry Monakhov static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
48084f3493SThomas Renninger #endif
491da177e4SLinus Torvalds 
509c0ebcf7SViresh Kumar static inline bool has_target(void)
519c0ebcf7SViresh Kumar {
529c0ebcf7SViresh Kumar 	return cpufreq_driver->target_index || cpufreq_driver->target;
539c0ebcf7SViresh Kumar }
549c0ebcf7SViresh Kumar 
555a01f2e8SVenkatesh Pallipadi /*
566eed9404SViresh Kumar  * rwsem to guarantee that cpufreq driver module doesn't unload during critical
576eed9404SViresh Kumar  * sections
586eed9404SViresh Kumar  */
596eed9404SViresh Kumar static DECLARE_RWSEM(cpufreq_rwsem);
606eed9404SViresh Kumar 
611da177e4SLinus Torvalds /* internal prototypes */
6229464f28SDave Jones static int __cpufreq_governor(struct cpufreq_policy *policy,
6329464f28SDave Jones 		unsigned int event);
645a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu);
6565f27f38SDavid Howells static void handle_update(struct work_struct *work);
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds /**
681da177e4SLinus Torvalds  * Two notifier lists: the "policy" list is involved in the
691da177e4SLinus Torvalds  * validation process for a new CPU frequency policy; the
701da177e4SLinus Torvalds  * "transition" list for kernel code that needs to handle
711da177e4SLinus Torvalds  * changes to devices when the CPU clock speed changes.
721da177e4SLinus Torvalds  * The mutex locks both lists.
731da177e4SLinus Torvalds  */
74e041c683SAlan Stern static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
75b4dfdbb3SAlan Stern static struct srcu_notifier_head cpufreq_transition_notifier_list;
761da177e4SLinus Torvalds 
7774212ca4SCesar Eduardo Barros static bool init_cpufreq_transition_notifier_list_called;
78b4dfdbb3SAlan Stern static int __init init_cpufreq_transition_notifier_list(void)
79b4dfdbb3SAlan Stern {
80b4dfdbb3SAlan Stern 	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
8174212ca4SCesar Eduardo Barros 	init_cpufreq_transition_notifier_list_called = true;
82b4dfdbb3SAlan Stern 	return 0;
83b4dfdbb3SAlan Stern }
84b3438f82SLinus Torvalds pure_initcall(init_cpufreq_transition_notifier_list);
851da177e4SLinus Torvalds 
86a7b422cdSKonrad Rzeszutek Wilk static int off __read_mostly;
87da584455SViresh Kumar static int cpufreq_disabled(void)
88a7b422cdSKonrad Rzeszutek Wilk {
89a7b422cdSKonrad Rzeszutek Wilk 	return off;
90a7b422cdSKonrad Rzeszutek Wilk }
91a7b422cdSKonrad Rzeszutek Wilk void disable_cpufreq(void)
92a7b422cdSKonrad Rzeszutek Wilk {
93a7b422cdSKonrad Rzeszutek Wilk 	off = 1;
94a7b422cdSKonrad Rzeszutek Wilk }
951da177e4SLinus Torvalds static LIST_HEAD(cpufreq_governor_list);
963fc54d37Sakpm@osdl.org static DEFINE_MUTEX(cpufreq_governor_mutex);
971da177e4SLinus Torvalds 
984d5dcc42SViresh Kumar bool have_governor_per_policy(void)
994d5dcc42SViresh Kumar {
1000b981e70SViresh Kumar 	return !!(cpufreq_driver->flags & CPUFREQ_HAVE_GOVERNOR_PER_POLICY);
1014d5dcc42SViresh Kumar }
1023f869d6dSViresh Kumar EXPORT_SYMBOL_GPL(have_governor_per_policy);
1034d5dcc42SViresh Kumar 
104944e9a03SViresh Kumar struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
105944e9a03SViresh Kumar {
106944e9a03SViresh Kumar 	if (have_governor_per_policy())
107944e9a03SViresh Kumar 		return &policy->kobj;
108944e9a03SViresh Kumar 	else
109944e9a03SViresh Kumar 		return cpufreq_global_kobject;
110944e9a03SViresh Kumar }
111944e9a03SViresh Kumar EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
112944e9a03SViresh Kumar 
11372a4ce34SViresh Kumar static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
11472a4ce34SViresh Kumar {
11572a4ce34SViresh Kumar 	u64 idle_time;
11672a4ce34SViresh Kumar 	u64 cur_wall_time;
11772a4ce34SViresh Kumar 	u64 busy_time;
11872a4ce34SViresh Kumar 
11972a4ce34SViresh Kumar 	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
12072a4ce34SViresh Kumar 
12172a4ce34SViresh Kumar 	busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
12272a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
12372a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
12472a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
12572a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
12672a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
12772a4ce34SViresh Kumar 
12872a4ce34SViresh Kumar 	idle_time = cur_wall_time - busy_time;
12972a4ce34SViresh Kumar 	if (wall)
13072a4ce34SViresh Kumar 		*wall = cputime_to_usecs(cur_wall_time);
13172a4ce34SViresh Kumar 
13272a4ce34SViresh Kumar 	return cputime_to_usecs(idle_time);
13372a4ce34SViresh Kumar }
13472a4ce34SViresh Kumar 
13572a4ce34SViresh Kumar u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
13672a4ce34SViresh Kumar {
13772a4ce34SViresh Kumar 	u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL);
13872a4ce34SViresh Kumar 
13972a4ce34SViresh Kumar 	if (idle_time == -1ULL)
14072a4ce34SViresh Kumar 		return get_cpu_idle_time_jiffy(cpu, wall);
14172a4ce34SViresh Kumar 	else if (!io_busy)
14272a4ce34SViresh Kumar 		idle_time += get_cpu_iowait_time_us(cpu, wall);
14372a4ce34SViresh Kumar 
14472a4ce34SViresh Kumar 	return idle_time;
14572a4ce34SViresh Kumar }
14672a4ce34SViresh Kumar EXPORT_SYMBOL_GPL(get_cpu_idle_time);
14772a4ce34SViresh Kumar 
14870e9e778SViresh Kumar /*
14970e9e778SViresh Kumar  * This is a generic cpufreq init() routine which can be used by cpufreq
15070e9e778SViresh Kumar  * drivers of SMP systems. It will do following:
15170e9e778SViresh Kumar  * - validate & show freq table passed
15270e9e778SViresh Kumar  * - set policies transition latency
15370e9e778SViresh Kumar  * - policy->cpus with all possible CPUs
15470e9e778SViresh Kumar  */
15570e9e778SViresh Kumar int cpufreq_generic_init(struct cpufreq_policy *policy,
15670e9e778SViresh Kumar 		struct cpufreq_frequency_table *table,
15770e9e778SViresh Kumar 		unsigned int transition_latency)
15870e9e778SViresh Kumar {
15970e9e778SViresh Kumar 	int ret;
16070e9e778SViresh Kumar 
16170e9e778SViresh Kumar 	ret = cpufreq_table_validate_and_show(policy, table);
16270e9e778SViresh Kumar 	if (ret) {
16370e9e778SViresh Kumar 		pr_err("%s: invalid frequency table: %d\n", __func__, ret);
16470e9e778SViresh Kumar 		return ret;
16570e9e778SViresh Kumar 	}
16670e9e778SViresh Kumar 
16770e9e778SViresh Kumar 	policy->cpuinfo.transition_latency = transition_latency;
16870e9e778SViresh Kumar 
16970e9e778SViresh Kumar 	/*
17070e9e778SViresh Kumar 	 * The driver only supports the SMP configuartion where all processors
17170e9e778SViresh Kumar 	 * share the clock and voltage and clock.
17270e9e778SViresh Kumar 	 */
17370e9e778SViresh Kumar 	cpumask_setall(policy->cpus);
17470e9e778SViresh Kumar 
17570e9e778SViresh Kumar 	return 0;
17670e9e778SViresh Kumar }
17770e9e778SViresh Kumar EXPORT_SYMBOL_GPL(cpufreq_generic_init);
17870e9e778SViresh Kumar 
1796eed9404SViresh Kumar struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
1801da177e4SLinus Torvalds {
1816eed9404SViresh Kumar 	struct cpufreq_policy *policy = NULL;
1821da177e4SLinus Torvalds 	unsigned long flags;
1831da177e4SLinus Torvalds 
1846eed9404SViresh Kumar 	if (cpufreq_disabled() || (cpu >= nr_cpu_ids))
1856eed9404SViresh Kumar 		return NULL;
1866eed9404SViresh Kumar 
1876eed9404SViresh Kumar 	if (!down_read_trylock(&cpufreq_rwsem))
1886eed9404SViresh Kumar 		return NULL;
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	/* get the cpufreq driver */
1910d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1921da177e4SLinus Torvalds 
1936eed9404SViresh Kumar 	if (cpufreq_driver) {
1941da177e4SLinus Torvalds 		/* get the CPU */
1953a3e9e06SViresh Kumar 		policy = per_cpu(cpufreq_cpu_data, cpu);
1966eed9404SViresh Kumar 		if (policy)
1976eed9404SViresh Kumar 			kobject_get(&policy->kobj);
1986eed9404SViresh Kumar 	}
1996eed9404SViresh Kumar 
2006eed9404SViresh Kumar 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
2011da177e4SLinus Torvalds 
2023a3e9e06SViresh Kumar 	if (!policy)
2036eed9404SViresh Kumar 		up_read(&cpufreq_rwsem);
2041da177e4SLinus Torvalds 
2053a3e9e06SViresh Kumar 	return policy;
206a9144436SStephen Boyd }
2071da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
2081da177e4SLinus Torvalds 
2093a3e9e06SViresh Kumar void cpufreq_cpu_put(struct cpufreq_policy *policy)
210a9144436SStephen Boyd {
211d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
212d5aaffa9SDirk Brandewie 		return;
213d5aaffa9SDirk Brandewie 
2146eed9404SViresh Kumar 	kobject_put(&policy->kobj);
2156eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
216a9144436SStephen Boyd }
2171da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds /*********************************************************************
2201da177e4SLinus Torvalds  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
2211da177e4SLinus Torvalds  *********************************************************************/
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds /**
2241da177e4SLinus Torvalds  * adjust_jiffies - adjust the system "loops_per_jiffy"
2251da177e4SLinus Torvalds  *
2261da177e4SLinus Torvalds  * This function alters the system "loops_per_jiffy" for the clock
2271da177e4SLinus Torvalds  * speed change. Note that loops_per_jiffy cannot be updated on SMP
2281da177e4SLinus Torvalds  * systems as each CPU might be scaled differently. So, use the arch
2291da177e4SLinus Torvalds  * per-CPU loops_per_jiffy value wherever possible.
2301da177e4SLinus Torvalds  */
2311da177e4SLinus Torvalds #ifndef CONFIG_SMP
2321da177e4SLinus Torvalds static unsigned long l_p_j_ref;
2331da177e4SLinus Torvalds static unsigned int l_p_j_ref_freq;
2341da177e4SLinus Torvalds 
235858119e1SArjan van de Ven static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
2361da177e4SLinus Torvalds {
2371da177e4SLinus Torvalds 	if (ci->flags & CPUFREQ_CONST_LOOPS)
2381da177e4SLinus Torvalds 		return;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	if (!l_p_j_ref_freq) {
2411da177e4SLinus Torvalds 		l_p_j_ref = loops_per_jiffy;
2421da177e4SLinus Torvalds 		l_p_j_ref_freq = ci->old;
2432d06d8c4SDominik Brodowski 		pr_debug("saving %lu as reference value for loops_per_jiffy; "
244e08f5f5bSGautham R Shenoy 			"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
2451da177e4SLinus Torvalds 	}
246d08de0c1SAfzal Mohammed 	if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
24742d4dc3fSBenjamin Herrenschmidt 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
248e08f5f5bSGautham R Shenoy 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
249e08f5f5bSGautham R Shenoy 								ci->new);
2502d06d8c4SDominik Brodowski 		pr_debug("scaling loops_per_jiffy to %lu "
251e08f5f5bSGautham R Shenoy 			"for frequency %u kHz\n", loops_per_jiffy, ci->new);
2521da177e4SLinus Torvalds 	}
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds #else
255e08f5f5bSGautham R Shenoy static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
256e08f5f5bSGautham R Shenoy {
257e08f5f5bSGautham R Shenoy 	return;
258e08f5f5bSGautham R Shenoy }
2591da177e4SLinus Torvalds #endif
2601da177e4SLinus Torvalds 
2610956df9cSViresh Kumar static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
262b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
2631da177e4SLinus Torvalds {
2641da177e4SLinus Torvalds 	BUG_ON(irqs_disabled());
2651da177e4SLinus Torvalds 
266d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
267d5aaffa9SDirk Brandewie 		return;
268d5aaffa9SDirk Brandewie 
2691c3d85ddSRafael J. Wysocki 	freqs->flags = cpufreq_driver->flags;
2702d06d8c4SDominik Brodowski 	pr_debug("notification %u of frequency transition to %u kHz\n",
271e4472cb3SDave Jones 		state, freqs->new);
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds 	switch (state) {
274e4472cb3SDave Jones 
2751da177e4SLinus Torvalds 	case CPUFREQ_PRECHANGE:
276e4472cb3SDave Jones 		/* detect if the driver reported a value as "old frequency"
277e4472cb3SDave Jones 		 * which is not equal to what the cpufreq core thinks is
278e4472cb3SDave Jones 		 * "old frequency".
2791da177e4SLinus Torvalds 		 */
2801c3d85ddSRafael J. Wysocki 		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
281e4472cb3SDave Jones 			if ((policy) && (policy->cpu == freqs->cpu) &&
282e4472cb3SDave Jones 			    (policy->cur) && (policy->cur != freqs->old)) {
2832d06d8c4SDominik Brodowski 				pr_debug("Warning: CPU frequency is"
284e4472cb3SDave Jones 					" %u, cpufreq assumed %u kHz.\n",
285e4472cb3SDave Jones 					freqs->old, policy->cur);
286e4472cb3SDave Jones 				freqs->old = policy->cur;
2871da177e4SLinus Torvalds 			}
2881da177e4SLinus Torvalds 		}
289b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
290e4472cb3SDave Jones 				CPUFREQ_PRECHANGE, freqs);
2911da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
2921da177e4SLinus Torvalds 		break;
293e4472cb3SDave Jones 
2941da177e4SLinus Torvalds 	case CPUFREQ_POSTCHANGE:
2951da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
2962d06d8c4SDominik Brodowski 		pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
2976f4f2723SThomas Renninger 			(unsigned long)freqs->cpu);
29825e41933SThomas Renninger 		trace_cpu_frequency(freqs->new, freqs->cpu);
299b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
300e4472cb3SDave Jones 				CPUFREQ_POSTCHANGE, freqs);
301e4472cb3SDave Jones 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
302e4472cb3SDave Jones 			policy->cur = freqs->new;
3031da177e4SLinus Torvalds 		break;
3041da177e4SLinus Torvalds 	}
3051da177e4SLinus Torvalds }
306bb176f7dSViresh Kumar 
307b43a7ffbSViresh Kumar /**
308b43a7ffbSViresh Kumar  * cpufreq_notify_transition - call notifier chain and adjust_jiffies
309b43a7ffbSViresh Kumar  * on frequency transition.
310b43a7ffbSViresh Kumar  *
311b43a7ffbSViresh Kumar  * This function calls the transition notifiers and the "adjust_jiffies"
312b43a7ffbSViresh Kumar  * function. It is called twice on all CPU frequency changes that have
313b43a7ffbSViresh Kumar  * external effects.
314b43a7ffbSViresh Kumar  */
315b43a7ffbSViresh Kumar void cpufreq_notify_transition(struct cpufreq_policy *policy,
316b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
317b43a7ffbSViresh Kumar {
318b43a7ffbSViresh Kumar 	for_each_cpu(freqs->cpu, policy->cpus)
319b43a7ffbSViresh Kumar 		__cpufreq_notify_transition(policy, freqs, state);
320b43a7ffbSViresh Kumar }
3211da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
3221da177e4SLinus Torvalds 
323f7ba3b41SViresh Kumar /* Do post notifications when there are chances that transition has failed */
324f7ba3b41SViresh Kumar void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
325f7ba3b41SViresh Kumar 		struct cpufreq_freqs *freqs, int transition_failed)
326f7ba3b41SViresh Kumar {
327f7ba3b41SViresh Kumar 	cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
328f7ba3b41SViresh Kumar 	if (!transition_failed)
329f7ba3b41SViresh Kumar 		return;
330f7ba3b41SViresh Kumar 
331f7ba3b41SViresh Kumar 	swap(freqs->old, freqs->new);
332f7ba3b41SViresh Kumar 	cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
333f7ba3b41SViresh Kumar 	cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
334f7ba3b41SViresh Kumar }
335f7ba3b41SViresh Kumar EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
336f7ba3b41SViresh Kumar 
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds /*********************************************************************
3391da177e4SLinus Torvalds  *                          SYSFS INTERFACE                          *
3401da177e4SLinus Torvalds  *********************************************************************/
3411da177e4SLinus Torvalds 
3423bcb09a3SJeremy Fitzhardinge static struct cpufreq_governor *__find_governor(const char *str_governor)
3433bcb09a3SJeremy Fitzhardinge {
3443bcb09a3SJeremy Fitzhardinge 	struct cpufreq_governor *t;
3453bcb09a3SJeremy Fitzhardinge 
3463bcb09a3SJeremy Fitzhardinge 	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
3473bcb09a3SJeremy Fitzhardinge 		if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN))
3483bcb09a3SJeremy Fitzhardinge 			return t;
3493bcb09a3SJeremy Fitzhardinge 
3503bcb09a3SJeremy Fitzhardinge 	return NULL;
3513bcb09a3SJeremy Fitzhardinge }
3523bcb09a3SJeremy Fitzhardinge 
3531da177e4SLinus Torvalds /**
3541da177e4SLinus Torvalds  * cpufreq_parse_governor - parse a governor string
3551da177e4SLinus Torvalds  */
3561da177e4SLinus Torvalds static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
3571da177e4SLinus Torvalds 				struct cpufreq_governor **governor)
3581da177e4SLinus Torvalds {
3593bcb09a3SJeremy Fitzhardinge 	int err = -EINVAL;
3603bcb09a3SJeremy Fitzhardinge 
3611c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver)
3623bcb09a3SJeremy Fitzhardinge 		goto out;
3633bcb09a3SJeremy Fitzhardinge 
3641c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->setpolicy) {
3651da177e4SLinus Torvalds 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
3661da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_PERFORMANCE;
3673bcb09a3SJeremy Fitzhardinge 			err = 0;
368e08f5f5bSGautham R Shenoy 		} else if (!strnicmp(str_governor, "powersave",
369e08f5f5bSGautham R Shenoy 						CPUFREQ_NAME_LEN)) {
3701da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_POWERSAVE;
3713bcb09a3SJeremy Fitzhardinge 			err = 0;
3721da177e4SLinus Torvalds 		}
3739c0ebcf7SViresh Kumar 	} else if (has_target()) {
3741da177e4SLinus Torvalds 		struct cpufreq_governor *t;
3753bcb09a3SJeremy Fitzhardinge 
3763fc54d37Sakpm@osdl.org 		mutex_lock(&cpufreq_governor_mutex);
3773bcb09a3SJeremy Fitzhardinge 
3783bcb09a3SJeremy Fitzhardinge 		t = __find_governor(str_governor);
3793bcb09a3SJeremy Fitzhardinge 
380ea714970SJeremy Fitzhardinge 		if (t == NULL) {
381ea714970SJeremy Fitzhardinge 			int ret;
382ea714970SJeremy Fitzhardinge 
383ea714970SJeremy Fitzhardinge 			mutex_unlock(&cpufreq_governor_mutex);
3841a8e1463SKees Cook 			ret = request_module("cpufreq_%s", str_governor);
385ea714970SJeremy Fitzhardinge 			mutex_lock(&cpufreq_governor_mutex);
386ea714970SJeremy Fitzhardinge 
387ea714970SJeremy Fitzhardinge 			if (ret == 0)
388ea714970SJeremy Fitzhardinge 				t = __find_governor(str_governor);
389ea714970SJeremy Fitzhardinge 		}
390ea714970SJeremy Fitzhardinge 
3913bcb09a3SJeremy Fitzhardinge 		if (t != NULL) {
3921da177e4SLinus Torvalds 			*governor = t;
3933bcb09a3SJeremy Fitzhardinge 			err = 0;
3941da177e4SLinus Torvalds 		}
3953bcb09a3SJeremy Fitzhardinge 
3963bcb09a3SJeremy Fitzhardinge 		mutex_unlock(&cpufreq_governor_mutex);
3971da177e4SLinus Torvalds 	}
3981da177e4SLinus Torvalds out:
3993bcb09a3SJeremy Fitzhardinge 	return err;
4001da177e4SLinus Torvalds }
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds /**
403e08f5f5bSGautham R Shenoy  * cpufreq_per_cpu_attr_read() / show_##file_name() -
404e08f5f5bSGautham R Shenoy  * print out cpufreq information
4051da177e4SLinus Torvalds  *
4061da177e4SLinus Torvalds  * Write out information from cpufreq_driver->policy[cpu]; object must be
4071da177e4SLinus Torvalds  * "unsigned int".
4081da177e4SLinus Torvalds  */
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds #define show_one(file_name, object)			\
4111da177e4SLinus Torvalds static ssize_t show_##file_name				\
4121da177e4SLinus Torvalds (struct cpufreq_policy *policy, char *buf)		\
4131da177e4SLinus Torvalds {							\
4141da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", policy->object);	\
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds 
4171da177e4SLinus Torvalds show_one(cpuinfo_min_freq, cpuinfo.min_freq);
4181da177e4SLinus Torvalds show_one(cpuinfo_max_freq, cpuinfo.max_freq);
419ed129784SThomas Renninger show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
4201da177e4SLinus Torvalds show_one(scaling_min_freq, min);
4211da177e4SLinus Torvalds show_one(scaling_max_freq, max);
4221da177e4SLinus Torvalds show_one(scaling_cur_freq, cur);
4231da177e4SLinus Torvalds 
424037ce839SViresh Kumar static int cpufreq_set_policy(struct cpufreq_policy *policy,
4253a3e9e06SViresh Kumar 				struct cpufreq_policy *new_policy);
4267970e08bSThomas Renninger 
4271da177e4SLinus Torvalds /**
4281da177e4SLinus Torvalds  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
4291da177e4SLinus Torvalds  */
4301da177e4SLinus Torvalds #define store_one(file_name, object)			\
4311da177e4SLinus Torvalds static ssize_t store_##file_name					\
4321da177e4SLinus Torvalds (struct cpufreq_policy *policy, const char *buf, size_t count)		\
4331da177e4SLinus Torvalds {									\
4345136fa56SSrivatsa S. Bhat 	int ret;							\
4351da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;				\
4361da177e4SLinus Torvalds 									\
4371da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
4381da177e4SLinus Torvalds 	if (ret)							\
4391da177e4SLinus Torvalds 		return -EINVAL;						\
4401da177e4SLinus Torvalds 									\
4411da177e4SLinus Torvalds 	ret = sscanf(buf, "%u", &new_policy.object);			\
4421da177e4SLinus Torvalds 	if (ret != 1)							\
4431da177e4SLinus Torvalds 		return -EINVAL;						\
4441da177e4SLinus Torvalds 									\
445037ce839SViresh Kumar 	ret = cpufreq_set_policy(policy, &new_policy);		\
4467970e08bSThomas Renninger 	policy->user_policy.object = policy->object;			\
4471da177e4SLinus Torvalds 									\
4481da177e4SLinus Torvalds 	return ret ? ret : count;					\
4491da177e4SLinus Torvalds }
4501da177e4SLinus Torvalds 
4511da177e4SLinus Torvalds store_one(scaling_min_freq, min);
4521da177e4SLinus Torvalds store_one(scaling_max_freq, max);
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds /**
4551da177e4SLinus Torvalds  * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
4561da177e4SLinus Torvalds  */
457e08f5f5bSGautham R Shenoy static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
458e08f5f5bSGautham R Shenoy 					char *buf)
4591da177e4SLinus Torvalds {
4605a01f2e8SVenkatesh Pallipadi 	unsigned int cur_freq = __cpufreq_get(policy->cpu);
4611da177e4SLinus Torvalds 	if (!cur_freq)
4621da177e4SLinus Torvalds 		return sprintf(buf, "<unknown>");
4631da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", cur_freq);
4641da177e4SLinus Torvalds }
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds /**
4671da177e4SLinus Torvalds  * show_scaling_governor - show the current policy for the specified CPU
4681da177e4SLinus Torvalds  */
469905d77cdSDave Jones static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
4701da177e4SLinus Torvalds {
4711da177e4SLinus Torvalds 	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
4721da177e4SLinus Torvalds 		return sprintf(buf, "powersave\n");
4731da177e4SLinus Torvalds 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
4741da177e4SLinus Torvalds 		return sprintf(buf, "performance\n");
4751da177e4SLinus Torvalds 	else if (policy->governor)
4764b972f0bSviresh kumar 		return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
47729464f28SDave Jones 				policy->governor->name);
4781da177e4SLinus Torvalds 	return -EINVAL;
4791da177e4SLinus Torvalds }
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds /**
4821da177e4SLinus Torvalds  * store_scaling_governor - store policy for the specified CPU
4831da177e4SLinus Torvalds  */
4841da177e4SLinus Torvalds static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
4851da177e4SLinus Torvalds 					const char *buf, size_t count)
4861da177e4SLinus Torvalds {
4875136fa56SSrivatsa S. Bhat 	int ret;
4881da177e4SLinus Torvalds 	char	str_governor[16];
4891da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);
4921da177e4SLinus Torvalds 	if (ret)
4931da177e4SLinus Torvalds 		return ret;
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds 	ret = sscanf(buf, "%15s", str_governor);
4961da177e4SLinus Torvalds 	if (ret != 1)
4971da177e4SLinus Torvalds 		return -EINVAL;
4981da177e4SLinus Torvalds 
499e08f5f5bSGautham R Shenoy 	if (cpufreq_parse_governor(str_governor, &new_policy.policy,
500e08f5f5bSGautham R Shenoy 						&new_policy.governor))
5011da177e4SLinus Torvalds 		return -EINVAL;
5021da177e4SLinus Torvalds 
503037ce839SViresh Kumar 	ret = cpufreq_set_policy(policy, &new_policy);
5047970e08bSThomas Renninger 
5057970e08bSThomas Renninger 	policy->user_policy.policy = policy->policy;
5067970e08bSThomas Renninger 	policy->user_policy.governor = policy->governor;
5077970e08bSThomas Renninger 
508e08f5f5bSGautham R Shenoy 	if (ret)
509e08f5f5bSGautham R Shenoy 		return ret;
510e08f5f5bSGautham R Shenoy 	else
511e08f5f5bSGautham R Shenoy 		return count;
5121da177e4SLinus Torvalds }
5131da177e4SLinus Torvalds 
5141da177e4SLinus Torvalds /**
5151da177e4SLinus Torvalds  * show_scaling_driver - show the cpufreq driver currently loaded
5161da177e4SLinus Torvalds  */
5171da177e4SLinus Torvalds static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
5181da177e4SLinus Torvalds {
5191c3d85ddSRafael J. Wysocki 	return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
5201da177e4SLinus Torvalds }
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds /**
5231da177e4SLinus Torvalds  * show_scaling_available_governors - show the available CPUfreq governors
5241da177e4SLinus Torvalds  */
5251da177e4SLinus Torvalds static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
5261da177e4SLinus Torvalds 						char *buf)
5271da177e4SLinus Torvalds {
5281da177e4SLinus Torvalds 	ssize_t i = 0;
5291da177e4SLinus Torvalds 	struct cpufreq_governor *t;
5301da177e4SLinus Torvalds 
5319c0ebcf7SViresh Kumar 	if (!has_target()) {
5321da177e4SLinus Torvalds 		i += sprintf(buf, "performance powersave");
5331da177e4SLinus Torvalds 		goto out;
5341da177e4SLinus Torvalds 	}
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
53729464f28SDave Jones 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
53829464f28SDave Jones 		    - (CPUFREQ_NAME_LEN + 2)))
5391da177e4SLinus Torvalds 			goto out;
5404b972f0bSviresh kumar 		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
5411da177e4SLinus Torvalds 	}
5421da177e4SLinus Torvalds out:
5431da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
5441da177e4SLinus Torvalds 	return i;
5451da177e4SLinus Torvalds }
546e8628dd0SDarrick J. Wong 
547f4fd3797SLan Tianyu ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf)
5481da177e4SLinus Torvalds {
5491da177e4SLinus Torvalds 	ssize_t i = 0;
5501da177e4SLinus Torvalds 	unsigned int cpu;
5511da177e4SLinus Torvalds 
552835481d9SRusty Russell 	for_each_cpu(cpu, mask) {
5531da177e4SLinus Torvalds 		if (i)
5541da177e4SLinus Torvalds 			i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
5551da177e4SLinus Torvalds 		i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
5561da177e4SLinus Torvalds 		if (i >= (PAGE_SIZE - 5))
5571da177e4SLinus Torvalds 			break;
5581da177e4SLinus Torvalds 	}
5591da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
5601da177e4SLinus Torvalds 	return i;
5611da177e4SLinus Torvalds }
562f4fd3797SLan Tianyu EXPORT_SYMBOL_GPL(cpufreq_show_cpus);
5631da177e4SLinus Torvalds 
564e8628dd0SDarrick J. Wong /**
565e8628dd0SDarrick J. Wong  * show_related_cpus - show the CPUs affected by each transition even if
566e8628dd0SDarrick J. Wong  * hw coordination is in use
567e8628dd0SDarrick J. Wong  */
568e8628dd0SDarrick J. Wong static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
569e8628dd0SDarrick J. Wong {
570f4fd3797SLan Tianyu 	return cpufreq_show_cpus(policy->related_cpus, buf);
571e8628dd0SDarrick J. Wong }
572e8628dd0SDarrick J. Wong 
573e8628dd0SDarrick J. Wong /**
574e8628dd0SDarrick J. Wong  * show_affected_cpus - show the CPUs affected by each transition
575e8628dd0SDarrick J. Wong  */
576e8628dd0SDarrick J. Wong static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
577e8628dd0SDarrick J. Wong {
578f4fd3797SLan Tianyu 	return cpufreq_show_cpus(policy->cpus, buf);
579e8628dd0SDarrick J. Wong }
580e8628dd0SDarrick J. Wong 
5819e76988eSVenki Pallipadi static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
5829e76988eSVenki Pallipadi 					const char *buf, size_t count)
5839e76988eSVenki Pallipadi {
5849e76988eSVenki Pallipadi 	unsigned int freq = 0;
5859e76988eSVenki Pallipadi 	unsigned int ret;
5869e76988eSVenki Pallipadi 
587879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->store_setspeed)
5889e76988eSVenki Pallipadi 		return -EINVAL;
5899e76988eSVenki Pallipadi 
5909e76988eSVenki Pallipadi 	ret = sscanf(buf, "%u", &freq);
5919e76988eSVenki Pallipadi 	if (ret != 1)
5929e76988eSVenki Pallipadi 		return -EINVAL;
5939e76988eSVenki Pallipadi 
5949e76988eSVenki Pallipadi 	policy->governor->store_setspeed(policy, freq);
5959e76988eSVenki Pallipadi 
5969e76988eSVenki Pallipadi 	return count;
5979e76988eSVenki Pallipadi }
5989e76988eSVenki Pallipadi 
5999e76988eSVenki Pallipadi static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
6009e76988eSVenki Pallipadi {
601879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->show_setspeed)
6029e76988eSVenki Pallipadi 		return sprintf(buf, "<unsupported>\n");
6039e76988eSVenki Pallipadi 
6049e76988eSVenki Pallipadi 	return policy->governor->show_setspeed(policy, buf);
6059e76988eSVenki Pallipadi }
6061da177e4SLinus Torvalds 
607e2f74f35SThomas Renninger /**
6088bf1ac72Sviresh kumar  * show_bios_limit - show the current cpufreq HW/BIOS limitation
609e2f74f35SThomas Renninger  */
610e2f74f35SThomas Renninger static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
611e2f74f35SThomas Renninger {
612e2f74f35SThomas Renninger 	unsigned int limit;
613e2f74f35SThomas Renninger 	int ret;
6141c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->bios_limit) {
6151c3d85ddSRafael J. Wysocki 		ret = cpufreq_driver->bios_limit(policy->cpu, &limit);
616e2f74f35SThomas Renninger 		if (!ret)
617e2f74f35SThomas Renninger 			return sprintf(buf, "%u\n", limit);
618e2f74f35SThomas Renninger 	}
619e2f74f35SThomas Renninger 	return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
620e2f74f35SThomas Renninger }
621e2f74f35SThomas Renninger 
6226dad2a29SBorislav Petkov cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
6236dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_min_freq);
6246dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_max_freq);
6256dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_transition_latency);
6266dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_available_governors);
6276dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_driver);
6286dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_cur_freq);
6296dad2a29SBorislav Petkov cpufreq_freq_attr_ro(bios_limit);
6306dad2a29SBorislav Petkov cpufreq_freq_attr_ro(related_cpus);
6316dad2a29SBorislav Petkov cpufreq_freq_attr_ro(affected_cpus);
6326dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_min_freq);
6336dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_max_freq);
6346dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_governor);
6356dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_setspeed);
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds static struct attribute *default_attrs[] = {
6381da177e4SLinus Torvalds 	&cpuinfo_min_freq.attr,
6391da177e4SLinus Torvalds 	&cpuinfo_max_freq.attr,
640ed129784SThomas Renninger 	&cpuinfo_transition_latency.attr,
6411da177e4SLinus Torvalds 	&scaling_min_freq.attr,
6421da177e4SLinus Torvalds 	&scaling_max_freq.attr,
6431da177e4SLinus Torvalds 	&affected_cpus.attr,
644e8628dd0SDarrick J. Wong 	&related_cpus.attr,
6451da177e4SLinus Torvalds 	&scaling_governor.attr,
6461da177e4SLinus Torvalds 	&scaling_driver.attr,
6471da177e4SLinus Torvalds 	&scaling_available_governors.attr,
6489e76988eSVenki Pallipadi 	&scaling_setspeed.attr,
6491da177e4SLinus Torvalds 	NULL
6501da177e4SLinus Torvalds };
6511da177e4SLinus Torvalds 
6521da177e4SLinus Torvalds #define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
6531da177e4SLinus Torvalds #define to_attr(a) container_of(a, struct freq_attr, attr)
6541da177e4SLinus Torvalds 
6551da177e4SLinus Torvalds static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
6561da177e4SLinus Torvalds {
6571da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
6581da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
6591b750e3bSViresh Kumar 	ssize_t ret;
6606eed9404SViresh Kumar 
6616eed9404SViresh Kumar 	if (!down_read_trylock(&cpufreq_rwsem))
6621b750e3bSViresh Kumar 		return -EINVAL;
6635a01f2e8SVenkatesh Pallipadi 
664ad7722daSviresh kumar 	down_read(&policy->rwsem);
6655a01f2e8SVenkatesh Pallipadi 
666e08f5f5bSGautham R Shenoy 	if (fattr->show)
667e08f5f5bSGautham R Shenoy 		ret = fattr->show(policy, buf);
668e08f5f5bSGautham R Shenoy 	else
669e08f5f5bSGautham R Shenoy 		ret = -EIO;
670e08f5f5bSGautham R Shenoy 
671ad7722daSviresh kumar 	up_read(&policy->rwsem);
6726eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
6731b750e3bSViresh Kumar 
6741da177e4SLinus Torvalds 	return ret;
6751da177e4SLinus Torvalds }
6761da177e4SLinus Torvalds 
6771da177e4SLinus Torvalds static ssize_t store(struct kobject *kobj, struct attribute *attr,
6781da177e4SLinus Torvalds 		     const char *buf, size_t count)
6791da177e4SLinus Torvalds {
6801da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
6811da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
682a07530b4SDave Jones 	ssize_t ret = -EINVAL;
6836eed9404SViresh Kumar 
6844f750c93SSrivatsa S. Bhat 	get_online_cpus();
6854f750c93SSrivatsa S. Bhat 
6864f750c93SSrivatsa S. Bhat 	if (!cpu_online(policy->cpu))
6874f750c93SSrivatsa S. Bhat 		goto unlock;
6884f750c93SSrivatsa S. Bhat 
6896eed9404SViresh Kumar 	if (!down_read_trylock(&cpufreq_rwsem))
6904f750c93SSrivatsa S. Bhat 		goto unlock;
6915a01f2e8SVenkatesh Pallipadi 
692ad7722daSviresh kumar 	down_write(&policy->rwsem);
6935a01f2e8SVenkatesh Pallipadi 
694e08f5f5bSGautham R Shenoy 	if (fattr->store)
695e08f5f5bSGautham R Shenoy 		ret = fattr->store(policy, buf, count);
696e08f5f5bSGautham R Shenoy 	else
697e08f5f5bSGautham R Shenoy 		ret = -EIO;
698e08f5f5bSGautham R Shenoy 
699ad7722daSviresh kumar 	up_write(&policy->rwsem);
7006eed9404SViresh Kumar 
7016eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
7024f750c93SSrivatsa S. Bhat unlock:
7034f750c93SSrivatsa S. Bhat 	put_online_cpus();
7044f750c93SSrivatsa S. Bhat 
7051da177e4SLinus Torvalds 	return ret;
7061da177e4SLinus Torvalds }
7071da177e4SLinus Torvalds 
7081da177e4SLinus Torvalds static void cpufreq_sysfs_release(struct kobject *kobj)
7091da177e4SLinus Torvalds {
7101da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7112d06d8c4SDominik Brodowski 	pr_debug("last reference is dropped\n");
7121da177e4SLinus Torvalds 	complete(&policy->kobj_unregister);
7131da177e4SLinus Torvalds }
7141da177e4SLinus Torvalds 
71552cf25d0SEmese Revfy static const struct sysfs_ops sysfs_ops = {
7161da177e4SLinus Torvalds 	.show	= show,
7171da177e4SLinus Torvalds 	.store	= store,
7181da177e4SLinus Torvalds };
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds static struct kobj_type ktype_cpufreq = {
7211da177e4SLinus Torvalds 	.sysfs_ops	= &sysfs_ops,
7221da177e4SLinus Torvalds 	.default_attrs	= default_attrs,
7231da177e4SLinus Torvalds 	.release	= cpufreq_sysfs_release,
7241da177e4SLinus Torvalds };
7251da177e4SLinus Torvalds 
7262361be23SViresh Kumar struct kobject *cpufreq_global_kobject;
7272361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_global_kobject);
7282361be23SViresh Kumar 
7292361be23SViresh Kumar static int cpufreq_global_kobject_usage;
7302361be23SViresh Kumar 
7312361be23SViresh Kumar int cpufreq_get_global_kobject(void)
7322361be23SViresh Kumar {
7332361be23SViresh Kumar 	if (!cpufreq_global_kobject_usage++)
7342361be23SViresh Kumar 		return kobject_add(cpufreq_global_kobject,
7352361be23SViresh Kumar 				&cpu_subsys.dev_root->kobj, "%s", "cpufreq");
7362361be23SViresh Kumar 
7372361be23SViresh Kumar 	return 0;
7382361be23SViresh Kumar }
7392361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_get_global_kobject);
7402361be23SViresh Kumar 
7412361be23SViresh Kumar void cpufreq_put_global_kobject(void)
7422361be23SViresh Kumar {
7432361be23SViresh Kumar 	if (!--cpufreq_global_kobject_usage)
7442361be23SViresh Kumar 		kobject_del(cpufreq_global_kobject);
7452361be23SViresh Kumar }
7462361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_put_global_kobject);
7472361be23SViresh Kumar 
7482361be23SViresh Kumar int cpufreq_sysfs_create_file(const struct attribute *attr)
7492361be23SViresh Kumar {
7502361be23SViresh Kumar 	int ret = cpufreq_get_global_kobject();
7512361be23SViresh Kumar 
7522361be23SViresh Kumar 	if (!ret) {
7532361be23SViresh Kumar 		ret = sysfs_create_file(cpufreq_global_kobject, attr);
7542361be23SViresh Kumar 		if (ret)
7552361be23SViresh Kumar 			cpufreq_put_global_kobject();
7562361be23SViresh Kumar 	}
7572361be23SViresh Kumar 
7582361be23SViresh Kumar 	return ret;
7592361be23SViresh Kumar }
7602361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_create_file);
7612361be23SViresh Kumar 
7622361be23SViresh Kumar void cpufreq_sysfs_remove_file(const struct attribute *attr)
7632361be23SViresh Kumar {
7642361be23SViresh Kumar 	sysfs_remove_file(cpufreq_global_kobject, attr);
7652361be23SViresh Kumar 	cpufreq_put_global_kobject();
7662361be23SViresh Kumar }
7672361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_remove_file);
7682361be23SViresh Kumar 
76919d6f7ecSDave Jones /* symlink affected CPUs */
770308b60e7SViresh Kumar static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy)
77119d6f7ecSDave Jones {
77219d6f7ecSDave Jones 	unsigned int j;
77319d6f7ecSDave Jones 	int ret = 0;
77419d6f7ecSDave Jones 
77519d6f7ecSDave Jones 	for_each_cpu(j, policy->cpus) {
7768a25a2fdSKay Sievers 		struct device *cpu_dev;
77719d6f7ecSDave Jones 
778308b60e7SViresh Kumar 		if (j == policy->cpu)
77919d6f7ecSDave Jones 			continue;
78019d6f7ecSDave Jones 
781e8fdde10SViresh Kumar 		pr_debug("Adding link for CPU: %u\n", j);
7828a25a2fdSKay Sievers 		cpu_dev = get_cpu_device(j);
7838a25a2fdSKay Sievers 		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
78419d6f7ecSDave Jones 					"cpufreq");
78571c3461eSRafael J. Wysocki 		if (ret)
78671c3461eSRafael J. Wysocki 			break;
78719d6f7ecSDave Jones 	}
78819d6f7ecSDave Jones 	return ret;
78919d6f7ecSDave Jones }
79019d6f7ecSDave Jones 
791308b60e7SViresh Kumar static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
7928a25a2fdSKay Sievers 				     struct device *dev)
793909a694eSDave Jones {
794909a694eSDave Jones 	struct freq_attr **drv_attr;
795909a694eSDave Jones 	int ret = 0;
796909a694eSDave Jones 
797909a694eSDave Jones 	/* prepare interface data */
798909a694eSDave Jones 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
7998a25a2fdSKay Sievers 				   &dev->kobj, "cpufreq");
800909a694eSDave Jones 	if (ret)
801909a694eSDave Jones 		return ret;
802909a694eSDave Jones 
803909a694eSDave Jones 	/* set up files for this cpu device */
8041c3d85ddSRafael J. Wysocki 	drv_attr = cpufreq_driver->attr;
805909a694eSDave Jones 	while ((drv_attr) && (*drv_attr)) {
806909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
807909a694eSDave Jones 		if (ret)
8081c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
809909a694eSDave Jones 		drv_attr++;
810909a694eSDave Jones 	}
8111c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->get) {
812909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
813909a694eSDave Jones 		if (ret)
8141c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
815909a694eSDave Jones 	}
8169c0ebcf7SViresh Kumar 	if (has_target()) {
817909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
818909a694eSDave Jones 		if (ret)
8191c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
820909a694eSDave Jones 	}
8211c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->bios_limit) {
822e2f74f35SThomas Renninger 		ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
823e2f74f35SThomas Renninger 		if (ret)
8241c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
825e2f74f35SThomas Renninger 	}
826909a694eSDave Jones 
827308b60e7SViresh Kumar 	ret = cpufreq_add_dev_symlink(policy);
828ecf7e461SDave Jones 	if (ret)
829ecf7e461SDave Jones 		goto err_out_kobj_put;
830ecf7e461SDave Jones 
831e18f1682SSrivatsa S. Bhat 	return ret;
832e18f1682SSrivatsa S. Bhat 
833e18f1682SSrivatsa S. Bhat err_out_kobj_put:
834e18f1682SSrivatsa S. Bhat 	kobject_put(&policy->kobj);
835e18f1682SSrivatsa S. Bhat 	wait_for_completion(&policy->kobj_unregister);
836e18f1682SSrivatsa S. Bhat 	return ret;
837e18f1682SSrivatsa S. Bhat }
838e18f1682SSrivatsa S. Bhat 
839e18f1682SSrivatsa S. Bhat static void cpufreq_init_policy(struct cpufreq_policy *policy)
840e18f1682SSrivatsa S. Bhat {
841e18f1682SSrivatsa S. Bhat 	struct cpufreq_policy new_policy;
842e18f1682SSrivatsa S. Bhat 	int ret = 0;
843e18f1682SSrivatsa S. Bhat 
844d5b73cd8SViresh Kumar 	memcpy(&new_policy, policy, sizeof(*policy));
845a27a9ab7SJason Baron 
846a27a9ab7SJason Baron 	/* Use the default policy if its valid. */
847a27a9ab7SJason Baron 	if (cpufreq_driver->setpolicy)
848a27a9ab7SJason Baron 		cpufreq_parse_governor(policy->governor->name,
849a27a9ab7SJason Baron 					&new_policy.policy, NULL);
850a27a9ab7SJason Baron 
851037ce839SViresh Kumar 	/* assure that the starting sequence is run in cpufreq_set_policy */
852ecf7e461SDave Jones 	policy->governor = NULL;
853ecf7e461SDave Jones 
854ecf7e461SDave Jones 	/* set default policy */
855037ce839SViresh Kumar 	ret = cpufreq_set_policy(policy, &new_policy);
856ecf7e461SDave Jones 	if (ret) {
8572d06d8c4SDominik Brodowski 		pr_debug("setting policy failed\n");
8581c3d85ddSRafael J. Wysocki 		if (cpufreq_driver->exit)
8591c3d85ddSRafael J. Wysocki 			cpufreq_driver->exit(policy);
860ecf7e461SDave Jones 	}
861909a694eSDave Jones }
862909a694eSDave Jones 
863fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
864d8d3b471SViresh Kumar static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
86542f921a6SViresh Kumar 				  unsigned int cpu, struct device *dev)
866fcf80582SViresh Kumar {
8679c0ebcf7SViresh Kumar 	int ret = 0;
868fcf80582SViresh Kumar 	unsigned long flags;
869fcf80582SViresh Kumar 
8709c0ebcf7SViresh Kumar 	if (has_target()) {
8713de9bdebSViresh Kumar 		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
8723de9bdebSViresh Kumar 		if (ret) {
8733de9bdebSViresh Kumar 			pr_err("%s: Failed to stop governor\n", __func__);
8743de9bdebSViresh Kumar 			return ret;
8753de9bdebSViresh Kumar 		}
8763de9bdebSViresh Kumar 	}
877fcf80582SViresh Kumar 
878ad7722daSviresh kumar 	down_write(&policy->rwsem);
8792eaa3e2dSViresh Kumar 
8800d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
8812eaa3e2dSViresh Kumar 
882fcf80582SViresh Kumar 	cpumask_set_cpu(cpu, policy->cpus);
883fcf80582SViresh Kumar 	per_cpu(cpufreq_cpu_data, cpu) = policy;
8840d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
885fcf80582SViresh Kumar 
886ad7722daSviresh kumar 	up_write(&policy->rwsem);
8872eaa3e2dSViresh Kumar 
8889c0ebcf7SViresh Kumar 	if (has_target()) {
8893de9bdebSViresh Kumar 		if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
8903de9bdebSViresh Kumar 			(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
8913de9bdebSViresh Kumar 			pr_err("%s: Failed to start governor\n", __func__);
8923de9bdebSViresh Kumar 			return ret;
8933de9bdebSViresh Kumar 		}
894820c6ca2SViresh Kumar 	}
895fcf80582SViresh Kumar 
89642f921a6SViresh Kumar 	return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
897fcf80582SViresh Kumar }
898fcf80582SViresh Kumar #endif
8991da177e4SLinus Torvalds 
9008414809cSSrivatsa S. Bhat static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
9018414809cSSrivatsa S. Bhat {
9028414809cSSrivatsa S. Bhat 	struct cpufreq_policy *policy;
9038414809cSSrivatsa S. Bhat 	unsigned long flags;
9048414809cSSrivatsa S. Bhat 
90544871c9cSLan Tianyu 	read_lock_irqsave(&cpufreq_driver_lock, flags);
9068414809cSSrivatsa S. Bhat 
9078414809cSSrivatsa S. Bhat 	policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
9088414809cSSrivatsa S. Bhat 
90944871c9cSLan Tianyu 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
9108414809cSSrivatsa S. Bhat 
9118414809cSSrivatsa S. Bhat 	return policy;
9128414809cSSrivatsa S. Bhat }
9138414809cSSrivatsa S. Bhat 
914e9698cc5SSrivatsa S. Bhat static struct cpufreq_policy *cpufreq_policy_alloc(void)
915e9698cc5SSrivatsa S. Bhat {
916e9698cc5SSrivatsa S. Bhat 	struct cpufreq_policy *policy;
917e9698cc5SSrivatsa S. Bhat 
918e9698cc5SSrivatsa S. Bhat 	policy = kzalloc(sizeof(*policy), GFP_KERNEL);
919e9698cc5SSrivatsa S. Bhat 	if (!policy)
920e9698cc5SSrivatsa S. Bhat 		return NULL;
921e9698cc5SSrivatsa S. Bhat 
922e9698cc5SSrivatsa S. Bhat 	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
923e9698cc5SSrivatsa S. Bhat 		goto err_free_policy;
924e9698cc5SSrivatsa S. Bhat 
925e9698cc5SSrivatsa S. Bhat 	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
926e9698cc5SSrivatsa S. Bhat 		goto err_free_cpumask;
927e9698cc5SSrivatsa S. Bhat 
928c88a1f8bSLukasz Majewski 	INIT_LIST_HEAD(&policy->policy_list);
929ad7722daSviresh kumar 	init_rwsem(&policy->rwsem);
930ad7722daSviresh kumar 
931e9698cc5SSrivatsa S. Bhat 	return policy;
932e9698cc5SSrivatsa S. Bhat 
933e9698cc5SSrivatsa S. Bhat err_free_cpumask:
934e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->cpus);
935e9698cc5SSrivatsa S. Bhat err_free_policy:
936e9698cc5SSrivatsa S. Bhat 	kfree(policy);
937e9698cc5SSrivatsa S. Bhat 
938e9698cc5SSrivatsa S. Bhat 	return NULL;
939e9698cc5SSrivatsa S. Bhat }
940e9698cc5SSrivatsa S. Bhat 
94142f921a6SViresh Kumar static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
94242f921a6SViresh Kumar {
94342f921a6SViresh Kumar 	struct kobject *kobj;
94442f921a6SViresh Kumar 	struct completion *cmp;
94542f921a6SViresh Kumar 
946*fcd7af91SViresh Kumar 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
947*fcd7af91SViresh Kumar 			CPUFREQ_REMOVE_POLICY, policy);
948*fcd7af91SViresh Kumar 
94942f921a6SViresh Kumar 	down_read(&policy->rwsem);
95042f921a6SViresh Kumar 	kobj = &policy->kobj;
95142f921a6SViresh Kumar 	cmp = &policy->kobj_unregister;
95242f921a6SViresh Kumar 	up_read(&policy->rwsem);
95342f921a6SViresh Kumar 	kobject_put(kobj);
95442f921a6SViresh Kumar 
95542f921a6SViresh Kumar 	/*
95642f921a6SViresh Kumar 	 * We need to make sure that the underlying kobj is
95742f921a6SViresh Kumar 	 * actually not referenced anymore by anybody before we
95842f921a6SViresh Kumar 	 * proceed with unloading.
95942f921a6SViresh Kumar 	 */
96042f921a6SViresh Kumar 	pr_debug("waiting for dropping of refcount\n");
96142f921a6SViresh Kumar 	wait_for_completion(cmp);
96242f921a6SViresh Kumar 	pr_debug("wait complete\n");
96342f921a6SViresh Kumar }
96442f921a6SViresh Kumar 
965e9698cc5SSrivatsa S. Bhat static void cpufreq_policy_free(struct cpufreq_policy *policy)
966e9698cc5SSrivatsa S. Bhat {
967e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->related_cpus);
968e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->cpus);
969e9698cc5SSrivatsa S. Bhat 	kfree(policy);
970e9698cc5SSrivatsa S. Bhat }
971e9698cc5SSrivatsa S. Bhat 
9720d66b91eSSrivatsa S. Bhat static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
9730d66b91eSSrivatsa S. Bhat {
97499ec899eSSrivatsa S. Bhat 	if (WARN_ON(cpu == policy->cpu))
975cb38ed5cSSrivatsa S. Bhat 		return;
976cb38ed5cSSrivatsa S. Bhat 
977ad7722daSviresh kumar 	down_write(&policy->rwsem);
9788efd5765SViresh Kumar 
9790d66b91eSSrivatsa S. Bhat 	policy->last_cpu = policy->cpu;
9800d66b91eSSrivatsa S. Bhat 	policy->cpu = cpu;
9810d66b91eSSrivatsa S. Bhat 
982ad7722daSviresh kumar 	up_write(&policy->rwsem);
9838efd5765SViresh Kumar 
9840d66b91eSSrivatsa S. Bhat 	cpufreq_frequency_table_update_policy_cpu(policy);
9850d66b91eSSrivatsa S. Bhat 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
9860d66b91eSSrivatsa S. Bhat 			CPUFREQ_UPDATE_POLICY_CPU, policy);
9870d66b91eSSrivatsa S. Bhat }
9880d66b91eSSrivatsa S. Bhat 
989a82fab29SSrivatsa S. Bhat static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
990a82fab29SSrivatsa S. Bhat 			     bool frozen)
9911da177e4SLinus Torvalds {
992fcf80582SViresh Kumar 	unsigned int j, cpu = dev->id;
99365922465SViresh Kumar 	int ret = -ENOMEM;
9941da177e4SLinus Torvalds 	struct cpufreq_policy *policy;
9951da177e4SLinus Torvalds 	unsigned long flags;
99690e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
9971b274294SViresh Kumar 	struct cpufreq_policy *tpolicy;
998fcf80582SViresh Kumar 	struct cpufreq_governor *gov;
99990e41bacSPrarit Bhargava #endif
10001da177e4SLinus Torvalds 
1001c32b6b8eSAshok Raj 	if (cpu_is_offline(cpu))
1002c32b6b8eSAshok Raj 		return 0;
1003c32b6b8eSAshok Raj 
10042d06d8c4SDominik Brodowski 	pr_debug("adding CPU %u\n", cpu);
10051da177e4SLinus Torvalds 
10061da177e4SLinus Torvalds #ifdef CONFIG_SMP
10071da177e4SLinus Torvalds 	/* check whether a different CPU already registered this
10081da177e4SLinus Torvalds 	 * CPU because it is in the same boat. */
10091da177e4SLinus Torvalds 	policy = cpufreq_cpu_get(cpu);
10101da177e4SLinus Torvalds 	if (unlikely(policy)) {
10118ff69732SDave Jones 		cpufreq_cpu_put(policy);
10121da177e4SLinus Torvalds 		return 0;
10131da177e4SLinus Torvalds 	}
10145025d628SLi Zhong #endif
1015fcf80582SViresh Kumar 
10166eed9404SViresh Kumar 	if (!down_read_trylock(&cpufreq_rwsem))
10176eed9404SViresh Kumar 		return 0;
10186eed9404SViresh Kumar 
1019fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
1020fcf80582SViresh Kumar 	/* Check if this cpu was hot-unplugged earlier and has siblings */
10210d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
10221b274294SViresh Kumar 	list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
10231b274294SViresh Kumar 		if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
10240d1857a1SNathan Zimmer 			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
102542f921a6SViresh Kumar 			ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
10266eed9404SViresh Kumar 			up_read(&cpufreq_rwsem);
10276eed9404SViresh Kumar 			return ret;
1028fcf80582SViresh Kumar 		}
10292eaa3e2dSViresh Kumar 	}
10300d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1031fcf80582SViresh Kumar #endif
10321da177e4SLinus Torvalds 
103372368d12SRafael J. Wysocki 	/*
103472368d12SRafael J. Wysocki 	 * Restore the saved policy when doing light-weight init and fall back
103572368d12SRafael J. Wysocki 	 * to the full init if that fails.
103672368d12SRafael J. Wysocki 	 */
103772368d12SRafael J. Wysocki 	policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
103872368d12SRafael J. Wysocki 	if (!policy) {
103972368d12SRafael J. Wysocki 		frozen = false;
1040e9698cc5SSrivatsa S. Bhat 		policy = cpufreq_policy_alloc();
1041059019a3SDave Jones 		if (!policy)
10421da177e4SLinus Torvalds 			goto nomem_out;
104372368d12SRafael J. Wysocki 	}
10440d66b91eSSrivatsa S. Bhat 
10450d66b91eSSrivatsa S. Bhat 	/*
10460d66b91eSSrivatsa S. Bhat 	 * In the resume path, since we restore a saved policy, the assignment
10470d66b91eSSrivatsa S. Bhat 	 * to policy->cpu is like an update of the existing policy, rather than
10480d66b91eSSrivatsa S. Bhat 	 * the creation of a brand new one. So we need to perform this update
10490d66b91eSSrivatsa S. Bhat 	 * by invoking update_policy_cpu().
10500d66b91eSSrivatsa S. Bhat 	 */
10510d66b91eSSrivatsa S. Bhat 	if (frozen && cpu != policy->cpu)
10520d66b91eSSrivatsa S. Bhat 		update_policy_cpu(policy, cpu);
10530d66b91eSSrivatsa S. Bhat 	else
10541da177e4SLinus Torvalds 		policy->cpu = cpu;
10550d66b91eSSrivatsa S. Bhat 
105665922465SViresh Kumar 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
1057835481d9SRusty Russell 	cpumask_copy(policy->cpus, cpumask_of(cpu));
10581da177e4SLinus Torvalds 
10591da177e4SLinus Torvalds 	init_completion(&policy->kobj_unregister);
106065f27f38SDavid Howells 	INIT_WORK(&policy->update, handle_update);
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds 	/* call driver. From then on the cpufreq must be able
10631da177e4SLinus Torvalds 	 * to accept all calls to ->verify and ->setpolicy for this CPU
10641da177e4SLinus Torvalds 	 */
10651c3d85ddSRafael J. Wysocki 	ret = cpufreq_driver->init(policy);
10661da177e4SLinus Torvalds 	if (ret) {
10672d06d8c4SDominik Brodowski 		pr_debug("initialization failed\n");
10682eaa3e2dSViresh Kumar 		goto err_set_policy_cpu;
10691da177e4SLinus Torvalds 	}
1070643ae6e8SViresh Kumar 
1071da60ce9fSViresh Kumar 	if (cpufreq_driver->get) {
1072da60ce9fSViresh Kumar 		policy->cur = cpufreq_driver->get(policy->cpu);
1073da60ce9fSViresh Kumar 		if (!policy->cur) {
1074da60ce9fSViresh Kumar 			pr_err("%s: ->get() failed\n", __func__);
1075da60ce9fSViresh Kumar 			goto err_get_freq;
1076da60ce9fSViresh Kumar 		}
1077da60ce9fSViresh Kumar 	}
1078da60ce9fSViresh Kumar 
1079d3916691SViresh Kumar 	/*
1080d3916691SViresh Kumar 	 * Sometimes boot loaders set CPU frequency to a value outside of
1081d3916691SViresh Kumar 	 * frequency table present with cpufreq core. In such cases CPU might be
1082d3916691SViresh Kumar 	 * unstable if it has to run on that frequency for long duration of time
1083d3916691SViresh Kumar 	 * and so its better to set it to a frequency which is specified in
1084d3916691SViresh Kumar 	 * freq-table. This also makes cpufreq stats inconsistent as
1085d3916691SViresh Kumar 	 * cpufreq-stats would fail to register because current frequency of CPU
1086d3916691SViresh Kumar 	 * isn't found in freq-table.
1087d3916691SViresh Kumar 	 *
1088d3916691SViresh Kumar 	 * Because we don't want this change to effect boot process badly, we go
1089d3916691SViresh Kumar 	 * for the next freq which is >= policy->cur ('cur' must be set by now,
1090d3916691SViresh Kumar 	 * otherwise we will end up setting freq to lowest of the table as 'cur'
1091d3916691SViresh Kumar 	 * is initialized to zero).
1092d3916691SViresh Kumar 	 *
1093d3916691SViresh Kumar 	 * We are passing target-freq as "policy->cur - 1" otherwise
1094d3916691SViresh Kumar 	 * __cpufreq_driver_target() would simply fail, as policy->cur will be
1095d3916691SViresh Kumar 	 * equal to target-freq.
1096d3916691SViresh Kumar 	 */
1097d3916691SViresh Kumar 	if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
1098d3916691SViresh Kumar 	    && has_target()) {
1099d3916691SViresh Kumar 		/* Are we running at unknown frequency ? */
1100d3916691SViresh Kumar 		ret = cpufreq_frequency_table_get_index(policy, policy->cur);
1101d3916691SViresh Kumar 		if (ret == -EINVAL) {
1102d3916691SViresh Kumar 			/* Warn user and fix it */
1103d3916691SViresh Kumar 			pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n",
1104d3916691SViresh Kumar 				__func__, policy->cpu, policy->cur);
1105d3916691SViresh Kumar 			ret = __cpufreq_driver_target(policy, policy->cur - 1,
1106d3916691SViresh Kumar 				CPUFREQ_RELATION_L);
1107d3916691SViresh Kumar 
1108d3916691SViresh Kumar 			/*
1109d3916691SViresh Kumar 			 * Reaching here after boot in a few seconds may not
1110d3916691SViresh Kumar 			 * mean that system will remain stable at "unknown"
1111d3916691SViresh Kumar 			 * frequency for longer duration. Hence, a BUG_ON().
1112d3916691SViresh Kumar 			 */
1113d3916691SViresh Kumar 			BUG_ON(ret);
1114d3916691SViresh Kumar 			pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n",
1115d3916691SViresh Kumar 				__func__, policy->cpu, policy->cur);
1116d3916691SViresh Kumar 		}
1117d3916691SViresh Kumar 	}
1118d3916691SViresh Kumar 
1119fcf80582SViresh Kumar 	/* related cpus should atleast have policy->cpus */
1120fcf80582SViresh Kumar 	cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
1121fcf80582SViresh Kumar 
1122643ae6e8SViresh Kumar 	/*
1123643ae6e8SViresh Kumar 	 * affected cpus must always be the one, which are online. We aren't
1124643ae6e8SViresh Kumar 	 * managing offline cpus here.
1125643ae6e8SViresh Kumar 	 */
1126643ae6e8SViresh Kumar 	cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
1127643ae6e8SViresh Kumar 
112808fd8c1cSViresh Kumar 	if (!frozen) {
1129187d9f4eSMike Chan 		policy->user_policy.min = policy->min;
1130187d9f4eSMike Chan 		policy->user_policy.max = policy->max;
113108fd8c1cSViresh Kumar 	}
11321da177e4SLinus Torvalds 
1133a1531acdSThomas Renninger 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1134a1531acdSThomas Renninger 				     CPUFREQ_START, policy);
1135a1531acdSThomas Renninger 
1136fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
1137fcf80582SViresh Kumar 	gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
1138fcf80582SViresh Kumar 	if (gov) {
1139fcf80582SViresh Kumar 		policy->governor = gov;
1140fcf80582SViresh Kumar 		pr_debug("Restoring governor %s for cpu %d\n",
1141fcf80582SViresh Kumar 		       policy->governor->name, cpu);
11424bfa042cSThomas Renninger 	}
1143fcf80582SViresh Kumar #endif
11441da177e4SLinus Torvalds 
1145e18f1682SSrivatsa S. Bhat 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1146474deff7SViresh Kumar 	for_each_cpu(j, policy->cpus)
1147e18f1682SSrivatsa S. Bhat 		per_cpu(cpufreq_cpu_data, j) = policy;
1148e18f1682SSrivatsa S. Bhat 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1149e18f1682SSrivatsa S. Bhat 
1150a82fab29SSrivatsa S. Bhat 	if (!frozen) {
1151308b60e7SViresh Kumar 		ret = cpufreq_add_dev_interface(policy, dev);
115219d6f7ecSDave Jones 		if (ret)
11530142f9dcSAhmed S. Darwish 			goto err_out_unregister;
1154*fcd7af91SViresh Kumar 		blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1155*fcd7af91SViresh Kumar 				CPUFREQ_CREATE_POLICY, policy);
11569515f4d6SViresh Kumar 	}
1157c88a1f8bSLukasz Majewski 
1158c88a1f8bSLukasz Majewski 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1159c88a1f8bSLukasz Majewski 	list_add(&policy->policy_list, &cpufreq_policy_list);
1160c88a1f8bSLukasz Majewski 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
11618ff69732SDave Jones 
1162e18f1682SSrivatsa S. Bhat 	cpufreq_init_policy(policy);
1163e18f1682SSrivatsa S. Bhat 
116408fd8c1cSViresh Kumar 	if (!frozen) {
116508fd8c1cSViresh Kumar 		policy->user_policy.policy = policy->policy;
116608fd8c1cSViresh Kumar 		policy->user_policy.governor = policy->governor;
116708fd8c1cSViresh Kumar 	}
116808fd8c1cSViresh Kumar 
1169038c5b3eSGreg Kroah-Hartman 	kobject_uevent(&policy->kobj, KOBJ_ADD);
11706eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
11716eed9404SViresh Kumar 
11722d06d8c4SDominik Brodowski 	pr_debug("initialization complete\n");
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 	return 0;
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds err_out_unregister:
11770d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1178474deff7SViresh Kumar 	for_each_cpu(j, policy->cpus)
11797a6aedfaSMike Travis 		per_cpu(cpufreq_cpu_data, j) = NULL;
11800d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
11811da177e4SLinus Torvalds 
1182da60ce9fSViresh Kumar err_get_freq:
1183da60ce9fSViresh Kumar 	if (cpufreq_driver->exit)
1184da60ce9fSViresh Kumar 		cpufreq_driver->exit(policy);
11852eaa3e2dSViresh Kumar err_set_policy_cpu:
118672368d12SRafael J. Wysocki 	if (frozen) {
118772368d12SRafael J. Wysocki 		/* Do not leave stale fallback data behind. */
118872368d12SRafael J. Wysocki 		per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
118942f921a6SViresh Kumar 		cpufreq_policy_put_kobj(policy);
119072368d12SRafael J. Wysocki 	}
1191e9698cc5SSrivatsa S. Bhat 	cpufreq_policy_free(policy);
119242f921a6SViresh Kumar 
11931da177e4SLinus Torvalds nomem_out:
11946eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
11956eed9404SViresh Kumar 
11961da177e4SLinus Torvalds 	return ret;
11971da177e4SLinus Torvalds }
11981da177e4SLinus Torvalds 
1199a82fab29SSrivatsa S. Bhat /**
1200a82fab29SSrivatsa S. Bhat  * cpufreq_add_dev - add a CPU device
1201a82fab29SSrivatsa S. Bhat  *
1202a82fab29SSrivatsa S. Bhat  * Adds the cpufreq interface for a CPU device.
1203a82fab29SSrivatsa S. Bhat  *
1204a82fab29SSrivatsa S. Bhat  * The Oracle says: try running cpufreq registration/unregistration concurrently
1205a82fab29SSrivatsa S. Bhat  * with with cpu hotplugging and all hell will break loose. Tried to clean this
1206a82fab29SSrivatsa S. Bhat  * mess up, but more thorough testing is needed. - Mathieu
1207a82fab29SSrivatsa S. Bhat  */
1208a82fab29SSrivatsa S. Bhat static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1209a82fab29SSrivatsa S. Bhat {
1210a82fab29SSrivatsa S. Bhat 	return __cpufreq_add_dev(dev, sif, false);
1211a82fab29SSrivatsa S. Bhat }
1212a82fab29SSrivatsa S. Bhat 
12133a3e9e06SViresh Kumar static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
121442f921a6SViresh Kumar 					   unsigned int old_cpu)
1215f9ba680dSSrivatsa S. Bhat {
1216f9ba680dSSrivatsa S. Bhat 	struct device *cpu_dev;
1217f9ba680dSSrivatsa S. Bhat 	int ret;
1218f9ba680dSSrivatsa S. Bhat 
1219f9ba680dSSrivatsa S. Bhat 	/* first sibling now owns the new sysfs dir */
12209c8f1ee4SViresh Kumar 	cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
1221a82fab29SSrivatsa S. Bhat 
1222f9ba680dSSrivatsa S. Bhat 	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
12233a3e9e06SViresh Kumar 	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
1224f9ba680dSSrivatsa S. Bhat 	if (ret) {
1225f9ba680dSSrivatsa S. Bhat 		pr_err("%s: Failed to move kobj: %d", __func__, ret);
1226f9ba680dSSrivatsa S. Bhat 
1227ad7722daSviresh kumar 		down_write(&policy->rwsem);
12283a3e9e06SViresh Kumar 		cpumask_set_cpu(old_cpu, policy->cpus);
1229ad7722daSviresh kumar 		up_write(&policy->rwsem);
1230f9ba680dSSrivatsa S. Bhat 
12313a3e9e06SViresh Kumar 		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
1232f9ba680dSSrivatsa S. Bhat 					"cpufreq");
1233f9ba680dSSrivatsa S. Bhat 
1234f9ba680dSSrivatsa S. Bhat 		return -EINVAL;
1235f9ba680dSSrivatsa S. Bhat 	}
1236f9ba680dSSrivatsa S. Bhat 
1237f9ba680dSSrivatsa S. Bhat 	return cpu_dev->id;
1238f9ba680dSSrivatsa S. Bhat }
1239f9ba680dSSrivatsa S. Bhat 
1240cedb70afSSrivatsa S. Bhat static int __cpufreq_remove_dev_prepare(struct device *dev,
1241cedb70afSSrivatsa S. Bhat 					struct subsys_interface *sif,
1242cedb70afSSrivatsa S. Bhat 					bool frozen)
12431da177e4SLinus Torvalds {
1244f9ba680dSSrivatsa S. Bhat 	unsigned int cpu = dev->id, cpus;
12453de9bdebSViresh Kumar 	int new_cpu, ret;
12461da177e4SLinus Torvalds 	unsigned long flags;
12473a3e9e06SViresh Kumar 	struct cpufreq_policy *policy;
12481da177e4SLinus Torvalds 
1249b8eed8afSViresh Kumar 	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
12501da177e4SLinus Torvalds 
12510d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
12521da177e4SLinus Torvalds 
12533a3e9e06SViresh Kumar 	policy = per_cpu(cpufreq_cpu_data, cpu);
12541da177e4SLinus Torvalds 
12558414809cSSrivatsa S. Bhat 	/* Save the policy somewhere when doing a light-weight tear-down */
12568414809cSSrivatsa S. Bhat 	if (frozen)
12573a3e9e06SViresh Kumar 		per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
12588414809cSSrivatsa S. Bhat 
12590d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
12601da177e4SLinus Torvalds 
12613a3e9e06SViresh Kumar 	if (!policy) {
1262b8eed8afSViresh Kumar 		pr_debug("%s: No cpu_data found\n", __func__);
12631da177e4SLinus Torvalds 		return -EINVAL;
12641da177e4SLinus Torvalds 	}
12651da177e4SLinus Torvalds 
12669c0ebcf7SViresh Kumar 	if (has_target()) {
12673de9bdebSViresh Kumar 		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
12683de9bdebSViresh Kumar 		if (ret) {
12693de9bdebSViresh Kumar 			pr_err("%s: Failed to stop governor\n", __func__);
12703de9bdebSViresh Kumar 			return ret;
12713de9bdebSViresh Kumar 		}
12723de9bdebSViresh Kumar 	}
12735a01f2e8SVenkatesh Pallipadi 
12741da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG_CPU
12751c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->setpolicy)
1276fa69e33fSDirk Brandewie 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
12773a3e9e06SViresh Kumar 			policy->governor->name, CPUFREQ_NAME_LEN);
12781da177e4SLinus Torvalds #endif
12791da177e4SLinus Torvalds 
1280ad7722daSviresh kumar 	down_read(&policy->rwsem);
12813a3e9e06SViresh Kumar 	cpus = cpumask_weight(policy->cpus);
1282ad7722daSviresh kumar 	up_read(&policy->rwsem);
12831da177e4SLinus Torvalds 
128461173f25SSrivatsa S. Bhat 	if (cpu != policy->cpu) {
128561173f25SSrivatsa S. Bhat 		if (!frozen)
128673bf0fc2SViresh Kumar 			sysfs_remove_link(&dev->kobj, "cpufreq");
128773bf0fc2SViresh Kumar 	} else if (cpus > 1) {
128842f921a6SViresh Kumar 		new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
1289f9ba680dSSrivatsa S. Bhat 		if (new_cpu >= 0) {
12903a3e9e06SViresh Kumar 			update_policy_cpu(policy, new_cpu);
1291a82fab29SSrivatsa S. Bhat 
1292a82fab29SSrivatsa S. Bhat 			if (!frozen) {
129375949c9aSViresh Kumar 				pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
129475949c9aSViresh Kumar 						__func__, new_cpu, cpu);
12951da177e4SLinus Torvalds 			}
12961da177e4SLinus Torvalds 		}
1297a82fab29SSrivatsa S. Bhat 	}
1298b8eed8afSViresh Kumar 
1299cedb70afSSrivatsa S. Bhat 	return 0;
1300cedb70afSSrivatsa S. Bhat }
1301cedb70afSSrivatsa S. Bhat 
1302cedb70afSSrivatsa S. Bhat static int __cpufreq_remove_dev_finish(struct device *dev,
1303cedb70afSSrivatsa S. Bhat 				       struct subsys_interface *sif,
1304cedb70afSSrivatsa S. Bhat 				       bool frozen)
1305cedb70afSSrivatsa S. Bhat {
1306cedb70afSSrivatsa S. Bhat 	unsigned int cpu = dev->id, cpus;
1307cedb70afSSrivatsa S. Bhat 	int ret;
1308cedb70afSSrivatsa S. Bhat 	unsigned long flags;
1309cedb70afSSrivatsa S. Bhat 	struct cpufreq_policy *policy;
1310cedb70afSSrivatsa S. Bhat 
1311cedb70afSSrivatsa S. Bhat 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1312cedb70afSSrivatsa S. Bhat 	policy = per_cpu(cpufreq_cpu_data, cpu);
1313cedb70afSSrivatsa S. Bhat 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1314cedb70afSSrivatsa S. Bhat 
1315cedb70afSSrivatsa S. Bhat 	if (!policy) {
1316cedb70afSSrivatsa S. Bhat 		pr_debug("%s: No cpu_data found\n", __func__);
1317cedb70afSSrivatsa S. Bhat 		return -EINVAL;
1318cedb70afSSrivatsa S. Bhat 	}
1319cedb70afSSrivatsa S. Bhat 
1320ad7722daSviresh kumar 	down_write(&policy->rwsem);
1321cedb70afSSrivatsa S. Bhat 	cpus = cpumask_weight(policy->cpus);
13229c8f1ee4SViresh Kumar 
13239c8f1ee4SViresh Kumar 	if (cpus > 1)
13249c8f1ee4SViresh Kumar 		cpumask_clear_cpu(cpu, policy->cpus);
1325ad7722daSviresh kumar 	up_write(&policy->rwsem);
1326cedb70afSSrivatsa S. Bhat 
1327b8eed8afSViresh Kumar 	/* If cpu is last user of policy, free policy */
1328b8eed8afSViresh Kumar 	if (cpus == 1) {
13299c0ebcf7SViresh Kumar 		if (has_target()) {
13303de9bdebSViresh Kumar 			ret = __cpufreq_governor(policy,
13313de9bdebSViresh Kumar 					CPUFREQ_GOV_POLICY_EXIT);
13323de9bdebSViresh Kumar 			if (ret) {
13333de9bdebSViresh Kumar 				pr_err("%s: Failed to exit governor\n",
13343de9bdebSViresh Kumar 						__func__);
13353de9bdebSViresh Kumar 				return ret;
13363de9bdebSViresh Kumar 			}
13373de9bdebSViresh Kumar 		}
13382a998599SRafael J. Wysocki 
133942f921a6SViresh Kumar 		if (!frozen)
134042f921a6SViresh Kumar 			cpufreq_policy_put_kobj(policy);
13411da177e4SLinus Torvalds 
13428414809cSSrivatsa S. Bhat 		/*
13438414809cSSrivatsa S. Bhat 		 * Perform the ->exit() even during light-weight tear-down,
13448414809cSSrivatsa S. Bhat 		 * since this is a core component, and is essential for the
13458414809cSSrivatsa S. Bhat 		 * subsequent light-weight ->init() to succeed.
13468414809cSSrivatsa S. Bhat 		 */
13471c3d85ddSRafael J. Wysocki 		if (cpufreq_driver->exit)
13483a3e9e06SViresh Kumar 			cpufreq_driver->exit(policy);
134927ecddc2SJacob Shin 
13509515f4d6SViresh Kumar 		/* Remove policy from list of active policies */
13519515f4d6SViresh Kumar 		write_lock_irqsave(&cpufreq_driver_lock, flags);
13529515f4d6SViresh Kumar 		list_del(&policy->policy_list);
13539515f4d6SViresh Kumar 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
13549515f4d6SViresh Kumar 
13558414809cSSrivatsa S. Bhat 		if (!frozen)
13563a3e9e06SViresh Kumar 			cpufreq_policy_free(policy);
13572a998599SRafael J. Wysocki 	} else {
13589c0ebcf7SViresh Kumar 		if (has_target()) {
13593de9bdebSViresh Kumar 			if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
13603de9bdebSViresh Kumar 					(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
13613de9bdebSViresh Kumar 				pr_err("%s: Failed to start governor\n",
13623de9bdebSViresh Kumar 						__func__);
13633de9bdebSViresh Kumar 				return ret;
13643de9bdebSViresh Kumar 			}
1365b8eed8afSViresh Kumar 		}
13662a998599SRafael J. Wysocki 	}
13671da177e4SLinus Torvalds 
1368474deff7SViresh Kumar 	per_cpu(cpufreq_cpu_data, cpu) = NULL;
13691da177e4SLinus Torvalds 	return 0;
13701da177e4SLinus Torvalds }
13711da177e4SLinus Torvalds 
1372cedb70afSSrivatsa S. Bhat /**
137327a862e9SViresh Kumar  * cpufreq_remove_dev - remove a CPU device
1374cedb70afSSrivatsa S. Bhat  *
1375cedb70afSSrivatsa S. Bhat  * Removes the cpufreq interface for a CPU device.
1376cedb70afSSrivatsa S. Bhat  */
13778a25a2fdSKay Sievers static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
13785a01f2e8SVenkatesh Pallipadi {
13798a25a2fdSKay Sievers 	unsigned int cpu = dev->id;
138027a862e9SViresh Kumar 	int ret;
1381ec28297aSVenki Pallipadi 
1382ec28297aSVenki Pallipadi 	if (cpu_is_offline(cpu))
1383ec28297aSVenki Pallipadi 		return 0;
1384ec28297aSVenki Pallipadi 
138527a862e9SViresh Kumar 	ret = __cpufreq_remove_dev_prepare(dev, sif, false);
138627a862e9SViresh Kumar 
138727a862e9SViresh Kumar 	if (!ret)
138827a862e9SViresh Kumar 		ret = __cpufreq_remove_dev_finish(dev, sif, false);
138927a862e9SViresh Kumar 
139027a862e9SViresh Kumar 	return ret;
13915a01f2e8SVenkatesh Pallipadi }
13925a01f2e8SVenkatesh Pallipadi 
139365f27f38SDavid Howells static void handle_update(struct work_struct *work)
13941da177e4SLinus Torvalds {
139565f27f38SDavid Howells 	struct cpufreq_policy *policy =
139665f27f38SDavid Howells 		container_of(work, struct cpufreq_policy, update);
139765f27f38SDavid Howells 	unsigned int cpu = policy->cpu;
13982d06d8c4SDominik Brodowski 	pr_debug("handle_update for cpu %u called\n", cpu);
13991da177e4SLinus Torvalds 	cpufreq_update_policy(cpu);
14001da177e4SLinus Torvalds }
14011da177e4SLinus Torvalds 
14021da177e4SLinus Torvalds /**
1403bb176f7dSViresh Kumar  *	cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're
1404bb176f7dSViresh Kumar  *	in deep trouble.
14051da177e4SLinus Torvalds  *	@cpu: cpu number
14061da177e4SLinus Torvalds  *	@old_freq: CPU frequency the kernel thinks the CPU runs at
14071da177e4SLinus Torvalds  *	@new_freq: CPU frequency the CPU actually runs at
14081da177e4SLinus Torvalds  *
140929464f28SDave Jones  *	We adjust to current frequency first, and need to clean up later.
141029464f28SDave Jones  *	So either call to cpufreq_update_policy() or schedule handle_update()).
14111da177e4SLinus Torvalds  */
1412e08f5f5bSGautham R Shenoy static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
1413e08f5f5bSGautham R Shenoy 				unsigned int new_freq)
14141da177e4SLinus Torvalds {
1415b43a7ffbSViresh Kumar 	struct cpufreq_policy *policy;
14161da177e4SLinus Torvalds 	struct cpufreq_freqs freqs;
1417b43a7ffbSViresh Kumar 	unsigned long flags;
1418b43a7ffbSViresh Kumar 
14192d06d8c4SDominik Brodowski 	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
14201da177e4SLinus Torvalds 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
14211da177e4SLinus Torvalds 
14221da177e4SLinus Torvalds 	freqs.old = old_freq;
14231da177e4SLinus Torvalds 	freqs.new = new_freq;
1424b43a7ffbSViresh Kumar 
1425b43a7ffbSViresh Kumar 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1426b43a7ffbSViresh Kumar 	policy = per_cpu(cpufreq_cpu_data, cpu);
1427b43a7ffbSViresh Kumar 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1428b43a7ffbSViresh Kumar 
1429b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
1430b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
14311da177e4SLinus Torvalds }
14321da177e4SLinus Torvalds 
14331da177e4SLinus Torvalds /**
14344ab70df4SDhaval Giani  * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
143595235ca2SVenkatesh Pallipadi  * @cpu: CPU number
143695235ca2SVenkatesh Pallipadi  *
143795235ca2SVenkatesh Pallipadi  * This is the last known freq, without actually getting it from the driver.
143895235ca2SVenkatesh Pallipadi  * Return value will be same as what is shown in scaling_cur_freq in sysfs.
143995235ca2SVenkatesh Pallipadi  */
144095235ca2SVenkatesh Pallipadi unsigned int cpufreq_quick_get(unsigned int cpu)
144195235ca2SVenkatesh Pallipadi {
14429e21ba8bSDirk Brandewie 	struct cpufreq_policy *policy;
1443e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
144495235ca2SVenkatesh Pallipadi 
14451c3d85ddSRafael J. Wysocki 	if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
14461c3d85ddSRafael J. Wysocki 		return cpufreq_driver->get(cpu);
14479e21ba8bSDirk Brandewie 
14489e21ba8bSDirk Brandewie 	policy = cpufreq_cpu_get(cpu);
144995235ca2SVenkatesh Pallipadi 	if (policy) {
1450e08f5f5bSGautham R Shenoy 		ret_freq = policy->cur;
145195235ca2SVenkatesh Pallipadi 		cpufreq_cpu_put(policy);
145295235ca2SVenkatesh Pallipadi 	}
145395235ca2SVenkatesh Pallipadi 
14544d34a67dSDave Jones 	return ret_freq;
145595235ca2SVenkatesh Pallipadi }
145695235ca2SVenkatesh Pallipadi EXPORT_SYMBOL(cpufreq_quick_get);
145795235ca2SVenkatesh Pallipadi 
14583d737108SJesse Barnes /**
14593d737108SJesse Barnes  * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
14603d737108SJesse Barnes  * @cpu: CPU number
14613d737108SJesse Barnes  *
14623d737108SJesse Barnes  * Just return the max possible frequency for a given CPU.
14633d737108SJesse Barnes  */
14643d737108SJesse Barnes unsigned int cpufreq_quick_get_max(unsigned int cpu)
14653d737108SJesse Barnes {
14663d737108SJesse Barnes 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
14673d737108SJesse Barnes 	unsigned int ret_freq = 0;
14683d737108SJesse Barnes 
14693d737108SJesse Barnes 	if (policy) {
14703d737108SJesse Barnes 		ret_freq = policy->max;
14713d737108SJesse Barnes 		cpufreq_cpu_put(policy);
14723d737108SJesse Barnes 	}
14733d737108SJesse Barnes 
14743d737108SJesse Barnes 	return ret_freq;
14753d737108SJesse Barnes }
14763d737108SJesse Barnes EXPORT_SYMBOL(cpufreq_quick_get_max);
14773d737108SJesse Barnes 
14785a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu)
14791da177e4SLinus Torvalds {
14807a6aedfaSMike Travis 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
1481e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
14821da177e4SLinus Torvalds 
14831c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->get)
14844d34a67dSDave Jones 		return ret_freq;
14851da177e4SLinus Torvalds 
14861c3d85ddSRafael J. Wysocki 	ret_freq = cpufreq_driver->get(cpu);
14871da177e4SLinus Torvalds 
1488e08f5f5bSGautham R Shenoy 	if (ret_freq && policy->cur &&
14891c3d85ddSRafael J. Wysocki 		!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
1490e08f5f5bSGautham R Shenoy 		/* verify no discrepancy between actual and
1491e08f5f5bSGautham R Shenoy 					saved value exists */
1492e08f5f5bSGautham R Shenoy 		if (unlikely(ret_freq != policy->cur)) {
1493e08f5f5bSGautham R Shenoy 			cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
14941da177e4SLinus Torvalds 			schedule_work(&policy->update);
14951da177e4SLinus Torvalds 		}
14961da177e4SLinus Torvalds 	}
14971da177e4SLinus Torvalds 
14984d34a67dSDave Jones 	return ret_freq;
14995a01f2e8SVenkatesh Pallipadi }
15001da177e4SLinus Torvalds 
15015a01f2e8SVenkatesh Pallipadi /**
15025a01f2e8SVenkatesh Pallipadi  * cpufreq_get - get the current CPU frequency (in kHz)
15035a01f2e8SVenkatesh Pallipadi  * @cpu: CPU number
15045a01f2e8SVenkatesh Pallipadi  *
15055a01f2e8SVenkatesh Pallipadi  * Get the CPU current (static) CPU frequency
15065a01f2e8SVenkatesh Pallipadi  */
15075a01f2e8SVenkatesh Pallipadi unsigned int cpufreq_get(unsigned int cpu)
15085a01f2e8SVenkatesh Pallipadi {
1509ad7722daSviresh kumar 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
15105a01f2e8SVenkatesh Pallipadi 	unsigned int ret_freq = 0;
15115a01f2e8SVenkatesh Pallipadi 
151226ca8694SViresh Kumar 	if (cpufreq_disabled() || !cpufreq_driver)
151326ca8694SViresh Kumar 		return -ENOENT;
151426ca8694SViresh Kumar 
1515ad7722daSviresh kumar 	BUG_ON(!policy);
1516ad7722daSviresh kumar 
15176eed9404SViresh Kumar 	if (!down_read_trylock(&cpufreq_rwsem))
15186eed9404SViresh Kumar 		return 0;
15195a01f2e8SVenkatesh Pallipadi 
1520ad7722daSviresh kumar 	down_read(&policy->rwsem);
15215a01f2e8SVenkatesh Pallipadi 
15225a01f2e8SVenkatesh Pallipadi 	ret_freq = __cpufreq_get(cpu);
15235a01f2e8SVenkatesh Pallipadi 
1524ad7722daSviresh kumar 	up_read(&policy->rwsem);
15256eed9404SViresh Kumar 	up_read(&cpufreq_rwsem);
15266eed9404SViresh Kumar 
15274d34a67dSDave Jones 	return ret_freq;
15281da177e4SLinus Torvalds }
15291da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get);
15301da177e4SLinus Torvalds 
15318a25a2fdSKay Sievers static struct subsys_interface cpufreq_interface = {
15328a25a2fdSKay Sievers 	.name		= "cpufreq",
15338a25a2fdSKay Sievers 	.subsys		= &cpu_subsys,
15348a25a2fdSKay Sievers 	.add_dev	= cpufreq_add_dev,
15358a25a2fdSKay Sievers 	.remove_dev	= cpufreq_remove_dev,
1536e00e56dfSRafael J. Wysocki };
1537e00e56dfSRafael J. Wysocki 
15381da177e4SLinus Torvalds /**
1539e00e56dfSRafael J. Wysocki  * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
1540e00e56dfSRafael J. Wysocki  *
1541e00e56dfSRafael J. Wysocki  * This function is only executed for the boot processor.  The other CPUs
1542e00e56dfSRafael J. Wysocki  * have been put offline by means of CPU hotplug.
154342d4dc3fSBenjamin Herrenschmidt  */
1544e00e56dfSRafael J. Wysocki static int cpufreq_bp_suspend(void)
154542d4dc3fSBenjamin Herrenschmidt {
1546e08f5f5bSGautham R Shenoy 	int ret = 0;
15474bc5d341SDave Jones 
1548e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
15493a3e9e06SViresh Kumar 	struct cpufreq_policy *policy;
155042d4dc3fSBenjamin Herrenschmidt 
15512d06d8c4SDominik Brodowski 	pr_debug("suspending cpu %u\n", cpu);
155242d4dc3fSBenjamin Herrenschmidt 
1553e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
15543a3e9e06SViresh Kumar 	policy = cpufreq_cpu_get(cpu);
15553a3e9e06SViresh Kumar 	if (!policy)
1556e00e56dfSRafael J. Wysocki 		return 0;
155742d4dc3fSBenjamin Herrenschmidt 
15581c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->suspend) {
15593a3e9e06SViresh Kumar 		ret = cpufreq_driver->suspend(policy);
1560ce6c3997SDominik Brodowski 		if (ret)
156142d4dc3fSBenjamin Herrenschmidt 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
15623a3e9e06SViresh Kumar 					"step on CPU %u\n", policy->cpu);
156342d4dc3fSBenjamin Herrenschmidt 	}
156442d4dc3fSBenjamin Herrenschmidt 
15653a3e9e06SViresh Kumar 	cpufreq_cpu_put(policy);
1566c9060494SDave Jones 	return ret;
156742d4dc3fSBenjamin Herrenschmidt }
156842d4dc3fSBenjamin Herrenschmidt 
156942d4dc3fSBenjamin Herrenschmidt /**
1570e00e56dfSRafael J. Wysocki  * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
15711da177e4SLinus Torvalds  *
15721da177e4SLinus Torvalds  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
1573ce6c3997SDominik Brodowski  *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
1574ce6c3997SDominik Brodowski  *	    restored. It will verify that the current freq is in sync with
1575ce6c3997SDominik Brodowski  *	    what we believe it to be. This is a bit later than when it
1576ce6c3997SDominik Brodowski  *	    should be, but nonethteless it's better than calling
1577ce6c3997SDominik Brodowski  *	    cpufreq_driver->get() here which might re-enable interrupts...
1578e00e56dfSRafael J. Wysocki  *
1579e00e56dfSRafael J. Wysocki  * This function is only executed for the boot CPU.  The other CPUs have not
1580e00e56dfSRafael J. Wysocki  * been turned on yet.
15811da177e4SLinus Torvalds  */
1582e00e56dfSRafael J. Wysocki static void cpufreq_bp_resume(void)
15831da177e4SLinus Torvalds {
1584e08f5f5bSGautham R Shenoy 	int ret = 0;
15854bc5d341SDave Jones 
1586e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
15873a3e9e06SViresh Kumar 	struct cpufreq_policy *policy;
15881da177e4SLinus Torvalds 
15892d06d8c4SDominik Brodowski 	pr_debug("resuming cpu %u\n", cpu);
15901da177e4SLinus Torvalds 
1591e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
15923a3e9e06SViresh Kumar 	policy = cpufreq_cpu_get(cpu);
15933a3e9e06SViresh Kumar 	if (!policy)
1594e00e56dfSRafael J. Wysocki 		return;
15951da177e4SLinus Torvalds 
15961c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->resume) {
15973a3e9e06SViresh Kumar 		ret = cpufreq_driver->resume(policy);
15981da177e4SLinus Torvalds 		if (ret) {
15991da177e4SLinus Torvalds 			printk(KERN_ERR "cpufreq: resume failed in ->resume "
16003a3e9e06SViresh Kumar 					"step on CPU %u\n", policy->cpu);
1601c9060494SDave Jones 			goto fail;
16021da177e4SLinus Torvalds 		}
16031da177e4SLinus Torvalds 	}
16041da177e4SLinus Torvalds 
16053a3e9e06SViresh Kumar 	schedule_work(&policy->update);
1606ce6c3997SDominik Brodowski 
1607c9060494SDave Jones fail:
16083a3e9e06SViresh Kumar 	cpufreq_cpu_put(policy);
16091da177e4SLinus Torvalds }
16101da177e4SLinus Torvalds 
1611e00e56dfSRafael J. Wysocki static struct syscore_ops cpufreq_syscore_ops = {
1612e00e56dfSRafael J. Wysocki 	.suspend	= cpufreq_bp_suspend,
1613e00e56dfSRafael J. Wysocki 	.resume		= cpufreq_bp_resume,
16141da177e4SLinus Torvalds };
16151da177e4SLinus Torvalds 
16169d95046eSBorislav Petkov /**
16179d95046eSBorislav Petkov  *	cpufreq_get_current_driver - return current driver's name
16189d95046eSBorislav Petkov  *
16199d95046eSBorislav Petkov  *	Return the name string of the currently loaded cpufreq driver
16209d95046eSBorislav Petkov  *	or NULL, if none.
16219d95046eSBorislav Petkov  */
16229d95046eSBorislav Petkov const char *cpufreq_get_current_driver(void)
16239d95046eSBorislav Petkov {
16241c3d85ddSRafael J. Wysocki 	if (cpufreq_driver)
16251c3d85ddSRafael J. Wysocki 		return cpufreq_driver->name;
16261c3d85ddSRafael J. Wysocki 
16271c3d85ddSRafael J. Wysocki 	return NULL;
16289d95046eSBorislav Petkov }
16299d95046eSBorislav Petkov EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
16301da177e4SLinus Torvalds 
16311da177e4SLinus Torvalds /*********************************************************************
16321da177e4SLinus Torvalds  *                     NOTIFIER LISTS INTERFACE                      *
16331da177e4SLinus Torvalds  *********************************************************************/
16341da177e4SLinus Torvalds 
16351da177e4SLinus Torvalds /**
16361da177e4SLinus Torvalds  *	cpufreq_register_notifier - register a driver with cpufreq
16371da177e4SLinus Torvalds  *	@nb: notifier function to register
16381da177e4SLinus Torvalds  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
16391da177e4SLinus Torvalds  *
16401da177e4SLinus Torvalds  *	Add a driver to one of two lists: either a list of drivers that
16411da177e4SLinus Torvalds  *      are notified about clock rate changes (once before and once after
16421da177e4SLinus Torvalds  *      the transition), or a list of drivers that are notified about
16431da177e4SLinus Torvalds  *      changes in cpufreq policy.
16441da177e4SLinus Torvalds  *
16451da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1646e041c683SAlan Stern  *	blocking_notifier_chain_register.
16471da177e4SLinus Torvalds  */
16481da177e4SLinus Torvalds int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
16491da177e4SLinus Torvalds {
16501da177e4SLinus Torvalds 	int ret;
16511da177e4SLinus Torvalds 
1652d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1653d5aaffa9SDirk Brandewie 		return -EINVAL;
1654d5aaffa9SDirk Brandewie 
165574212ca4SCesar Eduardo Barros 	WARN_ON(!init_cpufreq_transition_notifier_list_called);
165674212ca4SCesar Eduardo Barros 
16571da177e4SLinus Torvalds 	switch (list) {
16581da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1659b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_register(
1660e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
16611da177e4SLinus Torvalds 		break;
16621da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1663e041c683SAlan Stern 		ret = blocking_notifier_chain_register(
1664e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
16651da177e4SLinus Torvalds 		break;
16661da177e4SLinus Torvalds 	default:
16671da177e4SLinus Torvalds 		ret = -EINVAL;
16681da177e4SLinus Torvalds 	}
16691da177e4SLinus Torvalds 
16701da177e4SLinus Torvalds 	return ret;
16711da177e4SLinus Torvalds }
16721da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_register_notifier);
16731da177e4SLinus Torvalds 
16741da177e4SLinus Torvalds /**
16751da177e4SLinus Torvalds  *	cpufreq_unregister_notifier - unregister a driver with cpufreq
16761da177e4SLinus Torvalds  *	@nb: notifier block to be unregistered
16771da177e4SLinus Torvalds  *	@list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
16781da177e4SLinus Torvalds  *
16791da177e4SLinus Torvalds  *	Remove a driver from the CPU frequency notifier list.
16801da177e4SLinus Torvalds  *
16811da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1682e041c683SAlan Stern  *	blocking_notifier_chain_unregister.
16831da177e4SLinus Torvalds  */
16841da177e4SLinus Torvalds int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
16851da177e4SLinus Torvalds {
16861da177e4SLinus Torvalds 	int ret;
16871da177e4SLinus Torvalds 
1688d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1689d5aaffa9SDirk Brandewie 		return -EINVAL;
1690d5aaffa9SDirk Brandewie 
16911da177e4SLinus Torvalds 	switch (list) {
16921da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1693b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_unregister(
1694e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
16951da177e4SLinus Torvalds 		break;
16961da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1697e041c683SAlan Stern 		ret = blocking_notifier_chain_unregister(
1698e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
16991da177e4SLinus Torvalds 		break;
17001da177e4SLinus Torvalds 	default:
17011da177e4SLinus Torvalds 		ret = -EINVAL;
17021da177e4SLinus Torvalds 	}
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds 	return ret;
17051da177e4SLinus Torvalds }
17061da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_unregister_notifier);
17071da177e4SLinus Torvalds 
17081da177e4SLinus Torvalds 
17091da177e4SLinus Torvalds /*********************************************************************
17101da177e4SLinus Torvalds  *                              GOVERNORS                            *
17111da177e4SLinus Torvalds  *********************************************************************/
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds int __cpufreq_driver_target(struct cpufreq_policy *policy,
17141da177e4SLinus Torvalds 			    unsigned int target_freq,
17151da177e4SLinus Torvalds 			    unsigned int relation)
17161da177e4SLinus Torvalds {
17171da177e4SLinus Torvalds 	int retval = -EINVAL;
17187249924eSViresh Kumar 	unsigned int old_target_freq = target_freq;
1719c32b6b8eSAshok Raj 
1720a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1721a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
1722a7b422cdSKonrad Rzeszutek Wilk 
17237249924eSViresh Kumar 	/* Make sure that target_freq is within supported range */
17247249924eSViresh Kumar 	if (target_freq > policy->max)
17257249924eSViresh Kumar 		target_freq = policy->max;
17267249924eSViresh Kumar 	if (target_freq < policy->min)
17277249924eSViresh Kumar 		target_freq = policy->min;
17287249924eSViresh Kumar 
17297249924eSViresh Kumar 	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
17307249924eSViresh Kumar 			policy->cpu, target_freq, relation, old_target_freq);
17315a1c0228SViresh Kumar 
17329c0ebcf7SViresh Kumar 	/*
17339c0ebcf7SViresh Kumar 	 * This might look like a redundant call as we are checking it again
17349c0ebcf7SViresh Kumar 	 * after finding index. But it is left intentionally for cases where
17359c0ebcf7SViresh Kumar 	 * exactly same freq is called again and so we can save on few function
17369c0ebcf7SViresh Kumar 	 * calls.
17379c0ebcf7SViresh Kumar 	 */
17385a1c0228SViresh Kumar 	if (target_freq == policy->cur)
17395a1c0228SViresh Kumar 		return 0;
17405a1c0228SViresh Kumar 
17411c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->target)
17421c3d85ddSRafael J. Wysocki 		retval = cpufreq_driver->target(policy, target_freq, relation);
17439c0ebcf7SViresh Kumar 	else if (cpufreq_driver->target_index) {
17449c0ebcf7SViresh Kumar 		struct cpufreq_frequency_table *freq_table;
1745d4019f0aSViresh Kumar 		struct cpufreq_freqs freqs;
1746d4019f0aSViresh Kumar 		bool notify;
17479c0ebcf7SViresh Kumar 		int index;
174890d45d17SAshok Raj 
17499c0ebcf7SViresh Kumar 		freq_table = cpufreq_frequency_get_table(policy->cpu);
17509c0ebcf7SViresh Kumar 		if (unlikely(!freq_table)) {
17519c0ebcf7SViresh Kumar 			pr_err("%s: Unable to find freq_table\n", __func__);
17529c0ebcf7SViresh Kumar 			goto out;
17539c0ebcf7SViresh Kumar 		}
17549c0ebcf7SViresh Kumar 
17559c0ebcf7SViresh Kumar 		retval = cpufreq_frequency_table_target(policy, freq_table,
17569c0ebcf7SViresh Kumar 				target_freq, relation, &index);
17579c0ebcf7SViresh Kumar 		if (unlikely(retval)) {
17589c0ebcf7SViresh Kumar 			pr_err("%s: Unable to find matching freq\n", __func__);
17599c0ebcf7SViresh Kumar 			goto out;
17609c0ebcf7SViresh Kumar 		}
17619c0ebcf7SViresh Kumar 
1762d4019f0aSViresh Kumar 		if (freq_table[index].frequency == policy->cur) {
17639c0ebcf7SViresh Kumar 			retval = 0;
1764d4019f0aSViresh Kumar 			goto out;
1765d4019f0aSViresh Kumar 		}
1766d4019f0aSViresh Kumar 
1767d4019f0aSViresh Kumar 		notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
1768d4019f0aSViresh Kumar 
1769d4019f0aSViresh Kumar 		if (notify) {
1770d4019f0aSViresh Kumar 			freqs.old = policy->cur;
1771d4019f0aSViresh Kumar 			freqs.new = freq_table[index].frequency;
1772d4019f0aSViresh Kumar 			freqs.flags = 0;
1773d4019f0aSViresh Kumar 
1774d4019f0aSViresh Kumar 			pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
1775d4019f0aSViresh Kumar 					__func__, policy->cpu, freqs.old,
1776d4019f0aSViresh Kumar 					freqs.new);
1777d4019f0aSViresh Kumar 
1778d4019f0aSViresh Kumar 			cpufreq_notify_transition(policy, &freqs,
1779d4019f0aSViresh Kumar 					CPUFREQ_PRECHANGE);
1780d4019f0aSViresh Kumar 		}
1781d4019f0aSViresh Kumar 
17829c0ebcf7SViresh Kumar 		retval = cpufreq_driver->target_index(policy, index);
1783d4019f0aSViresh Kumar 		if (retval)
1784d4019f0aSViresh Kumar 			pr_err("%s: Failed to change cpu frequency: %d\n",
1785d4019f0aSViresh Kumar 					__func__, retval);
1786d4019f0aSViresh Kumar 
1787ab1b1c4eSViresh Kumar 		if (notify)
1788ab1b1c4eSViresh Kumar 			cpufreq_notify_post_transition(policy, &freqs, retval);
17899c0ebcf7SViresh Kumar 	}
17909c0ebcf7SViresh Kumar 
17919c0ebcf7SViresh Kumar out:
17921da177e4SLinus Torvalds 	return retval;
17931da177e4SLinus Torvalds }
17941da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
17951da177e4SLinus Torvalds 
17961da177e4SLinus Torvalds int cpufreq_driver_target(struct cpufreq_policy *policy,
17971da177e4SLinus Torvalds 			  unsigned int target_freq,
17981da177e4SLinus Torvalds 			  unsigned int relation)
17991da177e4SLinus Torvalds {
1800f1829e4aSJulia Lawall 	int ret = -EINVAL;
18011da177e4SLinus Torvalds 
1802ad7722daSviresh kumar 	down_write(&policy->rwsem);
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds 	ret = __cpufreq_driver_target(policy, target_freq, relation);
18051da177e4SLinus Torvalds 
1806ad7722daSviresh kumar 	up_write(&policy->rwsem);
18071da177e4SLinus Torvalds 
18081da177e4SLinus Torvalds 	return ret;
18091da177e4SLinus Torvalds }
18101da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_driver_target);
18111da177e4SLinus Torvalds 
1812153d7f3fSArjan van de Ven /*
1813153d7f3fSArjan van de Ven  * when "event" is CPUFREQ_GOV_LIMITS
1814153d7f3fSArjan van de Ven  */
18151da177e4SLinus Torvalds 
1816e08f5f5bSGautham R Shenoy static int __cpufreq_governor(struct cpufreq_policy *policy,
1817e08f5f5bSGautham R Shenoy 					unsigned int event)
18181da177e4SLinus Torvalds {
1819cc993cabSDave Jones 	int ret;
18206afde10cSThomas Renninger 
18216afde10cSThomas Renninger 	/* Only must be defined when default governor is known to have latency
18226afde10cSThomas Renninger 	   restrictions, like e.g. conservative or ondemand.
18236afde10cSThomas Renninger 	   That this is the case is already ensured in Kconfig
18246afde10cSThomas Renninger 	*/
18256afde10cSThomas Renninger #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
18266afde10cSThomas Renninger 	struct cpufreq_governor *gov = &cpufreq_gov_performance;
18276afde10cSThomas Renninger #else
18286afde10cSThomas Renninger 	struct cpufreq_governor *gov = NULL;
18296afde10cSThomas Renninger #endif
18301c256245SThomas Renninger 
18311c256245SThomas Renninger 	if (policy->governor->max_transition_latency &&
18321c256245SThomas Renninger 	    policy->cpuinfo.transition_latency >
18331c256245SThomas Renninger 	    policy->governor->max_transition_latency) {
18346afde10cSThomas Renninger 		if (!gov)
18356afde10cSThomas Renninger 			return -EINVAL;
18366afde10cSThomas Renninger 		else {
18371c256245SThomas Renninger 			printk(KERN_WARNING "%s governor failed, too long"
18381c256245SThomas Renninger 			       " transition latency of HW, fallback"
18391c256245SThomas Renninger 			       " to %s governor\n",
18401c256245SThomas Renninger 			       policy->governor->name,
18411c256245SThomas Renninger 			       gov->name);
18421c256245SThomas Renninger 			policy->governor = gov;
18431c256245SThomas Renninger 		}
18446afde10cSThomas Renninger 	}
18451da177e4SLinus Torvalds 
1846fe492f3fSViresh Kumar 	if (event == CPUFREQ_GOV_POLICY_INIT)
18471da177e4SLinus Torvalds 		if (!try_module_get(policy->governor->owner))
18481da177e4SLinus Torvalds 			return -EINVAL;
18491da177e4SLinus Torvalds 
18502d06d8c4SDominik Brodowski 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
1851e08f5f5bSGautham R Shenoy 						policy->cpu, event);
185295731ebbSXiaoguang Chen 
185395731ebbSXiaoguang Chen 	mutex_lock(&cpufreq_governor_lock);
185456d07db2SSrivatsa S. Bhat 	if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
1855f73d3933SViresh Kumar 	    || (!policy->governor_enabled
1856f73d3933SViresh Kumar 	    && (event == CPUFREQ_GOV_LIMITS || event == CPUFREQ_GOV_STOP))) {
185795731ebbSXiaoguang Chen 		mutex_unlock(&cpufreq_governor_lock);
185895731ebbSXiaoguang Chen 		return -EBUSY;
185995731ebbSXiaoguang Chen 	}
186095731ebbSXiaoguang Chen 
186195731ebbSXiaoguang Chen 	if (event == CPUFREQ_GOV_STOP)
186295731ebbSXiaoguang Chen 		policy->governor_enabled = false;
186395731ebbSXiaoguang Chen 	else if (event == CPUFREQ_GOV_START)
186495731ebbSXiaoguang Chen 		policy->governor_enabled = true;
186595731ebbSXiaoguang Chen 
186695731ebbSXiaoguang Chen 	mutex_unlock(&cpufreq_governor_lock);
186795731ebbSXiaoguang Chen 
18681da177e4SLinus Torvalds 	ret = policy->governor->governor(policy, event);
18691da177e4SLinus Torvalds 
18704d5dcc42SViresh Kumar 	if (!ret) {
18714d5dcc42SViresh Kumar 		if (event == CPUFREQ_GOV_POLICY_INIT)
18728e53695fSViresh Kumar 			policy->governor->initialized++;
18734d5dcc42SViresh Kumar 		else if (event == CPUFREQ_GOV_POLICY_EXIT)
18748e53695fSViresh Kumar 			policy->governor->initialized--;
187595731ebbSXiaoguang Chen 	} else {
187695731ebbSXiaoguang Chen 		/* Restore original values */
187795731ebbSXiaoguang Chen 		mutex_lock(&cpufreq_governor_lock);
187895731ebbSXiaoguang Chen 		if (event == CPUFREQ_GOV_STOP)
187995731ebbSXiaoguang Chen 			policy->governor_enabled = true;
188095731ebbSXiaoguang Chen 		else if (event == CPUFREQ_GOV_START)
188195731ebbSXiaoguang Chen 			policy->governor_enabled = false;
188295731ebbSXiaoguang Chen 		mutex_unlock(&cpufreq_governor_lock);
18834d5dcc42SViresh Kumar 	}
1884b394058fSViresh Kumar 
1885fe492f3fSViresh Kumar 	if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
1886fe492f3fSViresh Kumar 			((event == CPUFREQ_GOV_POLICY_EXIT) && !ret))
18871da177e4SLinus Torvalds 		module_put(policy->governor->owner);
18881da177e4SLinus Torvalds 
18891da177e4SLinus Torvalds 	return ret;
18901da177e4SLinus Torvalds }
18911da177e4SLinus Torvalds 
18921da177e4SLinus Torvalds int cpufreq_register_governor(struct cpufreq_governor *governor)
18931da177e4SLinus Torvalds {
18943bcb09a3SJeremy Fitzhardinge 	int err;
18951da177e4SLinus Torvalds 
18961da177e4SLinus Torvalds 	if (!governor)
18971da177e4SLinus Torvalds 		return -EINVAL;
18981da177e4SLinus Torvalds 
1899a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1900a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
1901a7b422cdSKonrad Rzeszutek Wilk 
19023fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
19031da177e4SLinus Torvalds 
1904b394058fSViresh Kumar 	governor->initialized = 0;
19053bcb09a3SJeremy Fitzhardinge 	err = -EBUSY;
19063bcb09a3SJeremy Fitzhardinge 	if (__find_governor(governor->name) == NULL) {
19073bcb09a3SJeremy Fitzhardinge 		err = 0;
19081da177e4SLinus Torvalds 		list_add(&governor->governor_list, &cpufreq_governor_list);
19093bcb09a3SJeremy Fitzhardinge 	}
19101da177e4SLinus Torvalds 
19113fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
19123bcb09a3SJeremy Fitzhardinge 	return err;
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_governor);
19151da177e4SLinus Torvalds 
19161da177e4SLinus Torvalds void cpufreq_unregister_governor(struct cpufreq_governor *governor)
19171da177e4SLinus Torvalds {
191890e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
191990e41bacSPrarit Bhargava 	int cpu;
192090e41bacSPrarit Bhargava #endif
192190e41bacSPrarit Bhargava 
19221da177e4SLinus Torvalds 	if (!governor)
19231da177e4SLinus Torvalds 		return;
19241da177e4SLinus Torvalds 
1925a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1926a7b422cdSKonrad Rzeszutek Wilk 		return;
1927a7b422cdSKonrad Rzeszutek Wilk 
192890e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
192990e41bacSPrarit Bhargava 	for_each_present_cpu(cpu) {
193090e41bacSPrarit Bhargava 		if (cpu_online(cpu))
193190e41bacSPrarit Bhargava 			continue;
193290e41bacSPrarit Bhargava 		if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
193390e41bacSPrarit Bhargava 			strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
193490e41bacSPrarit Bhargava 	}
193590e41bacSPrarit Bhargava #endif
193690e41bacSPrarit Bhargava 
19373fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
19381da177e4SLinus Torvalds 	list_del(&governor->governor_list);
19393fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
19401da177e4SLinus Torvalds 	return;
19411da177e4SLinus Torvalds }
19421da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
19431da177e4SLinus Torvalds 
19441da177e4SLinus Torvalds 
19451da177e4SLinus Torvalds /*********************************************************************
19461da177e4SLinus Torvalds  *                          POLICY INTERFACE                         *
19471da177e4SLinus Torvalds  *********************************************************************/
19481da177e4SLinus Torvalds 
19491da177e4SLinus Torvalds /**
19501da177e4SLinus Torvalds  * cpufreq_get_policy - get the current cpufreq_policy
195129464f28SDave Jones  * @policy: struct cpufreq_policy into which the current cpufreq_policy
195229464f28SDave Jones  *	is written
19531da177e4SLinus Torvalds  *
19541da177e4SLinus Torvalds  * Reads the current cpufreq policy.
19551da177e4SLinus Torvalds  */
19561da177e4SLinus Torvalds int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
19571da177e4SLinus Torvalds {
19581da177e4SLinus Torvalds 	struct cpufreq_policy *cpu_policy;
19591da177e4SLinus Torvalds 	if (!policy)
19601da177e4SLinus Torvalds 		return -EINVAL;
19611da177e4SLinus Torvalds 
19621da177e4SLinus Torvalds 	cpu_policy = cpufreq_cpu_get(cpu);
19631da177e4SLinus Torvalds 	if (!cpu_policy)
19641da177e4SLinus Torvalds 		return -EINVAL;
19651da177e4SLinus Torvalds 
1966d5b73cd8SViresh Kumar 	memcpy(policy, cpu_policy, sizeof(*policy));
19671da177e4SLinus Torvalds 
19681da177e4SLinus Torvalds 	cpufreq_cpu_put(cpu_policy);
19691da177e4SLinus Torvalds 	return 0;
19701da177e4SLinus Torvalds }
19711da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get_policy);
19721da177e4SLinus Torvalds 
1973153d7f3fSArjan van de Ven /*
1974037ce839SViresh Kumar  * policy : current policy.
1975037ce839SViresh Kumar  * new_policy: policy to be set.
1976153d7f3fSArjan van de Ven  */
1977037ce839SViresh Kumar static int cpufreq_set_policy(struct cpufreq_policy *policy,
19783a3e9e06SViresh Kumar 				struct cpufreq_policy *new_policy)
19791da177e4SLinus Torvalds {
19807bd353a9SViresh Kumar 	int ret = 0, failed = 1;
19811da177e4SLinus Torvalds 
19823a3e9e06SViresh Kumar 	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu,
19833a3e9e06SViresh Kumar 		new_policy->min, new_policy->max);
19841da177e4SLinus Torvalds 
1985d5b73cd8SViresh Kumar 	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
19861da177e4SLinus Torvalds 
19873a3e9e06SViresh Kumar 	if (new_policy->min > policy->max || new_policy->max < policy->min) {
19889c9a43edSMattia Dongili 		ret = -EINVAL;
19899c9a43edSMattia Dongili 		goto error_out;
19909c9a43edSMattia Dongili 	}
19919c9a43edSMattia Dongili 
19921da177e4SLinus Torvalds 	/* verify the cpu speed can be set within this limit */
19933a3e9e06SViresh Kumar 	ret = cpufreq_driver->verify(new_policy);
19941da177e4SLinus Torvalds 	if (ret)
19951da177e4SLinus Torvalds 		goto error_out;
19961da177e4SLinus Torvalds 
19971da177e4SLinus Torvalds 	/* adjust if necessary - all reasons */
1998e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
19993a3e9e06SViresh Kumar 			CPUFREQ_ADJUST, new_policy);
20001da177e4SLinus Torvalds 
20011da177e4SLinus Torvalds 	/* adjust if necessary - hardware incompatibility*/
2002e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
20033a3e9e06SViresh Kumar 			CPUFREQ_INCOMPATIBLE, new_policy);
20041da177e4SLinus Torvalds 
2005bb176f7dSViresh Kumar 	/*
2006bb176f7dSViresh Kumar 	 * verify the cpu speed can be set within this limit, which might be
2007bb176f7dSViresh Kumar 	 * different to the first one
2008bb176f7dSViresh Kumar 	 */
20093a3e9e06SViresh Kumar 	ret = cpufreq_driver->verify(new_policy);
2010e041c683SAlan Stern 	if (ret)
20111da177e4SLinus Torvalds 		goto error_out;
20121da177e4SLinus Torvalds 
20131da177e4SLinus Torvalds 	/* notification of the new policy */
2014e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
20153a3e9e06SViresh Kumar 			CPUFREQ_NOTIFY, new_policy);
20161da177e4SLinus Torvalds 
20173a3e9e06SViresh Kumar 	policy->min = new_policy->min;
20183a3e9e06SViresh Kumar 	policy->max = new_policy->max;
20191da177e4SLinus Torvalds 
20202d06d8c4SDominik Brodowski 	pr_debug("new min and max freqs are %u - %u kHz\n",
20213a3e9e06SViresh Kumar 					policy->min, policy->max);
20221da177e4SLinus Torvalds 
20231c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->setpolicy) {
20243a3e9e06SViresh Kumar 		policy->policy = new_policy->policy;
20252d06d8c4SDominik Brodowski 		pr_debug("setting range\n");
20263a3e9e06SViresh Kumar 		ret = cpufreq_driver->setpolicy(new_policy);
20271da177e4SLinus Torvalds 	} else {
20283a3e9e06SViresh Kumar 		if (new_policy->governor != policy->governor) {
20291da177e4SLinus Torvalds 			/* save old, working values */
20303a3e9e06SViresh Kumar 			struct cpufreq_governor *old_gov = policy->governor;
20311da177e4SLinus Torvalds 
20322d06d8c4SDominik Brodowski 			pr_debug("governor switch\n");
20331da177e4SLinus Torvalds 
20341da177e4SLinus Torvalds 			/* end old governor */
20353a3e9e06SViresh Kumar 			if (policy->governor) {
20363a3e9e06SViresh Kumar 				__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
2037ad7722daSviresh kumar 				up_write(&policy->rwsem);
20383a3e9e06SViresh Kumar 				__cpufreq_governor(policy,
20397bd353a9SViresh Kumar 						CPUFREQ_GOV_POLICY_EXIT);
2040ad7722daSviresh kumar 				down_write(&policy->rwsem);
20417bd353a9SViresh Kumar 			}
20421da177e4SLinus Torvalds 
20431da177e4SLinus Torvalds 			/* start new governor */
20443a3e9e06SViresh Kumar 			policy->governor = new_policy->governor;
20453a3e9e06SViresh Kumar 			if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
20463a3e9e06SViresh Kumar 				if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
20477bd353a9SViresh Kumar 					failed = 0;
2048955ef483SViresh Kumar 				} else {
2049ad7722daSviresh kumar 					up_write(&policy->rwsem);
20503a3e9e06SViresh Kumar 					__cpufreq_governor(policy,
20517bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_EXIT);
2052ad7722daSviresh kumar 					down_write(&policy->rwsem);
2053955ef483SViresh Kumar 				}
20547bd353a9SViresh Kumar 			}
20557bd353a9SViresh Kumar 
20567bd353a9SViresh Kumar 			if (failed) {
20571da177e4SLinus Torvalds 				/* new governor failed, so re-start old one */
20582d06d8c4SDominik Brodowski 				pr_debug("starting governor %s failed\n",
20593a3e9e06SViresh Kumar 							policy->governor->name);
20601da177e4SLinus Torvalds 				if (old_gov) {
20613a3e9e06SViresh Kumar 					policy->governor = old_gov;
20623a3e9e06SViresh Kumar 					__cpufreq_governor(policy,
20637bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_INIT);
20643a3e9e06SViresh Kumar 					__cpufreq_governor(policy,
2065e08f5f5bSGautham R Shenoy 							   CPUFREQ_GOV_START);
20661da177e4SLinus Torvalds 				}
20671da177e4SLinus Torvalds 				ret = -EINVAL;
20681da177e4SLinus Torvalds 				goto error_out;
20691da177e4SLinus Torvalds 			}
20701da177e4SLinus Torvalds 			/* might be a policy change, too, so fall through */
20711da177e4SLinus Torvalds 		}
20722d06d8c4SDominik Brodowski 		pr_debug("governor: change or update limits\n");
20733de9bdebSViresh Kumar 		ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
20741da177e4SLinus Torvalds 	}
20751da177e4SLinus Torvalds 
20761da177e4SLinus Torvalds error_out:
20771da177e4SLinus Torvalds 	return ret;
20781da177e4SLinus Torvalds }
20791da177e4SLinus Torvalds 
20801da177e4SLinus Torvalds /**
20811da177e4SLinus Torvalds  *	cpufreq_update_policy - re-evaluate an existing cpufreq policy
20821da177e4SLinus Torvalds  *	@cpu: CPU which shall be re-evaluated
20831da177e4SLinus Torvalds  *
208425985edcSLucas De Marchi  *	Useful for policy notifiers which have different necessities
20851da177e4SLinus Torvalds  *	at different times.
20861da177e4SLinus Torvalds  */
20871da177e4SLinus Torvalds int cpufreq_update_policy(unsigned int cpu)
20881da177e4SLinus Torvalds {
20893a3e9e06SViresh Kumar 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
20903a3e9e06SViresh Kumar 	struct cpufreq_policy new_policy;
2091f1829e4aSJulia Lawall 	int ret;
20921da177e4SLinus Torvalds 
20933a3e9e06SViresh Kumar 	if (!policy) {
2094f1829e4aSJulia Lawall 		ret = -ENODEV;
2095f1829e4aSJulia Lawall 		goto no_policy;
2096f1829e4aSJulia Lawall 	}
20971da177e4SLinus Torvalds 
2098ad7722daSviresh kumar 	down_write(&policy->rwsem);
20991da177e4SLinus Torvalds 
21002d06d8c4SDominik Brodowski 	pr_debug("updating policy for CPU %u\n", cpu);
2101d5b73cd8SViresh Kumar 	memcpy(&new_policy, policy, sizeof(*policy));
21023a3e9e06SViresh Kumar 	new_policy.min = policy->user_policy.min;
21033a3e9e06SViresh Kumar 	new_policy.max = policy->user_policy.max;
21043a3e9e06SViresh Kumar 	new_policy.policy = policy->user_policy.policy;
21053a3e9e06SViresh Kumar 	new_policy.governor = policy->user_policy.governor;
21061da177e4SLinus Torvalds 
2107bb176f7dSViresh Kumar 	/*
2108bb176f7dSViresh Kumar 	 * BIOS might change freq behind our back
2109bb176f7dSViresh Kumar 	 * -> ask driver for current freq and notify governors about a change
2110bb176f7dSViresh Kumar 	 */
21111c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->get) {
21123a3e9e06SViresh Kumar 		new_policy.cur = cpufreq_driver->get(cpu);
21133a3e9e06SViresh Kumar 		if (!policy->cur) {
21142d06d8c4SDominik Brodowski 			pr_debug("Driver did not initialize current freq");
21153a3e9e06SViresh Kumar 			policy->cur = new_policy.cur;
2116a85f7bd3SThomas Renninger 		} else {
21179c0ebcf7SViresh Kumar 			if (policy->cur != new_policy.cur && has_target())
21183a3e9e06SViresh Kumar 				cpufreq_out_of_sync(cpu, policy->cur,
21193a3e9e06SViresh Kumar 								new_policy.cur);
21200961dd0dSThomas Renninger 		}
2121a85f7bd3SThomas Renninger 	}
21220961dd0dSThomas Renninger 
2123037ce839SViresh Kumar 	ret = cpufreq_set_policy(policy, &new_policy);
21241da177e4SLinus Torvalds 
2125ad7722daSviresh kumar 	up_write(&policy->rwsem);
21265a01f2e8SVenkatesh Pallipadi 
21273a3e9e06SViresh Kumar 	cpufreq_cpu_put(policy);
2128f1829e4aSJulia Lawall no_policy:
21291da177e4SLinus Torvalds 	return ret;
21301da177e4SLinus Torvalds }
21311da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_update_policy);
21321da177e4SLinus Torvalds 
21332760984fSPaul Gortmaker static int cpufreq_cpu_callback(struct notifier_block *nfb,
2134c32b6b8eSAshok Raj 					unsigned long action, void *hcpu)
2135c32b6b8eSAshok Raj {
2136c32b6b8eSAshok Raj 	unsigned int cpu = (unsigned long)hcpu;
21378a25a2fdSKay Sievers 	struct device *dev;
21385302c3fbSSrivatsa S. Bhat 	bool frozen = false;
2139c32b6b8eSAshok Raj 
21408a25a2fdSKay Sievers 	dev = get_cpu_device(cpu);
21418a25a2fdSKay Sievers 	if (dev) {
21425302c3fbSSrivatsa S. Bhat 
2143d4faadd5SRafael J. Wysocki 		if (action & CPU_TASKS_FROZEN)
2144d4faadd5SRafael J. Wysocki 			frozen = true;
2145d4faadd5SRafael J. Wysocki 
21465302c3fbSSrivatsa S. Bhat 		switch (action & ~CPU_TASKS_FROZEN) {
2147c32b6b8eSAshok Raj 		case CPU_ONLINE:
21485302c3fbSSrivatsa S. Bhat 			__cpufreq_add_dev(dev, NULL, frozen);
214923d32899SSrivatsa S. Bhat 			cpufreq_update_policy(cpu);
2150c32b6b8eSAshok Raj 			break;
21515302c3fbSSrivatsa S. Bhat 
2152c32b6b8eSAshok Raj 		case CPU_DOWN_PREPARE:
2153cedb70afSSrivatsa S. Bhat 			__cpufreq_remove_dev_prepare(dev, NULL, frozen);
21541aee40acSSrivatsa S. Bhat 			break;
21551aee40acSSrivatsa S. Bhat 
21561aee40acSSrivatsa S. Bhat 		case CPU_POST_DEAD:
2157cedb70afSSrivatsa S. Bhat 			__cpufreq_remove_dev_finish(dev, NULL, frozen);
2158c32b6b8eSAshok Raj 			break;
21595302c3fbSSrivatsa S. Bhat 
21605a01f2e8SVenkatesh Pallipadi 		case CPU_DOWN_FAILED:
21615302c3fbSSrivatsa S. Bhat 			__cpufreq_add_dev(dev, NULL, frozen);
2162c32b6b8eSAshok Raj 			break;
2163c32b6b8eSAshok Raj 		}
2164c32b6b8eSAshok Raj 	}
2165c32b6b8eSAshok Raj 	return NOTIFY_OK;
2166c32b6b8eSAshok Raj }
2167c32b6b8eSAshok Raj 
21689c36f746SNeal Buckendahl static struct notifier_block __refdata cpufreq_cpu_notifier = {
2169c32b6b8eSAshok Raj 	.notifier_call = cpufreq_cpu_callback,
2170c32b6b8eSAshok Raj };
21711da177e4SLinus Torvalds 
21721da177e4SLinus Torvalds /*********************************************************************
21731da177e4SLinus Torvalds  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
21741da177e4SLinus Torvalds  *********************************************************************/
21751da177e4SLinus Torvalds 
21761da177e4SLinus Torvalds /**
21771da177e4SLinus Torvalds  * cpufreq_register_driver - register a CPU Frequency driver
21781da177e4SLinus Torvalds  * @driver_data: A struct cpufreq_driver containing the values#
21791da177e4SLinus Torvalds  * submitted by the CPU Frequency driver.
21801da177e4SLinus Torvalds  *
21811da177e4SLinus Torvalds  * Registers a CPU Frequency driver to this core code. This code
21821da177e4SLinus Torvalds  * returns zero on success, -EBUSY when another driver got here first
21831da177e4SLinus Torvalds  * (and isn't unregistered in the meantime).
21841da177e4SLinus Torvalds  *
21851da177e4SLinus Torvalds  */
2186221dee28SLinus Torvalds int cpufreq_register_driver(struct cpufreq_driver *driver_data)
21871da177e4SLinus Torvalds {
21881da177e4SLinus Torvalds 	unsigned long flags;
21891da177e4SLinus Torvalds 	int ret;
21901da177e4SLinus Torvalds 
2191a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2192a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2193a7b422cdSKonrad Rzeszutek Wilk 
21941da177e4SLinus Torvalds 	if (!driver_data || !driver_data->verify || !driver_data->init ||
21959c0ebcf7SViresh Kumar 	    !(driver_data->setpolicy || driver_data->target_index ||
21969c0ebcf7SViresh Kumar 		    driver_data->target))
21971da177e4SLinus Torvalds 		return -EINVAL;
21981da177e4SLinus Torvalds 
21992d06d8c4SDominik Brodowski 	pr_debug("trying to register driver %s\n", driver_data->name);
22001da177e4SLinus Torvalds 
22011da177e4SLinus Torvalds 	if (driver_data->setpolicy)
22021da177e4SLinus Torvalds 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
22031da177e4SLinus Torvalds 
22040d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
22051c3d85ddSRafael J. Wysocki 	if (cpufreq_driver) {
22060d1857a1SNathan Zimmer 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
22074dea5806SYinghai Lu 		return -EEXIST;
22081da177e4SLinus Torvalds 	}
22091c3d85ddSRafael J. Wysocki 	cpufreq_driver = driver_data;
22100d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
22111da177e4SLinus Torvalds 
22128a25a2fdSKay Sievers 	ret = subsys_interface_register(&cpufreq_interface);
22138f5bc2abSJiri Slaby 	if (ret)
22148f5bc2abSJiri Slaby 		goto err_null_driver;
22151da177e4SLinus Torvalds 
22161c3d85ddSRafael J. Wysocki 	if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
22171da177e4SLinus Torvalds 		int i;
22181da177e4SLinus Torvalds 		ret = -ENODEV;
22191da177e4SLinus Torvalds 
22201da177e4SLinus Torvalds 		/* check for at least one working CPU */
22217a6aedfaSMike Travis 		for (i = 0; i < nr_cpu_ids; i++)
22227a6aedfaSMike Travis 			if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
22231da177e4SLinus Torvalds 				ret = 0;
22247a6aedfaSMike Travis 				break;
22257a6aedfaSMike Travis 			}
22261da177e4SLinus Torvalds 
22271da177e4SLinus Torvalds 		/* if all ->init() calls failed, unregister */
22281da177e4SLinus Torvalds 		if (ret) {
22292d06d8c4SDominik Brodowski 			pr_debug("no CPU initialized for driver %s\n",
2230e08f5f5bSGautham R Shenoy 							driver_data->name);
22318a25a2fdSKay Sievers 			goto err_if_unreg;
22321da177e4SLinus Torvalds 		}
22331da177e4SLinus Torvalds 	}
22341da177e4SLinus Torvalds 
223565edc68cSChandra Seetharaman 	register_hotcpu_notifier(&cpufreq_cpu_notifier);
22362d06d8c4SDominik Brodowski 	pr_debug("driver %s up and running\n", driver_data->name);
22371da177e4SLinus Torvalds 
22388f5bc2abSJiri Slaby 	return 0;
22398a25a2fdSKay Sievers err_if_unreg:
22408a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
22418f5bc2abSJiri Slaby err_null_driver:
22420d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
22431c3d85ddSRafael J. Wysocki 	cpufreq_driver = NULL;
22440d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
22454d34a67dSDave Jones 	return ret;
22461da177e4SLinus Torvalds }
22471da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_driver);
22481da177e4SLinus Torvalds 
22491da177e4SLinus Torvalds /**
22501da177e4SLinus Torvalds  * cpufreq_unregister_driver - unregister the current CPUFreq driver
22511da177e4SLinus Torvalds  *
22521da177e4SLinus Torvalds  * Unregister the current CPUFreq driver. Only call this if you have
22531da177e4SLinus Torvalds  * the right to do so, i.e. if you have succeeded in initialising before!
22541da177e4SLinus Torvalds  * Returns zero if successful, and -EINVAL if the cpufreq_driver is
22551da177e4SLinus Torvalds  * currently not initialised.
22561da177e4SLinus Torvalds  */
2257221dee28SLinus Torvalds int cpufreq_unregister_driver(struct cpufreq_driver *driver)
22581da177e4SLinus Torvalds {
22591da177e4SLinus Torvalds 	unsigned long flags;
22601da177e4SLinus Torvalds 
22611c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver || (driver != cpufreq_driver))
22621da177e4SLinus Torvalds 		return -EINVAL;
22631da177e4SLinus Torvalds 
22642d06d8c4SDominik Brodowski 	pr_debug("unregistering driver %s\n", driver->name);
22651da177e4SLinus Torvalds 
22668a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
226765edc68cSChandra Seetharaman 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
22681da177e4SLinus Torvalds 
22696eed9404SViresh Kumar 	down_write(&cpufreq_rwsem);
22700d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
22716eed9404SViresh Kumar 
22721c3d85ddSRafael J. Wysocki 	cpufreq_driver = NULL;
22736eed9404SViresh Kumar 
22740d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
22756eed9404SViresh Kumar 	up_write(&cpufreq_rwsem);
22761da177e4SLinus Torvalds 
22771da177e4SLinus Torvalds 	return 0;
22781da177e4SLinus Torvalds }
22791da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
22805a01f2e8SVenkatesh Pallipadi 
22815a01f2e8SVenkatesh Pallipadi static int __init cpufreq_core_init(void)
22825a01f2e8SVenkatesh Pallipadi {
2283a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2284a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2285a7b422cdSKonrad Rzeszutek Wilk 
22862361be23SViresh Kumar 	cpufreq_global_kobject = kobject_create();
22878aa84ad8SThomas Renninger 	BUG_ON(!cpufreq_global_kobject);
2288e00e56dfSRafael J. Wysocki 	register_syscore_ops(&cpufreq_syscore_ops);
22898aa84ad8SThomas Renninger 
22905a01f2e8SVenkatesh Pallipadi 	return 0;
22915a01f2e8SVenkatesh Pallipadi }
22925a01f2e8SVenkatesh Pallipadi core_initcall(cpufreq_core_init);
2293