xref: /openbmc/linux/drivers/cpufreq/cpufreq.c (revision 71c3461ef7c67024792d283b88630245a6c169ba)
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 
2072a4ce34SViresh Kumar #include <asm/cputime.h>
211da177e4SLinus Torvalds #include <linux/kernel.h>
2272a4ce34SViresh Kumar #include <linux/kernel_stat.h>
231da177e4SLinus Torvalds #include <linux/module.h>
241da177e4SLinus Torvalds #include <linux/init.h>
251da177e4SLinus Torvalds #include <linux/notifier.h>
261da177e4SLinus Torvalds #include <linux/cpufreq.h>
271da177e4SLinus Torvalds #include <linux/delay.h>
281da177e4SLinus Torvalds #include <linux/interrupt.h>
291da177e4SLinus Torvalds #include <linux/spinlock.h>
3072a4ce34SViresh Kumar #include <linux/tick.h>
311da177e4SLinus Torvalds #include <linux/device.h>
321da177e4SLinus Torvalds #include <linux/slab.h>
331da177e4SLinus Torvalds #include <linux/cpu.h>
341da177e4SLinus Torvalds #include <linux/completion.h>
353fc54d37Sakpm@osdl.org #include <linux/mutex.h>
36e00e56dfSRafael J. Wysocki #include <linux/syscore_ops.h>
371da177e4SLinus Torvalds 
386f4f2723SThomas Renninger #include <trace/events/power.h>
396f4f2723SThomas Renninger 
401da177e4SLinus Torvalds /**
41cd878479SDave Jones  * The "cpufreq driver" - the arch- or hardware-dependent low
421da177e4SLinus Torvalds  * level driver of CPUFreq support, and its spinlock. This lock
431da177e4SLinus Torvalds  * also protects the cpufreq_cpu_data array.
441da177e4SLinus Torvalds  */
451c3d85ddSRafael J. Wysocki static struct cpufreq_driver *cpufreq_driver;
467a6aedfaSMike Travis static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
478414809cSSrivatsa S. Bhat static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
48bb176f7dSViresh Kumar static DEFINE_RWLOCK(cpufreq_driver_lock);
49bb176f7dSViresh Kumar static DEFINE_MUTEX(cpufreq_governor_lock);
50bb176f7dSViresh Kumar 
51084f3493SThomas Renninger #ifdef CONFIG_HOTPLUG_CPU
52084f3493SThomas Renninger /* This one keeps track of the previously set governor of a removed CPU */
53e77b89f1SDmitry Monakhov static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
54084f3493SThomas Renninger #endif
551da177e4SLinus Torvalds 
565a01f2e8SVenkatesh Pallipadi /*
575a01f2e8SVenkatesh Pallipadi  * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
585a01f2e8SVenkatesh Pallipadi  * all cpufreq/hotplug/workqueue/etc related lock issues.
595a01f2e8SVenkatesh Pallipadi  *
605a01f2e8SVenkatesh Pallipadi  * The rules for this semaphore:
615a01f2e8SVenkatesh Pallipadi  * - Any routine that wants to read from the policy structure will
625a01f2e8SVenkatesh Pallipadi  *   do a down_read on this semaphore.
635a01f2e8SVenkatesh Pallipadi  * - Any routine that will write to the policy structure and/or may take away
645a01f2e8SVenkatesh Pallipadi  *   the policy altogether (eg. CPU hotplug), will hold this lock in write
655a01f2e8SVenkatesh Pallipadi  *   mode before doing so.
665a01f2e8SVenkatesh Pallipadi  *
675a01f2e8SVenkatesh Pallipadi  * Additional rules:
685a01f2e8SVenkatesh Pallipadi  * - Governor routines that can be called in cpufreq hotplug path should not
695a01f2e8SVenkatesh Pallipadi  *   take this sem as top level hotplug notifier handler takes this.
70395913d0SMathieu Desnoyers  * - Lock should not be held across
71395913d0SMathieu Desnoyers  *     __cpufreq_governor(data, CPUFREQ_GOV_STOP);
725a01f2e8SVenkatesh Pallipadi  */
73f1625066STejun Heo static DEFINE_PER_CPU(int, cpufreq_policy_cpu);
745a01f2e8SVenkatesh Pallipadi static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
755a01f2e8SVenkatesh Pallipadi 
765a01f2e8SVenkatesh Pallipadi #define lock_policy_rwsem(mode, cpu)					\
77fa1d8af4SViresh Kumar static int lock_policy_rwsem_##mode(int cpu)				\
785a01f2e8SVenkatesh Pallipadi {									\
79f1625066STejun Heo 	int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);		\
805a01f2e8SVenkatesh Pallipadi 	BUG_ON(policy_cpu == -1);					\
815a01f2e8SVenkatesh Pallipadi 	down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
825a01f2e8SVenkatesh Pallipadi 									\
835a01f2e8SVenkatesh Pallipadi 	return 0;							\
845a01f2e8SVenkatesh Pallipadi }
855a01f2e8SVenkatesh Pallipadi 
865a01f2e8SVenkatesh Pallipadi lock_policy_rwsem(read, cpu);
875a01f2e8SVenkatesh Pallipadi lock_policy_rwsem(write, cpu);
885a01f2e8SVenkatesh Pallipadi 
89fa1d8af4SViresh Kumar #define unlock_policy_rwsem(mode, cpu)					\
90fa1d8af4SViresh Kumar static void unlock_policy_rwsem_##mode(int cpu)				\
91fa1d8af4SViresh Kumar {									\
92fa1d8af4SViresh Kumar 	int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);		\
93fa1d8af4SViresh Kumar 	BUG_ON(policy_cpu == -1);					\
94fa1d8af4SViresh Kumar 	up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
955a01f2e8SVenkatesh Pallipadi }
965a01f2e8SVenkatesh Pallipadi 
97fa1d8af4SViresh Kumar unlock_policy_rwsem(read, cpu);
98fa1d8af4SViresh Kumar unlock_policy_rwsem(write, cpu);
995a01f2e8SVenkatesh Pallipadi 
1001da177e4SLinus Torvalds /* internal prototypes */
10129464f28SDave Jones static int __cpufreq_governor(struct cpufreq_policy *policy,
10229464f28SDave Jones 		unsigned int event);
1035a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu);
10465f27f38SDavid Howells static void handle_update(struct work_struct *work);
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds /**
1071da177e4SLinus Torvalds  * Two notifier lists: the "policy" list is involved in the
1081da177e4SLinus Torvalds  * validation process for a new CPU frequency policy; the
1091da177e4SLinus Torvalds  * "transition" list for kernel code that needs to handle
1101da177e4SLinus Torvalds  * changes to devices when the CPU clock speed changes.
1111da177e4SLinus Torvalds  * The mutex locks both lists.
1121da177e4SLinus Torvalds  */
113e041c683SAlan Stern static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
114b4dfdbb3SAlan Stern static struct srcu_notifier_head cpufreq_transition_notifier_list;
1151da177e4SLinus Torvalds 
11674212ca4SCesar Eduardo Barros static bool init_cpufreq_transition_notifier_list_called;
117b4dfdbb3SAlan Stern static int __init init_cpufreq_transition_notifier_list(void)
118b4dfdbb3SAlan Stern {
119b4dfdbb3SAlan Stern 	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
12074212ca4SCesar Eduardo Barros 	init_cpufreq_transition_notifier_list_called = true;
121b4dfdbb3SAlan Stern 	return 0;
122b4dfdbb3SAlan Stern }
123b3438f82SLinus Torvalds pure_initcall(init_cpufreq_transition_notifier_list);
1241da177e4SLinus Torvalds 
125a7b422cdSKonrad Rzeszutek Wilk static int off __read_mostly;
126da584455SViresh Kumar static int cpufreq_disabled(void)
127a7b422cdSKonrad Rzeszutek Wilk {
128a7b422cdSKonrad Rzeszutek Wilk 	return off;
129a7b422cdSKonrad Rzeszutek Wilk }
130a7b422cdSKonrad Rzeszutek Wilk void disable_cpufreq(void)
131a7b422cdSKonrad Rzeszutek Wilk {
132a7b422cdSKonrad Rzeszutek Wilk 	off = 1;
133a7b422cdSKonrad Rzeszutek Wilk }
1341da177e4SLinus Torvalds static LIST_HEAD(cpufreq_governor_list);
1353fc54d37Sakpm@osdl.org static DEFINE_MUTEX(cpufreq_governor_mutex);
1361da177e4SLinus Torvalds 
1374d5dcc42SViresh Kumar bool have_governor_per_policy(void)
1384d5dcc42SViresh Kumar {
1391c3d85ddSRafael J. Wysocki 	return cpufreq_driver->have_governor_per_policy;
1404d5dcc42SViresh Kumar }
1413f869d6dSViresh Kumar EXPORT_SYMBOL_GPL(have_governor_per_policy);
1424d5dcc42SViresh Kumar 
143944e9a03SViresh Kumar struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
144944e9a03SViresh Kumar {
145944e9a03SViresh Kumar 	if (have_governor_per_policy())
146944e9a03SViresh Kumar 		return &policy->kobj;
147944e9a03SViresh Kumar 	else
148944e9a03SViresh Kumar 		return cpufreq_global_kobject;
149944e9a03SViresh Kumar }
150944e9a03SViresh Kumar EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
151944e9a03SViresh Kumar 
15272a4ce34SViresh Kumar static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
15372a4ce34SViresh Kumar {
15472a4ce34SViresh Kumar 	u64 idle_time;
15572a4ce34SViresh Kumar 	u64 cur_wall_time;
15672a4ce34SViresh Kumar 	u64 busy_time;
15772a4ce34SViresh Kumar 
15872a4ce34SViresh Kumar 	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
15972a4ce34SViresh Kumar 
16072a4ce34SViresh Kumar 	busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
16172a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
16272a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
16372a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
16472a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
16572a4ce34SViresh Kumar 	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
16672a4ce34SViresh Kumar 
16772a4ce34SViresh Kumar 	idle_time = cur_wall_time - busy_time;
16872a4ce34SViresh Kumar 	if (wall)
16972a4ce34SViresh Kumar 		*wall = cputime_to_usecs(cur_wall_time);
17072a4ce34SViresh Kumar 
17172a4ce34SViresh Kumar 	return cputime_to_usecs(idle_time);
17272a4ce34SViresh Kumar }
17372a4ce34SViresh Kumar 
17472a4ce34SViresh Kumar u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
17572a4ce34SViresh Kumar {
17672a4ce34SViresh Kumar 	u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL);
17772a4ce34SViresh Kumar 
17872a4ce34SViresh Kumar 	if (idle_time == -1ULL)
17972a4ce34SViresh Kumar 		return get_cpu_idle_time_jiffy(cpu, wall);
18072a4ce34SViresh Kumar 	else if (!io_busy)
18172a4ce34SViresh Kumar 		idle_time += get_cpu_iowait_time_us(cpu, wall);
18272a4ce34SViresh Kumar 
18372a4ce34SViresh Kumar 	return idle_time;
18472a4ce34SViresh Kumar }
18572a4ce34SViresh Kumar EXPORT_SYMBOL_GPL(get_cpu_idle_time);
18672a4ce34SViresh Kumar 
187a9144436SStephen Boyd static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
1881da177e4SLinus Torvalds {
1891da177e4SLinus Torvalds 	struct cpufreq_policy *data;
1901da177e4SLinus Torvalds 	unsigned long flags;
1911da177e4SLinus Torvalds 
1927a6aedfaSMike Travis 	if (cpu >= nr_cpu_ids)
1931da177e4SLinus Torvalds 		goto err_out;
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds 	/* get the cpufreq driver */
1960d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1971da177e4SLinus Torvalds 
1981c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver)
1991c3d85ddSRafael J. Wysocki 		goto err_out_unlock;
2001c3d85ddSRafael J. Wysocki 
2011c3d85ddSRafael J. Wysocki 	if (!try_module_get(cpufreq_driver->owner))
2021c3d85ddSRafael J. Wysocki 		goto err_out_unlock;
2031c3d85ddSRafael J. Wysocki 
2041da177e4SLinus Torvalds 	/* get the CPU */
2057a6aedfaSMike Travis 	data = per_cpu(cpufreq_cpu_data, cpu);
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds 	if (!data)
2081da177e4SLinus Torvalds 		goto err_out_put_module;
2091da177e4SLinus Torvalds 
210a9144436SStephen Boyd 	if (!sysfs && !kobject_get(&data->kobj))
2111da177e4SLinus Torvalds 		goto err_out_put_module;
2121da177e4SLinus Torvalds 
2130d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
2141da177e4SLinus Torvalds 	return data;
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds err_out_put_module:
2171c3d85ddSRafael J. Wysocki 	module_put(cpufreq_driver->owner);
2185800043bSNathan Zimmer err_out_unlock:
2191c3d85ddSRafael J. Wysocki 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
2201da177e4SLinus Torvalds err_out:
2211da177e4SLinus Torvalds 	return NULL;
2221da177e4SLinus Torvalds }
223a9144436SStephen Boyd 
224a9144436SStephen Boyd struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
225a9144436SStephen Boyd {
226d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
227d5aaffa9SDirk Brandewie 		return NULL;
228d5aaffa9SDirk Brandewie 
229a9144436SStephen Boyd 	return __cpufreq_cpu_get(cpu, false);
230a9144436SStephen Boyd }
2311da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
2321da177e4SLinus Torvalds 
233a9144436SStephen Boyd static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
2341da177e4SLinus Torvalds {
235a9144436SStephen Boyd 	return __cpufreq_cpu_get(cpu, true);
236a9144436SStephen Boyd }
237a9144436SStephen Boyd 
238a9144436SStephen Boyd static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
239a9144436SStephen Boyd {
240a9144436SStephen Boyd 	if (!sysfs)
2411da177e4SLinus Torvalds 		kobject_put(&data->kobj);
2421c3d85ddSRafael J. Wysocki 	module_put(cpufreq_driver->owner);
2431da177e4SLinus Torvalds }
244a9144436SStephen Boyd 
245a9144436SStephen Boyd void cpufreq_cpu_put(struct cpufreq_policy *data)
246a9144436SStephen Boyd {
247d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
248d5aaffa9SDirk Brandewie 		return;
249d5aaffa9SDirk Brandewie 
250a9144436SStephen Boyd 	__cpufreq_cpu_put(data, false);
251a9144436SStephen Boyd }
2521da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
2531da177e4SLinus Torvalds 
254a9144436SStephen Boyd static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
255a9144436SStephen Boyd {
256a9144436SStephen Boyd 	__cpufreq_cpu_put(data, true);
257a9144436SStephen Boyd }
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds /*********************************************************************
2601da177e4SLinus Torvalds  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
2611da177e4SLinus Torvalds  *********************************************************************/
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds /**
2641da177e4SLinus Torvalds  * adjust_jiffies - adjust the system "loops_per_jiffy"
2651da177e4SLinus Torvalds  *
2661da177e4SLinus Torvalds  * This function alters the system "loops_per_jiffy" for the clock
2671da177e4SLinus Torvalds  * speed change. Note that loops_per_jiffy cannot be updated on SMP
2681da177e4SLinus Torvalds  * systems as each CPU might be scaled differently. So, use the arch
2691da177e4SLinus Torvalds  * per-CPU loops_per_jiffy value wherever possible.
2701da177e4SLinus Torvalds  */
2711da177e4SLinus Torvalds #ifndef CONFIG_SMP
2721da177e4SLinus Torvalds static unsigned long l_p_j_ref;
2731da177e4SLinus Torvalds static unsigned int l_p_j_ref_freq;
2741da177e4SLinus Torvalds 
275858119e1SArjan van de Ven static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
2761da177e4SLinus Torvalds {
2771da177e4SLinus Torvalds 	if (ci->flags & CPUFREQ_CONST_LOOPS)
2781da177e4SLinus Torvalds 		return;
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds 	if (!l_p_j_ref_freq) {
2811da177e4SLinus Torvalds 		l_p_j_ref = loops_per_jiffy;
2821da177e4SLinus Torvalds 		l_p_j_ref_freq = ci->old;
2832d06d8c4SDominik Brodowski 		pr_debug("saving %lu as reference value for loops_per_jiffy; "
284e08f5f5bSGautham R Shenoy 			"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
2851da177e4SLinus Torvalds 	}
286d08de0c1SAfzal Mohammed 	if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
28742d4dc3fSBenjamin Herrenschmidt 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
288e08f5f5bSGautham R Shenoy 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
289e08f5f5bSGautham R Shenoy 								ci->new);
2902d06d8c4SDominik Brodowski 		pr_debug("scaling loops_per_jiffy to %lu "
291e08f5f5bSGautham R Shenoy 			"for frequency %u kHz\n", loops_per_jiffy, ci->new);
2921da177e4SLinus Torvalds 	}
2931da177e4SLinus Torvalds }
2941da177e4SLinus Torvalds #else
295e08f5f5bSGautham R Shenoy static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
296e08f5f5bSGautham R Shenoy {
297e08f5f5bSGautham R Shenoy 	return;
298e08f5f5bSGautham R Shenoy }
2991da177e4SLinus Torvalds #endif
3001da177e4SLinus Torvalds 
3010956df9cSViresh Kumar static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
302b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
3031da177e4SLinus Torvalds {
3041da177e4SLinus Torvalds 	BUG_ON(irqs_disabled());
3051da177e4SLinus Torvalds 
306d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
307d5aaffa9SDirk Brandewie 		return;
308d5aaffa9SDirk Brandewie 
3091c3d85ddSRafael J. Wysocki 	freqs->flags = cpufreq_driver->flags;
3102d06d8c4SDominik Brodowski 	pr_debug("notification %u of frequency transition to %u kHz\n",
311e4472cb3SDave Jones 		state, freqs->new);
3121da177e4SLinus Torvalds 
3131da177e4SLinus Torvalds 	switch (state) {
314e4472cb3SDave Jones 
3151da177e4SLinus Torvalds 	case CPUFREQ_PRECHANGE:
316266c13d7SViresh Kumar 		if (WARN(policy->transition_ongoing ==
317266c13d7SViresh Kumar 					cpumask_weight(policy->cpus),
3187c30ed53SViresh Kumar 				"In middle of another frequency transition\n"))
3197c30ed53SViresh Kumar 			return;
3207c30ed53SViresh Kumar 
321266c13d7SViresh Kumar 		policy->transition_ongoing++;
3227c30ed53SViresh Kumar 
323e4472cb3SDave Jones 		/* detect if the driver reported a value as "old frequency"
324e4472cb3SDave Jones 		 * which is not equal to what the cpufreq core thinks is
325e4472cb3SDave Jones 		 * "old frequency".
3261da177e4SLinus Torvalds 		 */
3271c3d85ddSRafael J. Wysocki 		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
328e4472cb3SDave Jones 			if ((policy) && (policy->cpu == freqs->cpu) &&
329e4472cb3SDave Jones 			    (policy->cur) && (policy->cur != freqs->old)) {
3302d06d8c4SDominik Brodowski 				pr_debug("Warning: CPU frequency is"
331e4472cb3SDave Jones 					" %u, cpufreq assumed %u kHz.\n",
332e4472cb3SDave Jones 					freqs->old, policy->cur);
333e4472cb3SDave Jones 				freqs->old = policy->cur;
3341da177e4SLinus Torvalds 			}
3351da177e4SLinus Torvalds 		}
336b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
337e4472cb3SDave Jones 				CPUFREQ_PRECHANGE, freqs);
3381da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
3391da177e4SLinus Torvalds 		break;
340e4472cb3SDave Jones 
3411da177e4SLinus Torvalds 	case CPUFREQ_POSTCHANGE:
3427c30ed53SViresh Kumar 		if (WARN(!policy->transition_ongoing,
3437c30ed53SViresh Kumar 				"No frequency transition in progress\n"))
3447c30ed53SViresh Kumar 			return;
3457c30ed53SViresh Kumar 
346266c13d7SViresh Kumar 		policy->transition_ongoing--;
3477c30ed53SViresh Kumar 
3481da177e4SLinus Torvalds 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
3492d06d8c4SDominik Brodowski 		pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
3506f4f2723SThomas Renninger 			(unsigned long)freqs->cpu);
35125e41933SThomas Renninger 		trace_cpu_frequency(freqs->new, freqs->cpu);
352b4dfdbb3SAlan Stern 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
353e4472cb3SDave Jones 				CPUFREQ_POSTCHANGE, freqs);
354e4472cb3SDave Jones 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
355e4472cb3SDave Jones 			policy->cur = freqs->new;
3561da177e4SLinus Torvalds 		break;
3571da177e4SLinus Torvalds 	}
3581da177e4SLinus Torvalds }
359bb176f7dSViresh Kumar 
360b43a7ffbSViresh Kumar /**
361b43a7ffbSViresh Kumar  * cpufreq_notify_transition - call notifier chain and adjust_jiffies
362b43a7ffbSViresh Kumar  * on frequency transition.
363b43a7ffbSViresh Kumar  *
364b43a7ffbSViresh Kumar  * This function calls the transition notifiers and the "adjust_jiffies"
365b43a7ffbSViresh Kumar  * function. It is called twice on all CPU frequency changes that have
366b43a7ffbSViresh Kumar  * external effects.
367b43a7ffbSViresh Kumar  */
368b43a7ffbSViresh Kumar void cpufreq_notify_transition(struct cpufreq_policy *policy,
369b43a7ffbSViresh Kumar 		struct cpufreq_freqs *freqs, unsigned int state)
370b43a7ffbSViresh Kumar {
371b43a7ffbSViresh Kumar 	for_each_cpu(freqs->cpu, policy->cpus)
372b43a7ffbSViresh Kumar 		__cpufreq_notify_transition(policy, freqs, state);
373b43a7ffbSViresh Kumar }
3741da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds 
3771da177e4SLinus Torvalds /*********************************************************************
3781da177e4SLinus Torvalds  *                          SYSFS INTERFACE                          *
3791da177e4SLinus Torvalds  *********************************************************************/
3801da177e4SLinus Torvalds 
3813bcb09a3SJeremy Fitzhardinge static struct cpufreq_governor *__find_governor(const char *str_governor)
3823bcb09a3SJeremy Fitzhardinge {
3833bcb09a3SJeremy Fitzhardinge 	struct cpufreq_governor *t;
3843bcb09a3SJeremy Fitzhardinge 
3853bcb09a3SJeremy Fitzhardinge 	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
3863bcb09a3SJeremy Fitzhardinge 		if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN))
3873bcb09a3SJeremy Fitzhardinge 			return t;
3883bcb09a3SJeremy Fitzhardinge 
3893bcb09a3SJeremy Fitzhardinge 	return NULL;
3903bcb09a3SJeremy Fitzhardinge }
3913bcb09a3SJeremy Fitzhardinge 
3921da177e4SLinus Torvalds /**
3931da177e4SLinus Torvalds  * cpufreq_parse_governor - parse a governor string
3941da177e4SLinus Torvalds  */
3951da177e4SLinus Torvalds static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
3961da177e4SLinus Torvalds 				struct cpufreq_governor **governor)
3971da177e4SLinus Torvalds {
3983bcb09a3SJeremy Fitzhardinge 	int err = -EINVAL;
3993bcb09a3SJeremy Fitzhardinge 
4001c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver)
4013bcb09a3SJeremy Fitzhardinge 		goto out;
4023bcb09a3SJeremy Fitzhardinge 
4031c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->setpolicy) {
4041da177e4SLinus Torvalds 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
4051da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_PERFORMANCE;
4063bcb09a3SJeremy Fitzhardinge 			err = 0;
407e08f5f5bSGautham R Shenoy 		} else if (!strnicmp(str_governor, "powersave",
408e08f5f5bSGautham R Shenoy 						CPUFREQ_NAME_LEN)) {
4091da177e4SLinus Torvalds 			*policy = CPUFREQ_POLICY_POWERSAVE;
4103bcb09a3SJeremy Fitzhardinge 			err = 0;
4111da177e4SLinus Torvalds 		}
4121c3d85ddSRafael J. Wysocki 	} else if (cpufreq_driver->target) {
4131da177e4SLinus Torvalds 		struct cpufreq_governor *t;
4143bcb09a3SJeremy Fitzhardinge 
4153fc54d37Sakpm@osdl.org 		mutex_lock(&cpufreq_governor_mutex);
4163bcb09a3SJeremy Fitzhardinge 
4173bcb09a3SJeremy Fitzhardinge 		t = __find_governor(str_governor);
4183bcb09a3SJeremy Fitzhardinge 
419ea714970SJeremy Fitzhardinge 		if (t == NULL) {
420ea714970SJeremy Fitzhardinge 			int ret;
421ea714970SJeremy Fitzhardinge 
422ea714970SJeremy Fitzhardinge 			mutex_unlock(&cpufreq_governor_mutex);
4231a8e1463SKees Cook 			ret = request_module("cpufreq_%s", str_governor);
424ea714970SJeremy Fitzhardinge 			mutex_lock(&cpufreq_governor_mutex);
425ea714970SJeremy Fitzhardinge 
426ea714970SJeremy Fitzhardinge 			if (ret == 0)
427ea714970SJeremy Fitzhardinge 				t = __find_governor(str_governor);
428ea714970SJeremy Fitzhardinge 		}
429ea714970SJeremy Fitzhardinge 
4303bcb09a3SJeremy Fitzhardinge 		if (t != NULL) {
4311da177e4SLinus Torvalds 			*governor = t;
4323bcb09a3SJeremy Fitzhardinge 			err = 0;
4331da177e4SLinus Torvalds 		}
4343bcb09a3SJeremy Fitzhardinge 
4353bcb09a3SJeremy Fitzhardinge 		mutex_unlock(&cpufreq_governor_mutex);
4361da177e4SLinus Torvalds 	}
4371da177e4SLinus Torvalds out:
4383bcb09a3SJeremy Fitzhardinge 	return err;
4391da177e4SLinus Torvalds }
4401da177e4SLinus Torvalds 
4411da177e4SLinus Torvalds /**
442e08f5f5bSGautham R Shenoy  * cpufreq_per_cpu_attr_read() / show_##file_name() -
443e08f5f5bSGautham R Shenoy  * print out cpufreq information
4441da177e4SLinus Torvalds  *
4451da177e4SLinus Torvalds  * Write out information from cpufreq_driver->policy[cpu]; object must be
4461da177e4SLinus Torvalds  * "unsigned int".
4471da177e4SLinus Torvalds  */
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds #define show_one(file_name, object)			\
4501da177e4SLinus Torvalds static ssize_t show_##file_name				\
4511da177e4SLinus Torvalds (struct cpufreq_policy *policy, char *buf)		\
4521da177e4SLinus Torvalds {							\
4531da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", policy->object);	\
4541da177e4SLinus Torvalds }
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds show_one(cpuinfo_min_freq, cpuinfo.min_freq);
4571da177e4SLinus Torvalds show_one(cpuinfo_max_freq, cpuinfo.max_freq);
458ed129784SThomas Renninger show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
4591da177e4SLinus Torvalds show_one(scaling_min_freq, min);
4601da177e4SLinus Torvalds show_one(scaling_max_freq, max);
4611da177e4SLinus Torvalds show_one(scaling_cur_freq, cur);
4621da177e4SLinus Torvalds 
463e08f5f5bSGautham R Shenoy static int __cpufreq_set_policy(struct cpufreq_policy *data,
464e08f5f5bSGautham R Shenoy 				struct cpufreq_policy *policy);
4657970e08bSThomas Renninger 
4661da177e4SLinus Torvalds /**
4671da177e4SLinus Torvalds  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
4681da177e4SLinus Torvalds  */
4691da177e4SLinus Torvalds #define store_one(file_name, object)			\
4701da177e4SLinus Torvalds static ssize_t store_##file_name					\
4711da177e4SLinus Torvalds (struct cpufreq_policy *policy, const char *buf, size_t count)		\
4721da177e4SLinus Torvalds {									\
473f55c9c26SJingoo Han 	unsigned int ret;						\
4741da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;				\
4751da177e4SLinus Torvalds 									\
4761da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
4771da177e4SLinus Torvalds 	if (ret)							\
4781da177e4SLinus Torvalds 		return -EINVAL;						\
4791da177e4SLinus Torvalds 									\
4801da177e4SLinus Torvalds 	ret = sscanf(buf, "%u", &new_policy.object);			\
4811da177e4SLinus Torvalds 	if (ret != 1)							\
4821da177e4SLinus Torvalds 		return -EINVAL;						\
4831da177e4SLinus Torvalds 									\
4847970e08bSThomas Renninger 	ret = __cpufreq_set_policy(policy, &new_policy);		\
4857970e08bSThomas Renninger 	policy->user_policy.object = policy->object;			\
4861da177e4SLinus Torvalds 									\
4871da177e4SLinus Torvalds 	return ret ? ret : count;					\
4881da177e4SLinus Torvalds }
4891da177e4SLinus Torvalds 
4901da177e4SLinus Torvalds store_one(scaling_min_freq, min);
4911da177e4SLinus Torvalds store_one(scaling_max_freq, max);
4921da177e4SLinus Torvalds 
4931da177e4SLinus Torvalds /**
4941da177e4SLinus Torvalds  * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
4951da177e4SLinus Torvalds  */
496e08f5f5bSGautham R Shenoy static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
497e08f5f5bSGautham R Shenoy 					char *buf)
4981da177e4SLinus Torvalds {
4995a01f2e8SVenkatesh Pallipadi 	unsigned int cur_freq = __cpufreq_get(policy->cpu);
5001da177e4SLinus Torvalds 	if (!cur_freq)
5011da177e4SLinus Torvalds 		return sprintf(buf, "<unknown>");
5021da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", cur_freq);
5031da177e4SLinus Torvalds }
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds /**
5061da177e4SLinus Torvalds  * show_scaling_governor - show the current policy for the specified CPU
5071da177e4SLinus Torvalds  */
508905d77cdSDave Jones static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
5091da177e4SLinus Torvalds {
5101da177e4SLinus Torvalds 	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
5111da177e4SLinus Torvalds 		return sprintf(buf, "powersave\n");
5121da177e4SLinus Torvalds 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
5131da177e4SLinus Torvalds 		return sprintf(buf, "performance\n");
5141da177e4SLinus Torvalds 	else if (policy->governor)
5154b972f0bSviresh kumar 		return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
51629464f28SDave Jones 				policy->governor->name);
5171da177e4SLinus Torvalds 	return -EINVAL;
5181da177e4SLinus Torvalds }
5191da177e4SLinus Torvalds 
5201da177e4SLinus Torvalds /**
5211da177e4SLinus Torvalds  * store_scaling_governor - store policy for the specified CPU
5221da177e4SLinus Torvalds  */
5231da177e4SLinus Torvalds static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
5241da177e4SLinus Torvalds 					const char *buf, size_t count)
5251da177e4SLinus Torvalds {
526f55c9c26SJingoo Han 	unsigned int ret;
5271da177e4SLinus Torvalds 	char	str_governor[16];
5281da177e4SLinus Torvalds 	struct cpufreq_policy new_policy;
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds 	ret = cpufreq_get_policy(&new_policy, policy->cpu);
5311da177e4SLinus Torvalds 	if (ret)
5321da177e4SLinus Torvalds 		return ret;
5331da177e4SLinus Torvalds 
5341da177e4SLinus Torvalds 	ret = sscanf(buf, "%15s", str_governor);
5351da177e4SLinus Torvalds 	if (ret != 1)
5361da177e4SLinus Torvalds 		return -EINVAL;
5371da177e4SLinus Torvalds 
538e08f5f5bSGautham R Shenoy 	if (cpufreq_parse_governor(str_governor, &new_policy.policy,
539e08f5f5bSGautham R Shenoy 						&new_policy.governor))
5401da177e4SLinus Torvalds 		return -EINVAL;
5411da177e4SLinus Torvalds 
542bb176f7dSViresh Kumar 	/*
543bb176f7dSViresh Kumar 	 * Do not use cpufreq_set_policy here or the user_policy.max
544bb176f7dSViresh Kumar 	 * will be wrongly overridden
545bb176f7dSViresh Kumar 	 */
5467970e08bSThomas Renninger 	ret = __cpufreq_set_policy(policy, &new_policy);
5477970e08bSThomas Renninger 
5487970e08bSThomas Renninger 	policy->user_policy.policy = policy->policy;
5497970e08bSThomas Renninger 	policy->user_policy.governor = policy->governor;
5507970e08bSThomas Renninger 
551e08f5f5bSGautham R Shenoy 	if (ret)
552e08f5f5bSGautham R Shenoy 		return ret;
553e08f5f5bSGautham R Shenoy 	else
554e08f5f5bSGautham R Shenoy 		return count;
5551da177e4SLinus Torvalds }
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds /**
5581da177e4SLinus Torvalds  * show_scaling_driver - show the cpufreq driver currently loaded
5591da177e4SLinus Torvalds  */
5601da177e4SLinus Torvalds static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
5611da177e4SLinus Torvalds {
5621c3d85ddSRafael J. Wysocki 	return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
5631da177e4SLinus Torvalds }
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds /**
5661da177e4SLinus Torvalds  * show_scaling_available_governors - show the available CPUfreq governors
5671da177e4SLinus Torvalds  */
5681da177e4SLinus Torvalds static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
5691da177e4SLinus Torvalds 						char *buf)
5701da177e4SLinus Torvalds {
5711da177e4SLinus Torvalds 	ssize_t i = 0;
5721da177e4SLinus Torvalds 	struct cpufreq_governor *t;
5731da177e4SLinus Torvalds 
5741c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->target) {
5751da177e4SLinus Torvalds 		i += sprintf(buf, "performance powersave");
5761da177e4SLinus Torvalds 		goto out;
5771da177e4SLinus Torvalds 	}
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
58029464f28SDave Jones 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
58129464f28SDave Jones 		    - (CPUFREQ_NAME_LEN + 2)))
5821da177e4SLinus Torvalds 			goto out;
5834b972f0bSviresh kumar 		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
5841da177e4SLinus Torvalds 	}
5851da177e4SLinus Torvalds out:
5861da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
5871da177e4SLinus Torvalds 	return i;
5881da177e4SLinus Torvalds }
589e8628dd0SDarrick J. Wong 
590f4fd3797SLan Tianyu ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf)
5911da177e4SLinus Torvalds {
5921da177e4SLinus Torvalds 	ssize_t i = 0;
5931da177e4SLinus Torvalds 	unsigned int cpu;
5941da177e4SLinus Torvalds 
595835481d9SRusty Russell 	for_each_cpu(cpu, mask) {
5961da177e4SLinus Torvalds 		if (i)
5971da177e4SLinus Torvalds 			i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
5981da177e4SLinus Torvalds 		i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
5991da177e4SLinus Torvalds 		if (i >= (PAGE_SIZE - 5))
6001da177e4SLinus Torvalds 			break;
6011da177e4SLinus Torvalds 	}
6021da177e4SLinus Torvalds 	i += sprintf(&buf[i], "\n");
6031da177e4SLinus Torvalds 	return i;
6041da177e4SLinus Torvalds }
605f4fd3797SLan Tianyu EXPORT_SYMBOL_GPL(cpufreq_show_cpus);
6061da177e4SLinus Torvalds 
607e8628dd0SDarrick J. Wong /**
608e8628dd0SDarrick J. Wong  * show_related_cpus - show the CPUs affected by each transition even if
609e8628dd0SDarrick J. Wong  * hw coordination is in use
610e8628dd0SDarrick J. Wong  */
611e8628dd0SDarrick J. Wong static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
612e8628dd0SDarrick J. Wong {
613f4fd3797SLan Tianyu 	return cpufreq_show_cpus(policy->related_cpus, buf);
614e8628dd0SDarrick J. Wong }
615e8628dd0SDarrick J. Wong 
616e8628dd0SDarrick J. Wong /**
617e8628dd0SDarrick J. Wong  * show_affected_cpus - show the CPUs affected by each transition
618e8628dd0SDarrick J. Wong  */
619e8628dd0SDarrick J. Wong static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
620e8628dd0SDarrick J. Wong {
621f4fd3797SLan Tianyu 	return cpufreq_show_cpus(policy->cpus, buf);
622e8628dd0SDarrick J. Wong }
623e8628dd0SDarrick J. Wong 
6249e76988eSVenki Pallipadi static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
6259e76988eSVenki Pallipadi 					const char *buf, size_t count)
6269e76988eSVenki Pallipadi {
6279e76988eSVenki Pallipadi 	unsigned int freq = 0;
6289e76988eSVenki Pallipadi 	unsigned int ret;
6299e76988eSVenki Pallipadi 
630879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->store_setspeed)
6319e76988eSVenki Pallipadi 		return -EINVAL;
6329e76988eSVenki Pallipadi 
6339e76988eSVenki Pallipadi 	ret = sscanf(buf, "%u", &freq);
6349e76988eSVenki Pallipadi 	if (ret != 1)
6359e76988eSVenki Pallipadi 		return -EINVAL;
6369e76988eSVenki Pallipadi 
6379e76988eSVenki Pallipadi 	policy->governor->store_setspeed(policy, freq);
6389e76988eSVenki Pallipadi 
6399e76988eSVenki Pallipadi 	return count;
6409e76988eSVenki Pallipadi }
6419e76988eSVenki Pallipadi 
6429e76988eSVenki Pallipadi static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
6439e76988eSVenki Pallipadi {
644879000f9SCHIKAMA masaki 	if (!policy->governor || !policy->governor->show_setspeed)
6459e76988eSVenki Pallipadi 		return sprintf(buf, "<unsupported>\n");
6469e76988eSVenki Pallipadi 
6479e76988eSVenki Pallipadi 	return policy->governor->show_setspeed(policy, buf);
6489e76988eSVenki Pallipadi }
6491da177e4SLinus Torvalds 
650e2f74f35SThomas Renninger /**
6518bf1ac72Sviresh kumar  * show_bios_limit - show the current cpufreq HW/BIOS limitation
652e2f74f35SThomas Renninger  */
653e2f74f35SThomas Renninger static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
654e2f74f35SThomas Renninger {
655e2f74f35SThomas Renninger 	unsigned int limit;
656e2f74f35SThomas Renninger 	int ret;
6571c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->bios_limit) {
6581c3d85ddSRafael J. Wysocki 		ret = cpufreq_driver->bios_limit(policy->cpu, &limit);
659e2f74f35SThomas Renninger 		if (!ret)
660e2f74f35SThomas Renninger 			return sprintf(buf, "%u\n", limit);
661e2f74f35SThomas Renninger 	}
662e2f74f35SThomas Renninger 	return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
663e2f74f35SThomas Renninger }
664e2f74f35SThomas Renninger 
6656dad2a29SBorislav Petkov cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
6666dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_min_freq);
6676dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_max_freq);
6686dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_transition_latency);
6696dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_available_governors);
6706dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_driver);
6716dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_cur_freq);
6726dad2a29SBorislav Petkov cpufreq_freq_attr_ro(bios_limit);
6736dad2a29SBorislav Petkov cpufreq_freq_attr_ro(related_cpus);
6746dad2a29SBorislav Petkov cpufreq_freq_attr_ro(affected_cpus);
6756dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_min_freq);
6766dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_max_freq);
6776dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_governor);
6786dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_setspeed);
6791da177e4SLinus Torvalds 
6801da177e4SLinus Torvalds static struct attribute *default_attrs[] = {
6811da177e4SLinus Torvalds 	&cpuinfo_min_freq.attr,
6821da177e4SLinus Torvalds 	&cpuinfo_max_freq.attr,
683ed129784SThomas Renninger 	&cpuinfo_transition_latency.attr,
6841da177e4SLinus Torvalds 	&scaling_min_freq.attr,
6851da177e4SLinus Torvalds 	&scaling_max_freq.attr,
6861da177e4SLinus Torvalds 	&affected_cpus.attr,
687e8628dd0SDarrick J. Wong 	&related_cpus.attr,
6881da177e4SLinus Torvalds 	&scaling_governor.attr,
6891da177e4SLinus Torvalds 	&scaling_driver.attr,
6901da177e4SLinus Torvalds 	&scaling_available_governors.attr,
6919e76988eSVenki Pallipadi 	&scaling_setspeed.attr,
6921da177e4SLinus Torvalds 	NULL
6931da177e4SLinus Torvalds };
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds #define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
6961da177e4SLinus Torvalds #define to_attr(a) container_of(a, struct freq_attr, attr)
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
6991da177e4SLinus Torvalds {
7001da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7011da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
7020db4a8a9SDave Jones 	ssize_t ret = -EINVAL;
703a9144436SStephen Boyd 	policy = cpufreq_cpu_get_sysfs(policy->cpu);
7041da177e4SLinus Torvalds 	if (!policy)
7050db4a8a9SDave Jones 		goto no_policy;
7065a01f2e8SVenkatesh Pallipadi 
7075a01f2e8SVenkatesh Pallipadi 	if (lock_policy_rwsem_read(policy->cpu) < 0)
7080db4a8a9SDave Jones 		goto fail;
7095a01f2e8SVenkatesh Pallipadi 
710e08f5f5bSGautham R Shenoy 	if (fattr->show)
711e08f5f5bSGautham R Shenoy 		ret = fattr->show(policy, buf);
712e08f5f5bSGautham R Shenoy 	else
713e08f5f5bSGautham R Shenoy 		ret = -EIO;
714e08f5f5bSGautham R Shenoy 
7155a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_read(policy->cpu);
7160db4a8a9SDave Jones fail:
717a9144436SStephen Boyd 	cpufreq_cpu_put_sysfs(policy);
7180db4a8a9SDave Jones no_policy:
7191da177e4SLinus Torvalds 	return ret;
7201da177e4SLinus Torvalds }
7211da177e4SLinus Torvalds 
7221da177e4SLinus Torvalds static ssize_t store(struct kobject *kobj, struct attribute *attr,
7231da177e4SLinus Torvalds 		     const char *buf, size_t count)
7241da177e4SLinus Torvalds {
7251da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7261da177e4SLinus Torvalds 	struct freq_attr *fattr = to_attr(attr);
727a07530b4SDave Jones 	ssize_t ret = -EINVAL;
728a9144436SStephen Boyd 	policy = cpufreq_cpu_get_sysfs(policy->cpu);
7291da177e4SLinus Torvalds 	if (!policy)
730a07530b4SDave Jones 		goto no_policy;
7315a01f2e8SVenkatesh Pallipadi 
7325a01f2e8SVenkatesh Pallipadi 	if (lock_policy_rwsem_write(policy->cpu) < 0)
733a07530b4SDave Jones 		goto fail;
7345a01f2e8SVenkatesh Pallipadi 
735e08f5f5bSGautham R Shenoy 	if (fattr->store)
736e08f5f5bSGautham R Shenoy 		ret = fattr->store(policy, buf, count);
737e08f5f5bSGautham R Shenoy 	else
738e08f5f5bSGautham R Shenoy 		ret = -EIO;
739e08f5f5bSGautham R Shenoy 
7405a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(policy->cpu);
741a07530b4SDave Jones fail:
742a9144436SStephen Boyd 	cpufreq_cpu_put_sysfs(policy);
743a07530b4SDave Jones no_policy:
7441da177e4SLinus Torvalds 	return ret;
7451da177e4SLinus Torvalds }
7461da177e4SLinus Torvalds 
7471da177e4SLinus Torvalds static void cpufreq_sysfs_release(struct kobject *kobj)
7481da177e4SLinus Torvalds {
7491da177e4SLinus Torvalds 	struct cpufreq_policy *policy = to_policy(kobj);
7502d06d8c4SDominik Brodowski 	pr_debug("last reference is dropped\n");
7511da177e4SLinus Torvalds 	complete(&policy->kobj_unregister);
7521da177e4SLinus Torvalds }
7531da177e4SLinus Torvalds 
75452cf25d0SEmese Revfy static const struct sysfs_ops sysfs_ops = {
7551da177e4SLinus Torvalds 	.show	= show,
7561da177e4SLinus Torvalds 	.store	= store,
7571da177e4SLinus Torvalds };
7581da177e4SLinus Torvalds 
7591da177e4SLinus Torvalds static struct kobj_type ktype_cpufreq = {
7601da177e4SLinus Torvalds 	.sysfs_ops	= &sysfs_ops,
7611da177e4SLinus Torvalds 	.default_attrs	= default_attrs,
7621da177e4SLinus Torvalds 	.release	= cpufreq_sysfs_release,
7631da177e4SLinus Torvalds };
7641da177e4SLinus Torvalds 
7652361be23SViresh Kumar struct kobject *cpufreq_global_kobject;
7662361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_global_kobject);
7672361be23SViresh Kumar 
7682361be23SViresh Kumar static int cpufreq_global_kobject_usage;
7692361be23SViresh Kumar 
7702361be23SViresh Kumar int cpufreq_get_global_kobject(void)
7712361be23SViresh Kumar {
7722361be23SViresh Kumar 	if (!cpufreq_global_kobject_usage++)
7732361be23SViresh Kumar 		return kobject_add(cpufreq_global_kobject,
7742361be23SViresh Kumar 				&cpu_subsys.dev_root->kobj, "%s", "cpufreq");
7752361be23SViresh Kumar 
7762361be23SViresh Kumar 	return 0;
7772361be23SViresh Kumar }
7782361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_get_global_kobject);
7792361be23SViresh Kumar 
7802361be23SViresh Kumar void cpufreq_put_global_kobject(void)
7812361be23SViresh Kumar {
7822361be23SViresh Kumar 	if (!--cpufreq_global_kobject_usage)
7832361be23SViresh Kumar 		kobject_del(cpufreq_global_kobject);
7842361be23SViresh Kumar }
7852361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_put_global_kobject);
7862361be23SViresh Kumar 
7872361be23SViresh Kumar int cpufreq_sysfs_create_file(const struct attribute *attr)
7882361be23SViresh Kumar {
7892361be23SViresh Kumar 	int ret = cpufreq_get_global_kobject();
7902361be23SViresh Kumar 
7912361be23SViresh Kumar 	if (!ret) {
7922361be23SViresh Kumar 		ret = sysfs_create_file(cpufreq_global_kobject, attr);
7932361be23SViresh Kumar 		if (ret)
7942361be23SViresh Kumar 			cpufreq_put_global_kobject();
7952361be23SViresh Kumar 	}
7962361be23SViresh Kumar 
7972361be23SViresh Kumar 	return ret;
7982361be23SViresh Kumar }
7992361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_create_file);
8002361be23SViresh Kumar 
8012361be23SViresh Kumar void cpufreq_sysfs_remove_file(const struct attribute *attr)
8022361be23SViresh Kumar {
8032361be23SViresh Kumar 	sysfs_remove_file(cpufreq_global_kobject, attr);
8042361be23SViresh Kumar 	cpufreq_put_global_kobject();
8052361be23SViresh Kumar }
8062361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_remove_file);
8072361be23SViresh Kumar 
80819d6f7ecSDave Jones /* symlink affected CPUs */
809308b60e7SViresh Kumar static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy)
81019d6f7ecSDave Jones {
81119d6f7ecSDave Jones 	unsigned int j;
81219d6f7ecSDave Jones 	int ret = 0;
81319d6f7ecSDave Jones 
81419d6f7ecSDave Jones 	for_each_cpu(j, policy->cpus) {
8158a25a2fdSKay Sievers 		struct device *cpu_dev;
81619d6f7ecSDave Jones 
817308b60e7SViresh Kumar 		if (j == policy->cpu)
81819d6f7ecSDave Jones 			continue;
81919d6f7ecSDave Jones 
820e8fdde10SViresh Kumar 		pr_debug("Adding link for CPU: %u\n", j);
8218a25a2fdSKay Sievers 		cpu_dev = get_cpu_device(j);
8228a25a2fdSKay Sievers 		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
82319d6f7ecSDave Jones 					"cpufreq");
824*71c3461eSRafael J. Wysocki 		if (ret)
825*71c3461eSRafael J. Wysocki 			break;
82619d6f7ecSDave Jones 	}
82719d6f7ecSDave Jones 	return ret;
82819d6f7ecSDave Jones }
82919d6f7ecSDave Jones 
830308b60e7SViresh Kumar static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
8318a25a2fdSKay Sievers 				     struct device *dev)
832909a694eSDave Jones {
833909a694eSDave Jones 	struct freq_attr **drv_attr;
834909a694eSDave Jones 	int ret = 0;
835909a694eSDave Jones 
836909a694eSDave Jones 	/* prepare interface data */
837909a694eSDave Jones 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
8388a25a2fdSKay Sievers 				   &dev->kobj, "cpufreq");
839909a694eSDave Jones 	if (ret)
840909a694eSDave Jones 		return ret;
841909a694eSDave Jones 
842909a694eSDave Jones 	/* set up files for this cpu device */
8431c3d85ddSRafael J. Wysocki 	drv_attr = cpufreq_driver->attr;
844909a694eSDave Jones 	while ((drv_attr) && (*drv_attr)) {
845909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
846909a694eSDave Jones 		if (ret)
8471c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
848909a694eSDave Jones 		drv_attr++;
849909a694eSDave Jones 	}
8501c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->get) {
851909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
852909a694eSDave Jones 		if (ret)
8531c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
854909a694eSDave Jones 	}
8551c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->target) {
856909a694eSDave Jones 		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
857909a694eSDave Jones 		if (ret)
8581c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
859909a694eSDave Jones 	}
8601c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->bios_limit) {
861e2f74f35SThomas Renninger 		ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
862e2f74f35SThomas Renninger 		if (ret)
8631c3d85ddSRafael J. Wysocki 			goto err_out_kobj_put;
864e2f74f35SThomas Renninger 	}
865909a694eSDave Jones 
866308b60e7SViresh Kumar 	ret = cpufreq_add_dev_symlink(policy);
867ecf7e461SDave Jones 	if (ret)
868ecf7e461SDave Jones 		goto err_out_kobj_put;
869ecf7e461SDave Jones 
870e18f1682SSrivatsa S. Bhat 	return ret;
871e18f1682SSrivatsa S. Bhat 
872e18f1682SSrivatsa S. Bhat err_out_kobj_put:
873e18f1682SSrivatsa S. Bhat 	kobject_put(&policy->kobj);
874e18f1682SSrivatsa S. Bhat 	wait_for_completion(&policy->kobj_unregister);
875e18f1682SSrivatsa S. Bhat 	return ret;
876e18f1682SSrivatsa S. Bhat }
877e18f1682SSrivatsa S. Bhat 
878e18f1682SSrivatsa S. Bhat static void cpufreq_init_policy(struct cpufreq_policy *policy)
879e18f1682SSrivatsa S. Bhat {
880e18f1682SSrivatsa S. Bhat 	struct cpufreq_policy new_policy;
881e18f1682SSrivatsa S. Bhat 	int ret = 0;
882e18f1682SSrivatsa S. Bhat 
883ecf7e461SDave Jones 	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
884ecf7e461SDave Jones 	/* assure that the starting sequence is run in __cpufreq_set_policy */
885ecf7e461SDave Jones 	policy->governor = NULL;
886ecf7e461SDave Jones 
887ecf7e461SDave Jones 	/* set default policy */
888ecf7e461SDave Jones 	ret = __cpufreq_set_policy(policy, &new_policy);
889ecf7e461SDave Jones 	policy->user_policy.policy = policy->policy;
890ecf7e461SDave Jones 	policy->user_policy.governor = policy->governor;
891ecf7e461SDave Jones 
892ecf7e461SDave Jones 	if (ret) {
8932d06d8c4SDominik Brodowski 		pr_debug("setting policy failed\n");
8941c3d85ddSRafael J. Wysocki 		if (cpufreq_driver->exit)
8951c3d85ddSRafael J. Wysocki 			cpufreq_driver->exit(policy);
896ecf7e461SDave Jones 	}
897909a694eSDave Jones }
898909a694eSDave Jones 
899fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
900fcf80582SViresh Kumar static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
901a82fab29SSrivatsa S. Bhat 				  struct device *dev, bool frozen)
902fcf80582SViresh Kumar {
903fcf80582SViresh Kumar 	struct cpufreq_policy *policy;
9041c3d85ddSRafael J. Wysocki 	int ret = 0, has_target = !!cpufreq_driver->target;
905fcf80582SViresh Kumar 	unsigned long flags;
906fcf80582SViresh Kumar 
907fcf80582SViresh Kumar 	policy = cpufreq_cpu_get(sibling);
908*71c3461eSRafael J. Wysocki 	if (WARN_ON_ONCE(!policy))
909*71c3461eSRafael J. Wysocki 		return -ENODATA;
910fcf80582SViresh Kumar 
911820c6ca2SViresh Kumar 	if (has_target)
912fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
913fcf80582SViresh Kumar 
9142eaa3e2dSViresh Kumar 	lock_policy_rwsem_write(sibling);
9152eaa3e2dSViresh Kumar 
9160d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
9172eaa3e2dSViresh Kumar 
918fcf80582SViresh Kumar 	cpumask_set_cpu(cpu, policy->cpus);
9192eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu;
920fcf80582SViresh Kumar 	per_cpu(cpufreq_cpu_data, cpu) = policy;
9210d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
922fcf80582SViresh Kumar 
9232eaa3e2dSViresh Kumar 	unlock_policy_rwsem_write(sibling);
9242eaa3e2dSViresh Kumar 
925820c6ca2SViresh Kumar 	if (has_target) {
926fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_START);
927fcf80582SViresh Kumar 		__cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
928820c6ca2SViresh Kumar 	}
929fcf80582SViresh Kumar 
930a82fab29SSrivatsa S. Bhat 	/* Don't touch sysfs links during light-weight init */
931*71c3461eSRafael J. Wysocki 	if (!frozen)
932a82fab29SSrivatsa S. Bhat 		ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
933a82fab29SSrivatsa S. Bhat 
934*71c3461eSRafael J. Wysocki 	cpufreq_cpu_put(policy);
935a82fab29SSrivatsa S. Bhat 	return ret;
936fcf80582SViresh Kumar }
937fcf80582SViresh Kumar #endif
9381da177e4SLinus Torvalds 
9398414809cSSrivatsa S. Bhat static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
9408414809cSSrivatsa S. Bhat {
9418414809cSSrivatsa S. Bhat 	struct cpufreq_policy *policy;
9428414809cSSrivatsa S. Bhat 	unsigned long flags;
9438414809cSSrivatsa S. Bhat 
9448414809cSSrivatsa S. Bhat 	write_lock_irqsave(&cpufreq_driver_lock, flags);
9458414809cSSrivatsa S. Bhat 
9468414809cSSrivatsa S. Bhat 	policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
9478414809cSSrivatsa S. Bhat 
9488414809cSSrivatsa S. Bhat 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
9498414809cSSrivatsa S. Bhat 
9508414809cSSrivatsa S. Bhat 	return policy;
9518414809cSSrivatsa S. Bhat }
9528414809cSSrivatsa S. Bhat 
953e9698cc5SSrivatsa S. Bhat static struct cpufreq_policy *cpufreq_policy_alloc(void)
954e9698cc5SSrivatsa S. Bhat {
955e9698cc5SSrivatsa S. Bhat 	struct cpufreq_policy *policy;
956e9698cc5SSrivatsa S. Bhat 
957e9698cc5SSrivatsa S. Bhat 	policy = kzalloc(sizeof(*policy), GFP_KERNEL);
958e9698cc5SSrivatsa S. Bhat 	if (!policy)
959e9698cc5SSrivatsa S. Bhat 		return NULL;
960e9698cc5SSrivatsa S. Bhat 
961e9698cc5SSrivatsa S. Bhat 	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
962e9698cc5SSrivatsa S. Bhat 		goto err_free_policy;
963e9698cc5SSrivatsa S. Bhat 
964e9698cc5SSrivatsa S. Bhat 	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
965e9698cc5SSrivatsa S. Bhat 		goto err_free_cpumask;
966e9698cc5SSrivatsa S. Bhat 
967e9698cc5SSrivatsa S. Bhat 	return policy;
968e9698cc5SSrivatsa S. Bhat 
969e9698cc5SSrivatsa S. Bhat err_free_cpumask:
970e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->cpus);
971e9698cc5SSrivatsa S. Bhat err_free_policy:
972e9698cc5SSrivatsa S. Bhat 	kfree(policy);
973e9698cc5SSrivatsa S. Bhat 
974e9698cc5SSrivatsa S. Bhat 	return NULL;
975e9698cc5SSrivatsa S. Bhat }
976e9698cc5SSrivatsa S. Bhat 
977e9698cc5SSrivatsa S. Bhat static void cpufreq_policy_free(struct cpufreq_policy *policy)
978e9698cc5SSrivatsa S. Bhat {
979e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->related_cpus);
980e9698cc5SSrivatsa S. Bhat 	free_cpumask_var(policy->cpus);
981e9698cc5SSrivatsa S. Bhat 	kfree(policy);
982e9698cc5SSrivatsa S. Bhat }
983e9698cc5SSrivatsa S. Bhat 
984a82fab29SSrivatsa S. Bhat static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
985a82fab29SSrivatsa S. Bhat 			     bool frozen)
9861da177e4SLinus Torvalds {
987fcf80582SViresh Kumar 	unsigned int j, cpu = dev->id;
98865922465SViresh Kumar 	int ret = -ENOMEM;
9891da177e4SLinus Torvalds 	struct cpufreq_policy *policy;
9901da177e4SLinus Torvalds 	unsigned long flags;
99190e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
992fcf80582SViresh Kumar 	struct cpufreq_governor *gov;
99390e41bacSPrarit Bhargava 	int sibling;
99490e41bacSPrarit Bhargava #endif
9951da177e4SLinus Torvalds 
996c32b6b8eSAshok Raj 	if (cpu_is_offline(cpu))
997c32b6b8eSAshok Raj 		return 0;
998c32b6b8eSAshok Raj 
9992d06d8c4SDominik Brodowski 	pr_debug("adding CPU %u\n", cpu);
10001da177e4SLinus Torvalds 
10011da177e4SLinus Torvalds #ifdef CONFIG_SMP
10021da177e4SLinus Torvalds 	/* check whether a different CPU already registered this
10031da177e4SLinus Torvalds 	 * CPU because it is in the same boat. */
10041da177e4SLinus Torvalds 	policy = cpufreq_cpu_get(cpu);
10051da177e4SLinus Torvalds 	if (unlikely(policy)) {
10068ff69732SDave Jones 		cpufreq_cpu_put(policy);
10071da177e4SLinus Torvalds 		return 0;
10081da177e4SLinus Torvalds 	}
1009fcf80582SViresh Kumar 
1010fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
1011fcf80582SViresh Kumar 	/* Check if this cpu was hot-unplugged earlier and has siblings */
10120d1857a1SNathan Zimmer 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1013fcf80582SViresh Kumar 	for_each_online_cpu(sibling) {
1014fcf80582SViresh Kumar 		struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
10152eaa3e2dSViresh Kumar 		if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
10160d1857a1SNathan Zimmer 			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1017a82fab29SSrivatsa S. Bhat 			return cpufreq_add_policy_cpu(cpu, sibling, dev,
1018a82fab29SSrivatsa S. Bhat 						      frozen);
1019fcf80582SViresh Kumar 		}
10202eaa3e2dSViresh Kumar 	}
10210d1857a1SNathan Zimmer 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1022fcf80582SViresh Kumar #endif
10231da177e4SLinus Torvalds #endif
10241da177e4SLinus Torvalds 
10251c3d85ddSRafael J. Wysocki 	if (!try_module_get(cpufreq_driver->owner)) {
10261da177e4SLinus Torvalds 		ret = -EINVAL;
10271da177e4SLinus Torvalds 		goto module_out;
10281da177e4SLinus Torvalds 	}
10291da177e4SLinus Torvalds 
10308414809cSSrivatsa S. Bhat 	if (frozen)
10318414809cSSrivatsa S. Bhat 		/* Restore the saved policy when doing light-weight init */
10328414809cSSrivatsa S. Bhat 		policy = cpufreq_policy_restore(cpu);
10338414809cSSrivatsa S. Bhat 	else
1034e9698cc5SSrivatsa S. Bhat 		policy = cpufreq_policy_alloc();
10358414809cSSrivatsa S. Bhat 
1036059019a3SDave Jones 	if (!policy)
10371da177e4SLinus Torvalds 		goto nomem_out;
1038059019a3SDave Jones 
10391da177e4SLinus Torvalds 	policy->cpu = cpu;
104065922465SViresh Kumar 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
1041835481d9SRusty Russell 	cpumask_copy(policy->cpus, cpumask_of(cpu));
10421da177e4SLinus Torvalds 
10435a01f2e8SVenkatesh Pallipadi 	/* Initially set CPU itself as the policy_cpu */
1044f1625066STejun Heo 	per_cpu(cpufreq_policy_cpu, cpu) = cpu;
10455a01f2e8SVenkatesh Pallipadi 
10461da177e4SLinus Torvalds 	init_completion(&policy->kobj_unregister);
104765f27f38SDavid Howells 	INIT_WORK(&policy->update, handle_update);
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 	/* call driver. From then on the cpufreq must be able
10501da177e4SLinus Torvalds 	 * to accept all calls to ->verify and ->setpolicy for this CPU
10511da177e4SLinus Torvalds 	 */
10521c3d85ddSRafael J. Wysocki 	ret = cpufreq_driver->init(policy);
10531da177e4SLinus Torvalds 	if (ret) {
10542d06d8c4SDominik Brodowski 		pr_debug("initialization failed\n");
10552eaa3e2dSViresh Kumar 		goto err_set_policy_cpu;
10561da177e4SLinus Torvalds 	}
1057643ae6e8SViresh Kumar 
1058fcf80582SViresh Kumar 	/* related cpus should atleast have policy->cpus */
1059fcf80582SViresh Kumar 	cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
1060fcf80582SViresh Kumar 
1061643ae6e8SViresh Kumar 	/*
1062643ae6e8SViresh Kumar 	 * affected cpus must always be the one, which are online. We aren't
1063643ae6e8SViresh Kumar 	 * managing offline cpus here.
1064643ae6e8SViresh Kumar 	 */
1065643ae6e8SViresh Kumar 	cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
1066643ae6e8SViresh Kumar 
1067187d9f4eSMike Chan 	policy->user_policy.min = policy->min;
1068187d9f4eSMike Chan 	policy->user_policy.max = policy->max;
10691da177e4SLinus Torvalds 
1070a1531acdSThomas Renninger 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1071a1531acdSThomas Renninger 				     CPUFREQ_START, policy);
1072a1531acdSThomas Renninger 
1073fcf80582SViresh Kumar #ifdef CONFIG_HOTPLUG_CPU
1074fcf80582SViresh Kumar 	gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
1075fcf80582SViresh Kumar 	if (gov) {
1076fcf80582SViresh Kumar 		policy->governor = gov;
1077fcf80582SViresh Kumar 		pr_debug("Restoring governor %s for cpu %d\n",
1078fcf80582SViresh Kumar 		       policy->governor->name, cpu);
10794bfa042cSThomas Renninger 	}
1080fcf80582SViresh Kumar #endif
10811da177e4SLinus Torvalds 
1082e18f1682SSrivatsa S. Bhat 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1083e18f1682SSrivatsa S. Bhat 	for_each_cpu(j, policy->cpus) {
1084e18f1682SSrivatsa S. Bhat 		per_cpu(cpufreq_cpu_data, j) = policy;
1085e18f1682SSrivatsa S. Bhat 		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
1086e18f1682SSrivatsa S. Bhat 	}
1087e18f1682SSrivatsa S. Bhat 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1088e18f1682SSrivatsa S. Bhat 
1089a82fab29SSrivatsa S. Bhat 	if (!frozen) {
1090308b60e7SViresh Kumar 		ret = cpufreq_add_dev_interface(policy, dev);
109119d6f7ecSDave Jones 		if (ret)
10920142f9dcSAhmed S. Darwish 			goto err_out_unregister;
1093a82fab29SSrivatsa S. Bhat 	}
10948ff69732SDave Jones 
1095e18f1682SSrivatsa S. Bhat 	cpufreq_init_policy(policy);
1096e18f1682SSrivatsa S. Bhat 
1097038c5b3eSGreg Kroah-Hartman 	kobject_uevent(&policy->kobj, KOBJ_ADD);
10981c3d85ddSRafael J. Wysocki 	module_put(cpufreq_driver->owner);
10992d06d8c4SDominik Brodowski 	pr_debug("initialization complete\n");
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds 	return 0;
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds err_out_unregister:
11040d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
1105e18f1682SSrivatsa S. Bhat 	for_each_cpu(j, policy->cpus) {
11067a6aedfaSMike Travis 		per_cpu(cpufreq_cpu_data, j) = NULL;
1107e18f1682SSrivatsa S. Bhat 		if (j != cpu)
1108e18f1682SSrivatsa S. Bhat 			per_cpu(cpufreq_policy_cpu, j) = -1;
1109e18f1682SSrivatsa S. Bhat 	}
11100d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
11111da177e4SLinus Torvalds 
1112c10997f6SGreg Kroah-Hartman 	kobject_put(&policy->kobj);
11131da177e4SLinus Torvalds 	wait_for_completion(&policy->kobj_unregister);
11141da177e4SLinus Torvalds 
11152eaa3e2dSViresh Kumar err_set_policy_cpu:
11162eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = -1;
1117e9698cc5SSrivatsa S. Bhat 	cpufreq_policy_free(policy);
11181da177e4SLinus Torvalds nomem_out:
11191c3d85ddSRafael J. Wysocki 	module_put(cpufreq_driver->owner);
11201da177e4SLinus Torvalds module_out:
11211da177e4SLinus Torvalds 	return ret;
11221da177e4SLinus Torvalds }
11231da177e4SLinus Torvalds 
1124a82fab29SSrivatsa S. Bhat /**
1125a82fab29SSrivatsa S. Bhat  * cpufreq_add_dev - add a CPU device
1126a82fab29SSrivatsa S. Bhat  *
1127a82fab29SSrivatsa S. Bhat  * Adds the cpufreq interface for a CPU device.
1128a82fab29SSrivatsa S. Bhat  *
1129a82fab29SSrivatsa S. Bhat  * The Oracle says: try running cpufreq registration/unregistration concurrently
1130a82fab29SSrivatsa S. Bhat  * with with cpu hotplugging and all hell will break loose. Tried to clean this
1131a82fab29SSrivatsa S. Bhat  * mess up, but more thorough testing is needed. - Mathieu
1132a82fab29SSrivatsa S. Bhat  */
1133a82fab29SSrivatsa S. Bhat static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
1134a82fab29SSrivatsa S. Bhat {
1135a82fab29SSrivatsa S. Bhat 	return __cpufreq_add_dev(dev, sif, false);
1136a82fab29SSrivatsa S. Bhat }
1137a82fab29SSrivatsa S. Bhat 
1138b8eed8afSViresh Kumar static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
1139b8eed8afSViresh Kumar {
1140b8eed8afSViresh Kumar 	int j;
1141b8eed8afSViresh Kumar 
1142b8eed8afSViresh Kumar 	policy->last_cpu = policy->cpu;
1143b8eed8afSViresh Kumar 	policy->cpu = cpu;
1144b8eed8afSViresh Kumar 
11453361b7b1SViresh Kumar 	for_each_cpu(j, policy->cpus)
1146b8eed8afSViresh Kumar 		per_cpu(cpufreq_policy_cpu, j) = cpu;
1147b8eed8afSViresh Kumar 
1148b8eed8afSViresh Kumar #ifdef CONFIG_CPU_FREQ_TABLE
1149b8eed8afSViresh Kumar 	cpufreq_frequency_table_update_policy_cpu(policy);
1150b8eed8afSViresh Kumar #endif
1151b8eed8afSViresh Kumar 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1152b8eed8afSViresh Kumar 			CPUFREQ_UPDATE_POLICY_CPU, policy);
1153b8eed8afSViresh Kumar }
11541da177e4SLinus Torvalds 
1155f9ba680dSSrivatsa S. Bhat static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data,
1156a82fab29SSrivatsa S. Bhat 					   unsigned int old_cpu, bool frozen)
1157f9ba680dSSrivatsa S. Bhat {
1158f9ba680dSSrivatsa S. Bhat 	struct device *cpu_dev;
1159f9ba680dSSrivatsa S. Bhat 	unsigned long flags;
1160f9ba680dSSrivatsa S. Bhat 	int ret;
1161f9ba680dSSrivatsa S. Bhat 
1162f9ba680dSSrivatsa S. Bhat 	/* first sibling now owns the new sysfs dir */
1163f9ba680dSSrivatsa S. Bhat 	cpu_dev = get_cpu_device(cpumask_first(data->cpus));
1164a82fab29SSrivatsa S. Bhat 
1165a82fab29SSrivatsa S. Bhat 	/* Don't touch sysfs files during light-weight tear-down */
1166a82fab29SSrivatsa S. Bhat 	if (frozen)
1167a82fab29SSrivatsa S. Bhat 		return cpu_dev->id;
1168a82fab29SSrivatsa S. Bhat 
1169f9ba680dSSrivatsa S. Bhat 	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
1170f9ba680dSSrivatsa S. Bhat 	ret = kobject_move(&data->kobj, &cpu_dev->kobj);
1171f9ba680dSSrivatsa S. Bhat 	if (ret) {
1172f9ba680dSSrivatsa S. Bhat 		pr_err("%s: Failed to move kobj: %d", __func__, ret);
1173f9ba680dSSrivatsa S. Bhat 
1174f9ba680dSSrivatsa S. Bhat 		WARN_ON(lock_policy_rwsem_write(old_cpu));
1175f9ba680dSSrivatsa S. Bhat 		cpumask_set_cpu(old_cpu, data->cpus);
1176f9ba680dSSrivatsa S. Bhat 
1177f9ba680dSSrivatsa S. Bhat 		write_lock_irqsave(&cpufreq_driver_lock, flags);
1178f9ba680dSSrivatsa S. Bhat 		per_cpu(cpufreq_cpu_data, old_cpu) = data;
1179f9ba680dSSrivatsa S. Bhat 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1180f9ba680dSSrivatsa S. Bhat 
1181f9ba680dSSrivatsa S. Bhat 		unlock_policy_rwsem_write(old_cpu);
1182f9ba680dSSrivatsa S. Bhat 
1183f9ba680dSSrivatsa S. Bhat 		ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj,
1184f9ba680dSSrivatsa S. Bhat 					"cpufreq");
1185f9ba680dSSrivatsa S. Bhat 
1186f9ba680dSSrivatsa S. Bhat 		return -EINVAL;
1187f9ba680dSSrivatsa S. Bhat 	}
1188f9ba680dSSrivatsa S. Bhat 
1189f9ba680dSSrivatsa S. Bhat 	return cpu_dev->id;
1190f9ba680dSSrivatsa S. Bhat }
1191f9ba680dSSrivatsa S. Bhat 
11921da177e4SLinus Torvalds /**
11935a01f2e8SVenkatesh Pallipadi  * __cpufreq_remove_dev - remove a CPU device
11941da177e4SLinus Torvalds  *
11951da177e4SLinus Torvalds  * Removes the cpufreq interface for a CPU device.
11965a01f2e8SVenkatesh Pallipadi  * Caller should already have policy_rwsem in write mode for this CPU.
11975a01f2e8SVenkatesh Pallipadi  * This routine frees the rwsem before returning.
11981da177e4SLinus Torvalds  */
1199bb176f7dSViresh Kumar static int __cpufreq_remove_dev(struct device *dev,
1200a82fab29SSrivatsa S. Bhat 				struct subsys_interface *sif, bool frozen)
12011da177e4SLinus Torvalds {
1202f9ba680dSSrivatsa S. Bhat 	unsigned int cpu = dev->id, cpus;
1203f9ba680dSSrivatsa S. Bhat 	int new_cpu;
12041da177e4SLinus Torvalds 	unsigned long flags;
12051da177e4SLinus Torvalds 	struct cpufreq_policy *data;
1206499bca9bSAmerigo Wang 	struct kobject *kobj;
1207499bca9bSAmerigo Wang 	struct completion *cmp;
12081da177e4SLinus Torvalds 
1209b8eed8afSViresh Kumar 	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
12101da177e4SLinus Torvalds 
12110d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	data = per_cpu(cpufreq_cpu_data, cpu);
12147a6aedfaSMike Travis 	per_cpu(cpufreq_cpu_data, cpu) = NULL;
12151da177e4SLinus Torvalds 
12168414809cSSrivatsa S. Bhat 	/* Save the policy somewhere when doing a light-weight tear-down */
12178414809cSSrivatsa S. Bhat 	if (frozen)
12188414809cSSrivatsa S. Bhat 		per_cpu(cpufreq_cpu_data_fallback, cpu) = data;
12198414809cSSrivatsa S. Bhat 
12200d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
12211da177e4SLinus Torvalds 
12221da177e4SLinus Torvalds 	if (!data) {
1223b8eed8afSViresh Kumar 		pr_debug("%s: No cpu_data found\n", __func__);
12241da177e4SLinus Torvalds 		return -EINVAL;
12251da177e4SLinus Torvalds 	}
12261da177e4SLinus Torvalds 
12271c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->target)
12281da177e4SLinus Torvalds 		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
12295a01f2e8SVenkatesh Pallipadi 
12301da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG_CPU
12311c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->setpolicy)
1232fa69e33fSDirk Brandewie 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
1233fa69e33fSDirk Brandewie 			data->governor->name, CPUFREQ_NAME_LEN);
12341da177e4SLinus Torvalds #endif
12351da177e4SLinus Torvalds 
12362eaa3e2dSViresh Kumar 	WARN_ON(lock_policy_rwsem_write(cpu));
1237b8eed8afSViresh Kumar 	cpus = cpumask_weight(data->cpus);
1238e4969ebaSViresh Kumar 
1239e4969ebaSViresh Kumar 	if (cpus > 1)
1240b8eed8afSViresh Kumar 		cpumask_clear_cpu(cpu, data->cpus);
12412eaa3e2dSViresh Kumar 	unlock_policy_rwsem_write(cpu);
12421da177e4SLinus Torvalds 
1243a82fab29SSrivatsa S. Bhat 	if (cpu != data->cpu && !frozen) {
124473bf0fc2SViresh Kumar 		sysfs_remove_link(&dev->kobj, "cpufreq");
124573bf0fc2SViresh Kumar 	} else if (cpus > 1) {
12462eaa3e2dSViresh Kumar 
1247a82fab29SSrivatsa S. Bhat 		new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu, frozen);
1248f9ba680dSSrivatsa S. Bhat 		if (new_cpu >= 0) {
12492eaa3e2dSViresh Kumar 			WARN_ON(lock_policy_rwsem_write(cpu));
1250f9ba680dSSrivatsa S. Bhat 			update_policy_cpu(data, new_cpu);
12512eaa3e2dSViresh Kumar 			unlock_policy_rwsem_write(cpu);
1252a82fab29SSrivatsa S. Bhat 
1253a82fab29SSrivatsa S. Bhat 			if (!frozen) {
1254f9ba680dSSrivatsa S. Bhat 				pr_debug("%s: policy Kobject moved to cpu: %d "
1255f9ba680dSSrivatsa S. Bhat 					 "from: %d\n",__func__, new_cpu, cpu);
12561da177e4SLinus Torvalds 			}
12571da177e4SLinus Torvalds 		}
1258a82fab29SSrivatsa S. Bhat 	}
1259b8eed8afSViresh Kumar 
1260b8eed8afSViresh Kumar 	/* If cpu is last user of policy, free policy */
1261b8eed8afSViresh Kumar 	if (cpus == 1) {
12622a998599SRafael J. Wysocki 		if (cpufreq_driver->target)
12632a998599SRafael J. Wysocki 			__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
12642a998599SRafael J. Wysocki 
12658414809cSSrivatsa S. Bhat 		if (!frozen) {
12662eaa3e2dSViresh Kumar 			lock_policy_rwsem_read(cpu);
1267499bca9bSAmerigo Wang 			kobj = &data->kobj;
1268499bca9bSAmerigo Wang 			cmp = &data->kobj_unregister;
12692eaa3e2dSViresh Kumar 			unlock_policy_rwsem_read(cpu);
1270499bca9bSAmerigo Wang 			kobject_put(kobj);
12711da177e4SLinus Torvalds 
12728414809cSSrivatsa S. Bhat 			/*
12738414809cSSrivatsa S. Bhat 			 * We need to make sure that the underlying kobj is
12748414809cSSrivatsa S. Bhat 			 * actually not referenced anymore by anybody before we
12758414809cSSrivatsa S. Bhat 			 * proceed with unloading.
12761da177e4SLinus Torvalds 			 */
12772d06d8c4SDominik Brodowski 			pr_debug("waiting for dropping of refcount\n");
1278499bca9bSAmerigo Wang 			wait_for_completion(cmp);
12792d06d8c4SDominik Brodowski 			pr_debug("wait complete\n");
12808414809cSSrivatsa S. Bhat 		}
12811da177e4SLinus Torvalds 
12828414809cSSrivatsa S. Bhat 		/*
12838414809cSSrivatsa S. Bhat 		 * Perform the ->exit() even during light-weight tear-down,
12848414809cSSrivatsa S. Bhat 		 * since this is a core component, and is essential for the
12858414809cSSrivatsa S. Bhat 		 * subsequent light-weight ->init() to succeed.
12868414809cSSrivatsa S. Bhat 		 */
12871c3d85ddSRafael J. Wysocki 		if (cpufreq_driver->exit)
12881c3d85ddSRafael J. Wysocki 			cpufreq_driver->exit(data);
128927ecddc2SJacob Shin 
12908414809cSSrivatsa S. Bhat 		if (!frozen)
1291e9698cc5SSrivatsa S. Bhat 			cpufreq_policy_free(data);
12922a998599SRafael J. Wysocki 	} else {
12932a998599SRafael J. Wysocki 		if (cpufreq_driver->target) {
1294b8eed8afSViresh Kumar 			__cpufreq_governor(data, CPUFREQ_GOV_START);
1295b8eed8afSViresh Kumar 			__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
1296b8eed8afSViresh Kumar 		}
12972a998599SRafael J. Wysocki 	}
12981da177e4SLinus Torvalds 
12992eaa3e2dSViresh Kumar 	per_cpu(cpufreq_policy_cpu, cpu) = -1;
13001da177e4SLinus Torvalds 	return 0;
13011da177e4SLinus Torvalds }
13021da177e4SLinus Torvalds 
13038a25a2fdSKay Sievers static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
13045a01f2e8SVenkatesh Pallipadi {
13058a25a2fdSKay Sievers 	unsigned int cpu = dev->id;
13065a01f2e8SVenkatesh Pallipadi 	int retval;
1307ec28297aSVenki Pallipadi 
1308ec28297aSVenki Pallipadi 	if (cpu_is_offline(cpu))
1309ec28297aSVenki Pallipadi 		return 0;
1310ec28297aSVenki Pallipadi 
1311a82fab29SSrivatsa S. Bhat 	retval = __cpufreq_remove_dev(dev, sif, false);
13125a01f2e8SVenkatesh Pallipadi 	return retval;
13135a01f2e8SVenkatesh Pallipadi }
13145a01f2e8SVenkatesh Pallipadi 
131565f27f38SDavid Howells static void handle_update(struct work_struct *work)
13161da177e4SLinus Torvalds {
131765f27f38SDavid Howells 	struct cpufreq_policy *policy =
131865f27f38SDavid Howells 		container_of(work, struct cpufreq_policy, update);
131965f27f38SDavid Howells 	unsigned int cpu = policy->cpu;
13202d06d8c4SDominik Brodowski 	pr_debug("handle_update for cpu %u called\n", cpu);
13211da177e4SLinus Torvalds 	cpufreq_update_policy(cpu);
13221da177e4SLinus Torvalds }
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds /**
1325bb176f7dSViresh Kumar  *	cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're
1326bb176f7dSViresh Kumar  *	in deep trouble.
13271da177e4SLinus Torvalds  *	@cpu: cpu number
13281da177e4SLinus Torvalds  *	@old_freq: CPU frequency the kernel thinks the CPU runs at
13291da177e4SLinus Torvalds  *	@new_freq: CPU frequency the CPU actually runs at
13301da177e4SLinus Torvalds  *
133129464f28SDave Jones  *	We adjust to current frequency first, and need to clean up later.
133229464f28SDave Jones  *	So either call to cpufreq_update_policy() or schedule handle_update()).
13331da177e4SLinus Torvalds  */
1334e08f5f5bSGautham R Shenoy static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
1335e08f5f5bSGautham R Shenoy 				unsigned int new_freq)
13361da177e4SLinus Torvalds {
1337b43a7ffbSViresh Kumar 	struct cpufreq_policy *policy;
13381da177e4SLinus Torvalds 	struct cpufreq_freqs freqs;
1339b43a7ffbSViresh Kumar 	unsigned long flags;
1340b43a7ffbSViresh Kumar 
13412d06d8c4SDominik Brodowski 	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
13421da177e4SLinus Torvalds 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
13431da177e4SLinus Torvalds 
13441da177e4SLinus Torvalds 	freqs.old = old_freq;
13451da177e4SLinus Torvalds 	freqs.new = new_freq;
1346b43a7ffbSViresh Kumar 
1347b43a7ffbSViresh Kumar 	read_lock_irqsave(&cpufreq_driver_lock, flags);
1348b43a7ffbSViresh Kumar 	policy = per_cpu(cpufreq_cpu_data, cpu);
1349b43a7ffbSViresh Kumar 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1350b43a7ffbSViresh Kumar 
1351b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
1352b43a7ffbSViresh Kumar 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
13531da177e4SLinus Torvalds }
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds /**
13564ab70df4SDhaval Giani  * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
135795235ca2SVenkatesh Pallipadi  * @cpu: CPU number
135895235ca2SVenkatesh Pallipadi  *
135995235ca2SVenkatesh Pallipadi  * This is the last known freq, without actually getting it from the driver.
136095235ca2SVenkatesh Pallipadi  * Return value will be same as what is shown in scaling_cur_freq in sysfs.
136195235ca2SVenkatesh Pallipadi  */
136295235ca2SVenkatesh Pallipadi unsigned int cpufreq_quick_get(unsigned int cpu)
136395235ca2SVenkatesh Pallipadi {
13649e21ba8bSDirk Brandewie 	struct cpufreq_policy *policy;
1365e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
136695235ca2SVenkatesh Pallipadi 
13671c3d85ddSRafael J. Wysocki 	if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
13681c3d85ddSRafael J. Wysocki 		return cpufreq_driver->get(cpu);
13699e21ba8bSDirk Brandewie 
13709e21ba8bSDirk Brandewie 	policy = cpufreq_cpu_get(cpu);
137195235ca2SVenkatesh Pallipadi 	if (policy) {
1372e08f5f5bSGautham R Shenoy 		ret_freq = policy->cur;
137395235ca2SVenkatesh Pallipadi 		cpufreq_cpu_put(policy);
137495235ca2SVenkatesh Pallipadi 	}
137595235ca2SVenkatesh Pallipadi 
13764d34a67dSDave Jones 	return ret_freq;
137795235ca2SVenkatesh Pallipadi }
137895235ca2SVenkatesh Pallipadi EXPORT_SYMBOL(cpufreq_quick_get);
137995235ca2SVenkatesh Pallipadi 
13803d737108SJesse Barnes /**
13813d737108SJesse Barnes  * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
13823d737108SJesse Barnes  * @cpu: CPU number
13833d737108SJesse Barnes  *
13843d737108SJesse Barnes  * Just return the max possible frequency for a given CPU.
13853d737108SJesse Barnes  */
13863d737108SJesse Barnes unsigned int cpufreq_quick_get_max(unsigned int cpu)
13873d737108SJesse Barnes {
13883d737108SJesse Barnes 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
13893d737108SJesse Barnes 	unsigned int ret_freq = 0;
13903d737108SJesse Barnes 
13913d737108SJesse Barnes 	if (policy) {
13923d737108SJesse Barnes 		ret_freq = policy->max;
13933d737108SJesse Barnes 		cpufreq_cpu_put(policy);
13943d737108SJesse Barnes 	}
13953d737108SJesse Barnes 
13963d737108SJesse Barnes 	return ret_freq;
13973d737108SJesse Barnes }
13983d737108SJesse Barnes EXPORT_SYMBOL(cpufreq_quick_get_max);
13993d737108SJesse Barnes 
14005a01f2e8SVenkatesh Pallipadi static unsigned int __cpufreq_get(unsigned int cpu)
14011da177e4SLinus Torvalds {
14027a6aedfaSMike Travis 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
1403e08f5f5bSGautham R Shenoy 	unsigned int ret_freq = 0;
14041da177e4SLinus Torvalds 
14051c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->get)
14064d34a67dSDave Jones 		return ret_freq;
14071da177e4SLinus Torvalds 
14081c3d85ddSRafael J. Wysocki 	ret_freq = cpufreq_driver->get(cpu);
14091da177e4SLinus Torvalds 
1410e08f5f5bSGautham R Shenoy 	if (ret_freq && policy->cur &&
14111c3d85ddSRafael J. Wysocki 		!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
1412e08f5f5bSGautham R Shenoy 		/* verify no discrepancy between actual and
1413e08f5f5bSGautham R Shenoy 					saved value exists */
1414e08f5f5bSGautham R Shenoy 		if (unlikely(ret_freq != policy->cur)) {
1415e08f5f5bSGautham R Shenoy 			cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
14161da177e4SLinus Torvalds 			schedule_work(&policy->update);
14171da177e4SLinus Torvalds 		}
14181da177e4SLinus Torvalds 	}
14191da177e4SLinus Torvalds 
14204d34a67dSDave Jones 	return ret_freq;
14215a01f2e8SVenkatesh Pallipadi }
14221da177e4SLinus Torvalds 
14235a01f2e8SVenkatesh Pallipadi /**
14245a01f2e8SVenkatesh Pallipadi  * cpufreq_get - get the current CPU frequency (in kHz)
14255a01f2e8SVenkatesh Pallipadi  * @cpu: CPU number
14265a01f2e8SVenkatesh Pallipadi  *
14275a01f2e8SVenkatesh Pallipadi  * Get the CPU current (static) CPU frequency
14285a01f2e8SVenkatesh Pallipadi  */
14295a01f2e8SVenkatesh Pallipadi unsigned int cpufreq_get(unsigned int cpu)
14305a01f2e8SVenkatesh Pallipadi {
14315a01f2e8SVenkatesh Pallipadi 	unsigned int ret_freq = 0;
14325a01f2e8SVenkatesh Pallipadi 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
14335a01f2e8SVenkatesh Pallipadi 
14345a01f2e8SVenkatesh Pallipadi 	if (!policy)
14355a01f2e8SVenkatesh Pallipadi 		goto out;
14365a01f2e8SVenkatesh Pallipadi 
14375a01f2e8SVenkatesh Pallipadi 	if (unlikely(lock_policy_rwsem_read(cpu)))
14385a01f2e8SVenkatesh Pallipadi 		goto out_policy;
14395a01f2e8SVenkatesh Pallipadi 
14405a01f2e8SVenkatesh Pallipadi 	ret_freq = __cpufreq_get(cpu);
14415a01f2e8SVenkatesh Pallipadi 
14425a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_read(cpu);
14435a01f2e8SVenkatesh Pallipadi 
14445a01f2e8SVenkatesh Pallipadi out_policy:
14451da177e4SLinus Torvalds 	cpufreq_cpu_put(policy);
14465a01f2e8SVenkatesh Pallipadi out:
14474d34a67dSDave Jones 	return ret_freq;
14481da177e4SLinus Torvalds }
14491da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get);
14501da177e4SLinus Torvalds 
14518a25a2fdSKay Sievers static struct subsys_interface cpufreq_interface = {
14528a25a2fdSKay Sievers 	.name		= "cpufreq",
14538a25a2fdSKay Sievers 	.subsys		= &cpu_subsys,
14548a25a2fdSKay Sievers 	.add_dev	= cpufreq_add_dev,
14558a25a2fdSKay Sievers 	.remove_dev	= cpufreq_remove_dev,
1456e00e56dfSRafael J. Wysocki };
1457e00e56dfSRafael J. Wysocki 
14581da177e4SLinus Torvalds /**
1459e00e56dfSRafael J. Wysocki  * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
1460e00e56dfSRafael J. Wysocki  *
1461e00e56dfSRafael J. Wysocki  * This function is only executed for the boot processor.  The other CPUs
1462e00e56dfSRafael J. Wysocki  * have been put offline by means of CPU hotplug.
146342d4dc3fSBenjamin Herrenschmidt  */
1464e00e56dfSRafael J. Wysocki static int cpufreq_bp_suspend(void)
146542d4dc3fSBenjamin Herrenschmidt {
1466e08f5f5bSGautham R Shenoy 	int ret = 0;
14674bc5d341SDave Jones 
1468e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
146942d4dc3fSBenjamin Herrenschmidt 	struct cpufreq_policy *cpu_policy;
147042d4dc3fSBenjamin Herrenschmidt 
14712d06d8c4SDominik Brodowski 	pr_debug("suspending cpu %u\n", cpu);
147242d4dc3fSBenjamin Herrenschmidt 
1473e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
147442d4dc3fSBenjamin Herrenschmidt 	cpu_policy = cpufreq_cpu_get(cpu);
147542d4dc3fSBenjamin Herrenschmidt 	if (!cpu_policy)
1476e00e56dfSRafael J. Wysocki 		return 0;
147742d4dc3fSBenjamin Herrenschmidt 
14781c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->suspend) {
14791c3d85ddSRafael J. Wysocki 		ret = cpufreq_driver->suspend(cpu_policy);
1480ce6c3997SDominik Brodowski 		if (ret)
148142d4dc3fSBenjamin Herrenschmidt 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
148242d4dc3fSBenjamin Herrenschmidt 					"step on CPU %u\n", cpu_policy->cpu);
148342d4dc3fSBenjamin Herrenschmidt 	}
148442d4dc3fSBenjamin Herrenschmidt 
148542d4dc3fSBenjamin Herrenschmidt 	cpufreq_cpu_put(cpu_policy);
1486c9060494SDave Jones 	return ret;
148742d4dc3fSBenjamin Herrenschmidt }
148842d4dc3fSBenjamin Herrenschmidt 
148942d4dc3fSBenjamin Herrenschmidt /**
1490e00e56dfSRafael J. Wysocki  * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
14911da177e4SLinus Torvalds  *
14921da177e4SLinus Torvalds  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
1493ce6c3997SDominik Brodowski  *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
1494ce6c3997SDominik Brodowski  *	    restored. It will verify that the current freq is in sync with
1495ce6c3997SDominik Brodowski  *	    what we believe it to be. This is a bit later than when it
1496ce6c3997SDominik Brodowski  *	    should be, but nonethteless it's better than calling
1497ce6c3997SDominik Brodowski  *	    cpufreq_driver->get() here which might re-enable interrupts...
1498e00e56dfSRafael J. Wysocki  *
1499e00e56dfSRafael J. Wysocki  * This function is only executed for the boot CPU.  The other CPUs have not
1500e00e56dfSRafael J. Wysocki  * been turned on yet.
15011da177e4SLinus Torvalds  */
1502e00e56dfSRafael J. Wysocki static void cpufreq_bp_resume(void)
15031da177e4SLinus Torvalds {
1504e08f5f5bSGautham R Shenoy 	int ret = 0;
15054bc5d341SDave Jones 
1506e00e56dfSRafael J. Wysocki 	int cpu = smp_processor_id();
15071da177e4SLinus Torvalds 	struct cpufreq_policy *cpu_policy;
15081da177e4SLinus Torvalds 
15092d06d8c4SDominik Brodowski 	pr_debug("resuming cpu %u\n", cpu);
15101da177e4SLinus Torvalds 
1511e00e56dfSRafael J. Wysocki 	/* If there's no policy for the boot CPU, we have nothing to do. */
15121da177e4SLinus Torvalds 	cpu_policy = cpufreq_cpu_get(cpu);
15131da177e4SLinus Torvalds 	if (!cpu_policy)
1514e00e56dfSRafael J. Wysocki 		return;
15151da177e4SLinus Torvalds 
15161c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->resume) {
15171c3d85ddSRafael J. Wysocki 		ret = cpufreq_driver->resume(cpu_policy);
15181da177e4SLinus Torvalds 		if (ret) {
15191da177e4SLinus Torvalds 			printk(KERN_ERR "cpufreq: resume failed in ->resume "
15201da177e4SLinus Torvalds 					"step on CPU %u\n", cpu_policy->cpu);
1521c9060494SDave Jones 			goto fail;
15221da177e4SLinus Torvalds 		}
15231da177e4SLinus Torvalds 	}
15241da177e4SLinus Torvalds 
15251da177e4SLinus Torvalds 	schedule_work(&cpu_policy->update);
1526ce6c3997SDominik Brodowski 
1527c9060494SDave Jones fail:
15281da177e4SLinus Torvalds 	cpufreq_cpu_put(cpu_policy);
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds 
1531e00e56dfSRafael J. Wysocki static struct syscore_ops cpufreq_syscore_ops = {
1532e00e56dfSRafael J. Wysocki 	.suspend	= cpufreq_bp_suspend,
1533e00e56dfSRafael J. Wysocki 	.resume		= cpufreq_bp_resume,
15341da177e4SLinus Torvalds };
15351da177e4SLinus Torvalds 
15369d95046eSBorislav Petkov /**
15379d95046eSBorislav Petkov  *	cpufreq_get_current_driver - return current driver's name
15389d95046eSBorislav Petkov  *
15399d95046eSBorislav Petkov  *	Return the name string of the currently loaded cpufreq driver
15409d95046eSBorislav Petkov  *	or NULL, if none.
15419d95046eSBorislav Petkov  */
15429d95046eSBorislav Petkov const char *cpufreq_get_current_driver(void)
15439d95046eSBorislav Petkov {
15441c3d85ddSRafael J. Wysocki 	if (cpufreq_driver)
15451c3d85ddSRafael J. Wysocki 		return cpufreq_driver->name;
15461c3d85ddSRafael J. Wysocki 
15471c3d85ddSRafael J. Wysocki 	return NULL;
15489d95046eSBorislav Petkov }
15499d95046eSBorislav Petkov EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
15501da177e4SLinus Torvalds 
15511da177e4SLinus Torvalds /*********************************************************************
15521da177e4SLinus Torvalds  *                     NOTIFIER LISTS INTERFACE                      *
15531da177e4SLinus Torvalds  *********************************************************************/
15541da177e4SLinus Torvalds 
15551da177e4SLinus Torvalds /**
15561da177e4SLinus Torvalds  *	cpufreq_register_notifier - register a driver with cpufreq
15571da177e4SLinus Torvalds  *	@nb: notifier function to register
15581da177e4SLinus Torvalds  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
15591da177e4SLinus Torvalds  *
15601da177e4SLinus Torvalds  *	Add a driver to one of two lists: either a list of drivers that
15611da177e4SLinus Torvalds  *      are notified about clock rate changes (once before and once after
15621da177e4SLinus Torvalds  *      the transition), or a list of drivers that are notified about
15631da177e4SLinus Torvalds  *      changes in cpufreq policy.
15641da177e4SLinus Torvalds  *
15651da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1566e041c683SAlan Stern  *	blocking_notifier_chain_register.
15671da177e4SLinus Torvalds  */
15681da177e4SLinus Torvalds int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
15691da177e4SLinus Torvalds {
15701da177e4SLinus Torvalds 	int ret;
15711da177e4SLinus Torvalds 
1572d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1573d5aaffa9SDirk Brandewie 		return -EINVAL;
1574d5aaffa9SDirk Brandewie 
157574212ca4SCesar Eduardo Barros 	WARN_ON(!init_cpufreq_transition_notifier_list_called);
157674212ca4SCesar Eduardo Barros 
15771da177e4SLinus Torvalds 	switch (list) {
15781da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1579b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_register(
1580e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
15811da177e4SLinus Torvalds 		break;
15821da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1583e041c683SAlan Stern 		ret = blocking_notifier_chain_register(
1584e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
15851da177e4SLinus Torvalds 		break;
15861da177e4SLinus Torvalds 	default:
15871da177e4SLinus Torvalds 		ret = -EINVAL;
15881da177e4SLinus Torvalds 	}
15891da177e4SLinus Torvalds 
15901da177e4SLinus Torvalds 	return ret;
15911da177e4SLinus Torvalds }
15921da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_register_notifier);
15931da177e4SLinus Torvalds 
15941da177e4SLinus Torvalds /**
15951da177e4SLinus Torvalds  *	cpufreq_unregister_notifier - unregister a driver with cpufreq
15961da177e4SLinus Torvalds  *	@nb: notifier block to be unregistered
15971da177e4SLinus Torvalds  *	@list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
15981da177e4SLinus Torvalds  *
15991da177e4SLinus Torvalds  *	Remove a driver from the CPU frequency notifier list.
16001da177e4SLinus Torvalds  *
16011da177e4SLinus Torvalds  *	This function may sleep, and has the same return conditions as
1602e041c683SAlan Stern  *	blocking_notifier_chain_unregister.
16031da177e4SLinus Torvalds  */
16041da177e4SLinus Torvalds int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
16051da177e4SLinus Torvalds {
16061da177e4SLinus Torvalds 	int ret;
16071da177e4SLinus Torvalds 
1608d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1609d5aaffa9SDirk Brandewie 		return -EINVAL;
1610d5aaffa9SDirk Brandewie 
16111da177e4SLinus Torvalds 	switch (list) {
16121da177e4SLinus Torvalds 	case CPUFREQ_TRANSITION_NOTIFIER:
1613b4dfdbb3SAlan Stern 		ret = srcu_notifier_chain_unregister(
1614e041c683SAlan Stern 				&cpufreq_transition_notifier_list, nb);
16151da177e4SLinus Torvalds 		break;
16161da177e4SLinus Torvalds 	case CPUFREQ_POLICY_NOTIFIER:
1617e041c683SAlan Stern 		ret = blocking_notifier_chain_unregister(
1618e041c683SAlan Stern 				&cpufreq_policy_notifier_list, nb);
16191da177e4SLinus Torvalds 		break;
16201da177e4SLinus Torvalds 	default:
16211da177e4SLinus Torvalds 		ret = -EINVAL;
16221da177e4SLinus Torvalds 	}
16231da177e4SLinus Torvalds 
16241da177e4SLinus Torvalds 	return ret;
16251da177e4SLinus Torvalds }
16261da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_unregister_notifier);
16271da177e4SLinus Torvalds 
16281da177e4SLinus Torvalds 
16291da177e4SLinus Torvalds /*********************************************************************
16301da177e4SLinus Torvalds  *                              GOVERNORS                            *
16311da177e4SLinus Torvalds  *********************************************************************/
16321da177e4SLinus Torvalds 
16331da177e4SLinus Torvalds int __cpufreq_driver_target(struct cpufreq_policy *policy,
16341da177e4SLinus Torvalds 			    unsigned int target_freq,
16351da177e4SLinus Torvalds 			    unsigned int relation)
16361da177e4SLinus Torvalds {
16371da177e4SLinus Torvalds 	int retval = -EINVAL;
16387249924eSViresh Kumar 	unsigned int old_target_freq = target_freq;
1639c32b6b8eSAshok Raj 
1640a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1641a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
16427c30ed53SViresh Kumar 	if (policy->transition_ongoing)
16437c30ed53SViresh Kumar 		return -EBUSY;
1644a7b422cdSKonrad Rzeszutek Wilk 
16457249924eSViresh Kumar 	/* Make sure that target_freq is within supported range */
16467249924eSViresh Kumar 	if (target_freq > policy->max)
16477249924eSViresh Kumar 		target_freq = policy->max;
16487249924eSViresh Kumar 	if (target_freq < policy->min)
16497249924eSViresh Kumar 		target_freq = policy->min;
16507249924eSViresh Kumar 
16517249924eSViresh Kumar 	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
16527249924eSViresh Kumar 			policy->cpu, target_freq, relation, old_target_freq);
16535a1c0228SViresh Kumar 
16545a1c0228SViresh Kumar 	if (target_freq == policy->cur)
16555a1c0228SViresh Kumar 		return 0;
16565a1c0228SViresh Kumar 
16571c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->target)
16581c3d85ddSRafael J. Wysocki 		retval = cpufreq_driver->target(policy, target_freq, relation);
165990d45d17SAshok Raj 
16601da177e4SLinus Torvalds 	return retval;
16611da177e4SLinus Torvalds }
16621da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
16631da177e4SLinus Torvalds 
16641da177e4SLinus Torvalds int cpufreq_driver_target(struct cpufreq_policy *policy,
16651da177e4SLinus Torvalds 			  unsigned int target_freq,
16661da177e4SLinus Torvalds 			  unsigned int relation)
16671da177e4SLinus Torvalds {
1668f1829e4aSJulia Lawall 	int ret = -EINVAL;
16691da177e4SLinus Torvalds 
16705a01f2e8SVenkatesh Pallipadi 	if (unlikely(lock_policy_rwsem_write(policy->cpu)))
1671f1829e4aSJulia Lawall 		goto fail;
16721da177e4SLinus Torvalds 
16731da177e4SLinus Torvalds 	ret = __cpufreq_driver_target(policy, target_freq, relation);
16741da177e4SLinus Torvalds 
16755a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(policy->cpu);
16761da177e4SLinus Torvalds 
1677f1829e4aSJulia Lawall fail:
16781da177e4SLinus Torvalds 	return ret;
16791da177e4SLinus Torvalds }
16801da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_driver_target);
16811da177e4SLinus Torvalds 
1682bf0b90e3Svenkatesh.pallipadi@intel.com int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
1683dfde5d62SVenkatesh Pallipadi {
1684d5aaffa9SDirk Brandewie 	if (cpufreq_disabled())
1685a262e94cSViresh Kumar 		return 0;
1686d5aaffa9SDirk Brandewie 
16871c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver->getavg)
16880676f7f2SViresh Kumar 		return 0;
16890676f7f2SViresh Kumar 
1690a262e94cSViresh Kumar 	return cpufreq_driver->getavg(policy, cpu);
1691dfde5d62SVenkatesh Pallipadi }
16925a01f2e8SVenkatesh Pallipadi EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
1693dfde5d62SVenkatesh Pallipadi 
1694153d7f3fSArjan van de Ven /*
1695153d7f3fSArjan van de Ven  * when "event" is CPUFREQ_GOV_LIMITS
1696153d7f3fSArjan van de Ven  */
16971da177e4SLinus Torvalds 
1698e08f5f5bSGautham R Shenoy static int __cpufreq_governor(struct cpufreq_policy *policy,
1699e08f5f5bSGautham R Shenoy 					unsigned int event)
17001da177e4SLinus Torvalds {
1701cc993cabSDave Jones 	int ret;
17026afde10cSThomas Renninger 
17036afde10cSThomas Renninger 	/* Only must be defined when default governor is known to have latency
17046afde10cSThomas Renninger 	   restrictions, like e.g. conservative or ondemand.
17056afde10cSThomas Renninger 	   That this is the case is already ensured in Kconfig
17066afde10cSThomas Renninger 	*/
17076afde10cSThomas Renninger #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
17086afde10cSThomas Renninger 	struct cpufreq_governor *gov = &cpufreq_gov_performance;
17096afde10cSThomas Renninger #else
17106afde10cSThomas Renninger 	struct cpufreq_governor *gov = NULL;
17116afde10cSThomas Renninger #endif
17121c256245SThomas Renninger 
17131c256245SThomas Renninger 	if (policy->governor->max_transition_latency &&
17141c256245SThomas Renninger 	    policy->cpuinfo.transition_latency >
17151c256245SThomas Renninger 	    policy->governor->max_transition_latency) {
17166afde10cSThomas Renninger 		if (!gov)
17176afde10cSThomas Renninger 			return -EINVAL;
17186afde10cSThomas Renninger 		else {
17191c256245SThomas Renninger 			printk(KERN_WARNING "%s governor failed, too long"
17201c256245SThomas Renninger 			       " transition latency of HW, fallback"
17211c256245SThomas Renninger 			       " to %s governor\n",
17221c256245SThomas Renninger 			       policy->governor->name,
17231c256245SThomas Renninger 			       gov->name);
17241c256245SThomas Renninger 			policy->governor = gov;
17251c256245SThomas Renninger 		}
17266afde10cSThomas Renninger 	}
17271da177e4SLinus Torvalds 
17281da177e4SLinus Torvalds 	if (!try_module_get(policy->governor->owner))
17291da177e4SLinus Torvalds 		return -EINVAL;
17301da177e4SLinus Torvalds 
17312d06d8c4SDominik Brodowski 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
1732e08f5f5bSGautham R Shenoy 						policy->cpu, event);
173395731ebbSXiaoguang Chen 
173495731ebbSXiaoguang Chen 	mutex_lock(&cpufreq_governor_lock);
173595731ebbSXiaoguang Chen 	if ((!policy->governor_enabled && (event == CPUFREQ_GOV_STOP)) ||
173695731ebbSXiaoguang Chen 	    (policy->governor_enabled && (event == CPUFREQ_GOV_START))) {
173795731ebbSXiaoguang Chen 		mutex_unlock(&cpufreq_governor_lock);
173895731ebbSXiaoguang Chen 		return -EBUSY;
173995731ebbSXiaoguang Chen 	}
174095731ebbSXiaoguang Chen 
174195731ebbSXiaoguang Chen 	if (event == CPUFREQ_GOV_STOP)
174295731ebbSXiaoguang Chen 		policy->governor_enabled = false;
174395731ebbSXiaoguang Chen 	else if (event == CPUFREQ_GOV_START)
174495731ebbSXiaoguang Chen 		policy->governor_enabled = true;
174595731ebbSXiaoguang Chen 
174695731ebbSXiaoguang Chen 	mutex_unlock(&cpufreq_governor_lock);
174795731ebbSXiaoguang Chen 
17481da177e4SLinus Torvalds 	ret = policy->governor->governor(policy, event);
17491da177e4SLinus Torvalds 
17504d5dcc42SViresh Kumar 	if (!ret) {
17514d5dcc42SViresh Kumar 		if (event == CPUFREQ_GOV_POLICY_INIT)
17528e53695fSViresh Kumar 			policy->governor->initialized++;
17534d5dcc42SViresh Kumar 		else if (event == CPUFREQ_GOV_POLICY_EXIT)
17548e53695fSViresh Kumar 			policy->governor->initialized--;
175595731ebbSXiaoguang Chen 	} else {
175695731ebbSXiaoguang Chen 		/* Restore original values */
175795731ebbSXiaoguang Chen 		mutex_lock(&cpufreq_governor_lock);
175895731ebbSXiaoguang Chen 		if (event == CPUFREQ_GOV_STOP)
175995731ebbSXiaoguang Chen 			policy->governor_enabled = true;
176095731ebbSXiaoguang Chen 		else if (event == CPUFREQ_GOV_START)
176195731ebbSXiaoguang Chen 			policy->governor_enabled = false;
176295731ebbSXiaoguang Chen 		mutex_unlock(&cpufreq_governor_lock);
17634d5dcc42SViresh Kumar 	}
1764b394058fSViresh Kumar 
1765e08f5f5bSGautham R Shenoy 	/* we keep one module reference alive for
1766e08f5f5bSGautham R Shenoy 			each CPU governed by this CPU */
17671da177e4SLinus Torvalds 	if ((event != CPUFREQ_GOV_START) || ret)
17681da177e4SLinus Torvalds 		module_put(policy->governor->owner);
17691da177e4SLinus Torvalds 	if ((event == CPUFREQ_GOV_STOP) && !ret)
17701da177e4SLinus Torvalds 		module_put(policy->governor->owner);
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 	return ret;
17731da177e4SLinus Torvalds }
17741da177e4SLinus Torvalds 
17751da177e4SLinus Torvalds int cpufreq_register_governor(struct cpufreq_governor *governor)
17761da177e4SLinus Torvalds {
17773bcb09a3SJeremy Fitzhardinge 	int err;
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 	if (!governor)
17801da177e4SLinus Torvalds 		return -EINVAL;
17811da177e4SLinus Torvalds 
1782a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1783a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
1784a7b422cdSKonrad Rzeszutek Wilk 
17853fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
17861da177e4SLinus Torvalds 
1787b394058fSViresh Kumar 	governor->initialized = 0;
17883bcb09a3SJeremy Fitzhardinge 	err = -EBUSY;
17893bcb09a3SJeremy Fitzhardinge 	if (__find_governor(governor->name) == NULL) {
17903bcb09a3SJeremy Fitzhardinge 		err = 0;
17911da177e4SLinus Torvalds 		list_add(&governor->governor_list, &cpufreq_governor_list);
17923bcb09a3SJeremy Fitzhardinge 	}
17931da177e4SLinus Torvalds 
17943fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
17953bcb09a3SJeremy Fitzhardinge 	return err;
17961da177e4SLinus Torvalds }
17971da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_governor);
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds void cpufreq_unregister_governor(struct cpufreq_governor *governor)
18001da177e4SLinus Torvalds {
180190e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
180290e41bacSPrarit Bhargava 	int cpu;
180390e41bacSPrarit Bhargava #endif
180490e41bacSPrarit Bhargava 
18051da177e4SLinus Torvalds 	if (!governor)
18061da177e4SLinus Torvalds 		return;
18071da177e4SLinus Torvalds 
1808a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
1809a7b422cdSKonrad Rzeszutek Wilk 		return;
1810a7b422cdSKonrad Rzeszutek Wilk 
181190e41bacSPrarit Bhargava #ifdef CONFIG_HOTPLUG_CPU
181290e41bacSPrarit Bhargava 	for_each_present_cpu(cpu) {
181390e41bacSPrarit Bhargava 		if (cpu_online(cpu))
181490e41bacSPrarit Bhargava 			continue;
181590e41bacSPrarit Bhargava 		if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
181690e41bacSPrarit Bhargava 			strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
181790e41bacSPrarit Bhargava 	}
181890e41bacSPrarit Bhargava #endif
181990e41bacSPrarit Bhargava 
18203fc54d37Sakpm@osdl.org 	mutex_lock(&cpufreq_governor_mutex);
18211da177e4SLinus Torvalds 	list_del(&governor->governor_list);
18223fc54d37Sakpm@osdl.org 	mutex_unlock(&cpufreq_governor_mutex);
18231da177e4SLinus Torvalds 	return;
18241da177e4SLinus Torvalds }
18251da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
18261da177e4SLinus Torvalds 
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds /*********************************************************************
18291da177e4SLinus Torvalds  *                          POLICY INTERFACE                         *
18301da177e4SLinus Torvalds  *********************************************************************/
18311da177e4SLinus Torvalds 
18321da177e4SLinus Torvalds /**
18331da177e4SLinus Torvalds  * cpufreq_get_policy - get the current cpufreq_policy
183429464f28SDave Jones  * @policy: struct cpufreq_policy into which the current cpufreq_policy
183529464f28SDave Jones  *	is written
18361da177e4SLinus Torvalds  *
18371da177e4SLinus Torvalds  * Reads the current cpufreq policy.
18381da177e4SLinus Torvalds  */
18391da177e4SLinus Torvalds int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
18401da177e4SLinus Torvalds {
18411da177e4SLinus Torvalds 	struct cpufreq_policy *cpu_policy;
18421da177e4SLinus Torvalds 	if (!policy)
18431da177e4SLinus Torvalds 		return -EINVAL;
18441da177e4SLinus Torvalds 
18451da177e4SLinus Torvalds 	cpu_policy = cpufreq_cpu_get(cpu);
18461da177e4SLinus Torvalds 	if (!cpu_policy)
18471da177e4SLinus Torvalds 		return -EINVAL;
18481da177e4SLinus Torvalds 
18491da177e4SLinus Torvalds 	memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
18501da177e4SLinus Torvalds 
18511da177e4SLinus Torvalds 	cpufreq_cpu_put(cpu_policy);
18521da177e4SLinus Torvalds 	return 0;
18531da177e4SLinus Torvalds }
18541da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get_policy);
18551da177e4SLinus Torvalds 
1856153d7f3fSArjan van de Ven /*
1857e08f5f5bSGautham R Shenoy  * data   : current policy.
1858e08f5f5bSGautham R Shenoy  * policy : policy to be set.
1859153d7f3fSArjan van de Ven  */
1860e08f5f5bSGautham R Shenoy static int __cpufreq_set_policy(struct cpufreq_policy *data,
1861e08f5f5bSGautham R Shenoy 				struct cpufreq_policy *policy)
18621da177e4SLinus Torvalds {
18637bd353a9SViresh Kumar 	int ret = 0, failed = 1;
18641da177e4SLinus Torvalds 
18652d06d8c4SDominik Brodowski 	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
18661da177e4SLinus Torvalds 		policy->min, policy->max);
18671da177e4SLinus Torvalds 
1868e08f5f5bSGautham R Shenoy 	memcpy(&policy->cpuinfo, &data->cpuinfo,
1869e08f5f5bSGautham R Shenoy 				sizeof(struct cpufreq_cpuinfo));
18701da177e4SLinus Torvalds 
187153391fa2SYi Yang 	if (policy->min > data->max || policy->max < data->min) {
18729c9a43edSMattia Dongili 		ret = -EINVAL;
18739c9a43edSMattia Dongili 		goto error_out;
18749c9a43edSMattia Dongili 	}
18759c9a43edSMattia Dongili 
18761da177e4SLinus Torvalds 	/* verify the cpu speed can be set within this limit */
18771c3d85ddSRafael J. Wysocki 	ret = cpufreq_driver->verify(policy);
18781da177e4SLinus Torvalds 	if (ret)
18791da177e4SLinus Torvalds 		goto error_out;
18801da177e4SLinus Torvalds 
18811da177e4SLinus Torvalds 	/* adjust if necessary - all reasons */
1882e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1883e041c683SAlan Stern 			CPUFREQ_ADJUST, policy);
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds 	/* adjust if necessary - hardware incompatibility*/
1886e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1887e041c683SAlan Stern 			CPUFREQ_INCOMPATIBLE, policy);
18881da177e4SLinus Torvalds 
1889bb176f7dSViresh Kumar 	/*
1890bb176f7dSViresh Kumar 	 * verify the cpu speed can be set within this limit, which might be
1891bb176f7dSViresh Kumar 	 * different to the first one
1892bb176f7dSViresh Kumar 	 */
18931c3d85ddSRafael J. Wysocki 	ret = cpufreq_driver->verify(policy);
1894e041c683SAlan Stern 	if (ret)
18951da177e4SLinus Torvalds 		goto error_out;
18961da177e4SLinus Torvalds 
18971da177e4SLinus Torvalds 	/* notification of the new policy */
1898e041c683SAlan Stern 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
1899e041c683SAlan Stern 			CPUFREQ_NOTIFY, policy);
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 	data->min = policy->min;
19021da177e4SLinus Torvalds 	data->max = policy->max;
19031da177e4SLinus Torvalds 
19042d06d8c4SDominik Brodowski 	pr_debug("new min and max freqs are %u - %u kHz\n",
1905e08f5f5bSGautham R Shenoy 					data->min, data->max);
19061da177e4SLinus Torvalds 
19071c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->setpolicy) {
19081da177e4SLinus Torvalds 		data->policy = policy->policy;
19092d06d8c4SDominik Brodowski 		pr_debug("setting range\n");
19101c3d85ddSRafael J. Wysocki 		ret = cpufreq_driver->setpolicy(policy);
19111da177e4SLinus Torvalds 	} else {
19121da177e4SLinus Torvalds 		if (policy->governor != data->governor) {
19131da177e4SLinus Torvalds 			/* save old, working values */
19141da177e4SLinus Torvalds 			struct cpufreq_governor *old_gov = data->governor;
19151da177e4SLinus Torvalds 
19162d06d8c4SDominik Brodowski 			pr_debug("governor switch\n");
19171da177e4SLinus Torvalds 
19181da177e4SLinus Torvalds 			/* end old governor */
19197bd353a9SViresh Kumar 			if (data->governor) {
19201da177e4SLinus Torvalds 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
1921955ef483SViresh Kumar 				unlock_policy_rwsem_write(policy->cpu);
19227bd353a9SViresh Kumar 				__cpufreq_governor(data,
19237bd353a9SViresh Kumar 						CPUFREQ_GOV_POLICY_EXIT);
1924955ef483SViresh Kumar 				lock_policy_rwsem_write(policy->cpu);
19257bd353a9SViresh Kumar 			}
19261da177e4SLinus Torvalds 
19271da177e4SLinus Torvalds 			/* start new governor */
19281da177e4SLinus Torvalds 			data->governor = policy->governor;
19297bd353a9SViresh Kumar 			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
1930955ef483SViresh Kumar 				if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
19317bd353a9SViresh Kumar 					failed = 0;
1932955ef483SViresh Kumar 				} else {
1933955ef483SViresh Kumar 					unlock_policy_rwsem_write(policy->cpu);
19347bd353a9SViresh Kumar 					__cpufreq_governor(data,
19357bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_EXIT);
1936955ef483SViresh Kumar 					lock_policy_rwsem_write(policy->cpu);
1937955ef483SViresh Kumar 				}
19387bd353a9SViresh Kumar 			}
19397bd353a9SViresh Kumar 
19407bd353a9SViresh Kumar 			if (failed) {
19411da177e4SLinus Torvalds 				/* new governor failed, so re-start old one */
19422d06d8c4SDominik Brodowski 				pr_debug("starting governor %s failed\n",
1943e08f5f5bSGautham R Shenoy 							data->governor->name);
19441da177e4SLinus Torvalds 				if (old_gov) {
19451da177e4SLinus Torvalds 					data->governor = old_gov;
1946e08f5f5bSGautham R Shenoy 					__cpufreq_governor(data,
19477bd353a9SViresh Kumar 							CPUFREQ_GOV_POLICY_INIT);
19487bd353a9SViresh Kumar 					__cpufreq_governor(data,
1949e08f5f5bSGautham R Shenoy 							   CPUFREQ_GOV_START);
19501da177e4SLinus Torvalds 				}
19511da177e4SLinus Torvalds 				ret = -EINVAL;
19521da177e4SLinus Torvalds 				goto error_out;
19531da177e4SLinus Torvalds 			}
19541da177e4SLinus Torvalds 			/* might be a policy change, too, so fall through */
19551da177e4SLinus Torvalds 		}
19562d06d8c4SDominik Brodowski 		pr_debug("governor: change or update limits\n");
19571da177e4SLinus Torvalds 		__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
19581da177e4SLinus Torvalds 	}
19591da177e4SLinus Torvalds 
19601da177e4SLinus Torvalds error_out:
19611da177e4SLinus Torvalds 	return ret;
19621da177e4SLinus Torvalds }
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds /**
19651da177e4SLinus Torvalds  *	cpufreq_update_policy - re-evaluate an existing cpufreq policy
19661da177e4SLinus Torvalds  *	@cpu: CPU which shall be re-evaluated
19671da177e4SLinus Torvalds  *
196825985edcSLucas De Marchi  *	Useful for policy notifiers which have different necessities
19691da177e4SLinus Torvalds  *	at different times.
19701da177e4SLinus Torvalds  */
19711da177e4SLinus Torvalds int cpufreq_update_policy(unsigned int cpu)
19721da177e4SLinus Torvalds {
19731da177e4SLinus Torvalds 	struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
19741da177e4SLinus Torvalds 	struct cpufreq_policy policy;
1975f1829e4aSJulia Lawall 	int ret;
19761da177e4SLinus Torvalds 
1977f1829e4aSJulia Lawall 	if (!data) {
1978f1829e4aSJulia Lawall 		ret = -ENODEV;
1979f1829e4aSJulia Lawall 		goto no_policy;
1980f1829e4aSJulia Lawall 	}
19811da177e4SLinus Torvalds 
1982f1829e4aSJulia Lawall 	if (unlikely(lock_policy_rwsem_write(cpu))) {
1983f1829e4aSJulia Lawall 		ret = -EINVAL;
1984f1829e4aSJulia Lawall 		goto fail;
1985f1829e4aSJulia Lawall 	}
19861da177e4SLinus Torvalds 
19872d06d8c4SDominik Brodowski 	pr_debug("updating policy for CPU %u\n", cpu);
19887d5e350fSDave Jones 	memcpy(&policy, data, sizeof(struct cpufreq_policy));
19891da177e4SLinus Torvalds 	policy.min = data->user_policy.min;
19901da177e4SLinus Torvalds 	policy.max = data->user_policy.max;
19911da177e4SLinus Torvalds 	policy.policy = data->user_policy.policy;
19921da177e4SLinus Torvalds 	policy.governor = data->user_policy.governor;
19931da177e4SLinus Torvalds 
1994bb176f7dSViresh Kumar 	/*
1995bb176f7dSViresh Kumar 	 * BIOS might change freq behind our back
1996bb176f7dSViresh Kumar 	 * -> ask driver for current freq and notify governors about a change
1997bb176f7dSViresh Kumar 	 */
19981c3d85ddSRafael J. Wysocki 	if (cpufreq_driver->get) {
19991c3d85ddSRafael J. Wysocki 		policy.cur = cpufreq_driver->get(cpu);
2000a85f7bd3SThomas Renninger 		if (!data->cur) {
20012d06d8c4SDominik Brodowski 			pr_debug("Driver did not initialize current freq");
2002a85f7bd3SThomas Renninger 			data->cur = policy.cur;
2003a85f7bd3SThomas Renninger 		} else {
20041c3d85ddSRafael J. Wysocki 			if (data->cur != policy.cur && cpufreq_driver->target)
2005e08f5f5bSGautham R Shenoy 				cpufreq_out_of_sync(cpu, data->cur,
2006e08f5f5bSGautham R Shenoy 								policy.cur);
20070961dd0dSThomas Renninger 		}
2008a85f7bd3SThomas Renninger 	}
20090961dd0dSThomas Renninger 
20101da177e4SLinus Torvalds 	ret = __cpufreq_set_policy(data, &policy);
20111da177e4SLinus Torvalds 
20125a01f2e8SVenkatesh Pallipadi 	unlock_policy_rwsem_write(cpu);
20135a01f2e8SVenkatesh Pallipadi 
2014f1829e4aSJulia Lawall fail:
20151da177e4SLinus Torvalds 	cpufreq_cpu_put(data);
2016f1829e4aSJulia Lawall no_policy:
20171da177e4SLinus Torvalds 	return ret;
20181da177e4SLinus Torvalds }
20191da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_update_policy);
20201da177e4SLinus Torvalds 
20212760984fSPaul Gortmaker static int cpufreq_cpu_callback(struct notifier_block *nfb,
2022c32b6b8eSAshok Raj 					unsigned long action, void *hcpu)
2023c32b6b8eSAshok Raj {
2024c32b6b8eSAshok Raj 	unsigned int cpu = (unsigned long)hcpu;
20258a25a2fdSKay Sievers 	struct device *dev;
20265302c3fbSSrivatsa S. Bhat 	bool frozen = false;
2027c32b6b8eSAshok Raj 
20288a25a2fdSKay Sievers 	dev = get_cpu_device(cpu);
20298a25a2fdSKay Sievers 	if (dev) {
20305302c3fbSSrivatsa S. Bhat 
20315302c3fbSSrivatsa S. Bhat 		if (action & CPU_TASKS_FROZEN)
20325302c3fbSSrivatsa S. Bhat 			frozen = true;
20335302c3fbSSrivatsa S. Bhat 
20345302c3fbSSrivatsa S. Bhat 		switch (action & ~CPU_TASKS_FROZEN) {
2035c32b6b8eSAshok Raj 		case CPU_ONLINE:
20365302c3fbSSrivatsa S. Bhat 			__cpufreq_add_dev(dev, NULL, frozen);
203723d32899SSrivatsa S. Bhat 			cpufreq_update_policy(cpu);
2038c32b6b8eSAshok Raj 			break;
20395302c3fbSSrivatsa S. Bhat 
2040c32b6b8eSAshok Raj 		case CPU_DOWN_PREPARE:
20415302c3fbSSrivatsa S. Bhat 			__cpufreq_remove_dev(dev, NULL, frozen);
2042c32b6b8eSAshok Raj 			break;
20435302c3fbSSrivatsa S. Bhat 
20445a01f2e8SVenkatesh Pallipadi 		case CPU_DOWN_FAILED:
20455302c3fbSSrivatsa S. Bhat 			__cpufreq_add_dev(dev, NULL, frozen);
2046c32b6b8eSAshok Raj 			break;
2047c32b6b8eSAshok Raj 		}
2048c32b6b8eSAshok Raj 	}
2049c32b6b8eSAshok Raj 	return NOTIFY_OK;
2050c32b6b8eSAshok Raj }
2051c32b6b8eSAshok Raj 
20529c36f746SNeal Buckendahl static struct notifier_block __refdata cpufreq_cpu_notifier = {
2053c32b6b8eSAshok Raj 	.notifier_call = cpufreq_cpu_callback,
2054c32b6b8eSAshok Raj };
20551da177e4SLinus Torvalds 
20561da177e4SLinus Torvalds /*********************************************************************
20571da177e4SLinus Torvalds  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
20581da177e4SLinus Torvalds  *********************************************************************/
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds /**
20611da177e4SLinus Torvalds  * cpufreq_register_driver - register a CPU Frequency driver
20621da177e4SLinus Torvalds  * @driver_data: A struct cpufreq_driver containing the values#
20631da177e4SLinus Torvalds  * submitted by the CPU Frequency driver.
20641da177e4SLinus Torvalds  *
20651da177e4SLinus Torvalds  * Registers a CPU Frequency driver to this core code. This code
20661da177e4SLinus Torvalds  * returns zero on success, -EBUSY when another driver got here first
20671da177e4SLinus Torvalds  * (and isn't unregistered in the meantime).
20681da177e4SLinus Torvalds  *
20691da177e4SLinus Torvalds  */
2070221dee28SLinus Torvalds int cpufreq_register_driver(struct cpufreq_driver *driver_data)
20711da177e4SLinus Torvalds {
20721da177e4SLinus Torvalds 	unsigned long flags;
20731da177e4SLinus Torvalds 	int ret;
20741da177e4SLinus Torvalds 
2075a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2076a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2077a7b422cdSKonrad Rzeszutek Wilk 
20781da177e4SLinus Torvalds 	if (!driver_data || !driver_data->verify || !driver_data->init ||
20791da177e4SLinus Torvalds 	    ((!driver_data->setpolicy) && (!driver_data->target)))
20801da177e4SLinus Torvalds 		return -EINVAL;
20811da177e4SLinus Torvalds 
20822d06d8c4SDominik Brodowski 	pr_debug("trying to register driver %s\n", driver_data->name);
20831da177e4SLinus Torvalds 
20841da177e4SLinus Torvalds 	if (driver_data->setpolicy)
20851da177e4SLinus Torvalds 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
20861da177e4SLinus Torvalds 
20870d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
20881c3d85ddSRafael J. Wysocki 	if (cpufreq_driver) {
20890d1857a1SNathan Zimmer 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20901da177e4SLinus Torvalds 		return -EBUSY;
20911da177e4SLinus Torvalds 	}
20921c3d85ddSRafael J. Wysocki 	cpufreq_driver = driver_data;
20930d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
20941da177e4SLinus Torvalds 
20958a25a2fdSKay Sievers 	ret = subsys_interface_register(&cpufreq_interface);
20968f5bc2abSJiri Slaby 	if (ret)
20978f5bc2abSJiri Slaby 		goto err_null_driver;
20981da177e4SLinus Torvalds 
20991c3d85ddSRafael J. Wysocki 	if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
21001da177e4SLinus Torvalds 		int i;
21011da177e4SLinus Torvalds 		ret = -ENODEV;
21021da177e4SLinus Torvalds 
21031da177e4SLinus Torvalds 		/* check for at least one working CPU */
21047a6aedfaSMike Travis 		for (i = 0; i < nr_cpu_ids; i++)
21057a6aedfaSMike Travis 			if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
21061da177e4SLinus Torvalds 				ret = 0;
21077a6aedfaSMike Travis 				break;
21087a6aedfaSMike Travis 			}
21091da177e4SLinus Torvalds 
21101da177e4SLinus Torvalds 		/* if all ->init() calls failed, unregister */
21111da177e4SLinus Torvalds 		if (ret) {
21122d06d8c4SDominik Brodowski 			pr_debug("no CPU initialized for driver %s\n",
2113e08f5f5bSGautham R Shenoy 							driver_data->name);
21148a25a2fdSKay Sievers 			goto err_if_unreg;
21151da177e4SLinus Torvalds 		}
21161da177e4SLinus Torvalds 	}
21171da177e4SLinus Torvalds 
211865edc68cSChandra Seetharaman 	register_hotcpu_notifier(&cpufreq_cpu_notifier);
21192d06d8c4SDominik Brodowski 	pr_debug("driver %s up and running\n", driver_data->name);
21201da177e4SLinus Torvalds 
21218f5bc2abSJiri Slaby 	return 0;
21228a25a2fdSKay Sievers err_if_unreg:
21238a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
21248f5bc2abSJiri Slaby err_null_driver:
21250d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
21261c3d85ddSRafael J. Wysocki 	cpufreq_driver = NULL;
21270d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
21284d34a67dSDave Jones 	return ret;
21291da177e4SLinus Torvalds }
21301da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_driver);
21311da177e4SLinus Torvalds 
21321da177e4SLinus Torvalds /**
21331da177e4SLinus Torvalds  * cpufreq_unregister_driver - unregister the current CPUFreq driver
21341da177e4SLinus Torvalds  *
21351da177e4SLinus Torvalds  * Unregister the current CPUFreq driver. Only call this if you have
21361da177e4SLinus Torvalds  * the right to do so, i.e. if you have succeeded in initialising before!
21371da177e4SLinus Torvalds  * Returns zero if successful, and -EINVAL if the cpufreq_driver is
21381da177e4SLinus Torvalds  * currently not initialised.
21391da177e4SLinus Torvalds  */
2140221dee28SLinus Torvalds int cpufreq_unregister_driver(struct cpufreq_driver *driver)
21411da177e4SLinus Torvalds {
21421da177e4SLinus Torvalds 	unsigned long flags;
21431da177e4SLinus Torvalds 
21441c3d85ddSRafael J. Wysocki 	if (!cpufreq_driver || (driver != cpufreq_driver))
21451da177e4SLinus Torvalds 		return -EINVAL;
21461da177e4SLinus Torvalds 
21472d06d8c4SDominik Brodowski 	pr_debug("unregistering driver %s\n", driver->name);
21481da177e4SLinus Torvalds 
21498a25a2fdSKay Sievers 	subsys_interface_unregister(&cpufreq_interface);
215065edc68cSChandra Seetharaman 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
21511da177e4SLinus Torvalds 
21520d1857a1SNathan Zimmer 	write_lock_irqsave(&cpufreq_driver_lock, flags);
21531c3d85ddSRafael J. Wysocki 	cpufreq_driver = NULL;
21540d1857a1SNathan Zimmer 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
21551da177e4SLinus Torvalds 
21561da177e4SLinus Torvalds 	return 0;
21571da177e4SLinus Torvalds }
21581da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
21595a01f2e8SVenkatesh Pallipadi 
21605a01f2e8SVenkatesh Pallipadi static int __init cpufreq_core_init(void)
21615a01f2e8SVenkatesh Pallipadi {
21625a01f2e8SVenkatesh Pallipadi 	int cpu;
21635a01f2e8SVenkatesh Pallipadi 
2164a7b422cdSKonrad Rzeszutek Wilk 	if (cpufreq_disabled())
2165a7b422cdSKonrad Rzeszutek Wilk 		return -ENODEV;
2166a7b422cdSKonrad Rzeszutek Wilk 
21675a01f2e8SVenkatesh Pallipadi 	for_each_possible_cpu(cpu) {
2168f1625066STejun Heo 		per_cpu(cpufreq_policy_cpu, cpu) = -1;
21695a01f2e8SVenkatesh Pallipadi 		init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
21705a01f2e8SVenkatesh Pallipadi 	}
21718aa84ad8SThomas Renninger 
21722361be23SViresh Kumar 	cpufreq_global_kobject = kobject_create();
21738aa84ad8SThomas Renninger 	BUG_ON(!cpufreq_global_kobject);
2174e00e56dfSRafael J. Wysocki 	register_syscore_ops(&cpufreq_syscore_ops);
21758aa84ad8SThomas Renninger 
21765a01f2e8SVenkatesh Pallipadi 	return 0;
21775a01f2e8SVenkatesh Pallipadi }
21785a01f2e8SVenkatesh Pallipadi core_initcall(cpufreq_core_init);
2179