#include <linux/tick.h>
#include <trace/events/power.h>
+/* Macros to iterate over lists */
+/* Iterate over online CPUs policies */
+static LIST_HEAD(cpufreq_policy_list);
+#define for_each_policy(__policy) \
+ list_for_each_entry(__policy, &cpufreq_policy_list, policy_list)
+
/**
* The "cpufreq driver" - the arch- or hardware-dependent low
* level driver of CPUFreq support, and its spinlock. This lock
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
static DEFINE_RWLOCK(cpufreq_driver_lock);
DEFINE_MUTEX(cpufreq_governor_lock);
-static LIST_HEAD(cpufreq_policy_list);
/* This one keeps track of the previously set governor of a removed CPU */
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
struct cpufreq_policy *policy = NULL;
unsigned long flags;
- if (cpufreq_disabled() || (cpu >= nr_cpu_ids))
+ if (cpu >= nr_cpu_ids)
return NULL;
if (!down_read_trylock(&cpufreq_rwsem))
void cpufreq_cpu_put(struct cpufreq_policy *policy)
{
- if (cpufreq_disabled())
- return;
-
kobject_put(&policy->kobj);
up_read(&cpufreq_rwsem);
}
* systems as each CPU might be scaled differently. So, use the arch
* per-CPU loops_per_jiffy value wherever possible.
*/
-#ifndef CONFIG_SMP
-static unsigned long l_p_j_ref;
-static unsigned int l_p_j_ref_freq;
-
static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
+#ifndef CONFIG_SMP
+ static unsigned long l_p_j_ref;
+ static unsigned int l_p_j_ref_freq;
+
if (ci->flags & CPUFREQ_CONST_LOOPS)
return;
pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n",
loops_per_jiffy, ci->new);
}
-}
-#else
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
-{
- return;
-}
#endif
+}
static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
struct cpufreq_freqs *freqs, unsigned int state)
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
init_waitqueue_head(&policy->transition_wait);
+ init_completion(&policy->kobj_unregister);
+ INIT_WORK(&policy->update, handle_update);
return policy;
}
down_write(&policy->rwsem);
-
- policy->last_cpu = policy->cpu;
policy->cpu = cpu;
-
up_write(&policy->rwsem);
- blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
- CPUFREQ_UPDATE_POLICY_CPU, policy);
-
return 0;
}
/* check whether a different CPU already registered this
* CPU because it is in the same boat. */
- policy = cpufreq_cpu_get(cpu);
- if (unlikely(policy)) {
- cpufreq_cpu_put(policy);
+ policy = cpufreq_cpu_get_raw(cpu);
+ if (unlikely(policy))
return 0;
- }
if (!down_read_trylock(&cpufreq_rwsem))
return 0;
/* Check if this cpu was hot-unplugged earlier and has siblings */
read_lock_irqsave(&cpufreq_driver_lock, flags);
- list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+ for_each_policy(policy) {
if (cpumask_test_cpu(cpu, policy->related_cpus)) {
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
ret = cpufreq_add_policy_cpu(policy, cpu, dev);
cpumask_copy(policy->cpus, cpumask_of(cpu));
- init_completion(&policy->kobj_unregister);
- INIT_WORK(&policy->update, handle_update);
-
/* call driver. From then on the cpufreq must be able
* to accept all calls to ->verify and ->setpolicy for this CPU
*/
unsigned long flags;
struct cpufreq_policy *policy;
- read_lock_irqsave(&cpufreq_driver_lock, flags);
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
policy = per_cpu(cpufreq_cpu_data, cpu);
- read_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ per_cpu(cpufreq_cpu_data, cpu) = NULL;
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (!policy) {
pr_debug("%s: No cpu_data found\n", __func__);
}
}
- per_cpu(cpufreq_cpu_data, cpu) = NULL;
return 0;
}
pr_debug("%s: Suspending Governors\n", __func__);
- list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+ for_each_policy(policy) {
if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
pr_err("%s: Failed to stop governor for policy: %p\n",
__func__, policy);
pr_debug("%s: Resuming Governors\n", __func__);
- list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+ for_each_policy(policy) {
if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
pr_err("%s: Failed to resume driver: %p\n", __func__,
policy);
struct cpufreq_policy *policy;
int ret = -EINVAL;
- list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+ for_each_policy(policy) {
freq_table = cpufreq_frequency_get_table(policy->cpu);
if (freq_table) {
ret = cpufreq_frequency_table_cpuinfo(policy,
if (ret)
goto err_boost_unreg;
- if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
- int i;
- ret = -ENODEV;
-
- /* check for at least one working CPU */
- for (i = 0; i < nr_cpu_ids; i++)
- if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
- ret = 0;
- break;
- }
-
+ if (!(cpufreq_driver->flags & CPUFREQ_STICKY) &&
+ list_empty(&cpufreq_policy_list)) {
/* if all ->init() calls failed, unregister */
- if (ret) {
- pr_debug("no CPU initialized for driver %s\n",
- driver_data->name);
- goto err_if_unreg;
- }
+ pr_debug("%s: No CPU initialized for driver %s\n", __func__,
+ driver_data->name);
+ goto err_if_unreg;
}
register_hotcpu_notifier(&cpufreq_cpu_notifier);