11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/drivers/cpufreq/cpufreq.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2001 Russell King 51da177e4SLinus Torvalds * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> 6bb176f7dSViresh Kumar * (C) 2013 Viresh Kumar <viresh.kumar@linaro.org> 71da177e4SLinus Torvalds * 8c32b6b8eSAshok Raj * Oct 2005 - Ashok Raj <ashok.raj@intel.com> 9c32b6b8eSAshok Raj * Added handling for CPU hotplug 108ff69732SDave Jones * Feb 2006 - Jacob Shin <jacob.shin@amd.com> 118ff69732SDave Jones * Fix handling for CPU hotplug -- affected CPUs 12c32b6b8eSAshok Raj * 131da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 141da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 151da177e4SLinus Torvalds * published by the Free Software Foundation. 161da177e4SLinus Torvalds */ 171da177e4SLinus Torvalds 18db701151SViresh Kumar #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19db701151SViresh Kumar 205ff0a268SViresh Kumar #include <linux/cpu.h> 211da177e4SLinus Torvalds #include <linux/cpufreq.h> 221da177e4SLinus Torvalds #include <linux/delay.h> 231da177e4SLinus Torvalds #include <linux/device.h> 245ff0a268SViresh Kumar #include <linux/init.h> 255ff0a268SViresh Kumar #include <linux/kernel_stat.h> 265ff0a268SViresh Kumar #include <linux/module.h> 273fc54d37Sakpm@osdl.org #include <linux/mutex.h> 285ff0a268SViresh Kumar #include <linux/slab.h> 292f0aea93SViresh Kumar #include <linux/suspend.h> 3090de2a4aSDoug Anderson #include <linux/syscore_ops.h> 315ff0a268SViresh Kumar #include <linux/tick.h> 326f4f2723SThomas Renninger #include <trace/events/power.h> 336f4f2723SThomas Renninger 34b4f0676fSViresh Kumar static LIST_HEAD(cpufreq_policy_list); 35f963735aSViresh Kumar 36f963735aSViresh Kumar static inline bool policy_is_inactive(struct cpufreq_policy *policy) 37f963735aSViresh Kumar { 38f963735aSViresh Kumar return cpumask_empty(policy->cpus); 39f963735aSViresh Kumar } 40f963735aSViresh Kumar 41f963735aSViresh Kumar static bool suitable_policy(struct cpufreq_policy *policy, bool active) 42f963735aSViresh Kumar { 43f963735aSViresh Kumar return active == !policy_is_inactive(policy); 44f963735aSViresh Kumar } 45f963735aSViresh Kumar 46f963735aSViresh Kumar /* Finds Next Acive/Inactive policy */ 47f963735aSViresh Kumar static struct cpufreq_policy *next_policy(struct cpufreq_policy *policy, 48f963735aSViresh Kumar bool active) 49f963735aSViresh Kumar { 50f963735aSViresh Kumar do { 51f963735aSViresh Kumar policy = list_next_entry(policy, policy_list); 52f963735aSViresh Kumar 53f963735aSViresh Kumar /* No more policies in the list */ 54f963735aSViresh Kumar if (&policy->policy_list == &cpufreq_policy_list) 55f963735aSViresh Kumar return NULL; 56f963735aSViresh Kumar } while (!suitable_policy(policy, active)); 57f963735aSViresh Kumar 58f963735aSViresh Kumar return policy; 59f963735aSViresh Kumar } 60f963735aSViresh Kumar 61f963735aSViresh Kumar static struct cpufreq_policy *first_policy(bool active) 62f963735aSViresh Kumar { 63f963735aSViresh Kumar struct cpufreq_policy *policy; 64f963735aSViresh Kumar 65f963735aSViresh Kumar /* No policies in the list */ 66f963735aSViresh Kumar if (list_empty(&cpufreq_policy_list)) 67f963735aSViresh Kumar return NULL; 68f963735aSViresh Kumar 69f963735aSViresh Kumar policy = list_first_entry(&cpufreq_policy_list, typeof(*policy), 70f963735aSViresh Kumar policy_list); 71f963735aSViresh Kumar 72f963735aSViresh Kumar if (!suitable_policy(policy, active)) 73f963735aSViresh Kumar policy = next_policy(policy, active); 74f963735aSViresh Kumar 75f963735aSViresh Kumar return policy; 76f963735aSViresh Kumar } 77f963735aSViresh Kumar 78f963735aSViresh Kumar /* Macros to iterate over CPU policies */ 79f963735aSViresh Kumar #define for_each_suitable_policy(__policy, __active) \ 80f963735aSViresh Kumar for (__policy = first_policy(__active); \ 81f963735aSViresh Kumar __policy; \ 82f963735aSViresh Kumar __policy = next_policy(__policy, __active)) 83f963735aSViresh Kumar 84f963735aSViresh Kumar #define for_each_active_policy(__policy) \ 85f963735aSViresh Kumar for_each_suitable_policy(__policy, true) 86f963735aSViresh Kumar #define for_each_inactive_policy(__policy) \ 87f963735aSViresh Kumar for_each_suitable_policy(__policy, false) 88f963735aSViresh Kumar 89b4f0676fSViresh Kumar #define for_each_policy(__policy) \ 90b4f0676fSViresh Kumar list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) 91b4f0676fSViresh Kumar 92f7b27061SViresh Kumar /* Iterate over governors */ 93f7b27061SViresh Kumar static LIST_HEAD(cpufreq_governor_list); 94f7b27061SViresh Kumar #define for_each_governor(__governor) \ 95f7b27061SViresh Kumar list_for_each_entry(__governor, &cpufreq_governor_list, governor_list) 96f7b27061SViresh Kumar 971da177e4SLinus Torvalds /** 98cd878479SDave Jones * The "cpufreq driver" - the arch- or hardware-dependent low 991da177e4SLinus Torvalds * level driver of CPUFreq support, and its spinlock. This lock 1001da177e4SLinus Torvalds * also protects the cpufreq_cpu_data array. 1011da177e4SLinus Torvalds */ 1021c3d85ddSRafael J. Wysocki static struct cpufreq_driver *cpufreq_driver; 1037a6aedfaSMike Travis static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); 104bb176f7dSViresh Kumar static DEFINE_RWLOCK(cpufreq_driver_lock); 1056f1e4efdSJane Li DEFINE_MUTEX(cpufreq_governor_lock); 106bb176f7dSViresh Kumar 1072f0aea93SViresh Kumar /* Flag to suspend/resume CPUFreq governors */ 1082f0aea93SViresh Kumar static bool cpufreq_suspended; 1091da177e4SLinus Torvalds 1109c0ebcf7SViresh Kumar static inline bool has_target(void) 1119c0ebcf7SViresh Kumar { 1129c0ebcf7SViresh Kumar return cpufreq_driver->target_index || cpufreq_driver->target; 1139c0ebcf7SViresh Kumar } 1149c0ebcf7SViresh Kumar 1155a01f2e8SVenkatesh Pallipadi /* 1166eed9404SViresh Kumar * rwsem to guarantee that cpufreq driver module doesn't unload during critical 1176eed9404SViresh Kumar * sections 1186eed9404SViresh Kumar */ 1196eed9404SViresh Kumar static DECLARE_RWSEM(cpufreq_rwsem); 1206eed9404SViresh Kumar 1211da177e4SLinus Torvalds /* internal prototypes */ 12229464f28SDave Jones static int __cpufreq_governor(struct cpufreq_policy *policy, 12329464f28SDave Jones unsigned int event); 124d92d50a4SViresh Kumar static unsigned int __cpufreq_get(struct cpufreq_policy *policy); 12565f27f38SDavid Howells static void handle_update(struct work_struct *work); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds /** 1281da177e4SLinus Torvalds * Two notifier lists: the "policy" list is involved in the 1291da177e4SLinus Torvalds * validation process for a new CPU frequency policy; the 1301da177e4SLinus Torvalds * "transition" list for kernel code that needs to handle 1311da177e4SLinus Torvalds * changes to devices when the CPU clock speed changes. 1321da177e4SLinus Torvalds * The mutex locks both lists. 1331da177e4SLinus Torvalds */ 134e041c683SAlan Stern static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); 135b4dfdbb3SAlan Stern static struct srcu_notifier_head cpufreq_transition_notifier_list; 1361da177e4SLinus Torvalds 13774212ca4SCesar Eduardo Barros static bool init_cpufreq_transition_notifier_list_called; 138b4dfdbb3SAlan Stern static int __init init_cpufreq_transition_notifier_list(void) 139b4dfdbb3SAlan Stern { 140b4dfdbb3SAlan Stern srcu_init_notifier_head(&cpufreq_transition_notifier_list); 14174212ca4SCesar Eduardo Barros init_cpufreq_transition_notifier_list_called = true; 142b4dfdbb3SAlan Stern return 0; 143b4dfdbb3SAlan Stern } 144b3438f82SLinus Torvalds pure_initcall(init_cpufreq_transition_notifier_list); 1451da177e4SLinus Torvalds 146a7b422cdSKonrad Rzeszutek Wilk static int off __read_mostly; 147da584455SViresh Kumar static int cpufreq_disabled(void) 148a7b422cdSKonrad Rzeszutek Wilk { 149a7b422cdSKonrad Rzeszutek Wilk return off; 150a7b422cdSKonrad Rzeszutek Wilk } 151a7b422cdSKonrad Rzeszutek Wilk void disable_cpufreq(void) 152a7b422cdSKonrad Rzeszutek Wilk { 153a7b422cdSKonrad Rzeszutek Wilk off = 1; 154a7b422cdSKonrad Rzeszutek Wilk } 1553fc54d37Sakpm@osdl.org static DEFINE_MUTEX(cpufreq_governor_mutex); 1561da177e4SLinus Torvalds 1574d5dcc42SViresh Kumar bool have_governor_per_policy(void) 1584d5dcc42SViresh Kumar { 1590b981e70SViresh Kumar return !!(cpufreq_driver->flags & CPUFREQ_HAVE_GOVERNOR_PER_POLICY); 1604d5dcc42SViresh Kumar } 1613f869d6dSViresh Kumar EXPORT_SYMBOL_GPL(have_governor_per_policy); 1624d5dcc42SViresh Kumar 163944e9a03SViresh Kumar struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) 164944e9a03SViresh Kumar { 165944e9a03SViresh Kumar if (have_governor_per_policy()) 166944e9a03SViresh Kumar return &policy->kobj; 167944e9a03SViresh Kumar else 168944e9a03SViresh Kumar return cpufreq_global_kobject; 169944e9a03SViresh Kumar } 170944e9a03SViresh Kumar EXPORT_SYMBOL_GPL(get_governor_parent_kobj); 171944e9a03SViresh Kumar 1725a31d594SViresh Kumar struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) 1735a31d594SViresh Kumar { 1745a31d594SViresh Kumar struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); 1755a31d594SViresh Kumar 1765a31d594SViresh Kumar return policy && !policy_is_inactive(policy) ? 1775a31d594SViresh Kumar policy->freq_table : NULL; 1785a31d594SViresh Kumar } 1795a31d594SViresh Kumar EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); 1805a31d594SViresh Kumar 18172a4ce34SViresh Kumar static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) 18272a4ce34SViresh Kumar { 18372a4ce34SViresh Kumar u64 idle_time; 18472a4ce34SViresh Kumar u64 cur_wall_time; 18572a4ce34SViresh Kumar u64 busy_time; 18672a4ce34SViresh Kumar 18772a4ce34SViresh Kumar cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); 18872a4ce34SViresh Kumar 18972a4ce34SViresh Kumar busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; 19072a4ce34SViresh Kumar busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; 19172a4ce34SViresh Kumar busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; 19272a4ce34SViresh Kumar busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; 19372a4ce34SViresh Kumar busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; 19472a4ce34SViresh Kumar busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; 19572a4ce34SViresh Kumar 19672a4ce34SViresh Kumar idle_time = cur_wall_time - busy_time; 19772a4ce34SViresh Kumar if (wall) 19872a4ce34SViresh Kumar *wall = cputime_to_usecs(cur_wall_time); 19972a4ce34SViresh Kumar 20072a4ce34SViresh Kumar return cputime_to_usecs(idle_time); 20172a4ce34SViresh Kumar } 20272a4ce34SViresh Kumar 20372a4ce34SViresh Kumar u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy) 20472a4ce34SViresh Kumar { 20572a4ce34SViresh Kumar u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL); 20672a4ce34SViresh Kumar 20772a4ce34SViresh Kumar if (idle_time == -1ULL) 20872a4ce34SViresh Kumar return get_cpu_idle_time_jiffy(cpu, wall); 20972a4ce34SViresh Kumar else if (!io_busy) 21072a4ce34SViresh Kumar idle_time += get_cpu_iowait_time_us(cpu, wall); 21172a4ce34SViresh Kumar 21272a4ce34SViresh Kumar return idle_time; 21372a4ce34SViresh Kumar } 21472a4ce34SViresh Kumar EXPORT_SYMBOL_GPL(get_cpu_idle_time); 21572a4ce34SViresh Kumar 21670e9e778SViresh Kumar /* 21770e9e778SViresh Kumar * This is a generic cpufreq init() routine which can be used by cpufreq 21870e9e778SViresh Kumar * drivers of SMP systems. It will do following: 21970e9e778SViresh Kumar * - validate & show freq table passed 22070e9e778SViresh Kumar * - set policies transition latency 22170e9e778SViresh Kumar * - policy->cpus with all possible CPUs 22270e9e778SViresh Kumar */ 22370e9e778SViresh Kumar int cpufreq_generic_init(struct cpufreq_policy *policy, 22470e9e778SViresh Kumar struct cpufreq_frequency_table *table, 22570e9e778SViresh Kumar unsigned int transition_latency) 22670e9e778SViresh Kumar { 22770e9e778SViresh Kumar int ret; 22870e9e778SViresh Kumar 22970e9e778SViresh Kumar ret = cpufreq_table_validate_and_show(policy, table); 23070e9e778SViresh Kumar if (ret) { 23170e9e778SViresh Kumar pr_err("%s: invalid frequency table: %d\n", __func__, ret); 23270e9e778SViresh Kumar return ret; 23370e9e778SViresh Kumar } 23470e9e778SViresh Kumar 23570e9e778SViresh Kumar policy->cpuinfo.transition_latency = transition_latency; 23670e9e778SViresh Kumar 23770e9e778SViresh Kumar /* 23858405af6SShailendra Verma * The driver only supports the SMP configuration where all processors 23970e9e778SViresh Kumar * share the clock and voltage and clock. 24070e9e778SViresh Kumar */ 24170e9e778SViresh Kumar cpumask_setall(policy->cpus); 24270e9e778SViresh Kumar 24370e9e778SViresh Kumar return 0; 24470e9e778SViresh Kumar } 24570e9e778SViresh Kumar EXPORT_SYMBOL_GPL(cpufreq_generic_init); 24670e9e778SViresh Kumar 247988bed09SViresh Kumar /* Only for cpufreq core internal use */ 248988bed09SViresh Kumar struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu) 249652ed95dSViresh Kumar { 250652ed95dSViresh Kumar struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); 251652ed95dSViresh Kumar 252988bed09SViresh Kumar return policy && cpumask_test_cpu(cpu, policy->cpus) ? policy : NULL; 253988bed09SViresh Kumar } 254988bed09SViresh Kumar 255988bed09SViresh Kumar unsigned int cpufreq_generic_get(unsigned int cpu) 256988bed09SViresh Kumar { 257988bed09SViresh Kumar struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); 258988bed09SViresh Kumar 259652ed95dSViresh Kumar if (!policy || IS_ERR(policy->clk)) { 260e837f9b5SJoe Perches pr_err("%s: No %s associated to cpu: %d\n", 261e837f9b5SJoe Perches __func__, policy ? "clk" : "policy", cpu); 262652ed95dSViresh Kumar return 0; 263652ed95dSViresh Kumar } 264652ed95dSViresh Kumar 265652ed95dSViresh Kumar return clk_get_rate(policy->clk) / 1000; 266652ed95dSViresh Kumar } 267652ed95dSViresh Kumar EXPORT_SYMBOL_GPL(cpufreq_generic_get); 268652ed95dSViresh Kumar 26950e9c852SViresh Kumar /** 27050e9c852SViresh Kumar * cpufreq_cpu_get: returns policy for a cpu and marks it busy. 27150e9c852SViresh Kumar * 27250e9c852SViresh Kumar * @cpu: cpu to find policy for. 27350e9c852SViresh Kumar * 27450e9c852SViresh Kumar * This returns policy for 'cpu', returns NULL if it doesn't exist. 27550e9c852SViresh Kumar * It also increments the kobject reference count to mark it busy and so would 27650e9c852SViresh Kumar * require a corresponding call to cpufreq_cpu_put() to decrement it back. 27750e9c852SViresh Kumar * If corresponding call cpufreq_cpu_put() isn't made, the policy wouldn't be 27850e9c852SViresh Kumar * freed as that depends on the kobj count. 27950e9c852SViresh Kumar * 28050e9c852SViresh Kumar * It also takes a read-lock of 'cpufreq_rwsem' and doesn't put it back if a 28150e9c852SViresh Kumar * valid policy is found. This is done to make sure the driver doesn't get 28250e9c852SViresh Kumar * unregistered while the policy is being used. 28350e9c852SViresh Kumar * 28450e9c852SViresh Kumar * Return: A valid policy on success, otherwise NULL on failure. 28550e9c852SViresh Kumar */ 2866eed9404SViresh Kumar struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) 2871da177e4SLinus Torvalds { 2886eed9404SViresh Kumar struct cpufreq_policy *policy = NULL; 2891da177e4SLinus Torvalds unsigned long flags; 2901da177e4SLinus Torvalds 2911b947c90SViresh Kumar if (WARN_ON(cpu >= nr_cpu_ids)) 2926eed9404SViresh Kumar return NULL; 2936eed9404SViresh Kumar 2946eed9404SViresh Kumar if (!down_read_trylock(&cpufreq_rwsem)) 2956eed9404SViresh Kumar return NULL; 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds /* get the cpufreq driver */ 2980d1857a1SNathan Zimmer read_lock_irqsave(&cpufreq_driver_lock, flags); 2991da177e4SLinus Torvalds 3006eed9404SViresh Kumar if (cpufreq_driver) { 3011da177e4SLinus Torvalds /* get the CPU */ 302988bed09SViresh Kumar policy = cpufreq_cpu_get_raw(cpu); 3036eed9404SViresh Kumar if (policy) 3046eed9404SViresh Kumar kobject_get(&policy->kobj); 3056eed9404SViresh Kumar } 3066eed9404SViresh Kumar 3076eed9404SViresh Kumar read_unlock_irqrestore(&cpufreq_driver_lock, flags); 3081da177e4SLinus Torvalds 3093a3e9e06SViresh Kumar if (!policy) 3106eed9404SViresh Kumar up_read(&cpufreq_rwsem); 3111da177e4SLinus Torvalds 3123a3e9e06SViresh Kumar return policy; 313a9144436SStephen Boyd } 3141da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_get); 3151da177e4SLinus Torvalds 31650e9c852SViresh Kumar /** 31750e9c852SViresh Kumar * cpufreq_cpu_put: Decrements the usage count of a policy 31850e9c852SViresh Kumar * 31950e9c852SViresh Kumar * @policy: policy earlier returned by cpufreq_cpu_get(). 32050e9c852SViresh Kumar * 32150e9c852SViresh Kumar * This decrements the kobject reference count incremented earlier by calling 32250e9c852SViresh Kumar * cpufreq_cpu_get(). 32350e9c852SViresh Kumar * 32450e9c852SViresh Kumar * It also drops the read-lock of 'cpufreq_rwsem' taken at cpufreq_cpu_get(). 32550e9c852SViresh Kumar */ 3263a3e9e06SViresh Kumar void cpufreq_cpu_put(struct cpufreq_policy *policy) 327a9144436SStephen Boyd { 3286eed9404SViresh Kumar kobject_put(&policy->kobj); 3296eed9404SViresh Kumar up_read(&cpufreq_rwsem); 330a9144436SStephen Boyd } 3311da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_cpu_put); 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds /********************************************************************* 3341da177e4SLinus Torvalds * EXTERNALLY AFFECTING FREQUENCY CHANGES * 3351da177e4SLinus Torvalds *********************************************************************/ 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds /** 3381da177e4SLinus Torvalds * adjust_jiffies - adjust the system "loops_per_jiffy" 3391da177e4SLinus Torvalds * 3401da177e4SLinus Torvalds * This function alters the system "loops_per_jiffy" for the clock 3411da177e4SLinus Torvalds * speed change. Note that loops_per_jiffy cannot be updated on SMP 3421da177e4SLinus Torvalds * systems as each CPU might be scaled differently. So, use the arch 3431da177e4SLinus Torvalds * per-CPU loops_per_jiffy value wherever possible. 3441da177e4SLinus Torvalds */ 34539c132eeSViresh Kumar static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) 34639c132eeSViresh Kumar { 3471da177e4SLinus Torvalds #ifndef CONFIG_SMP 3481da177e4SLinus Torvalds static unsigned long l_p_j_ref; 3491da177e4SLinus Torvalds static unsigned int l_p_j_ref_freq; 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds if (ci->flags & CPUFREQ_CONST_LOOPS) 3521da177e4SLinus Torvalds return; 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds if (!l_p_j_ref_freq) { 3551da177e4SLinus Torvalds l_p_j_ref = loops_per_jiffy; 3561da177e4SLinus Torvalds l_p_j_ref_freq = ci->old; 357e837f9b5SJoe Perches pr_debug("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", 358e837f9b5SJoe Perches l_p_j_ref, l_p_j_ref_freq); 3591da177e4SLinus Torvalds } 3600b443eadSViresh Kumar if (val == CPUFREQ_POSTCHANGE && ci->old != ci->new) { 361e08f5f5bSGautham R Shenoy loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, 362e08f5f5bSGautham R Shenoy ci->new); 363e837f9b5SJoe Perches pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n", 364e837f9b5SJoe Perches loops_per_jiffy, ci->new); 3651da177e4SLinus Torvalds } 3661da177e4SLinus Torvalds #endif 36739c132eeSViresh Kumar } 3681da177e4SLinus Torvalds 3690956df9cSViresh Kumar static void __cpufreq_notify_transition(struct cpufreq_policy *policy, 370b43a7ffbSViresh Kumar struct cpufreq_freqs *freqs, unsigned int state) 3711da177e4SLinus Torvalds { 3721da177e4SLinus Torvalds BUG_ON(irqs_disabled()); 3731da177e4SLinus Torvalds 374d5aaffa9SDirk Brandewie if (cpufreq_disabled()) 375d5aaffa9SDirk Brandewie return; 376d5aaffa9SDirk Brandewie 3771c3d85ddSRafael J. Wysocki freqs->flags = cpufreq_driver->flags; 3782d06d8c4SDominik Brodowski pr_debug("notification %u of frequency transition to %u kHz\n", 379e4472cb3SDave Jones state, freqs->new); 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds switch (state) { 382e4472cb3SDave Jones 3831da177e4SLinus Torvalds case CPUFREQ_PRECHANGE: 384e4472cb3SDave Jones /* detect if the driver reported a value as "old frequency" 385e4472cb3SDave Jones * which is not equal to what the cpufreq core thinks is 386e4472cb3SDave Jones * "old frequency". 3871da177e4SLinus Torvalds */ 3881c3d85ddSRafael J. Wysocki if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { 389e4472cb3SDave Jones if ((policy) && (policy->cpu == freqs->cpu) && 390e4472cb3SDave Jones (policy->cur) && (policy->cur != freqs->old)) { 391e837f9b5SJoe Perches pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n", 392e4472cb3SDave Jones freqs->old, policy->cur); 393e4472cb3SDave Jones freqs->old = policy->cur; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds } 396b4dfdbb3SAlan Stern srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 397e4472cb3SDave Jones CPUFREQ_PRECHANGE, freqs); 3981da177e4SLinus Torvalds adjust_jiffies(CPUFREQ_PRECHANGE, freqs); 3991da177e4SLinus Torvalds break; 400e4472cb3SDave Jones 4011da177e4SLinus Torvalds case CPUFREQ_POSTCHANGE: 4021da177e4SLinus Torvalds adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); 403e837f9b5SJoe Perches pr_debug("FREQ: %lu - CPU: %lu\n", 404e837f9b5SJoe Perches (unsigned long)freqs->new, (unsigned long)freqs->cpu); 40525e41933SThomas Renninger trace_cpu_frequency(freqs->new, freqs->cpu); 406b4dfdbb3SAlan Stern srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 407e4472cb3SDave Jones CPUFREQ_POSTCHANGE, freqs); 408e4472cb3SDave Jones if (likely(policy) && likely(policy->cpu == freqs->cpu)) 409e4472cb3SDave Jones policy->cur = freqs->new; 4101da177e4SLinus Torvalds break; 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds } 413bb176f7dSViresh Kumar 414b43a7ffbSViresh Kumar /** 415b43a7ffbSViresh Kumar * cpufreq_notify_transition - call notifier chain and adjust_jiffies 416b43a7ffbSViresh Kumar * on frequency transition. 417b43a7ffbSViresh Kumar * 418b43a7ffbSViresh Kumar * This function calls the transition notifiers and the "adjust_jiffies" 419b43a7ffbSViresh Kumar * function. It is called twice on all CPU frequency changes that have 420b43a7ffbSViresh Kumar * external effects. 421b43a7ffbSViresh Kumar */ 422236a9800SViresh Kumar static void cpufreq_notify_transition(struct cpufreq_policy *policy, 423b43a7ffbSViresh Kumar struct cpufreq_freqs *freqs, unsigned int state) 424b43a7ffbSViresh Kumar { 425b43a7ffbSViresh Kumar for_each_cpu(freqs->cpu, policy->cpus) 426b43a7ffbSViresh Kumar __cpufreq_notify_transition(policy, freqs, state); 427b43a7ffbSViresh Kumar } 4281da177e4SLinus Torvalds 429f7ba3b41SViresh Kumar /* Do post notifications when there are chances that transition has failed */ 430236a9800SViresh Kumar static void cpufreq_notify_post_transition(struct cpufreq_policy *policy, 431f7ba3b41SViresh Kumar struct cpufreq_freqs *freqs, int transition_failed) 432f7ba3b41SViresh Kumar { 433f7ba3b41SViresh Kumar cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); 434f7ba3b41SViresh Kumar if (!transition_failed) 435f7ba3b41SViresh Kumar return; 436f7ba3b41SViresh Kumar 437f7ba3b41SViresh Kumar swap(freqs->old, freqs->new); 438f7ba3b41SViresh Kumar cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); 439f7ba3b41SViresh Kumar cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); 440f7ba3b41SViresh Kumar } 441f7ba3b41SViresh Kumar 44212478cf0SSrivatsa S. Bhat void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, 44312478cf0SSrivatsa S. Bhat struct cpufreq_freqs *freqs) 44412478cf0SSrivatsa S. Bhat { 445ca654dc3SSrivatsa S. Bhat 446ca654dc3SSrivatsa S. Bhat /* 447ca654dc3SSrivatsa S. Bhat * Catch double invocations of _begin() which lead to self-deadlock. 448ca654dc3SSrivatsa S. Bhat * ASYNC_NOTIFICATION drivers are left out because the cpufreq core 449ca654dc3SSrivatsa S. Bhat * doesn't invoke _begin() on their behalf, and hence the chances of 450ca654dc3SSrivatsa S. Bhat * double invocations are very low. Moreover, there are scenarios 451ca654dc3SSrivatsa S. Bhat * where these checks can emit false-positive warnings in these 452ca654dc3SSrivatsa S. Bhat * drivers; so we avoid that by skipping them altogether. 453ca654dc3SSrivatsa S. Bhat */ 454ca654dc3SSrivatsa S. Bhat WARN_ON(!(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION) 455ca654dc3SSrivatsa S. Bhat && current == policy->transition_task); 456ca654dc3SSrivatsa S. Bhat 45712478cf0SSrivatsa S. Bhat wait: 45812478cf0SSrivatsa S. Bhat wait_event(policy->transition_wait, !policy->transition_ongoing); 45912478cf0SSrivatsa S. Bhat 46012478cf0SSrivatsa S. Bhat spin_lock(&policy->transition_lock); 46112478cf0SSrivatsa S. Bhat 46212478cf0SSrivatsa S. Bhat if (unlikely(policy->transition_ongoing)) { 46312478cf0SSrivatsa S. Bhat spin_unlock(&policy->transition_lock); 46412478cf0SSrivatsa S. Bhat goto wait; 46512478cf0SSrivatsa S. Bhat } 46612478cf0SSrivatsa S. Bhat 46712478cf0SSrivatsa S. Bhat policy->transition_ongoing = true; 468ca654dc3SSrivatsa S. Bhat policy->transition_task = current; 46912478cf0SSrivatsa S. Bhat 47012478cf0SSrivatsa S. Bhat spin_unlock(&policy->transition_lock); 47112478cf0SSrivatsa S. Bhat 47212478cf0SSrivatsa S. Bhat cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); 47312478cf0SSrivatsa S. Bhat } 47412478cf0SSrivatsa S. Bhat EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin); 47512478cf0SSrivatsa S. Bhat 47612478cf0SSrivatsa S. Bhat void cpufreq_freq_transition_end(struct cpufreq_policy *policy, 47712478cf0SSrivatsa S. Bhat struct cpufreq_freqs *freqs, int transition_failed) 47812478cf0SSrivatsa S. Bhat { 47912478cf0SSrivatsa S. Bhat if (unlikely(WARN_ON(!policy->transition_ongoing))) 48012478cf0SSrivatsa S. Bhat return; 48112478cf0SSrivatsa S. Bhat 48212478cf0SSrivatsa S. Bhat cpufreq_notify_post_transition(policy, freqs, transition_failed); 48312478cf0SSrivatsa S. Bhat 48412478cf0SSrivatsa S. Bhat policy->transition_ongoing = false; 485ca654dc3SSrivatsa S. Bhat policy->transition_task = NULL; 48612478cf0SSrivatsa S. Bhat 48712478cf0SSrivatsa S. Bhat wake_up(&policy->transition_wait); 48812478cf0SSrivatsa S. Bhat } 48912478cf0SSrivatsa S. Bhat EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end); 49012478cf0SSrivatsa S. Bhat 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds /********************************************************************* 4931da177e4SLinus Torvalds * SYSFS INTERFACE * 4941da177e4SLinus Torvalds *********************************************************************/ 4958a5c74a1SRashika Kheria static ssize_t show_boost(struct kobject *kobj, 4966f19efc0SLukasz Majewski struct attribute *attr, char *buf) 4976f19efc0SLukasz Majewski { 4986f19efc0SLukasz Majewski return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); 4996f19efc0SLukasz Majewski } 5006f19efc0SLukasz Majewski 5016f19efc0SLukasz Majewski static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, 5026f19efc0SLukasz Majewski const char *buf, size_t count) 5036f19efc0SLukasz Majewski { 5046f19efc0SLukasz Majewski int ret, enable; 5056f19efc0SLukasz Majewski 5066f19efc0SLukasz Majewski ret = sscanf(buf, "%d", &enable); 5076f19efc0SLukasz Majewski if (ret != 1 || enable < 0 || enable > 1) 5086f19efc0SLukasz Majewski return -EINVAL; 5096f19efc0SLukasz Majewski 5106f19efc0SLukasz Majewski if (cpufreq_boost_trigger_state(enable)) { 511e837f9b5SJoe Perches pr_err("%s: Cannot %s BOOST!\n", 512e837f9b5SJoe Perches __func__, enable ? "enable" : "disable"); 5136f19efc0SLukasz Majewski return -EINVAL; 5146f19efc0SLukasz Majewski } 5156f19efc0SLukasz Majewski 516e837f9b5SJoe Perches pr_debug("%s: cpufreq BOOST %s\n", 517e837f9b5SJoe Perches __func__, enable ? "enabled" : "disabled"); 5186f19efc0SLukasz Majewski 5196f19efc0SLukasz Majewski return count; 5206f19efc0SLukasz Majewski } 5216f19efc0SLukasz Majewski define_one_global_rw(boost); 5221da177e4SLinus Torvalds 52342f91fa1SViresh Kumar static struct cpufreq_governor *find_governor(const char *str_governor) 5243bcb09a3SJeremy Fitzhardinge { 5253bcb09a3SJeremy Fitzhardinge struct cpufreq_governor *t; 5263bcb09a3SJeremy Fitzhardinge 527f7b27061SViresh Kumar for_each_governor(t) 5287c4f4539SRasmus Villemoes if (!strncasecmp(str_governor, t->name, CPUFREQ_NAME_LEN)) 5293bcb09a3SJeremy Fitzhardinge return t; 5303bcb09a3SJeremy Fitzhardinge 5313bcb09a3SJeremy Fitzhardinge return NULL; 5323bcb09a3SJeremy Fitzhardinge } 5333bcb09a3SJeremy Fitzhardinge 5341da177e4SLinus Torvalds /** 5351da177e4SLinus Torvalds * cpufreq_parse_governor - parse a governor string 5361da177e4SLinus Torvalds */ 5371da177e4SLinus Torvalds static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, 5381da177e4SLinus Torvalds struct cpufreq_governor **governor) 5391da177e4SLinus Torvalds { 5403bcb09a3SJeremy Fitzhardinge int err = -EINVAL; 5413bcb09a3SJeremy Fitzhardinge 5421c3d85ddSRafael J. Wysocki if (!cpufreq_driver) 5433bcb09a3SJeremy Fitzhardinge goto out; 5443bcb09a3SJeremy Fitzhardinge 5451c3d85ddSRafael J. Wysocki if (cpufreq_driver->setpolicy) { 5467c4f4539SRasmus Villemoes if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { 5471da177e4SLinus Torvalds *policy = CPUFREQ_POLICY_PERFORMANCE; 5483bcb09a3SJeremy Fitzhardinge err = 0; 5497c4f4539SRasmus Villemoes } else if (!strncasecmp(str_governor, "powersave", 550e08f5f5bSGautham R Shenoy CPUFREQ_NAME_LEN)) { 5511da177e4SLinus Torvalds *policy = CPUFREQ_POLICY_POWERSAVE; 5523bcb09a3SJeremy Fitzhardinge err = 0; 5531da177e4SLinus Torvalds } 5542e1cc3a5SViresh Kumar } else { 5551da177e4SLinus Torvalds struct cpufreq_governor *t; 5563bcb09a3SJeremy Fitzhardinge 5573fc54d37Sakpm@osdl.org mutex_lock(&cpufreq_governor_mutex); 5583bcb09a3SJeremy Fitzhardinge 55942f91fa1SViresh Kumar t = find_governor(str_governor); 5603bcb09a3SJeremy Fitzhardinge 561ea714970SJeremy Fitzhardinge if (t == NULL) { 562ea714970SJeremy Fitzhardinge int ret; 563ea714970SJeremy Fitzhardinge 564ea714970SJeremy Fitzhardinge mutex_unlock(&cpufreq_governor_mutex); 5651a8e1463SKees Cook ret = request_module("cpufreq_%s", str_governor); 566ea714970SJeremy Fitzhardinge mutex_lock(&cpufreq_governor_mutex); 567ea714970SJeremy Fitzhardinge 568ea714970SJeremy Fitzhardinge if (ret == 0) 56942f91fa1SViresh Kumar t = find_governor(str_governor); 570ea714970SJeremy Fitzhardinge } 571ea714970SJeremy Fitzhardinge 5723bcb09a3SJeremy Fitzhardinge if (t != NULL) { 5731da177e4SLinus Torvalds *governor = t; 5743bcb09a3SJeremy Fitzhardinge err = 0; 5751da177e4SLinus Torvalds } 5763bcb09a3SJeremy Fitzhardinge 5773bcb09a3SJeremy Fitzhardinge mutex_unlock(&cpufreq_governor_mutex); 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds out: 5803bcb09a3SJeremy Fitzhardinge return err; 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds /** 584e08f5f5bSGautham R Shenoy * cpufreq_per_cpu_attr_read() / show_##file_name() - 585e08f5f5bSGautham R Shenoy * print out cpufreq information 5861da177e4SLinus Torvalds * 5871da177e4SLinus Torvalds * Write out information from cpufreq_driver->policy[cpu]; object must be 5881da177e4SLinus Torvalds * "unsigned int". 5891da177e4SLinus Torvalds */ 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds #define show_one(file_name, object) \ 5921da177e4SLinus Torvalds static ssize_t show_##file_name \ 5931da177e4SLinus Torvalds (struct cpufreq_policy *policy, char *buf) \ 5941da177e4SLinus Torvalds { \ 5951da177e4SLinus Torvalds return sprintf(buf, "%u\n", policy->object); \ 5961da177e4SLinus Torvalds } 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds show_one(cpuinfo_min_freq, cpuinfo.min_freq); 5991da177e4SLinus Torvalds show_one(cpuinfo_max_freq, cpuinfo.max_freq); 600ed129784SThomas Renninger show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); 6011da177e4SLinus Torvalds show_one(scaling_min_freq, min); 6021da177e4SLinus Torvalds show_one(scaling_max_freq, max); 603c034b02eSDirk Brandewie 60409347b29SViresh Kumar static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf) 605c034b02eSDirk Brandewie { 606c034b02eSDirk Brandewie ssize_t ret; 607c034b02eSDirk Brandewie 608c034b02eSDirk Brandewie if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) 609c034b02eSDirk Brandewie ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu)); 610c034b02eSDirk Brandewie else 611c034b02eSDirk Brandewie ret = sprintf(buf, "%u\n", policy->cur); 612c034b02eSDirk Brandewie return ret; 613c034b02eSDirk Brandewie } 6141da177e4SLinus Torvalds 615037ce839SViresh Kumar static int cpufreq_set_policy(struct cpufreq_policy *policy, 6163a3e9e06SViresh Kumar struct cpufreq_policy *new_policy); 6177970e08bSThomas Renninger 6181da177e4SLinus Torvalds /** 6191da177e4SLinus Torvalds * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access 6201da177e4SLinus Torvalds */ 6211da177e4SLinus Torvalds #define store_one(file_name, object) \ 6221da177e4SLinus Torvalds static ssize_t store_##file_name \ 6231da177e4SLinus Torvalds (struct cpufreq_policy *policy, const char *buf, size_t count) \ 6241da177e4SLinus Torvalds { \ 625619c144cSVince Hsu int ret, temp; \ 6261da177e4SLinus Torvalds struct cpufreq_policy new_policy; \ 6271da177e4SLinus Torvalds \ 6281da177e4SLinus Torvalds ret = cpufreq_get_policy(&new_policy, policy->cpu); \ 6291da177e4SLinus Torvalds if (ret) \ 6301da177e4SLinus Torvalds return -EINVAL; \ 6311da177e4SLinus Torvalds \ 6321da177e4SLinus Torvalds ret = sscanf(buf, "%u", &new_policy.object); \ 6331da177e4SLinus Torvalds if (ret != 1) \ 6341da177e4SLinus Torvalds return -EINVAL; \ 6351da177e4SLinus Torvalds \ 636619c144cSVince Hsu temp = new_policy.object; \ 637037ce839SViresh Kumar ret = cpufreq_set_policy(policy, &new_policy); \ 638619c144cSVince Hsu if (!ret) \ 639619c144cSVince Hsu policy->user_policy.object = temp; \ 6401da177e4SLinus Torvalds \ 6411da177e4SLinus Torvalds return ret ? ret : count; \ 6421da177e4SLinus Torvalds } 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds store_one(scaling_min_freq, min); 6451da177e4SLinus Torvalds store_one(scaling_max_freq, max); 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds /** 6481da177e4SLinus Torvalds * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware 6491da177e4SLinus Torvalds */ 650e08f5f5bSGautham R Shenoy static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, 651e08f5f5bSGautham R Shenoy char *buf) 6521da177e4SLinus Torvalds { 653d92d50a4SViresh Kumar unsigned int cur_freq = __cpufreq_get(policy); 6541da177e4SLinus Torvalds if (!cur_freq) 6551da177e4SLinus Torvalds return sprintf(buf, "<unknown>"); 6561da177e4SLinus Torvalds return sprintf(buf, "%u\n", cur_freq); 6571da177e4SLinus Torvalds } 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds /** 6601da177e4SLinus Torvalds * show_scaling_governor - show the current policy for the specified CPU 6611da177e4SLinus Torvalds */ 662905d77cdSDave Jones static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf) 6631da177e4SLinus Torvalds { 6641da177e4SLinus Torvalds if (policy->policy == CPUFREQ_POLICY_POWERSAVE) 6651da177e4SLinus Torvalds return sprintf(buf, "powersave\n"); 6661da177e4SLinus Torvalds else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) 6671da177e4SLinus Torvalds return sprintf(buf, "performance\n"); 6681da177e4SLinus Torvalds else if (policy->governor) 6694b972f0bSviresh kumar return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", 67029464f28SDave Jones policy->governor->name); 6711da177e4SLinus Torvalds return -EINVAL; 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds /** 6751da177e4SLinus Torvalds * store_scaling_governor - store policy for the specified CPU 6761da177e4SLinus Torvalds */ 6771da177e4SLinus Torvalds static ssize_t store_scaling_governor(struct cpufreq_policy *policy, 6781da177e4SLinus Torvalds const char *buf, size_t count) 6791da177e4SLinus Torvalds { 6805136fa56SSrivatsa S. Bhat int ret; 6811da177e4SLinus Torvalds char str_governor[16]; 6821da177e4SLinus Torvalds struct cpufreq_policy new_policy; 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds ret = cpufreq_get_policy(&new_policy, policy->cpu); 6851da177e4SLinus Torvalds if (ret) 6861da177e4SLinus Torvalds return ret; 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds ret = sscanf(buf, "%15s", str_governor); 6891da177e4SLinus Torvalds if (ret != 1) 6901da177e4SLinus Torvalds return -EINVAL; 6911da177e4SLinus Torvalds 692e08f5f5bSGautham R Shenoy if (cpufreq_parse_governor(str_governor, &new_policy.policy, 693e08f5f5bSGautham R Shenoy &new_policy.governor)) 6941da177e4SLinus Torvalds return -EINVAL; 6951da177e4SLinus Torvalds 696037ce839SViresh Kumar ret = cpufreq_set_policy(policy, &new_policy); 6977970e08bSThomas Renninger 6987970e08bSThomas Renninger policy->user_policy.policy = policy->policy; 6997970e08bSThomas Renninger policy->user_policy.governor = policy->governor; 7007970e08bSThomas Renninger 701e08f5f5bSGautham R Shenoy if (ret) 702e08f5f5bSGautham R Shenoy return ret; 703e08f5f5bSGautham R Shenoy else 704e08f5f5bSGautham R Shenoy return count; 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 7071da177e4SLinus Torvalds /** 7081da177e4SLinus Torvalds * show_scaling_driver - show the cpufreq driver currently loaded 7091da177e4SLinus Torvalds */ 7101da177e4SLinus Torvalds static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) 7111da177e4SLinus Torvalds { 7121c3d85ddSRafael J. Wysocki return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name); 7131da177e4SLinus Torvalds } 7141da177e4SLinus Torvalds 7151da177e4SLinus Torvalds /** 7161da177e4SLinus Torvalds * show_scaling_available_governors - show the available CPUfreq governors 7171da177e4SLinus Torvalds */ 7181da177e4SLinus Torvalds static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, 7191da177e4SLinus Torvalds char *buf) 7201da177e4SLinus Torvalds { 7211da177e4SLinus Torvalds ssize_t i = 0; 7221da177e4SLinus Torvalds struct cpufreq_governor *t; 7231da177e4SLinus Torvalds 7249c0ebcf7SViresh Kumar if (!has_target()) { 7251da177e4SLinus Torvalds i += sprintf(buf, "performance powersave"); 7261da177e4SLinus Torvalds goto out; 7271da177e4SLinus Torvalds } 7281da177e4SLinus Torvalds 729f7b27061SViresh Kumar for_each_governor(t) { 73029464f28SDave Jones if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) 73129464f28SDave Jones - (CPUFREQ_NAME_LEN + 2))) 7321da177e4SLinus Torvalds goto out; 7334b972f0bSviresh kumar i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name); 7341da177e4SLinus Torvalds } 7351da177e4SLinus Torvalds out: 7361da177e4SLinus Torvalds i += sprintf(&buf[i], "\n"); 7371da177e4SLinus Torvalds return i; 7381da177e4SLinus Torvalds } 739e8628dd0SDarrick J. Wong 740f4fd3797SLan Tianyu ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf) 7411da177e4SLinus Torvalds { 7421da177e4SLinus Torvalds ssize_t i = 0; 7431da177e4SLinus Torvalds unsigned int cpu; 7441da177e4SLinus Torvalds 745835481d9SRusty Russell for_each_cpu(cpu, mask) { 7461da177e4SLinus Torvalds if (i) 7471da177e4SLinus Torvalds i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " "); 7481da177e4SLinus Torvalds i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu); 7491da177e4SLinus Torvalds if (i >= (PAGE_SIZE - 5)) 7501da177e4SLinus Torvalds break; 7511da177e4SLinus Torvalds } 7521da177e4SLinus Torvalds i += sprintf(&buf[i], "\n"); 7531da177e4SLinus Torvalds return i; 7541da177e4SLinus Torvalds } 755f4fd3797SLan Tianyu EXPORT_SYMBOL_GPL(cpufreq_show_cpus); 7561da177e4SLinus Torvalds 757e8628dd0SDarrick J. Wong /** 758e8628dd0SDarrick J. Wong * show_related_cpus - show the CPUs affected by each transition even if 759e8628dd0SDarrick J. Wong * hw coordination is in use 760e8628dd0SDarrick J. Wong */ 761e8628dd0SDarrick J. Wong static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) 762e8628dd0SDarrick J. Wong { 763f4fd3797SLan Tianyu return cpufreq_show_cpus(policy->related_cpus, buf); 764e8628dd0SDarrick J. Wong } 765e8628dd0SDarrick J. Wong 766e8628dd0SDarrick J. Wong /** 767e8628dd0SDarrick J. Wong * show_affected_cpus - show the CPUs affected by each transition 768e8628dd0SDarrick J. Wong */ 769e8628dd0SDarrick J. Wong static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) 770e8628dd0SDarrick J. Wong { 771f4fd3797SLan Tianyu return cpufreq_show_cpus(policy->cpus, buf); 772e8628dd0SDarrick J. Wong } 773e8628dd0SDarrick J. Wong 7749e76988eSVenki Pallipadi static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, 7759e76988eSVenki Pallipadi const char *buf, size_t count) 7769e76988eSVenki Pallipadi { 7779e76988eSVenki Pallipadi unsigned int freq = 0; 7789e76988eSVenki Pallipadi unsigned int ret; 7799e76988eSVenki Pallipadi 780879000f9SCHIKAMA masaki if (!policy->governor || !policy->governor->store_setspeed) 7819e76988eSVenki Pallipadi return -EINVAL; 7829e76988eSVenki Pallipadi 7839e76988eSVenki Pallipadi ret = sscanf(buf, "%u", &freq); 7849e76988eSVenki Pallipadi if (ret != 1) 7859e76988eSVenki Pallipadi return -EINVAL; 7869e76988eSVenki Pallipadi 7879e76988eSVenki Pallipadi policy->governor->store_setspeed(policy, freq); 7889e76988eSVenki Pallipadi 7899e76988eSVenki Pallipadi return count; 7909e76988eSVenki Pallipadi } 7919e76988eSVenki Pallipadi 7929e76988eSVenki Pallipadi static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) 7939e76988eSVenki Pallipadi { 794879000f9SCHIKAMA masaki if (!policy->governor || !policy->governor->show_setspeed) 7959e76988eSVenki Pallipadi return sprintf(buf, "<unsupported>\n"); 7969e76988eSVenki Pallipadi 7979e76988eSVenki Pallipadi return policy->governor->show_setspeed(policy, buf); 7989e76988eSVenki Pallipadi } 7991da177e4SLinus Torvalds 800e2f74f35SThomas Renninger /** 8018bf1ac72Sviresh kumar * show_bios_limit - show the current cpufreq HW/BIOS limitation 802e2f74f35SThomas Renninger */ 803e2f74f35SThomas Renninger static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) 804e2f74f35SThomas Renninger { 805e2f74f35SThomas Renninger unsigned int limit; 806e2f74f35SThomas Renninger int ret; 8071c3d85ddSRafael J. Wysocki if (cpufreq_driver->bios_limit) { 8081c3d85ddSRafael J. Wysocki ret = cpufreq_driver->bios_limit(policy->cpu, &limit); 809e2f74f35SThomas Renninger if (!ret) 810e2f74f35SThomas Renninger return sprintf(buf, "%u\n", limit); 811e2f74f35SThomas Renninger } 812e2f74f35SThomas Renninger return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); 813e2f74f35SThomas Renninger } 814e2f74f35SThomas Renninger 8156dad2a29SBorislav Petkov cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); 8166dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_min_freq); 8176dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_max_freq); 8186dad2a29SBorislav Petkov cpufreq_freq_attr_ro(cpuinfo_transition_latency); 8196dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_available_governors); 8206dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_driver); 8216dad2a29SBorislav Petkov cpufreq_freq_attr_ro(scaling_cur_freq); 8226dad2a29SBorislav Petkov cpufreq_freq_attr_ro(bios_limit); 8236dad2a29SBorislav Petkov cpufreq_freq_attr_ro(related_cpus); 8246dad2a29SBorislav Petkov cpufreq_freq_attr_ro(affected_cpus); 8256dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_min_freq); 8266dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_max_freq); 8276dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_governor); 8286dad2a29SBorislav Petkov cpufreq_freq_attr_rw(scaling_setspeed); 8291da177e4SLinus Torvalds 8301da177e4SLinus Torvalds static struct attribute *default_attrs[] = { 8311da177e4SLinus Torvalds &cpuinfo_min_freq.attr, 8321da177e4SLinus Torvalds &cpuinfo_max_freq.attr, 833ed129784SThomas Renninger &cpuinfo_transition_latency.attr, 8341da177e4SLinus Torvalds &scaling_min_freq.attr, 8351da177e4SLinus Torvalds &scaling_max_freq.attr, 8361da177e4SLinus Torvalds &affected_cpus.attr, 837e8628dd0SDarrick J. Wong &related_cpus.attr, 8381da177e4SLinus Torvalds &scaling_governor.attr, 8391da177e4SLinus Torvalds &scaling_driver.attr, 8401da177e4SLinus Torvalds &scaling_available_governors.attr, 8419e76988eSVenki Pallipadi &scaling_setspeed.attr, 8421da177e4SLinus Torvalds NULL 8431da177e4SLinus Torvalds }; 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds #define to_policy(k) container_of(k, struct cpufreq_policy, kobj) 8461da177e4SLinus Torvalds #define to_attr(a) container_of(a, struct freq_attr, attr) 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) 8491da177e4SLinus Torvalds { 8501da177e4SLinus Torvalds struct cpufreq_policy *policy = to_policy(kobj); 8511da177e4SLinus Torvalds struct freq_attr *fattr = to_attr(attr); 8521b750e3bSViresh Kumar ssize_t ret; 8536eed9404SViresh Kumar 8546eed9404SViresh Kumar if (!down_read_trylock(&cpufreq_rwsem)) 8551b750e3bSViresh Kumar return -EINVAL; 8565a01f2e8SVenkatesh Pallipadi 857ad7722daSviresh kumar down_read(&policy->rwsem); 8585a01f2e8SVenkatesh Pallipadi 859e08f5f5bSGautham R Shenoy if (fattr->show) 860e08f5f5bSGautham R Shenoy ret = fattr->show(policy, buf); 861e08f5f5bSGautham R Shenoy else 862e08f5f5bSGautham R Shenoy ret = -EIO; 863e08f5f5bSGautham R Shenoy 864ad7722daSviresh kumar up_read(&policy->rwsem); 8656eed9404SViresh Kumar up_read(&cpufreq_rwsem); 8661b750e3bSViresh Kumar 8671da177e4SLinus Torvalds return ret; 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds static ssize_t store(struct kobject *kobj, struct attribute *attr, 8711da177e4SLinus Torvalds const char *buf, size_t count) 8721da177e4SLinus Torvalds { 8731da177e4SLinus Torvalds struct cpufreq_policy *policy = to_policy(kobj); 8741da177e4SLinus Torvalds struct freq_attr *fattr = to_attr(attr); 875a07530b4SDave Jones ssize_t ret = -EINVAL; 8766eed9404SViresh Kumar 8774f750c93SSrivatsa S. Bhat get_online_cpus(); 8784f750c93SSrivatsa S. Bhat 8794f750c93SSrivatsa S. Bhat if (!cpu_online(policy->cpu)) 8804f750c93SSrivatsa S. Bhat goto unlock; 8814f750c93SSrivatsa S. Bhat 8826eed9404SViresh Kumar if (!down_read_trylock(&cpufreq_rwsem)) 8834f750c93SSrivatsa S. Bhat goto unlock; 8845a01f2e8SVenkatesh Pallipadi 885ad7722daSviresh kumar down_write(&policy->rwsem); 8865a01f2e8SVenkatesh Pallipadi 88711e584cfSViresh Kumar /* Updating inactive policies is invalid, so avoid doing that. */ 88811e584cfSViresh Kumar if (unlikely(policy_is_inactive(policy))) { 88911e584cfSViresh Kumar ret = -EBUSY; 89011e584cfSViresh Kumar goto unlock_policy_rwsem; 89111e584cfSViresh Kumar } 89211e584cfSViresh Kumar 893e08f5f5bSGautham R Shenoy if (fattr->store) 894e08f5f5bSGautham R Shenoy ret = fattr->store(policy, buf, count); 895e08f5f5bSGautham R Shenoy else 896e08f5f5bSGautham R Shenoy ret = -EIO; 897e08f5f5bSGautham R Shenoy 89811e584cfSViresh Kumar unlock_policy_rwsem: 899ad7722daSviresh kumar up_write(&policy->rwsem); 9006eed9404SViresh Kumar 9016eed9404SViresh Kumar up_read(&cpufreq_rwsem); 9024f750c93SSrivatsa S. Bhat unlock: 9034f750c93SSrivatsa S. Bhat put_online_cpus(); 9044f750c93SSrivatsa S. Bhat 9051da177e4SLinus Torvalds return ret; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds 9081da177e4SLinus Torvalds static void cpufreq_sysfs_release(struct kobject *kobj) 9091da177e4SLinus Torvalds { 9101da177e4SLinus Torvalds struct cpufreq_policy *policy = to_policy(kobj); 9112d06d8c4SDominik Brodowski pr_debug("last reference is dropped\n"); 9121da177e4SLinus Torvalds complete(&policy->kobj_unregister); 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds 91552cf25d0SEmese Revfy static const struct sysfs_ops sysfs_ops = { 9161da177e4SLinus Torvalds .show = show, 9171da177e4SLinus Torvalds .store = store, 9181da177e4SLinus Torvalds }; 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds static struct kobj_type ktype_cpufreq = { 9211da177e4SLinus Torvalds .sysfs_ops = &sysfs_ops, 9221da177e4SLinus Torvalds .default_attrs = default_attrs, 9231da177e4SLinus Torvalds .release = cpufreq_sysfs_release, 9241da177e4SLinus Torvalds }; 9251da177e4SLinus Torvalds 9262361be23SViresh Kumar struct kobject *cpufreq_global_kobject; 9272361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_global_kobject); 9282361be23SViresh Kumar 9292361be23SViresh Kumar static int cpufreq_global_kobject_usage; 9302361be23SViresh Kumar 9312361be23SViresh Kumar int cpufreq_get_global_kobject(void) 9322361be23SViresh Kumar { 9332361be23SViresh Kumar if (!cpufreq_global_kobject_usage++) 9342361be23SViresh Kumar return kobject_add(cpufreq_global_kobject, 9352361be23SViresh Kumar &cpu_subsys.dev_root->kobj, "%s", "cpufreq"); 9362361be23SViresh Kumar 9372361be23SViresh Kumar return 0; 9382361be23SViresh Kumar } 9392361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_get_global_kobject); 9402361be23SViresh Kumar 9412361be23SViresh Kumar void cpufreq_put_global_kobject(void) 9422361be23SViresh Kumar { 9432361be23SViresh Kumar if (!--cpufreq_global_kobject_usage) 9442361be23SViresh Kumar kobject_del(cpufreq_global_kobject); 9452361be23SViresh Kumar } 9462361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_put_global_kobject); 9472361be23SViresh Kumar 9482361be23SViresh Kumar int cpufreq_sysfs_create_file(const struct attribute *attr) 9492361be23SViresh Kumar { 9502361be23SViresh Kumar int ret = cpufreq_get_global_kobject(); 9512361be23SViresh Kumar 9522361be23SViresh Kumar if (!ret) { 9532361be23SViresh Kumar ret = sysfs_create_file(cpufreq_global_kobject, attr); 9542361be23SViresh Kumar if (ret) 9552361be23SViresh Kumar cpufreq_put_global_kobject(); 9562361be23SViresh Kumar } 9572361be23SViresh Kumar 9582361be23SViresh Kumar return ret; 9592361be23SViresh Kumar } 9602361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_create_file); 9612361be23SViresh Kumar 9622361be23SViresh Kumar void cpufreq_sysfs_remove_file(const struct attribute *attr) 9632361be23SViresh Kumar { 9642361be23SViresh Kumar sysfs_remove_file(cpufreq_global_kobject, attr); 9652361be23SViresh Kumar cpufreq_put_global_kobject(); 9662361be23SViresh Kumar } 9672361be23SViresh Kumar EXPORT_SYMBOL(cpufreq_sysfs_remove_file); 9682361be23SViresh Kumar 96987549141SViresh Kumar static int add_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu) 97087549141SViresh Kumar { 97187549141SViresh Kumar struct device *cpu_dev; 97287549141SViresh Kumar 97387549141SViresh Kumar pr_debug("%s: Adding symlink for CPU: %u\n", __func__, cpu); 97487549141SViresh Kumar 97587549141SViresh Kumar if (!policy) 97687549141SViresh Kumar return 0; 97787549141SViresh Kumar 97887549141SViresh Kumar cpu_dev = get_cpu_device(cpu); 97987549141SViresh Kumar if (WARN_ON(!cpu_dev)) 98087549141SViresh Kumar return 0; 98187549141SViresh Kumar 98287549141SViresh Kumar return sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); 98387549141SViresh Kumar } 98487549141SViresh Kumar 98587549141SViresh Kumar static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu) 98687549141SViresh Kumar { 98787549141SViresh Kumar struct device *cpu_dev; 98887549141SViresh Kumar 98987549141SViresh Kumar pr_debug("%s: Removing symlink for CPU: %u\n", __func__, cpu); 99087549141SViresh Kumar 99187549141SViresh Kumar cpu_dev = get_cpu_device(cpu); 99287549141SViresh Kumar if (WARN_ON(!cpu_dev)) 99387549141SViresh Kumar return; 99487549141SViresh Kumar 99587549141SViresh Kumar sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); 99687549141SViresh Kumar } 99787549141SViresh Kumar 99887549141SViresh Kumar /* Add/remove symlinks for all related CPUs */ 999308b60e7SViresh Kumar static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy) 100019d6f7ecSDave Jones { 100119d6f7ecSDave Jones unsigned int j; 100219d6f7ecSDave Jones int ret = 0; 100319d6f7ecSDave Jones 100487549141SViresh Kumar /* Some related CPUs might not be present (physically hotplugged) */ 100587549141SViresh Kumar for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) { 10069d16f207SSaravana Kannan if (j == policy->kobj_cpu) 100719d6f7ecSDave Jones continue; 100819d6f7ecSDave Jones 100987549141SViresh Kumar ret = add_cpu_dev_symlink(policy, j); 101071c3461eSRafael J. Wysocki if (ret) 101171c3461eSRafael J. Wysocki break; 101219d6f7ecSDave Jones } 101387549141SViresh Kumar 101419d6f7ecSDave Jones return ret; 101519d6f7ecSDave Jones } 101619d6f7ecSDave Jones 101787549141SViresh Kumar static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy) 101887549141SViresh Kumar { 101987549141SViresh Kumar unsigned int j; 102087549141SViresh Kumar 102187549141SViresh Kumar /* Some related CPUs might not be present (physically hotplugged) */ 102287549141SViresh Kumar for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) { 102387549141SViresh Kumar if (j == policy->kobj_cpu) 102487549141SViresh Kumar continue; 102587549141SViresh Kumar 102687549141SViresh Kumar remove_cpu_dev_symlink(policy, j); 102787549141SViresh Kumar } 102887549141SViresh Kumar } 102987549141SViresh Kumar 1030308b60e7SViresh Kumar static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, 10318a25a2fdSKay Sievers struct device *dev) 1032909a694eSDave Jones { 1033909a694eSDave Jones struct freq_attr **drv_attr; 1034909a694eSDave Jones int ret = 0; 1035909a694eSDave Jones 1036909a694eSDave Jones /* set up files for this cpu device */ 10371c3d85ddSRafael J. Wysocki drv_attr = cpufreq_driver->attr; 1038f13f1184SViresh Kumar while (drv_attr && *drv_attr) { 1039909a694eSDave Jones ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); 1040909a694eSDave Jones if (ret) 10416d4e81edSTomeu Vizoso return ret; 1042909a694eSDave Jones drv_attr++; 1043909a694eSDave Jones } 10441c3d85ddSRafael J. Wysocki if (cpufreq_driver->get) { 1045909a694eSDave Jones ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); 1046909a694eSDave Jones if (ret) 10476d4e81edSTomeu Vizoso return ret; 1048909a694eSDave Jones } 1049c034b02eSDirk Brandewie 1050909a694eSDave Jones ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); 1051909a694eSDave Jones if (ret) 10526d4e81edSTomeu Vizoso return ret; 1053c034b02eSDirk Brandewie 10541c3d85ddSRafael J. Wysocki if (cpufreq_driver->bios_limit) { 1055e2f74f35SThomas Renninger ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); 1056e2f74f35SThomas Renninger if (ret) 10576d4e81edSTomeu Vizoso return ret; 1058e2f74f35SThomas Renninger } 1059909a694eSDave Jones 10606d4e81edSTomeu Vizoso return cpufreq_add_dev_symlink(policy); 1061e18f1682SSrivatsa S. Bhat } 1062e18f1682SSrivatsa S. Bhat 1063*7f0fa40fSViresh Kumar static int cpufreq_init_policy(struct cpufreq_policy *policy) 1064e18f1682SSrivatsa S. Bhat { 10656e2c89d1Sviresh kumar struct cpufreq_governor *gov = NULL; 1066e18f1682SSrivatsa S. Bhat struct cpufreq_policy new_policy; 1067e18f1682SSrivatsa S. Bhat 1068d5b73cd8SViresh Kumar memcpy(&new_policy, policy, sizeof(*policy)); 1069a27a9ab7SJason Baron 10706e2c89d1Sviresh kumar /* Update governor of new_policy to the governor used before hotplug */ 10714573237bSViresh Kumar gov = find_governor(policy->last_governor); 10726e2c89d1Sviresh kumar if (gov) 10736e2c89d1Sviresh kumar pr_debug("Restoring governor %s for cpu %d\n", 10746e2c89d1Sviresh kumar policy->governor->name, policy->cpu); 10756e2c89d1Sviresh kumar else 10766e2c89d1Sviresh kumar gov = CPUFREQ_DEFAULT_GOVERNOR; 10776e2c89d1Sviresh kumar 10786e2c89d1Sviresh kumar new_policy.governor = gov; 10796e2c89d1Sviresh kumar 1080a27a9ab7SJason Baron /* Use the default policy if its valid. */ 1081a27a9ab7SJason Baron if (cpufreq_driver->setpolicy) 10826e2c89d1Sviresh kumar cpufreq_parse_governor(gov->name, &new_policy.policy, NULL); 1083ecf7e461SDave Jones 1084ecf7e461SDave Jones /* set default policy */ 1085*7f0fa40fSViresh Kumar return cpufreq_set_policy(policy, &new_policy); 1086909a694eSDave Jones } 1087909a694eSDave Jones 1088d8d3b471SViresh Kumar static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, 108942f921a6SViresh Kumar unsigned int cpu, struct device *dev) 1090fcf80582SViresh Kumar { 10919c0ebcf7SViresh Kumar int ret = 0; 1092fcf80582SViresh Kumar 1093bb29ae15SViresh Kumar /* Has this CPU been taken care of already? */ 1094bb29ae15SViresh Kumar if (cpumask_test_cpu(cpu, policy->cpus)) 1095bb29ae15SViresh Kumar return 0; 1096bb29ae15SViresh Kumar 10979c0ebcf7SViresh Kumar if (has_target()) { 10983de9bdebSViresh Kumar ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); 10993de9bdebSViresh Kumar if (ret) { 11003de9bdebSViresh Kumar pr_err("%s: Failed to stop governor\n", __func__); 11013de9bdebSViresh Kumar return ret; 11023de9bdebSViresh Kumar } 11033de9bdebSViresh Kumar } 1104fcf80582SViresh Kumar 1105ad7722daSviresh kumar down_write(&policy->rwsem); 1106fcf80582SViresh Kumar cpumask_set_cpu(cpu, policy->cpus); 1107ad7722daSviresh kumar up_write(&policy->rwsem); 11082eaa3e2dSViresh Kumar 11099c0ebcf7SViresh Kumar if (has_target()) { 1110e5c87b76SStratos Karafotis ret = __cpufreq_governor(policy, CPUFREQ_GOV_START); 1111e5c87b76SStratos Karafotis if (!ret) 1112e5c87b76SStratos Karafotis ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 1113e5c87b76SStratos Karafotis 1114e5c87b76SStratos Karafotis if (ret) { 11153de9bdebSViresh Kumar pr_err("%s: Failed to start governor\n", __func__); 11163de9bdebSViresh Kumar return ret; 11173de9bdebSViresh Kumar } 1118820c6ca2SViresh Kumar } 1119fcf80582SViresh Kumar 112087549141SViresh Kumar return 0; 1121fcf80582SViresh Kumar } 11221da177e4SLinus Torvalds 11238414809cSSrivatsa S. Bhat static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) 11248414809cSSrivatsa S. Bhat { 11258414809cSSrivatsa S. Bhat struct cpufreq_policy *policy; 11268414809cSSrivatsa S. Bhat unsigned long flags; 11278414809cSSrivatsa S. Bhat 112844871c9cSLan Tianyu read_lock_irqsave(&cpufreq_driver_lock, flags); 11293914d379SViresh Kumar policy = per_cpu(cpufreq_cpu_data, cpu); 113044871c9cSLan Tianyu read_unlock_irqrestore(&cpufreq_driver_lock, flags); 11318414809cSSrivatsa S. Bhat 11323914d379SViresh Kumar if (likely(policy)) { 11333914d379SViresh Kumar /* Policy should be inactive here */ 11343914d379SViresh Kumar WARN_ON(!policy_is_inactive(policy)); 113537829029SViresh Kumar 113637829029SViresh Kumar down_write(&policy->rwsem); 113737829029SViresh Kumar policy->cpu = cpu; 113835afd02eSViresh Kumar policy->governor = NULL; 113937829029SViresh Kumar up_write(&policy->rwsem); 11403914d379SViresh Kumar } 11416e2c89d1Sviresh kumar 11428414809cSSrivatsa S. Bhat return policy; 11438414809cSSrivatsa S. Bhat } 11448414809cSSrivatsa S. Bhat 11452fc3384dSViresh Kumar static struct cpufreq_policy *cpufreq_policy_alloc(struct device *dev) 1146e9698cc5SSrivatsa S. Bhat { 1147e9698cc5SSrivatsa S. Bhat struct cpufreq_policy *policy; 11482fc3384dSViresh Kumar int ret; 1149e9698cc5SSrivatsa S. Bhat 1150e9698cc5SSrivatsa S. Bhat policy = kzalloc(sizeof(*policy), GFP_KERNEL); 1151e9698cc5SSrivatsa S. Bhat if (!policy) 1152e9698cc5SSrivatsa S. Bhat return NULL; 1153e9698cc5SSrivatsa S. Bhat 1154e9698cc5SSrivatsa S. Bhat if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) 1155e9698cc5SSrivatsa S. Bhat goto err_free_policy; 1156e9698cc5SSrivatsa S. Bhat 1157e9698cc5SSrivatsa S. Bhat if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) 1158e9698cc5SSrivatsa S. Bhat goto err_free_cpumask; 1159e9698cc5SSrivatsa S. Bhat 11602fc3384dSViresh Kumar ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &dev->kobj, 11612fc3384dSViresh Kumar "cpufreq"); 11622fc3384dSViresh Kumar if (ret) { 11632fc3384dSViresh Kumar pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret); 11642fc3384dSViresh Kumar goto err_free_rcpumask; 11652fc3384dSViresh Kumar } 11662fc3384dSViresh Kumar 1167c88a1f8bSLukasz Majewski INIT_LIST_HEAD(&policy->policy_list); 1168ad7722daSviresh kumar init_rwsem(&policy->rwsem); 116912478cf0SSrivatsa S. Bhat spin_lock_init(&policy->transition_lock); 117012478cf0SSrivatsa S. Bhat init_waitqueue_head(&policy->transition_wait); 1171818c5712SViresh Kumar init_completion(&policy->kobj_unregister); 1172818c5712SViresh Kumar INIT_WORK(&policy->update, handle_update); 1173ad7722daSviresh kumar 11742fc3384dSViresh Kumar policy->cpu = dev->id; 117587549141SViresh Kumar 117687549141SViresh Kumar /* Set this once on allocation */ 11772fc3384dSViresh Kumar policy->kobj_cpu = dev->id; 117887549141SViresh Kumar 1179e9698cc5SSrivatsa S. Bhat return policy; 1180e9698cc5SSrivatsa S. Bhat 11812fc3384dSViresh Kumar err_free_rcpumask: 11822fc3384dSViresh Kumar free_cpumask_var(policy->related_cpus); 1183e9698cc5SSrivatsa S. Bhat err_free_cpumask: 1184e9698cc5SSrivatsa S. Bhat free_cpumask_var(policy->cpus); 1185e9698cc5SSrivatsa S. Bhat err_free_policy: 1186e9698cc5SSrivatsa S. Bhat kfree(policy); 1187e9698cc5SSrivatsa S. Bhat 1188e9698cc5SSrivatsa S. Bhat return NULL; 1189e9698cc5SSrivatsa S. Bhat } 1190e9698cc5SSrivatsa S. Bhat 11912fc3384dSViresh Kumar static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify) 119242f921a6SViresh Kumar { 119342f921a6SViresh Kumar struct kobject *kobj; 119442f921a6SViresh Kumar struct completion *cmp; 119542f921a6SViresh Kumar 11962fc3384dSViresh Kumar if (notify) 1197fcd7af91SViresh Kumar blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1198fcd7af91SViresh Kumar CPUFREQ_REMOVE_POLICY, policy); 1199fcd7af91SViresh Kumar 120087549141SViresh Kumar down_write(&policy->rwsem); 120187549141SViresh Kumar cpufreq_remove_dev_symlink(policy); 120242f921a6SViresh Kumar kobj = &policy->kobj; 120342f921a6SViresh Kumar cmp = &policy->kobj_unregister; 120487549141SViresh Kumar up_write(&policy->rwsem); 120542f921a6SViresh Kumar kobject_put(kobj); 120642f921a6SViresh Kumar 120742f921a6SViresh Kumar /* 120842f921a6SViresh Kumar * We need to make sure that the underlying kobj is 120942f921a6SViresh Kumar * actually not referenced anymore by anybody before we 121042f921a6SViresh Kumar * proceed with unloading. 121142f921a6SViresh Kumar */ 121242f921a6SViresh Kumar pr_debug("waiting for dropping of refcount\n"); 121342f921a6SViresh Kumar wait_for_completion(cmp); 121442f921a6SViresh Kumar pr_debug("wait complete\n"); 121542f921a6SViresh Kumar } 121642f921a6SViresh Kumar 12173654c5ccSViresh Kumar static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify) 1218e9698cc5SSrivatsa S. Bhat { 1219988bed09SViresh Kumar unsigned long flags; 1220988bed09SViresh Kumar int cpu; 1221988bed09SViresh Kumar 1222988bed09SViresh Kumar /* Remove policy from list */ 1223988bed09SViresh Kumar write_lock_irqsave(&cpufreq_driver_lock, flags); 1224988bed09SViresh Kumar list_del(&policy->policy_list); 1225988bed09SViresh Kumar 1226988bed09SViresh Kumar for_each_cpu(cpu, policy->related_cpus) 1227988bed09SViresh Kumar per_cpu(cpufreq_cpu_data, cpu) = NULL; 1228988bed09SViresh Kumar write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1229988bed09SViresh Kumar 12303654c5ccSViresh Kumar cpufreq_policy_put_kobj(policy, notify); 1231e9698cc5SSrivatsa S. Bhat free_cpumask_var(policy->related_cpus); 1232e9698cc5SSrivatsa S. Bhat free_cpumask_var(policy->cpus); 1233e9698cc5SSrivatsa S. Bhat kfree(policy); 1234e9698cc5SSrivatsa S. Bhat } 1235e9698cc5SSrivatsa S. Bhat 123623faf0b7SViresh Kumar /** 123723faf0b7SViresh Kumar * cpufreq_add_dev - add a CPU device 123823faf0b7SViresh Kumar * 123923faf0b7SViresh Kumar * Adds the cpufreq interface for a CPU device. 124023faf0b7SViresh Kumar * 124123faf0b7SViresh Kumar * The Oracle says: try running cpufreq registration/unregistration concurrently 124223faf0b7SViresh Kumar * with with cpu hotplugging and all hell will break loose. Tried to clean this 124323faf0b7SViresh Kumar * mess up, but more thorough testing is needed. - Mathieu 124423faf0b7SViresh Kumar */ 124523faf0b7SViresh Kumar static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) 12461da177e4SLinus Torvalds { 1247fcf80582SViresh Kumar unsigned int j, cpu = dev->id; 124865922465SViresh Kumar int ret = -ENOMEM; 12497f0c020aSViresh Kumar struct cpufreq_policy *policy; 12501da177e4SLinus Torvalds unsigned long flags; 125187549141SViresh Kumar bool recover_policy = !sif; 1252c32b6b8eSAshok Raj 12532d06d8c4SDominik Brodowski pr_debug("adding CPU %u\n", cpu); 12541da177e4SLinus Torvalds 125587549141SViresh Kumar /* 125687549141SViresh Kumar * Only possible if 'cpu' wasn't physically present earlier and we are 125787549141SViresh Kumar * here from subsys_interface add callback. A hotplug notifier will 125887549141SViresh Kumar * follow and we will handle it like logical CPU hotplug then. For now, 125987549141SViresh Kumar * just create the sysfs link. 126087549141SViresh Kumar */ 126187549141SViresh Kumar if (cpu_is_offline(cpu)) 126287549141SViresh Kumar return add_cpu_dev_symlink(per_cpu(cpufreq_cpu_data, cpu), cpu); 126387549141SViresh Kumar 12646eed9404SViresh Kumar if (!down_read_trylock(&cpufreq_rwsem)) 12656eed9404SViresh Kumar return 0; 12666eed9404SViresh Kumar 1267bb29ae15SViresh Kumar /* Check if this CPU already has a policy to manage it */ 12689104bb26SViresh Kumar policy = per_cpu(cpufreq_cpu_data, cpu); 12699104bb26SViresh Kumar if (policy && !policy_is_inactive(policy)) { 12709104bb26SViresh Kumar WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); 12717f0c020aSViresh Kumar ret = cpufreq_add_policy_cpu(policy, cpu, dev); 12726eed9404SViresh Kumar up_read(&cpufreq_rwsem); 12736eed9404SViresh Kumar return ret; 1274fcf80582SViresh Kumar } 12751da177e4SLinus Torvalds 127672368d12SRafael J. Wysocki /* 127772368d12SRafael J. Wysocki * Restore the saved policy when doing light-weight init and fall back 127872368d12SRafael J. Wysocki * to the full init if that fails. 127972368d12SRafael J. Wysocki */ 128096bbbe4aSViresh Kumar policy = recover_policy ? cpufreq_policy_restore(cpu) : NULL; 128172368d12SRafael J. Wysocki if (!policy) { 128296bbbe4aSViresh Kumar recover_policy = false; 12832fc3384dSViresh Kumar policy = cpufreq_policy_alloc(dev); 1284059019a3SDave Jones if (!policy) 12858101f997SViresh Kumar goto out_release_rwsem; 128672368d12SRafael J. Wysocki } 12870d66b91eSSrivatsa S. Bhat 1288835481d9SRusty Russell cpumask_copy(policy->cpus, cpumask_of(cpu)); 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds /* call driver. From then on the cpufreq must be able 12911da177e4SLinus Torvalds * to accept all calls to ->verify and ->setpolicy for this CPU 12921da177e4SLinus Torvalds */ 12931c3d85ddSRafael J. Wysocki ret = cpufreq_driver->init(policy); 12941da177e4SLinus Torvalds if (ret) { 12952d06d8c4SDominik Brodowski pr_debug("initialization failed\n"); 12968101f997SViresh Kumar goto out_free_policy; 12971da177e4SLinus Torvalds } 1298643ae6e8SViresh Kumar 12996d4e81edSTomeu Vizoso down_write(&policy->rwsem); 13006d4e81edSTomeu Vizoso 13015a7e56a5SViresh Kumar /* related cpus should atleast have policy->cpus */ 13025a7e56a5SViresh Kumar cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); 13035a7e56a5SViresh Kumar 13045a7e56a5SViresh Kumar /* 13055a7e56a5SViresh Kumar * affected cpus must always be the one, which are online. We aren't 13065a7e56a5SViresh Kumar * managing offline cpus here. 13075a7e56a5SViresh Kumar */ 13085a7e56a5SViresh Kumar cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); 13095a7e56a5SViresh Kumar 131096bbbe4aSViresh Kumar if (!recover_policy) { 13115a7e56a5SViresh Kumar policy->user_policy.min = policy->min; 13125a7e56a5SViresh Kumar policy->user_policy.max = policy->max; 13136d4e81edSTomeu Vizoso 1314652ed95dSViresh Kumar write_lock_irqsave(&cpufreq_driver_lock, flags); 1315988bed09SViresh Kumar for_each_cpu(j, policy->related_cpus) 1316652ed95dSViresh Kumar per_cpu(cpufreq_cpu_data, j) = policy; 1317652ed95dSViresh Kumar write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1318988bed09SViresh Kumar } 1319652ed95dSViresh Kumar 13202ed99e39SRafael J. Wysocki if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { 1321da60ce9fSViresh Kumar policy->cur = cpufreq_driver->get(policy->cpu); 1322da60ce9fSViresh Kumar if (!policy->cur) { 1323da60ce9fSViresh Kumar pr_err("%s: ->get() failed\n", __func__); 13248101f997SViresh Kumar goto out_exit_policy; 1325da60ce9fSViresh Kumar } 1326da60ce9fSViresh Kumar } 1327da60ce9fSViresh Kumar 1328d3916691SViresh Kumar /* 1329d3916691SViresh Kumar * Sometimes boot loaders set CPU frequency to a value outside of 1330d3916691SViresh Kumar * frequency table present with cpufreq core. In such cases CPU might be 1331d3916691SViresh Kumar * unstable if it has to run on that frequency for long duration of time 1332d3916691SViresh Kumar * and so its better to set it to a frequency which is specified in 1333d3916691SViresh Kumar * freq-table. This also makes cpufreq stats inconsistent as 1334d3916691SViresh Kumar * cpufreq-stats would fail to register because current frequency of CPU 1335d3916691SViresh Kumar * isn't found in freq-table. 1336d3916691SViresh Kumar * 1337d3916691SViresh Kumar * Because we don't want this change to effect boot process badly, we go 1338d3916691SViresh Kumar * for the next freq which is >= policy->cur ('cur' must be set by now, 1339d3916691SViresh Kumar * otherwise we will end up setting freq to lowest of the table as 'cur' 1340d3916691SViresh Kumar * is initialized to zero). 1341d3916691SViresh Kumar * 1342d3916691SViresh Kumar * We are passing target-freq as "policy->cur - 1" otherwise 1343d3916691SViresh Kumar * __cpufreq_driver_target() would simply fail, as policy->cur will be 1344d3916691SViresh Kumar * equal to target-freq. 1345d3916691SViresh Kumar */ 1346d3916691SViresh Kumar if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK) 1347d3916691SViresh Kumar && has_target()) { 1348d3916691SViresh Kumar /* Are we running at unknown frequency ? */ 1349d3916691SViresh Kumar ret = cpufreq_frequency_table_get_index(policy, policy->cur); 1350d3916691SViresh Kumar if (ret == -EINVAL) { 1351d3916691SViresh Kumar /* Warn user and fix it */ 1352d3916691SViresh Kumar pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n", 1353d3916691SViresh Kumar __func__, policy->cpu, policy->cur); 1354d3916691SViresh Kumar ret = __cpufreq_driver_target(policy, policy->cur - 1, 1355d3916691SViresh Kumar CPUFREQ_RELATION_L); 1356d3916691SViresh Kumar 1357d3916691SViresh Kumar /* 1358d3916691SViresh Kumar * Reaching here after boot in a few seconds may not 1359d3916691SViresh Kumar * mean that system will remain stable at "unknown" 1360d3916691SViresh Kumar * frequency for longer duration. Hence, a BUG_ON(). 1361d3916691SViresh Kumar */ 1362d3916691SViresh Kumar BUG_ON(ret); 1363d3916691SViresh Kumar pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n", 1364d3916691SViresh Kumar __func__, policy->cpu, policy->cur); 1365d3916691SViresh Kumar } 1366d3916691SViresh Kumar } 1367d3916691SViresh Kumar 1368a1531acdSThomas Renninger blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1369a1531acdSThomas Renninger CPUFREQ_START, policy); 1370a1531acdSThomas Renninger 137196bbbe4aSViresh Kumar if (!recover_policy) { 1372308b60e7SViresh Kumar ret = cpufreq_add_dev_interface(policy, dev); 137319d6f7ecSDave Jones if (ret) 13748101f997SViresh Kumar goto out_exit_policy; 1375fcd7af91SViresh Kumar blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 1376fcd7af91SViresh Kumar CPUFREQ_CREATE_POLICY, policy); 1377c88a1f8bSLukasz Majewski 1378c88a1f8bSLukasz Majewski write_lock_irqsave(&cpufreq_driver_lock, flags); 1379c88a1f8bSLukasz Majewski list_add(&policy->policy_list, &cpufreq_policy_list); 1380c88a1f8bSLukasz Majewski write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1381988bed09SViresh Kumar } 13828ff69732SDave Jones 1383*7f0fa40fSViresh Kumar ret = cpufreq_init_policy(policy); 1384*7f0fa40fSViresh Kumar if (ret) { 1385*7f0fa40fSViresh Kumar pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n", 1386*7f0fa40fSViresh Kumar __func__, cpu, ret); 1387*7f0fa40fSViresh Kumar goto out_remove_policy_notify; 1388*7f0fa40fSViresh Kumar } 1389e18f1682SSrivatsa S. Bhat 139096bbbe4aSViresh Kumar if (!recover_policy) { 139108fd8c1cSViresh Kumar policy->user_policy.policy = policy->policy; 139208fd8c1cSViresh Kumar policy->user_policy.governor = policy->governor; 139308fd8c1cSViresh Kumar } 13944e97b631SViresh Kumar up_write(&policy->rwsem); 139508fd8c1cSViresh Kumar 1396038c5b3eSGreg Kroah-Hartman kobject_uevent(&policy->kobj, KOBJ_ADD); 13977c45cf31SViresh Kumar 13986eed9404SViresh Kumar up_read(&cpufreq_rwsem); 13996eed9404SViresh Kumar 14007c45cf31SViresh Kumar /* Callback for handling stuff after policy is ready */ 14017c45cf31SViresh Kumar if (cpufreq_driver->ready) 14027c45cf31SViresh Kumar cpufreq_driver->ready(policy); 14037c45cf31SViresh Kumar 14042d06d8c4SDominik Brodowski pr_debug("initialization complete\n"); 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds return 0; 14071da177e4SLinus Torvalds 1408*7f0fa40fSViresh Kumar out_remove_policy_notify: 1409*7f0fa40fSViresh Kumar /* cpufreq_policy_free() will notify based on this */ 1410*7f0fa40fSViresh Kumar recover_policy = true; 14118101f997SViresh Kumar out_exit_policy: 14127106e02bSPrarit Bhargava up_write(&policy->rwsem); 14137106e02bSPrarit Bhargava 1414da60ce9fSViresh Kumar if (cpufreq_driver->exit) 1415da60ce9fSViresh Kumar cpufreq_driver->exit(policy); 14168101f997SViresh Kumar out_free_policy: 14173654c5ccSViresh Kumar cpufreq_policy_free(policy, recover_policy); 14188101f997SViresh Kumar out_release_rwsem: 14196eed9404SViresh Kumar up_read(&cpufreq_rwsem); 14206eed9404SViresh Kumar 14211da177e4SLinus Torvalds return ret; 14221da177e4SLinus Torvalds } 14231da177e4SLinus Torvalds 1424cedb70afSSrivatsa S. Bhat static int __cpufreq_remove_dev_prepare(struct device *dev, 142596bbbe4aSViresh Kumar struct subsys_interface *sif) 14261da177e4SLinus Torvalds { 14279591becbSViresh Kumar unsigned int cpu = dev->id; 14289591becbSViresh Kumar int ret = 0; 14293a3e9e06SViresh Kumar struct cpufreq_policy *policy; 14301da177e4SLinus Torvalds 1431b8eed8afSViresh Kumar pr_debug("%s: unregistering CPU %u\n", __func__, cpu); 14321da177e4SLinus Torvalds 1433988bed09SViresh Kumar policy = cpufreq_cpu_get_raw(cpu); 14343a3e9e06SViresh Kumar if (!policy) { 1435b8eed8afSViresh Kumar pr_debug("%s: No cpu_data found\n", __func__); 14361da177e4SLinus Torvalds return -EINVAL; 14371da177e4SLinus Torvalds } 14381da177e4SLinus Torvalds 14399c0ebcf7SViresh Kumar if (has_target()) { 14403de9bdebSViresh Kumar ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); 14413de9bdebSViresh Kumar if (ret) { 14423de9bdebSViresh Kumar pr_err("%s: Failed to stop governor\n", __func__); 14433de9bdebSViresh Kumar return ret; 14443de9bdebSViresh Kumar } 1445db5f2995SViresh Kumar } 14461da177e4SLinus Torvalds 14474573237bSViresh Kumar down_write(&policy->rwsem); 14489591becbSViresh Kumar cpumask_clear_cpu(cpu, policy->cpus); 14494573237bSViresh Kumar 14509591becbSViresh Kumar if (policy_is_inactive(policy)) { 14519591becbSViresh Kumar if (has_target()) 14524573237bSViresh Kumar strncpy(policy->last_governor, policy->governor->name, 14534573237bSViresh Kumar CPUFREQ_NAME_LEN); 14549591becbSViresh Kumar } else if (cpu == policy->cpu) { 14559591becbSViresh Kumar /* Nominate new CPU */ 14569591becbSViresh Kumar policy->cpu = cpumask_any(policy->cpus); 14579591becbSViresh Kumar } 14584573237bSViresh Kumar up_write(&policy->rwsem); 14591da177e4SLinus Torvalds 14609591becbSViresh Kumar /* Start governor again for active policy */ 14619591becbSViresh Kumar if (!policy_is_inactive(policy)) { 14629591becbSViresh Kumar if (has_target()) { 14639591becbSViresh Kumar ret = __cpufreq_governor(policy, CPUFREQ_GOV_START); 14649591becbSViresh Kumar if (!ret) 14659591becbSViresh Kumar ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 146687549141SViresh Kumar 14679591becbSViresh Kumar if (ret) 14689591becbSViresh Kumar pr_err("%s: Failed to start governor\n", __func__); 14699591becbSViresh Kumar } 14709591becbSViresh Kumar } else if (cpufreq_driver->stop_cpu) { 1471367dc4aaSDirk Brandewie cpufreq_driver->stop_cpu(policy); 14729591becbSViresh Kumar } 1473b8eed8afSViresh Kumar 14749591becbSViresh Kumar return ret; 1475cedb70afSSrivatsa S. Bhat } 1476cedb70afSSrivatsa S. Bhat 1477cedb70afSSrivatsa S. Bhat static int __cpufreq_remove_dev_finish(struct device *dev, 147896bbbe4aSViresh Kumar struct subsys_interface *sif) 1479cedb70afSSrivatsa S. Bhat { 1480988bed09SViresh Kumar unsigned int cpu = dev->id; 1481cedb70afSSrivatsa S. Bhat int ret; 14829591becbSViresh Kumar struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); 1483cedb70afSSrivatsa S. Bhat 1484cedb70afSSrivatsa S. Bhat if (!policy) { 1485cedb70afSSrivatsa S. Bhat pr_debug("%s: No cpu_data found\n", __func__); 1486cedb70afSSrivatsa S. Bhat return -EINVAL; 1487cedb70afSSrivatsa S. Bhat } 1488cedb70afSSrivatsa S. Bhat 14899591becbSViresh Kumar /* Only proceed for inactive policies */ 14909591becbSViresh Kumar if (!policy_is_inactive(policy)) 149187549141SViresh Kumar return 0; 149287549141SViresh Kumar 149387549141SViresh Kumar /* If cpu is last user of policy, free policy */ 149487549141SViresh Kumar if (has_target()) { 149587549141SViresh Kumar ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); 149687549141SViresh Kumar if (ret) { 149787549141SViresh Kumar pr_err("%s: Failed to exit governor\n", __func__); 14983de9bdebSViresh Kumar return ret; 14993de9bdebSViresh Kumar } 15003de9bdebSViresh Kumar } 15012a998599SRafael J. Wysocki 15028414809cSSrivatsa S. Bhat /* 15038414809cSSrivatsa S. Bhat * Perform the ->exit() even during light-weight tear-down, 15048414809cSSrivatsa S. Bhat * since this is a core component, and is essential for the 15058414809cSSrivatsa S. Bhat * subsequent light-weight ->init() to succeed. 15068414809cSSrivatsa S. Bhat */ 15071c3d85ddSRafael J. Wysocki if (cpufreq_driver->exit) 15083a3e9e06SViresh Kumar cpufreq_driver->exit(policy); 150927ecddc2SJacob Shin 15103654c5ccSViresh Kumar /* Free the policy only if the driver is getting removed. */ 151187549141SViresh Kumar if (sif) 15123654c5ccSViresh Kumar cpufreq_policy_free(policy, true); 15131da177e4SLinus Torvalds 15141da177e4SLinus Torvalds return 0; 15151da177e4SLinus Torvalds } 15161da177e4SLinus Torvalds 1517cedb70afSSrivatsa S. Bhat /** 151827a862e9SViresh Kumar * cpufreq_remove_dev - remove a CPU device 1519cedb70afSSrivatsa S. Bhat * 1520cedb70afSSrivatsa S. Bhat * Removes the cpufreq interface for a CPU device. 1521cedb70afSSrivatsa S. Bhat */ 15228a25a2fdSKay Sievers static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) 15235a01f2e8SVenkatesh Pallipadi { 15248a25a2fdSKay Sievers unsigned int cpu = dev->id; 152527a862e9SViresh Kumar int ret; 1526ec28297aSVenki Pallipadi 152787549141SViresh Kumar /* 152887549141SViresh Kumar * Only possible if 'cpu' is getting physically removed now. A hotplug 152987549141SViresh Kumar * notifier should have already been called and we just need to remove 153087549141SViresh Kumar * link or free policy here. 153187549141SViresh Kumar */ 153287549141SViresh Kumar if (cpu_is_offline(cpu)) { 153387549141SViresh Kumar struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); 153487549141SViresh Kumar struct cpumask mask; 153587549141SViresh Kumar 153687549141SViresh Kumar if (!policy) 1537ec28297aSVenki Pallipadi return 0; 1538ec28297aSVenki Pallipadi 153987549141SViresh Kumar cpumask_copy(&mask, policy->related_cpus); 154087549141SViresh Kumar cpumask_clear_cpu(cpu, &mask); 154187549141SViresh Kumar 154287549141SViresh Kumar /* 154387549141SViresh Kumar * Free policy only if all policy->related_cpus are removed 154487549141SViresh Kumar * physically. 154587549141SViresh Kumar */ 154687549141SViresh Kumar if (cpumask_intersects(&mask, cpu_present_mask)) { 154787549141SViresh Kumar remove_cpu_dev_symlink(policy, cpu); 154887549141SViresh Kumar return 0; 154987549141SViresh Kumar } 155087549141SViresh Kumar 15513654c5ccSViresh Kumar cpufreq_policy_free(policy, true); 155287549141SViresh Kumar return 0; 155387549141SViresh Kumar } 155487549141SViresh Kumar 155596bbbe4aSViresh Kumar ret = __cpufreq_remove_dev_prepare(dev, sif); 155627a862e9SViresh Kumar 155727a862e9SViresh Kumar if (!ret) 155896bbbe4aSViresh Kumar ret = __cpufreq_remove_dev_finish(dev, sif); 155927a862e9SViresh Kumar 156027a862e9SViresh Kumar return ret; 15615a01f2e8SVenkatesh Pallipadi } 15625a01f2e8SVenkatesh Pallipadi 156365f27f38SDavid Howells static void handle_update(struct work_struct *work) 15641da177e4SLinus Torvalds { 156565f27f38SDavid Howells struct cpufreq_policy *policy = 156665f27f38SDavid Howells container_of(work, struct cpufreq_policy, update); 156765f27f38SDavid Howells unsigned int cpu = policy->cpu; 15682d06d8c4SDominik Brodowski pr_debug("handle_update for cpu %u called\n", cpu); 15691da177e4SLinus Torvalds cpufreq_update_policy(cpu); 15701da177e4SLinus Torvalds } 15711da177e4SLinus Torvalds 15721da177e4SLinus Torvalds /** 1573bb176f7dSViresh Kumar * cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're 1574bb176f7dSViresh Kumar * in deep trouble. 1575a1e1dc41SViresh Kumar * @policy: policy managing CPUs 15761da177e4SLinus Torvalds * @new_freq: CPU frequency the CPU actually runs at 15771da177e4SLinus Torvalds * 157829464f28SDave Jones * We adjust to current frequency first, and need to clean up later. 157929464f28SDave Jones * So either call to cpufreq_update_policy() or schedule handle_update()). 15801da177e4SLinus Torvalds */ 1581a1e1dc41SViresh Kumar static void cpufreq_out_of_sync(struct cpufreq_policy *policy, 1582e08f5f5bSGautham R Shenoy unsigned int new_freq) 15831da177e4SLinus Torvalds { 15841da177e4SLinus Torvalds struct cpufreq_freqs freqs; 1585b43a7ffbSViresh Kumar 1586e837f9b5SJoe Perches pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n", 1587a1e1dc41SViresh Kumar policy->cur, new_freq); 15881da177e4SLinus Torvalds 1589a1e1dc41SViresh Kumar freqs.old = policy->cur; 15901da177e4SLinus Torvalds freqs.new = new_freq; 1591b43a7ffbSViresh Kumar 15928fec051eSViresh Kumar cpufreq_freq_transition_begin(policy, &freqs); 15938fec051eSViresh Kumar cpufreq_freq_transition_end(policy, &freqs, 0); 15941da177e4SLinus Torvalds } 15951da177e4SLinus Torvalds 15961da177e4SLinus Torvalds /** 15974ab70df4SDhaval Giani * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur 159895235ca2SVenkatesh Pallipadi * @cpu: CPU number 159995235ca2SVenkatesh Pallipadi * 160095235ca2SVenkatesh Pallipadi * This is the last known freq, without actually getting it from the driver. 160195235ca2SVenkatesh Pallipadi * Return value will be same as what is shown in scaling_cur_freq in sysfs. 160295235ca2SVenkatesh Pallipadi */ 160395235ca2SVenkatesh Pallipadi unsigned int cpufreq_quick_get(unsigned int cpu) 160495235ca2SVenkatesh Pallipadi { 16059e21ba8bSDirk Brandewie struct cpufreq_policy *policy; 1606e08f5f5bSGautham R Shenoy unsigned int ret_freq = 0; 160795235ca2SVenkatesh Pallipadi 16081c3d85ddSRafael J. Wysocki if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) 16091c3d85ddSRafael J. Wysocki return cpufreq_driver->get(cpu); 16109e21ba8bSDirk Brandewie 16119e21ba8bSDirk Brandewie policy = cpufreq_cpu_get(cpu); 161295235ca2SVenkatesh Pallipadi if (policy) { 1613e08f5f5bSGautham R Shenoy ret_freq = policy->cur; 161495235ca2SVenkatesh Pallipadi cpufreq_cpu_put(policy); 161595235ca2SVenkatesh Pallipadi } 161695235ca2SVenkatesh Pallipadi 16174d34a67dSDave Jones return ret_freq; 161895235ca2SVenkatesh Pallipadi } 161995235ca2SVenkatesh Pallipadi EXPORT_SYMBOL(cpufreq_quick_get); 162095235ca2SVenkatesh Pallipadi 16213d737108SJesse Barnes /** 16223d737108SJesse Barnes * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU 16233d737108SJesse Barnes * @cpu: CPU number 16243d737108SJesse Barnes * 16253d737108SJesse Barnes * Just return the max possible frequency for a given CPU. 16263d737108SJesse Barnes */ 16273d737108SJesse Barnes unsigned int cpufreq_quick_get_max(unsigned int cpu) 16283d737108SJesse Barnes { 16293d737108SJesse Barnes struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 16303d737108SJesse Barnes unsigned int ret_freq = 0; 16313d737108SJesse Barnes 16323d737108SJesse Barnes if (policy) { 16333d737108SJesse Barnes ret_freq = policy->max; 16343d737108SJesse Barnes cpufreq_cpu_put(policy); 16353d737108SJesse Barnes } 16363d737108SJesse Barnes 16373d737108SJesse Barnes return ret_freq; 16383d737108SJesse Barnes } 16393d737108SJesse Barnes EXPORT_SYMBOL(cpufreq_quick_get_max); 16403d737108SJesse Barnes 1641d92d50a4SViresh Kumar static unsigned int __cpufreq_get(struct cpufreq_policy *policy) 16421da177e4SLinus Torvalds { 1643e08f5f5bSGautham R Shenoy unsigned int ret_freq = 0; 16441da177e4SLinus Torvalds 16451c3d85ddSRafael J. Wysocki if (!cpufreq_driver->get) 16464d34a67dSDave Jones return ret_freq; 16471da177e4SLinus Torvalds 1648d92d50a4SViresh Kumar ret_freq = cpufreq_driver->get(policy->cpu); 16491da177e4SLinus Torvalds 165011e584cfSViresh Kumar /* Updating inactive policies is invalid, so avoid doing that. */ 165111e584cfSViresh Kumar if (unlikely(policy_is_inactive(policy))) 165211e584cfSViresh Kumar return ret_freq; 165311e584cfSViresh Kumar 1654e08f5f5bSGautham R Shenoy if (ret_freq && policy->cur && 16551c3d85ddSRafael J. Wysocki !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { 1656e08f5f5bSGautham R Shenoy /* verify no discrepancy between actual and 1657e08f5f5bSGautham R Shenoy saved value exists */ 1658e08f5f5bSGautham R Shenoy if (unlikely(ret_freq != policy->cur)) { 1659a1e1dc41SViresh Kumar cpufreq_out_of_sync(policy, ret_freq); 16601da177e4SLinus Torvalds schedule_work(&policy->update); 16611da177e4SLinus Torvalds } 16621da177e4SLinus Torvalds } 16631da177e4SLinus Torvalds 16644d34a67dSDave Jones return ret_freq; 16655a01f2e8SVenkatesh Pallipadi } 16661da177e4SLinus Torvalds 16675a01f2e8SVenkatesh Pallipadi /** 16685a01f2e8SVenkatesh Pallipadi * cpufreq_get - get the current CPU frequency (in kHz) 16695a01f2e8SVenkatesh Pallipadi * @cpu: CPU number 16705a01f2e8SVenkatesh Pallipadi * 16715a01f2e8SVenkatesh Pallipadi * Get the CPU current (static) CPU frequency 16725a01f2e8SVenkatesh Pallipadi */ 16735a01f2e8SVenkatesh Pallipadi unsigned int cpufreq_get(unsigned int cpu) 16745a01f2e8SVenkatesh Pallipadi { 1675999976e0SAaron Plattner struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 16765a01f2e8SVenkatesh Pallipadi unsigned int ret_freq = 0; 16775a01f2e8SVenkatesh Pallipadi 1678999976e0SAaron Plattner if (policy) { 1679ad7722daSviresh kumar down_read(&policy->rwsem); 1680d92d50a4SViresh Kumar ret_freq = __cpufreq_get(policy); 1681ad7722daSviresh kumar up_read(&policy->rwsem); 1682999976e0SAaron Plattner 1683999976e0SAaron Plattner cpufreq_cpu_put(policy); 1684999976e0SAaron Plattner } 16856eed9404SViresh Kumar 16864d34a67dSDave Jones return ret_freq; 16871da177e4SLinus Torvalds } 16881da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get); 16891da177e4SLinus Torvalds 16908a25a2fdSKay Sievers static struct subsys_interface cpufreq_interface = { 16918a25a2fdSKay Sievers .name = "cpufreq", 16928a25a2fdSKay Sievers .subsys = &cpu_subsys, 16938a25a2fdSKay Sievers .add_dev = cpufreq_add_dev, 16948a25a2fdSKay Sievers .remove_dev = cpufreq_remove_dev, 1695e00e56dfSRafael J. Wysocki }; 1696e00e56dfSRafael J. Wysocki 1697e28867eaSViresh Kumar /* 1698e28867eaSViresh Kumar * In case platform wants some specific frequency to be configured 1699e28867eaSViresh Kumar * during suspend.. 170042d4dc3fSBenjamin Herrenschmidt */ 1701e28867eaSViresh Kumar int cpufreq_generic_suspend(struct cpufreq_policy *policy) 170242d4dc3fSBenjamin Herrenschmidt { 1703e28867eaSViresh Kumar int ret; 17044bc5d341SDave Jones 1705e28867eaSViresh Kumar if (!policy->suspend_freq) { 1706e28867eaSViresh Kumar pr_err("%s: suspend_freq can't be zero\n", __func__); 1707e28867eaSViresh Kumar return -EINVAL; 170842d4dc3fSBenjamin Herrenschmidt } 170942d4dc3fSBenjamin Herrenschmidt 1710e28867eaSViresh Kumar pr_debug("%s: Setting suspend-freq: %u\n", __func__, 1711e28867eaSViresh Kumar policy->suspend_freq); 1712e28867eaSViresh Kumar 1713e28867eaSViresh Kumar ret = __cpufreq_driver_target(policy, policy->suspend_freq, 1714e28867eaSViresh Kumar CPUFREQ_RELATION_H); 1715e28867eaSViresh Kumar if (ret) 1716e28867eaSViresh Kumar pr_err("%s: unable to set suspend-freq: %u. err: %d\n", 1717e28867eaSViresh Kumar __func__, policy->suspend_freq, ret); 1718e28867eaSViresh Kumar 1719c9060494SDave Jones return ret; 172042d4dc3fSBenjamin Herrenschmidt } 1721e28867eaSViresh Kumar EXPORT_SYMBOL(cpufreq_generic_suspend); 172242d4dc3fSBenjamin Herrenschmidt 172342d4dc3fSBenjamin Herrenschmidt /** 17242f0aea93SViresh Kumar * cpufreq_suspend() - Suspend CPUFreq governors 17251da177e4SLinus Torvalds * 17262f0aea93SViresh Kumar * Called during system wide Suspend/Hibernate cycles for suspending governors 17272f0aea93SViresh Kumar * as some platforms can't change frequency after this point in suspend cycle. 17282f0aea93SViresh Kumar * Because some of the devices (like: i2c, regulators, etc) they use for 17292f0aea93SViresh Kumar * changing frequency are suspended quickly after this point. 17301da177e4SLinus Torvalds */ 17312f0aea93SViresh Kumar void cpufreq_suspend(void) 17321da177e4SLinus Torvalds { 17333a3e9e06SViresh Kumar struct cpufreq_policy *policy; 17341da177e4SLinus Torvalds 17352f0aea93SViresh Kumar if (!cpufreq_driver) 1736e00e56dfSRafael J. Wysocki return; 17371da177e4SLinus Torvalds 17382f0aea93SViresh Kumar if (!has_target()) 1739b1b12babSViresh Kumar goto suspend; 17401da177e4SLinus Torvalds 17412f0aea93SViresh Kumar pr_debug("%s: Suspending Governors\n", __func__); 17422f0aea93SViresh Kumar 1743f963735aSViresh Kumar for_each_active_policy(policy) { 17442f0aea93SViresh Kumar if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) 17452f0aea93SViresh Kumar pr_err("%s: Failed to stop governor for policy: %p\n", 17462f0aea93SViresh Kumar __func__, policy); 17472f0aea93SViresh Kumar else if (cpufreq_driver->suspend 17482f0aea93SViresh Kumar && cpufreq_driver->suspend(policy)) 17492f0aea93SViresh Kumar pr_err("%s: Failed to suspend driver: %p\n", __func__, 17502f0aea93SViresh Kumar policy); 17511da177e4SLinus Torvalds } 1752b1b12babSViresh Kumar 1753b1b12babSViresh Kumar suspend: 1754b1b12babSViresh Kumar cpufreq_suspended = true; 17551da177e4SLinus Torvalds } 17561da177e4SLinus Torvalds 17571da177e4SLinus Torvalds /** 17582f0aea93SViresh Kumar * cpufreq_resume() - Resume CPUFreq governors 17591da177e4SLinus Torvalds * 17602f0aea93SViresh Kumar * Called during system wide Suspend/Hibernate cycle for resuming governors that 17612f0aea93SViresh Kumar * are suspended with cpufreq_suspend(). 17621da177e4SLinus Torvalds */ 17632f0aea93SViresh Kumar void cpufreq_resume(void) 17641da177e4SLinus Torvalds { 17651da177e4SLinus Torvalds struct cpufreq_policy *policy; 17661da177e4SLinus Torvalds 17672f0aea93SViresh Kumar if (!cpufreq_driver) 17681da177e4SLinus Torvalds return; 17691da177e4SLinus Torvalds 17708e30444eSLan Tianyu cpufreq_suspended = false; 17718e30444eSLan Tianyu 17722f0aea93SViresh Kumar if (!has_target()) 17732f0aea93SViresh Kumar return; 17741da177e4SLinus Torvalds 17752f0aea93SViresh Kumar pr_debug("%s: Resuming Governors\n", __func__); 17762f0aea93SViresh Kumar 1777f963735aSViresh Kumar for_each_active_policy(policy) { 17780c5aa405SViresh Kumar if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) 17790c5aa405SViresh Kumar pr_err("%s: Failed to resume driver: %p\n", __func__, 17800c5aa405SViresh Kumar policy); 17810c5aa405SViresh Kumar else if (__cpufreq_governor(policy, CPUFREQ_GOV_START) 17822f0aea93SViresh Kumar || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) 17832f0aea93SViresh Kumar pr_err("%s: Failed to start governor for policy: %p\n", 17842f0aea93SViresh Kumar __func__, policy); 1785c75de0acSViresh Kumar } 17862f0aea93SViresh Kumar 17872f0aea93SViresh Kumar /* 1788c75de0acSViresh Kumar * schedule call cpufreq_update_policy() for first-online CPU, as that 1789c75de0acSViresh Kumar * wouldn't be hotplugged-out on suspend. It will verify that the 1790c75de0acSViresh Kumar * current freq is in sync with what we believe it to be. 17912f0aea93SViresh Kumar */ 1792c75de0acSViresh Kumar policy = cpufreq_cpu_get_raw(cpumask_first(cpu_online_mask)); 1793c75de0acSViresh Kumar if (WARN_ON(!policy)) 1794c75de0acSViresh Kumar return; 1795c75de0acSViresh Kumar 17963a3e9e06SViresh Kumar schedule_work(&policy->update); 17971da177e4SLinus Torvalds } 17981da177e4SLinus Torvalds 17999d95046eSBorislav Petkov /** 18009d95046eSBorislav Petkov * cpufreq_get_current_driver - return current driver's name 18019d95046eSBorislav Petkov * 18029d95046eSBorislav Petkov * Return the name string of the currently loaded cpufreq driver 18039d95046eSBorislav Petkov * or NULL, if none. 18049d95046eSBorislav Petkov */ 18059d95046eSBorislav Petkov const char *cpufreq_get_current_driver(void) 18069d95046eSBorislav Petkov { 18071c3d85ddSRafael J. Wysocki if (cpufreq_driver) 18081c3d85ddSRafael J. Wysocki return cpufreq_driver->name; 18091c3d85ddSRafael J. Wysocki 18101c3d85ddSRafael J. Wysocki return NULL; 18119d95046eSBorislav Petkov } 18129d95046eSBorislav Petkov EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); 18131da177e4SLinus Torvalds 181451315cdfSThomas Petazzoni /** 181551315cdfSThomas Petazzoni * cpufreq_get_driver_data - return current driver data 181651315cdfSThomas Petazzoni * 181751315cdfSThomas Petazzoni * Return the private data of the currently loaded cpufreq 181851315cdfSThomas Petazzoni * driver, or NULL if no cpufreq driver is loaded. 181951315cdfSThomas Petazzoni */ 182051315cdfSThomas Petazzoni void *cpufreq_get_driver_data(void) 182151315cdfSThomas Petazzoni { 182251315cdfSThomas Petazzoni if (cpufreq_driver) 182351315cdfSThomas Petazzoni return cpufreq_driver->driver_data; 182451315cdfSThomas Petazzoni 182551315cdfSThomas Petazzoni return NULL; 182651315cdfSThomas Petazzoni } 182751315cdfSThomas Petazzoni EXPORT_SYMBOL_GPL(cpufreq_get_driver_data); 182851315cdfSThomas Petazzoni 18291da177e4SLinus Torvalds /********************************************************************* 18301da177e4SLinus Torvalds * NOTIFIER LISTS INTERFACE * 18311da177e4SLinus Torvalds *********************************************************************/ 18321da177e4SLinus Torvalds 18331da177e4SLinus Torvalds /** 18341da177e4SLinus Torvalds * cpufreq_register_notifier - register a driver with cpufreq 18351da177e4SLinus Torvalds * @nb: notifier function to register 18361da177e4SLinus Torvalds * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 18371da177e4SLinus Torvalds * 18381da177e4SLinus Torvalds * Add a driver to one of two lists: either a list of drivers that 18391da177e4SLinus Torvalds * are notified about clock rate changes (once before and once after 18401da177e4SLinus Torvalds * the transition), or a list of drivers that are notified about 18411da177e4SLinus Torvalds * changes in cpufreq policy. 18421da177e4SLinus Torvalds * 18431da177e4SLinus Torvalds * This function may sleep, and has the same return conditions as 1844e041c683SAlan Stern * blocking_notifier_chain_register. 18451da177e4SLinus Torvalds */ 18461da177e4SLinus Torvalds int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) 18471da177e4SLinus Torvalds { 18481da177e4SLinus Torvalds int ret; 18491da177e4SLinus Torvalds 1850d5aaffa9SDirk Brandewie if (cpufreq_disabled()) 1851d5aaffa9SDirk Brandewie return -EINVAL; 1852d5aaffa9SDirk Brandewie 185374212ca4SCesar Eduardo Barros WARN_ON(!init_cpufreq_transition_notifier_list_called); 185474212ca4SCesar Eduardo Barros 18551da177e4SLinus Torvalds switch (list) { 18561da177e4SLinus Torvalds case CPUFREQ_TRANSITION_NOTIFIER: 1857b4dfdbb3SAlan Stern ret = srcu_notifier_chain_register( 1858e041c683SAlan Stern &cpufreq_transition_notifier_list, nb); 18591da177e4SLinus Torvalds break; 18601da177e4SLinus Torvalds case CPUFREQ_POLICY_NOTIFIER: 1861e041c683SAlan Stern ret = blocking_notifier_chain_register( 1862e041c683SAlan Stern &cpufreq_policy_notifier_list, nb); 18631da177e4SLinus Torvalds break; 18641da177e4SLinus Torvalds default: 18651da177e4SLinus Torvalds ret = -EINVAL; 18661da177e4SLinus Torvalds } 18671da177e4SLinus Torvalds 18681da177e4SLinus Torvalds return ret; 18691da177e4SLinus Torvalds } 18701da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_register_notifier); 18711da177e4SLinus Torvalds 18721da177e4SLinus Torvalds /** 18731da177e4SLinus Torvalds * cpufreq_unregister_notifier - unregister a driver with cpufreq 18741da177e4SLinus Torvalds * @nb: notifier block to be unregistered 18751da177e4SLinus Torvalds * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER 18761da177e4SLinus Torvalds * 18771da177e4SLinus Torvalds * Remove a driver from the CPU frequency notifier list. 18781da177e4SLinus Torvalds * 18791da177e4SLinus Torvalds * This function may sleep, and has the same return conditions as 1880e041c683SAlan Stern * blocking_notifier_chain_unregister. 18811da177e4SLinus Torvalds */ 18821da177e4SLinus Torvalds int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) 18831da177e4SLinus Torvalds { 18841da177e4SLinus Torvalds int ret; 18851da177e4SLinus Torvalds 1886d5aaffa9SDirk Brandewie if (cpufreq_disabled()) 1887d5aaffa9SDirk Brandewie return -EINVAL; 1888d5aaffa9SDirk Brandewie 18891da177e4SLinus Torvalds switch (list) { 18901da177e4SLinus Torvalds case CPUFREQ_TRANSITION_NOTIFIER: 1891b4dfdbb3SAlan Stern ret = srcu_notifier_chain_unregister( 1892e041c683SAlan Stern &cpufreq_transition_notifier_list, nb); 18931da177e4SLinus Torvalds break; 18941da177e4SLinus Torvalds case CPUFREQ_POLICY_NOTIFIER: 1895e041c683SAlan Stern ret = blocking_notifier_chain_unregister( 1896e041c683SAlan Stern &cpufreq_policy_notifier_list, nb); 18971da177e4SLinus Torvalds break; 18981da177e4SLinus Torvalds default: 18991da177e4SLinus Torvalds ret = -EINVAL; 19001da177e4SLinus Torvalds } 19011da177e4SLinus Torvalds 19021da177e4SLinus Torvalds return ret; 19031da177e4SLinus Torvalds } 19041da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_unregister_notifier); 19051da177e4SLinus Torvalds 19061da177e4SLinus Torvalds 19071da177e4SLinus Torvalds /********************************************************************* 19081da177e4SLinus Torvalds * GOVERNORS * 19091da177e4SLinus Torvalds *********************************************************************/ 19101da177e4SLinus Torvalds 19111c03a2d0SViresh Kumar /* Must set freqs->new to intermediate frequency */ 19121c03a2d0SViresh Kumar static int __target_intermediate(struct cpufreq_policy *policy, 19131c03a2d0SViresh Kumar struct cpufreq_freqs *freqs, int index) 19141c03a2d0SViresh Kumar { 19151c03a2d0SViresh Kumar int ret; 19161c03a2d0SViresh Kumar 19171c03a2d0SViresh Kumar freqs->new = cpufreq_driver->get_intermediate(policy, index); 19181c03a2d0SViresh Kumar 19191c03a2d0SViresh Kumar /* We don't need to switch to intermediate freq */ 19201c03a2d0SViresh Kumar if (!freqs->new) 19211c03a2d0SViresh Kumar return 0; 19221c03a2d0SViresh Kumar 19231c03a2d0SViresh Kumar pr_debug("%s: cpu: %d, switching to intermediate freq: oldfreq: %u, intermediate freq: %u\n", 19241c03a2d0SViresh Kumar __func__, policy->cpu, freqs->old, freqs->new); 19251c03a2d0SViresh Kumar 19261c03a2d0SViresh Kumar cpufreq_freq_transition_begin(policy, freqs); 19271c03a2d0SViresh Kumar ret = cpufreq_driver->target_intermediate(policy, index); 19281c03a2d0SViresh Kumar cpufreq_freq_transition_end(policy, freqs, ret); 19291c03a2d0SViresh Kumar 19301c03a2d0SViresh Kumar if (ret) 19311c03a2d0SViresh Kumar pr_err("%s: Failed to change to intermediate frequency: %d\n", 19321c03a2d0SViresh Kumar __func__, ret); 19331c03a2d0SViresh Kumar 19341c03a2d0SViresh Kumar return ret; 19351c03a2d0SViresh Kumar } 19361c03a2d0SViresh Kumar 19378d65775dSViresh Kumar static int __target_index(struct cpufreq_policy *policy, 19388d65775dSViresh Kumar struct cpufreq_frequency_table *freq_table, int index) 19398d65775dSViresh Kumar { 19401c03a2d0SViresh Kumar struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0}; 19411c03a2d0SViresh Kumar unsigned int intermediate_freq = 0; 19428d65775dSViresh Kumar int retval = -EINVAL; 19438d65775dSViresh Kumar bool notify; 19448d65775dSViresh Kumar 19458d65775dSViresh Kumar notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); 19468d65775dSViresh Kumar if (notify) { 19471c03a2d0SViresh Kumar /* Handle switching to intermediate frequency */ 19481c03a2d0SViresh Kumar if (cpufreq_driver->get_intermediate) { 19491c03a2d0SViresh Kumar retval = __target_intermediate(policy, &freqs, index); 19501c03a2d0SViresh Kumar if (retval) 19511c03a2d0SViresh Kumar return retval; 19528d65775dSViresh Kumar 19531c03a2d0SViresh Kumar intermediate_freq = freqs.new; 19541c03a2d0SViresh Kumar /* Set old freq to intermediate */ 19551c03a2d0SViresh Kumar if (intermediate_freq) 19561c03a2d0SViresh Kumar freqs.old = freqs.new; 19571c03a2d0SViresh Kumar } 19581c03a2d0SViresh Kumar 19591c03a2d0SViresh Kumar freqs.new = freq_table[index].frequency; 19608d65775dSViresh Kumar pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", 19618d65775dSViresh Kumar __func__, policy->cpu, freqs.old, freqs.new); 19628d65775dSViresh Kumar 19638d65775dSViresh Kumar cpufreq_freq_transition_begin(policy, &freqs); 19648d65775dSViresh Kumar } 19658d65775dSViresh Kumar 19668d65775dSViresh Kumar retval = cpufreq_driver->target_index(policy, index); 19678d65775dSViresh Kumar if (retval) 19688d65775dSViresh Kumar pr_err("%s: Failed to change cpu frequency: %d\n", __func__, 19698d65775dSViresh Kumar retval); 19708d65775dSViresh Kumar 19711c03a2d0SViresh Kumar if (notify) { 19728d65775dSViresh Kumar cpufreq_freq_transition_end(policy, &freqs, retval); 19738d65775dSViresh Kumar 19741c03a2d0SViresh Kumar /* 19751c03a2d0SViresh Kumar * Failed after setting to intermediate freq? Driver should have 19761c03a2d0SViresh Kumar * reverted back to initial frequency and so should we. Check 19771c03a2d0SViresh Kumar * here for intermediate_freq instead of get_intermediate, in 197858405af6SShailendra Verma * case we haven't switched to intermediate freq at all. 19791c03a2d0SViresh Kumar */ 19801c03a2d0SViresh Kumar if (unlikely(retval && intermediate_freq)) { 19811c03a2d0SViresh Kumar freqs.old = intermediate_freq; 19821c03a2d0SViresh Kumar freqs.new = policy->restore_freq; 19831c03a2d0SViresh Kumar cpufreq_freq_transition_begin(policy, &freqs); 19841c03a2d0SViresh Kumar cpufreq_freq_transition_end(policy, &freqs, 0); 19851c03a2d0SViresh Kumar } 19861c03a2d0SViresh Kumar } 19871c03a2d0SViresh Kumar 19888d65775dSViresh Kumar return retval; 19898d65775dSViresh Kumar } 19908d65775dSViresh Kumar 19911da177e4SLinus Torvalds int __cpufreq_driver_target(struct cpufreq_policy *policy, 19921da177e4SLinus Torvalds unsigned int target_freq, 19931da177e4SLinus Torvalds unsigned int relation) 19941da177e4SLinus Torvalds { 19957249924eSViresh Kumar unsigned int old_target_freq = target_freq; 19968d65775dSViresh Kumar int retval = -EINVAL; 1997c32b6b8eSAshok Raj 1998a7b422cdSKonrad Rzeszutek Wilk if (cpufreq_disabled()) 1999a7b422cdSKonrad Rzeszutek Wilk return -ENODEV; 2000a7b422cdSKonrad Rzeszutek Wilk 20017249924eSViresh Kumar /* Make sure that target_freq is within supported range */ 20027249924eSViresh Kumar if (target_freq > policy->max) 20037249924eSViresh Kumar target_freq = policy->max; 20047249924eSViresh Kumar if (target_freq < policy->min) 20057249924eSViresh Kumar target_freq = policy->min; 20067249924eSViresh Kumar 20077249924eSViresh Kumar pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", 20087249924eSViresh Kumar policy->cpu, target_freq, relation, old_target_freq); 20095a1c0228SViresh Kumar 20109c0ebcf7SViresh Kumar /* 20119c0ebcf7SViresh Kumar * This might look like a redundant call as we are checking it again 20129c0ebcf7SViresh Kumar * after finding index. But it is left intentionally for cases where 20139c0ebcf7SViresh Kumar * exactly same freq is called again and so we can save on few function 20149c0ebcf7SViresh Kumar * calls. 20159c0ebcf7SViresh Kumar */ 20165a1c0228SViresh Kumar if (target_freq == policy->cur) 20175a1c0228SViresh Kumar return 0; 20185a1c0228SViresh Kumar 20191c03a2d0SViresh Kumar /* Save last value to restore later on errors */ 20201c03a2d0SViresh Kumar policy->restore_freq = policy->cur; 20211c03a2d0SViresh Kumar 20221c3d85ddSRafael J. Wysocki if (cpufreq_driver->target) 20231c3d85ddSRafael J. Wysocki retval = cpufreq_driver->target(policy, target_freq, relation); 20249c0ebcf7SViresh Kumar else if (cpufreq_driver->target_index) { 20259c0ebcf7SViresh Kumar struct cpufreq_frequency_table *freq_table; 20269c0ebcf7SViresh Kumar int index; 202790d45d17SAshok Raj 20289c0ebcf7SViresh Kumar freq_table = cpufreq_frequency_get_table(policy->cpu); 20299c0ebcf7SViresh Kumar if (unlikely(!freq_table)) { 20309c0ebcf7SViresh Kumar pr_err("%s: Unable to find freq_table\n", __func__); 20319c0ebcf7SViresh Kumar goto out; 20329c0ebcf7SViresh Kumar } 20339c0ebcf7SViresh Kumar 20349c0ebcf7SViresh Kumar retval = cpufreq_frequency_table_target(policy, freq_table, 20359c0ebcf7SViresh Kumar target_freq, relation, &index); 20369c0ebcf7SViresh Kumar if (unlikely(retval)) { 20379c0ebcf7SViresh Kumar pr_err("%s: Unable to find matching freq\n", __func__); 20389c0ebcf7SViresh Kumar goto out; 20399c0ebcf7SViresh Kumar } 20409c0ebcf7SViresh Kumar 2041d4019f0aSViresh Kumar if (freq_table[index].frequency == policy->cur) { 20429c0ebcf7SViresh Kumar retval = 0; 2043d4019f0aSViresh Kumar goto out; 2044d4019f0aSViresh Kumar } 2045d4019f0aSViresh Kumar 20468d65775dSViresh Kumar retval = __target_index(policy, freq_table, index); 20479c0ebcf7SViresh Kumar } 20489c0ebcf7SViresh Kumar 20499c0ebcf7SViresh Kumar out: 20501da177e4SLinus Torvalds return retval; 20511da177e4SLinus Torvalds } 20521da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(__cpufreq_driver_target); 20531da177e4SLinus Torvalds 20541da177e4SLinus Torvalds int cpufreq_driver_target(struct cpufreq_policy *policy, 20551da177e4SLinus Torvalds unsigned int target_freq, 20561da177e4SLinus Torvalds unsigned int relation) 20571da177e4SLinus Torvalds { 2058f1829e4aSJulia Lawall int ret = -EINVAL; 20591da177e4SLinus Torvalds 2060ad7722daSviresh kumar down_write(&policy->rwsem); 20611da177e4SLinus Torvalds 20621da177e4SLinus Torvalds ret = __cpufreq_driver_target(policy, target_freq, relation); 20631da177e4SLinus Torvalds 2064ad7722daSviresh kumar up_write(&policy->rwsem); 20651da177e4SLinus Torvalds 20661da177e4SLinus Torvalds return ret; 20671da177e4SLinus Torvalds } 20681da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_driver_target); 20691da177e4SLinus Torvalds 2070e08f5f5bSGautham R Shenoy static int __cpufreq_governor(struct cpufreq_policy *policy, 2071e08f5f5bSGautham R Shenoy unsigned int event) 20721da177e4SLinus Torvalds { 2073cc993cabSDave Jones int ret; 20746afde10cSThomas Renninger 20756afde10cSThomas Renninger /* Only must be defined when default governor is known to have latency 20766afde10cSThomas Renninger restrictions, like e.g. conservative or ondemand. 20776afde10cSThomas Renninger That this is the case is already ensured in Kconfig 20786afde10cSThomas Renninger */ 20796afde10cSThomas Renninger #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE 20806afde10cSThomas Renninger struct cpufreq_governor *gov = &cpufreq_gov_performance; 20816afde10cSThomas Renninger #else 20826afde10cSThomas Renninger struct cpufreq_governor *gov = NULL; 20836afde10cSThomas Renninger #endif 20841c256245SThomas Renninger 20852f0aea93SViresh Kumar /* Don't start any governor operations if we are entering suspend */ 20862f0aea93SViresh Kumar if (cpufreq_suspended) 20872f0aea93SViresh Kumar return 0; 2088cb57720bSEthan Zhao /* 2089cb57720bSEthan Zhao * Governor might not be initiated here if ACPI _PPC changed 2090cb57720bSEthan Zhao * notification happened, so check it. 2091cb57720bSEthan Zhao */ 2092cb57720bSEthan Zhao if (!policy->governor) 2093cb57720bSEthan Zhao return -EINVAL; 20942f0aea93SViresh Kumar 20951c256245SThomas Renninger if (policy->governor->max_transition_latency && 20961c256245SThomas Renninger policy->cpuinfo.transition_latency > 20971c256245SThomas Renninger policy->governor->max_transition_latency) { 20986afde10cSThomas Renninger if (!gov) 20996afde10cSThomas Renninger return -EINVAL; 21006afde10cSThomas Renninger else { 2101e837f9b5SJoe Perches pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n", 2102e837f9b5SJoe Perches policy->governor->name, gov->name); 21031c256245SThomas Renninger policy->governor = gov; 21041c256245SThomas Renninger } 21056afde10cSThomas Renninger } 21061da177e4SLinus Torvalds 2107fe492f3fSViresh Kumar if (event == CPUFREQ_GOV_POLICY_INIT) 21081da177e4SLinus Torvalds if (!try_module_get(policy->governor->owner)) 21091da177e4SLinus Torvalds return -EINVAL; 21101da177e4SLinus Torvalds 21112d06d8c4SDominik Brodowski pr_debug("__cpufreq_governor for CPU %u, event %u\n", 2112e08f5f5bSGautham R Shenoy policy->cpu, event); 211395731ebbSXiaoguang Chen 211495731ebbSXiaoguang Chen mutex_lock(&cpufreq_governor_lock); 211556d07db2SSrivatsa S. Bhat if ((policy->governor_enabled && event == CPUFREQ_GOV_START) 2116f73d3933SViresh Kumar || (!policy->governor_enabled 2117f73d3933SViresh Kumar && (event == CPUFREQ_GOV_LIMITS || event == CPUFREQ_GOV_STOP))) { 211895731ebbSXiaoguang Chen mutex_unlock(&cpufreq_governor_lock); 211995731ebbSXiaoguang Chen return -EBUSY; 212095731ebbSXiaoguang Chen } 212195731ebbSXiaoguang Chen 212295731ebbSXiaoguang Chen if (event == CPUFREQ_GOV_STOP) 212395731ebbSXiaoguang Chen policy->governor_enabled = false; 212495731ebbSXiaoguang Chen else if (event == CPUFREQ_GOV_START) 212595731ebbSXiaoguang Chen policy->governor_enabled = true; 212695731ebbSXiaoguang Chen 212795731ebbSXiaoguang Chen mutex_unlock(&cpufreq_governor_lock); 212895731ebbSXiaoguang Chen 21291da177e4SLinus Torvalds ret = policy->governor->governor(policy, event); 21301da177e4SLinus Torvalds 21314d5dcc42SViresh Kumar if (!ret) { 21324d5dcc42SViresh Kumar if (event == CPUFREQ_GOV_POLICY_INIT) 21338e53695fSViresh Kumar policy->governor->initialized++; 21344d5dcc42SViresh Kumar else if (event == CPUFREQ_GOV_POLICY_EXIT) 21358e53695fSViresh Kumar policy->governor->initialized--; 213695731ebbSXiaoguang Chen } else { 213795731ebbSXiaoguang Chen /* Restore original values */ 213895731ebbSXiaoguang Chen mutex_lock(&cpufreq_governor_lock); 213995731ebbSXiaoguang Chen if (event == CPUFREQ_GOV_STOP) 214095731ebbSXiaoguang Chen policy->governor_enabled = true; 214195731ebbSXiaoguang Chen else if (event == CPUFREQ_GOV_START) 214295731ebbSXiaoguang Chen policy->governor_enabled = false; 214395731ebbSXiaoguang Chen mutex_unlock(&cpufreq_governor_lock); 21444d5dcc42SViresh Kumar } 2145b394058fSViresh Kumar 2146fe492f3fSViresh Kumar if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) || 2147fe492f3fSViresh Kumar ((event == CPUFREQ_GOV_POLICY_EXIT) && !ret)) 21481da177e4SLinus Torvalds module_put(policy->governor->owner); 21491da177e4SLinus Torvalds 21501da177e4SLinus Torvalds return ret; 21511da177e4SLinus Torvalds } 21521da177e4SLinus Torvalds 21531da177e4SLinus Torvalds int cpufreq_register_governor(struct cpufreq_governor *governor) 21541da177e4SLinus Torvalds { 21553bcb09a3SJeremy Fitzhardinge int err; 21561da177e4SLinus Torvalds 21571da177e4SLinus Torvalds if (!governor) 21581da177e4SLinus Torvalds return -EINVAL; 21591da177e4SLinus Torvalds 2160a7b422cdSKonrad Rzeszutek Wilk if (cpufreq_disabled()) 2161a7b422cdSKonrad Rzeszutek Wilk return -ENODEV; 2162a7b422cdSKonrad Rzeszutek Wilk 21633fc54d37Sakpm@osdl.org mutex_lock(&cpufreq_governor_mutex); 21641da177e4SLinus Torvalds 2165b394058fSViresh Kumar governor->initialized = 0; 21663bcb09a3SJeremy Fitzhardinge err = -EBUSY; 216742f91fa1SViresh Kumar if (!find_governor(governor->name)) { 21683bcb09a3SJeremy Fitzhardinge err = 0; 21691da177e4SLinus Torvalds list_add(&governor->governor_list, &cpufreq_governor_list); 21703bcb09a3SJeremy Fitzhardinge } 21711da177e4SLinus Torvalds 21723fc54d37Sakpm@osdl.org mutex_unlock(&cpufreq_governor_mutex); 21733bcb09a3SJeremy Fitzhardinge return err; 21741da177e4SLinus Torvalds } 21751da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_governor); 21761da177e4SLinus Torvalds 21771da177e4SLinus Torvalds void cpufreq_unregister_governor(struct cpufreq_governor *governor) 21781da177e4SLinus Torvalds { 21794573237bSViresh Kumar struct cpufreq_policy *policy; 21804573237bSViresh Kumar unsigned long flags; 218190e41bacSPrarit Bhargava 21821da177e4SLinus Torvalds if (!governor) 21831da177e4SLinus Torvalds return; 21841da177e4SLinus Torvalds 2185a7b422cdSKonrad Rzeszutek Wilk if (cpufreq_disabled()) 2186a7b422cdSKonrad Rzeszutek Wilk return; 2187a7b422cdSKonrad Rzeszutek Wilk 21884573237bSViresh Kumar /* clear last_governor for all inactive policies */ 21894573237bSViresh Kumar read_lock_irqsave(&cpufreq_driver_lock, flags); 21904573237bSViresh Kumar for_each_inactive_policy(policy) { 219118bf3a12SViresh Kumar if (!strcmp(policy->last_governor, governor->name)) { 219218bf3a12SViresh Kumar policy->governor = NULL; 21934573237bSViresh Kumar strcpy(policy->last_governor, "\0"); 219490e41bacSPrarit Bhargava } 219518bf3a12SViresh Kumar } 21964573237bSViresh Kumar read_unlock_irqrestore(&cpufreq_driver_lock, flags); 219790e41bacSPrarit Bhargava 21983fc54d37Sakpm@osdl.org mutex_lock(&cpufreq_governor_mutex); 21991da177e4SLinus Torvalds list_del(&governor->governor_list); 22003fc54d37Sakpm@osdl.org mutex_unlock(&cpufreq_governor_mutex); 22011da177e4SLinus Torvalds return; 22021da177e4SLinus Torvalds } 22031da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); 22041da177e4SLinus Torvalds 22051da177e4SLinus Torvalds 22061da177e4SLinus Torvalds /********************************************************************* 22071da177e4SLinus Torvalds * POLICY INTERFACE * 22081da177e4SLinus Torvalds *********************************************************************/ 22091da177e4SLinus Torvalds 22101da177e4SLinus Torvalds /** 22111da177e4SLinus Torvalds * cpufreq_get_policy - get the current cpufreq_policy 221229464f28SDave Jones * @policy: struct cpufreq_policy into which the current cpufreq_policy 221329464f28SDave Jones * is written 22141da177e4SLinus Torvalds * 22151da177e4SLinus Torvalds * Reads the current cpufreq policy. 22161da177e4SLinus Torvalds */ 22171da177e4SLinus Torvalds int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) 22181da177e4SLinus Torvalds { 22191da177e4SLinus Torvalds struct cpufreq_policy *cpu_policy; 22201da177e4SLinus Torvalds if (!policy) 22211da177e4SLinus Torvalds return -EINVAL; 22221da177e4SLinus Torvalds 22231da177e4SLinus Torvalds cpu_policy = cpufreq_cpu_get(cpu); 22241da177e4SLinus Torvalds if (!cpu_policy) 22251da177e4SLinus Torvalds return -EINVAL; 22261da177e4SLinus Torvalds 2227d5b73cd8SViresh Kumar memcpy(policy, cpu_policy, sizeof(*policy)); 22281da177e4SLinus Torvalds 22291da177e4SLinus Torvalds cpufreq_cpu_put(cpu_policy); 22301da177e4SLinus Torvalds return 0; 22311da177e4SLinus Torvalds } 22321da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_get_policy); 22331da177e4SLinus Torvalds 2234153d7f3fSArjan van de Ven /* 2235037ce839SViresh Kumar * policy : current policy. 2236037ce839SViresh Kumar * new_policy: policy to be set. 2237153d7f3fSArjan van de Ven */ 2238037ce839SViresh Kumar static int cpufreq_set_policy(struct cpufreq_policy *policy, 22393a3e9e06SViresh Kumar struct cpufreq_policy *new_policy) 22401da177e4SLinus Torvalds { 2241d9a789c7SRafael J. Wysocki struct cpufreq_governor *old_gov; 2242d9a789c7SRafael J. Wysocki int ret; 22431da177e4SLinus Torvalds 2244e837f9b5SJoe Perches pr_debug("setting new policy for CPU %u: %u - %u kHz\n", 2245e837f9b5SJoe Perches new_policy->cpu, new_policy->min, new_policy->max); 22461da177e4SLinus Torvalds 2247d5b73cd8SViresh Kumar memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); 22481da177e4SLinus Torvalds 2249d9a789c7SRafael J. Wysocki if (new_policy->min > policy->max || new_policy->max < policy->min) 2250d9a789c7SRafael J. Wysocki return -EINVAL; 22519c9a43edSMattia Dongili 22521da177e4SLinus Torvalds /* verify the cpu speed can be set within this limit */ 22533a3e9e06SViresh Kumar ret = cpufreq_driver->verify(new_policy); 22541da177e4SLinus Torvalds if (ret) 2255d9a789c7SRafael J. Wysocki return ret; 22561da177e4SLinus Torvalds 22571da177e4SLinus Torvalds /* adjust if necessary - all reasons */ 2258e041c683SAlan Stern blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 22593a3e9e06SViresh Kumar CPUFREQ_ADJUST, new_policy); 22601da177e4SLinus Torvalds 22611da177e4SLinus Torvalds /* adjust if necessary - hardware incompatibility*/ 2262e041c683SAlan Stern blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 22633a3e9e06SViresh Kumar CPUFREQ_INCOMPATIBLE, new_policy); 22641da177e4SLinus Torvalds 2265bb176f7dSViresh Kumar /* 2266bb176f7dSViresh Kumar * verify the cpu speed can be set within this limit, which might be 2267bb176f7dSViresh Kumar * different to the first one 2268bb176f7dSViresh Kumar */ 22693a3e9e06SViresh Kumar ret = cpufreq_driver->verify(new_policy); 2270e041c683SAlan Stern if (ret) 2271d9a789c7SRafael J. Wysocki return ret; 22721da177e4SLinus Torvalds 22731da177e4SLinus Torvalds /* notification of the new policy */ 2274e041c683SAlan Stern blocking_notifier_call_chain(&cpufreq_policy_notifier_list, 22753a3e9e06SViresh Kumar CPUFREQ_NOTIFY, new_policy); 22761da177e4SLinus Torvalds 22773a3e9e06SViresh Kumar policy->min = new_policy->min; 22783a3e9e06SViresh Kumar policy->max = new_policy->max; 22791da177e4SLinus Torvalds 22802d06d8c4SDominik Brodowski pr_debug("new min and max freqs are %u - %u kHz\n", 22813a3e9e06SViresh Kumar policy->min, policy->max); 22821da177e4SLinus Torvalds 22831c3d85ddSRafael J. Wysocki if (cpufreq_driver->setpolicy) { 22843a3e9e06SViresh Kumar policy->policy = new_policy->policy; 22852d06d8c4SDominik Brodowski pr_debug("setting range\n"); 2286d9a789c7SRafael J. Wysocki return cpufreq_driver->setpolicy(new_policy); 2287d9a789c7SRafael J. Wysocki } 2288d9a789c7SRafael J. Wysocki 2289d9a789c7SRafael J. Wysocki if (new_policy->governor == policy->governor) 2290d9a789c7SRafael J. Wysocki goto out; 22911da177e4SLinus Torvalds 22922d06d8c4SDominik Brodowski pr_debug("governor switch\n"); 22931da177e4SLinus Torvalds 2294d9a789c7SRafael J. Wysocki /* save old, working values */ 2295d9a789c7SRafael J. Wysocki old_gov = policy->governor; 22961da177e4SLinus Torvalds /* end old governor */ 2297d9a789c7SRafael J. Wysocki if (old_gov) { 22983a3e9e06SViresh Kumar __cpufreq_governor(policy, CPUFREQ_GOV_STOP); 2299ad7722daSviresh kumar up_write(&policy->rwsem); 2300d9a789c7SRafael J. Wysocki __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); 2301ad7722daSviresh kumar down_write(&policy->rwsem); 23027bd353a9SViresh Kumar } 23031da177e4SLinus Torvalds 23041da177e4SLinus Torvalds /* start new governor */ 23053a3e9e06SViresh Kumar policy->governor = new_policy->governor; 23063a3e9e06SViresh Kumar if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { 2307d9a789c7SRafael J. Wysocki if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) 2308d9a789c7SRafael J. Wysocki goto out; 2309d9a789c7SRafael J. Wysocki 2310ad7722daSviresh kumar up_write(&policy->rwsem); 2311d9a789c7SRafael J. Wysocki __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); 2312ad7722daSviresh kumar down_write(&policy->rwsem); 2313955ef483SViresh Kumar } 23147bd353a9SViresh Kumar 23151da177e4SLinus Torvalds /* new governor failed, so re-start old one */ 2316d9a789c7SRafael J. Wysocki pr_debug("starting governor %s failed\n", policy->governor->name); 23171da177e4SLinus Torvalds if (old_gov) { 23183a3e9e06SViresh Kumar policy->governor = old_gov; 2319d9a789c7SRafael J. Wysocki __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); 2320d9a789c7SRafael J. Wysocki __cpufreq_governor(policy, CPUFREQ_GOV_START); 23211da177e4SLinus Torvalds } 23221da177e4SLinus Torvalds 2323d9a789c7SRafael J. Wysocki return -EINVAL; 2324d9a789c7SRafael J. Wysocki 2325d9a789c7SRafael J. Wysocki out: 2326d9a789c7SRafael J. Wysocki pr_debug("governor: change or update limits\n"); 2327d9a789c7SRafael J. Wysocki return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 23281da177e4SLinus Torvalds } 23291da177e4SLinus Torvalds 23301da177e4SLinus Torvalds /** 23311da177e4SLinus Torvalds * cpufreq_update_policy - re-evaluate an existing cpufreq policy 23321da177e4SLinus Torvalds * @cpu: CPU which shall be re-evaluated 23331da177e4SLinus Torvalds * 233425985edcSLucas De Marchi * Useful for policy notifiers which have different necessities 23351da177e4SLinus Torvalds * at different times. 23361da177e4SLinus Torvalds */ 23371da177e4SLinus Torvalds int cpufreq_update_policy(unsigned int cpu) 23381da177e4SLinus Torvalds { 23393a3e9e06SViresh Kumar struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 23403a3e9e06SViresh Kumar struct cpufreq_policy new_policy; 2341f1829e4aSJulia Lawall int ret; 23421da177e4SLinus Torvalds 2343fefa8ff8SAaron Plattner if (!policy) 2344fefa8ff8SAaron Plattner return -ENODEV; 23451da177e4SLinus Torvalds 2346ad7722daSviresh kumar down_write(&policy->rwsem); 23471da177e4SLinus Torvalds 23482d06d8c4SDominik Brodowski pr_debug("updating policy for CPU %u\n", cpu); 2349d5b73cd8SViresh Kumar memcpy(&new_policy, policy, sizeof(*policy)); 23503a3e9e06SViresh Kumar new_policy.min = policy->user_policy.min; 23513a3e9e06SViresh Kumar new_policy.max = policy->user_policy.max; 23523a3e9e06SViresh Kumar new_policy.policy = policy->user_policy.policy; 23533a3e9e06SViresh Kumar new_policy.governor = policy->user_policy.governor; 23541da177e4SLinus Torvalds 2355bb176f7dSViresh Kumar /* 2356bb176f7dSViresh Kumar * BIOS might change freq behind our back 2357bb176f7dSViresh Kumar * -> ask driver for current freq and notify governors about a change 2358bb176f7dSViresh Kumar */ 23592ed99e39SRafael J. Wysocki if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { 23603a3e9e06SViresh Kumar new_policy.cur = cpufreq_driver->get(cpu); 2361bd0fa9bbSViresh Kumar if (WARN_ON(!new_policy.cur)) { 2362bd0fa9bbSViresh Kumar ret = -EIO; 2363fefa8ff8SAaron Plattner goto unlock; 2364bd0fa9bbSViresh Kumar } 2365bd0fa9bbSViresh Kumar 23663a3e9e06SViresh Kumar if (!policy->cur) { 2367e837f9b5SJoe Perches pr_debug("Driver did not initialize current freq\n"); 23683a3e9e06SViresh Kumar policy->cur = new_policy.cur; 2369a85f7bd3SThomas Renninger } else { 23709c0ebcf7SViresh Kumar if (policy->cur != new_policy.cur && has_target()) 2371a1e1dc41SViresh Kumar cpufreq_out_of_sync(policy, new_policy.cur); 23720961dd0dSThomas Renninger } 2373a85f7bd3SThomas Renninger } 23740961dd0dSThomas Renninger 2375037ce839SViresh Kumar ret = cpufreq_set_policy(policy, &new_policy); 23761da177e4SLinus Torvalds 2377fefa8ff8SAaron Plattner unlock: 2378ad7722daSviresh kumar up_write(&policy->rwsem); 23795a01f2e8SVenkatesh Pallipadi 23803a3e9e06SViresh Kumar cpufreq_cpu_put(policy); 23811da177e4SLinus Torvalds return ret; 23821da177e4SLinus Torvalds } 23831da177e4SLinus Torvalds EXPORT_SYMBOL(cpufreq_update_policy); 23841da177e4SLinus Torvalds 23852760984fSPaul Gortmaker static int cpufreq_cpu_callback(struct notifier_block *nfb, 2386c32b6b8eSAshok Raj unsigned long action, void *hcpu) 2387c32b6b8eSAshok Raj { 2388c32b6b8eSAshok Raj unsigned int cpu = (unsigned long)hcpu; 23898a25a2fdSKay Sievers struct device *dev; 2390c32b6b8eSAshok Raj 23918a25a2fdSKay Sievers dev = get_cpu_device(cpu); 23928a25a2fdSKay Sievers if (dev) { 23935302c3fbSSrivatsa S. Bhat switch (action & ~CPU_TASKS_FROZEN) { 2394c32b6b8eSAshok Raj case CPU_ONLINE: 239523faf0b7SViresh Kumar cpufreq_add_dev(dev, NULL); 2396c32b6b8eSAshok Raj break; 23975302c3fbSSrivatsa S. Bhat 2398c32b6b8eSAshok Raj case CPU_DOWN_PREPARE: 239996bbbe4aSViresh Kumar __cpufreq_remove_dev_prepare(dev, NULL); 24001aee40acSSrivatsa S. Bhat break; 24011aee40acSSrivatsa S. Bhat 24021aee40acSSrivatsa S. Bhat case CPU_POST_DEAD: 240396bbbe4aSViresh Kumar __cpufreq_remove_dev_finish(dev, NULL); 2404c32b6b8eSAshok Raj break; 24055302c3fbSSrivatsa S. Bhat 24065a01f2e8SVenkatesh Pallipadi case CPU_DOWN_FAILED: 240723faf0b7SViresh Kumar cpufreq_add_dev(dev, NULL); 2408c32b6b8eSAshok Raj break; 2409c32b6b8eSAshok Raj } 2410c32b6b8eSAshok Raj } 2411c32b6b8eSAshok Raj return NOTIFY_OK; 2412c32b6b8eSAshok Raj } 2413c32b6b8eSAshok Raj 24149c36f746SNeal Buckendahl static struct notifier_block __refdata cpufreq_cpu_notifier = { 2415c32b6b8eSAshok Raj .notifier_call = cpufreq_cpu_callback, 2416c32b6b8eSAshok Raj }; 24171da177e4SLinus Torvalds 24181da177e4SLinus Torvalds /********************************************************************* 24196f19efc0SLukasz Majewski * BOOST * 24206f19efc0SLukasz Majewski *********************************************************************/ 24216f19efc0SLukasz Majewski static int cpufreq_boost_set_sw(int state) 24226f19efc0SLukasz Majewski { 24236f19efc0SLukasz Majewski struct cpufreq_frequency_table *freq_table; 24246f19efc0SLukasz Majewski struct cpufreq_policy *policy; 24256f19efc0SLukasz Majewski int ret = -EINVAL; 24266f19efc0SLukasz Majewski 2427f963735aSViresh Kumar for_each_active_policy(policy) { 24286f19efc0SLukasz Majewski freq_table = cpufreq_frequency_get_table(policy->cpu); 24296f19efc0SLukasz Majewski if (freq_table) { 24306f19efc0SLukasz Majewski ret = cpufreq_frequency_table_cpuinfo(policy, 24316f19efc0SLukasz Majewski freq_table); 24326f19efc0SLukasz Majewski if (ret) { 24336f19efc0SLukasz Majewski pr_err("%s: Policy frequency update failed\n", 24346f19efc0SLukasz Majewski __func__); 24356f19efc0SLukasz Majewski break; 24366f19efc0SLukasz Majewski } 24376f19efc0SLukasz Majewski policy->user_policy.max = policy->max; 24386f19efc0SLukasz Majewski __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); 24396f19efc0SLukasz Majewski } 24406f19efc0SLukasz Majewski } 24416f19efc0SLukasz Majewski 24426f19efc0SLukasz Majewski return ret; 24436f19efc0SLukasz Majewski } 24446f19efc0SLukasz Majewski 24456f19efc0SLukasz Majewski int cpufreq_boost_trigger_state(int state) 24466f19efc0SLukasz Majewski { 24476f19efc0SLukasz Majewski unsigned long flags; 24486f19efc0SLukasz Majewski int ret = 0; 24496f19efc0SLukasz Majewski 24506f19efc0SLukasz Majewski if (cpufreq_driver->boost_enabled == state) 24516f19efc0SLukasz Majewski return 0; 24526f19efc0SLukasz Majewski 24536f19efc0SLukasz Majewski write_lock_irqsave(&cpufreq_driver_lock, flags); 24546f19efc0SLukasz Majewski cpufreq_driver->boost_enabled = state; 24556f19efc0SLukasz Majewski write_unlock_irqrestore(&cpufreq_driver_lock, flags); 24566f19efc0SLukasz Majewski 24576f19efc0SLukasz Majewski ret = cpufreq_driver->set_boost(state); 24586f19efc0SLukasz Majewski if (ret) { 24596f19efc0SLukasz Majewski write_lock_irqsave(&cpufreq_driver_lock, flags); 24606f19efc0SLukasz Majewski cpufreq_driver->boost_enabled = !state; 24616f19efc0SLukasz Majewski write_unlock_irqrestore(&cpufreq_driver_lock, flags); 24626f19efc0SLukasz Majewski 2463e837f9b5SJoe Perches pr_err("%s: Cannot %s BOOST\n", 2464e837f9b5SJoe Perches __func__, state ? "enable" : "disable"); 24656f19efc0SLukasz Majewski } 24666f19efc0SLukasz Majewski 24676f19efc0SLukasz Majewski return ret; 24686f19efc0SLukasz Majewski } 24696f19efc0SLukasz Majewski 24706f19efc0SLukasz Majewski int cpufreq_boost_supported(void) 24716f19efc0SLukasz Majewski { 24726f19efc0SLukasz Majewski if (likely(cpufreq_driver)) 24736f19efc0SLukasz Majewski return cpufreq_driver->boost_supported; 24746f19efc0SLukasz Majewski 24756f19efc0SLukasz Majewski return 0; 24766f19efc0SLukasz Majewski } 24776f19efc0SLukasz Majewski EXPORT_SYMBOL_GPL(cpufreq_boost_supported); 24786f19efc0SLukasz Majewski 24796f19efc0SLukasz Majewski int cpufreq_boost_enabled(void) 24806f19efc0SLukasz Majewski { 24816f19efc0SLukasz Majewski return cpufreq_driver->boost_enabled; 24826f19efc0SLukasz Majewski } 24836f19efc0SLukasz Majewski EXPORT_SYMBOL_GPL(cpufreq_boost_enabled); 24846f19efc0SLukasz Majewski 24856f19efc0SLukasz Majewski /********************************************************************* 24861da177e4SLinus Torvalds * REGISTER / UNREGISTER CPUFREQ DRIVER * 24871da177e4SLinus Torvalds *********************************************************************/ 24881da177e4SLinus Torvalds 24891da177e4SLinus Torvalds /** 24901da177e4SLinus Torvalds * cpufreq_register_driver - register a CPU Frequency driver 24911da177e4SLinus Torvalds * @driver_data: A struct cpufreq_driver containing the values# 24921da177e4SLinus Torvalds * submitted by the CPU Frequency driver. 24931da177e4SLinus Torvalds * 24941da177e4SLinus Torvalds * Registers a CPU Frequency driver to this core code. This code 24951da177e4SLinus Torvalds * returns zero on success, -EBUSY when another driver got here first 24961da177e4SLinus Torvalds * (and isn't unregistered in the meantime). 24971da177e4SLinus Torvalds * 24981da177e4SLinus Torvalds */ 2499221dee28SLinus Torvalds int cpufreq_register_driver(struct cpufreq_driver *driver_data) 25001da177e4SLinus Torvalds { 25011da177e4SLinus Torvalds unsigned long flags; 25021da177e4SLinus Torvalds int ret; 25031da177e4SLinus Torvalds 2504a7b422cdSKonrad Rzeszutek Wilk if (cpufreq_disabled()) 2505a7b422cdSKonrad Rzeszutek Wilk return -ENODEV; 2506a7b422cdSKonrad Rzeszutek Wilk 25071da177e4SLinus Torvalds if (!driver_data || !driver_data->verify || !driver_data->init || 25089c0ebcf7SViresh Kumar !(driver_data->setpolicy || driver_data->target_index || 25099832235fSRafael J. Wysocki driver_data->target) || 25109832235fSRafael J. Wysocki (driver_data->setpolicy && (driver_data->target_index || 25111c03a2d0SViresh Kumar driver_data->target)) || 25121c03a2d0SViresh Kumar (!!driver_data->get_intermediate != !!driver_data->target_intermediate)) 25131da177e4SLinus Torvalds return -EINVAL; 25141da177e4SLinus Torvalds 25152d06d8c4SDominik Brodowski pr_debug("trying to register driver %s\n", driver_data->name); 25161da177e4SLinus Torvalds 25170d1857a1SNathan Zimmer write_lock_irqsave(&cpufreq_driver_lock, flags); 25181c3d85ddSRafael J. Wysocki if (cpufreq_driver) { 25190d1857a1SNathan Zimmer write_unlock_irqrestore(&cpufreq_driver_lock, flags); 25204dea5806SYinghai Lu return -EEXIST; 25211da177e4SLinus Torvalds } 25221c3d85ddSRafael J. Wysocki cpufreq_driver = driver_data; 25230d1857a1SNathan Zimmer write_unlock_irqrestore(&cpufreq_driver_lock, flags); 25241da177e4SLinus Torvalds 2525bc68b7dfSViresh Kumar if (driver_data->setpolicy) 2526bc68b7dfSViresh Kumar driver_data->flags |= CPUFREQ_CONST_LOOPS; 2527bc68b7dfSViresh Kumar 25286f19efc0SLukasz Majewski if (cpufreq_boost_supported()) { 25296f19efc0SLukasz Majewski /* 25306f19efc0SLukasz Majewski * Check if driver provides function to enable boost - 25316f19efc0SLukasz Majewski * if not, use cpufreq_boost_set_sw as default 25326f19efc0SLukasz Majewski */ 25336f19efc0SLukasz Majewski if (!cpufreq_driver->set_boost) 25346f19efc0SLukasz Majewski cpufreq_driver->set_boost = cpufreq_boost_set_sw; 25356f19efc0SLukasz Majewski 25366f19efc0SLukasz Majewski ret = cpufreq_sysfs_create_file(&boost.attr); 25376f19efc0SLukasz Majewski if (ret) { 25386f19efc0SLukasz Majewski pr_err("%s: cannot register global BOOST sysfs file\n", 25396f19efc0SLukasz Majewski __func__); 25406f19efc0SLukasz Majewski goto err_null_driver; 25416f19efc0SLukasz Majewski } 25426f19efc0SLukasz Majewski } 25436f19efc0SLukasz Majewski 25448a25a2fdSKay Sievers ret = subsys_interface_register(&cpufreq_interface); 25458f5bc2abSJiri Slaby if (ret) 25466f19efc0SLukasz Majewski goto err_boost_unreg; 25471da177e4SLinus Torvalds 2548ce1bcfe9SViresh Kumar if (!(cpufreq_driver->flags & CPUFREQ_STICKY) && 2549ce1bcfe9SViresh Kumar list_empty(&cpufreq_policy_list)) { 25501da177e4SLinus Torvalds /* if all ->init() calls failed, unregister */ 2551ce1bcfe9SViresh Kumar pr_debug("%s: No CPU initialized for driver %s\n", __func__, 2552e08f5f5bSGautham R Shenoy driver_data->name); 25538a25a2fdSKay Sievers goto err_if_unreg; 25541da177e4SLinus Torvalds } 25551da177e4SLinus Torvalds 255665edc68cSChandra Seetharaman register_hotcpu_notifier(&cpufreq_cpu_notifier); 25572d06d8c4SDominik Brodowski pr_debug("driver %s up and running\n", driver_data->name); 25581da177e4SLinus Torvalds 25598f5bc2abSJiri Slaby return 0; 25608a25a2fdSKay Sievers err_if_unreg: 25618a25a2fdSKay Sievers subsys_interface_unregister(&cpufreq_interface); 25626f19efc0SLukasz Majewski err_boost_unreg: 25636f19efc0SLukasz Majewski if (cpufreq_boost_supported()) 25646f19efc0SLukasz Majewski cpufreq_sysfs_remove_file(&boost.attr); 25658f5bc2abSJiri Slaby err_null_driver: 25660d1857a1SNathan Zimmer write_lock_irqsave(&cpufreq_driver_lock, flags); 25671c3d85ddSRafael J. Wysocki cpufreq_driver = NULL; 25680d1857a1SNathan Zimmer write_unlock_irqrestore(&cpufreq_driver_lock, flags); 25694d34a67dSDave Jones return ret; 25701da177e4SLinus Torvalds } 25711da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_register_driver); 25721da177e4SLinus Torvalds 25731da177e4SLinus Torvalds /** 25741da177e4SLinus Torvalds * cpufreq_unregister_driver - unregister the current CPUFreq driver 25751da177e4SLinus Torvalds * 25761da177e4SLinus Torvalds * Unregister the current CPUFreq driver. Only call this if you have 25771da177e4SLinus Torvalds * the right to do so, i.e. if you have succeeded in initialising before! 25781da177e4SLinus Torvalds * Returns zero if successful, and -EINVAL if the cpufreq_driver is 25791da177e4SLinus Torvalds * currently not initialised. 25801da177e4SLinus Torvalds */ 2581221dee28SLinus Torvalds int cpufreq_unregister_driver(struct cpufreq_driver *driver) 25821da177e4SLinus Torvalds { 25831da177e4SLinus Torvalds unsigned long flags; 25841da177e4SLinus Torvalds 25851c3d85ddSRafael J. Wysocki if (!cpufreq_driver || (driver != cpufreq_driver)) 25861da177e4SLinus Torvalds return -EINVAL; 25871da177e4SLinus Torvalds 25882d06d8c4SDominik Brodowski pr_debug("unregistering driver %s\n", driver->name); 25891da177e4SLinus Torvalds 25908a25a2fdSKay Sievers subsys_interface_unregister(&cpufreq_interface); 25916f19efc0SLukasz Majewski if (cpufreq_boost_supported()) 25926f19efc0SLukasz Majewski cpufreq_sysfs_remove_file(&boost.attr); 25936f19efc0SLukasz Majewski 259465edc68cSChandra Seetharaman unregister_hotcpu_notifier(&cpufreq_cpu_notifier); 25951da177e4SLinus Torvalds 25966eed9404SViresh Kumar down_write(&cpufreq_rwsem); 25970d1857a1SNathan Zimmer write_lock_irqsave(&cpufreq_driver_lock, flags); 25986eed9404SViresh Kumar 25991c3d85ddSRafael J. Wysocki cpufreq_driver = NULL; 26006eed9404SViresh Kumar 26010d1857a1SNathan Zimmer write_unlock_irqrestore(&cpufreq_driver_lock, flags); 26026eed9404SViresh Kumar up_write(&cpufreq_rwsem); 26031da177e4SLinus Torvalds 26041da177e4SLinus Torvalds return 0; 26051da177e4SLinus Torvalds } 26061da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); 26075a01f2e8SVenkatesh Pallipadi 260890de2a4aSDoug Anderson /* 260990de2a4aSDoug Anderson * Stop cpufreq at shutdown to make sure it isn't holding any locks 261090de2a4aSDoug Anderson * or mutexes when secondary CPUs are halted. 261190de2a4aSDoug Anderson */ 261290de2a4aSDoug Anderson static struct syscore_ops cpufreq_syscore_ops = { 261390de2a4aSDoug Anderson .shutdown = cpufreq_suspend, 261490de2a4aSDoug Anderson }; 261590de2a4aSDoug Anderson 26165a01f2e8SVenkatesh Pallipadi static int __init cpufreq_core_init(void) 26175a01f2e8SVenkatesh Pallipadi { 2618a7b422cdSKonrad Rzeszutek Wilk if (cpufreq_disabled()) 2619a7b422cdSKonrad Rzeszutek Wilk return -ENODEV; 2620a7b422cdSKonrad Rzeszutek Wilk 26212361be23SViresh Kumar cpufreq_global_kobject = kobject_create(); 26228aa84ad8SThomas Renninger BUG_ON(!cpufreq_global_kobject); 26238aa84ad8SThomas Renninger 262490de2a4aSDoug Anderson register_syscore_ops(&cpufreq_syscore_ops); 262590de2a4aSDoug Anderson 26265a01f2e8SVenkatesh Pallipadi return 0; 26275a01f2e8SVenkatesh Pallipadi } 26285a01f2e8SVenkatesh Pallipadi core_initcall(cpufreq_core_init); 2629