|
@@ -331,16 +331,15 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
|
|
|
* function. It is called twice on all CPU frequency changes that have
|
|
|
* external effects.
|
|
|
*/
|
|
|
-void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
|
|
+static void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
|
|
struct cpufreq_freqs *freqs, unsigned int state)
|
|
|
{
|
|
|
for_each_cpu(freqs->cpu, policy->cpus)
|
|
|
__cpufreq_notify_transition(policy, freqs, state);
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
|
|
|
|
|
|
/* Do post notifications when there are chances that transition has failed */
|
|
|
-void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
|
|
+static void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
|
|
struct cpufreq_freqs *freqs, int transition_failed)
|
|
|
{
|
|
|
cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
|
|
@@ -351,7 +350,41 @@ void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
|
|
cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
|
|
|
cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
|
|
|
+
|
|
|
+void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
|
|
|
+ struct cpufreq_freqs *freqs)
|
|
|
+{
|
|
|
+wait:
|
|
|
+ wait_event(policy->transition_wait, !policy->transition_ongoing);
|
|
|
+
|
|
|
+ spin_lock(&policy->transition_lock);
|
|
|
+
|
|
|
+ if (unlikely(policy->transition_ongoing)) {
|
|
|
+ spin_unlock(&policy->transition_lock);
|
|
|
+ goto wait;
|
|
|
+ }
|
|
|
+
|
|
|
+ policy->transition_ongoing = true;
|
|
|
+
|
|
|
+ spin_unlock(&policy->transition_lock);
|
|
|
+
|
|
|
+ cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin);
|
|
|
+
|
|
|
+void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
|
|
|
+ struct cpufreq_freqs *freqs, int transition_failed)
|
|
|
+{
|
|
|
+ if (unlikely(WARN_ON(!policy->transition_ongoing)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ cpufreq_notify_post_transition(policy, freqs, transition_failed);
|
|
|
+
|
|
|
+ policy->transition_ongoing = false;
|
|
|
+
|
|
|
+ wake_up(&policy->transition_wait);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
@@ -985,6 +1018,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void)
|
|
|
|
|
|
INIT_LIST_HEAD(&policy->policy_list);
|
|
|
init_rwsem(&policy->rwsem);
|
|
|
+ spin_lock_init(&policy->transition_lock);
|
|
|
+ init_waitqueue_head(&policy->transition_wait);
|
|
|
|
|
|
return policy;
|
|
|
|
|
@@ -1470,8 +1505,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
|
|
|
policy = per_cpu(cpufreq_cpu_data, cpu);
|
|
|
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
|
|
|
|
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
|
|
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
|
|
+ cpufreq_freq_transition_begin(policy, &freqs);
|
|
|
+ cpufreq_freq_transition_end(policy, &freqs, 0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1652,14 +1687,13 @@ void cpufreq_resume(void)
|
|
|
cpufreq_suspended = false;
|
|
|
|
|
|
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
|
|
- if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
|
|
|
+ if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
|
|
|
+ pr_err("%s: Failed to resume driver: %p\n", __func__,
|
|
|
+ policy);
|
|
|
+ else if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
|
|
|
|| __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
|
|
|
pr_err("%s: Failed to start governor for policy: %p\n",
|
|
|
__func__, policy);
|
|
|
- else if (cpufreq_driver->resume
|
|
|
- && cpufreq_driver->resume(policy))
|
|
|
- pr_err("%s: Failed to resume driver: %p\n", __func__,
|
|
|
- policy);
|
|
|
|
|
|
/*
|
|
|
* schedule call cpufreq_update_policy() for boot CPU, i.e. last
|
|
@@ -1832,8 +1866,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
|
|
pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
|
|
|
__func__, policy->cpu, freqs.old, freqs.new);
|
|
|
|
|
|
- cpufreq_notify_transition(policy, &freqs,
|
|
|
- CPUFREQ_PRECHANGE);
|
|
|
+ cpufreq_freq_transition_begin(policy, &freqs);
|
|
|
}
|
|
|
|
|
|
retval = cpufreq_driver->target_index(policy, index);
|
|
@@ -1842,7 +1875,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
|
|
__func__, retval);
|
|
|
|
|
|
if (notify)
|
|
|
- cpufreq_notify_post_transition(policy, &freqs, retval);
|
|
|
+ cpufreq_freq_transition_end(policy, &freqs, retval);
|
|
|
}
|
|
|
|
|
|
out:
|