msm: cpufreq: Implement suspend/resume for cpufreq driver

Cpufreq suspend variable get's updated in kernel pm notifier
callback which gets called in process context. This will create
window where cpufreq governor may try to change the frequency
before suspend variable is updated while resume.

Define suspend/resume for cpufreq driver to update suspend variable
in atomic context.

Don't update the policy->cur upon cpufreq driver failure.

CRs-fixed: 423791
Change-Id: Id78705f5c3b8bf801c6253e9362299280903769f
Signed-off-by: Anji Jonnala <anjir@codeaurora.org>
This commit is contained in:
Anji Jonnala 2012-12-13 14:03:54 +05:30 committed by Stephen Boyd
parent 766ad34146
commit ebc453cb2e
2 changed files with 19 additions and 29 deletions

View file

@ -278,20 +278,24 @@ static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
.notifier_call = msm_cpufreq_cpu_callback,
};
static int msm_cpufreq_suspend(void)
/*
* Define suspend/resume for cpufreq_driver. Kernel will call
* these during suspend/resume with interrupts disabled. This
* helps the suspend/resume variable get's updated before cpufreq
* governor tries to change the frequency after coming out of suspend.
*/
static int msm_cpufreq_suspend(struct cpufreq_policy *policy)
{
int cpu;
for_each_possible_cpu(cpu) {
mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
}
return NOTIFY_DONE;
return 0;
}
static int msm_cpufreq_resume(void)
static int msm_cpufreq_resume(struct cpufreq_policy *policy)
{
int cpu;
@ -299,28 +303,9 @@ static int msm_cpufreq_resume(void)
per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
}
return NOTIFY_DONE;
return 0;
}
static int msm_cpufreq_pm_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
switch (event) {
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
return msm_cpufreq_resume();
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
return msm_cpufreq_suspend();
default:
return NOTIFY_DONE;
}
}
static struct notifier_block msm_cpufreq_pm_notifier = {
.notifier_call = msm_cpufreq_pm_event,
};
static struct freq_attr *msm_freq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@ -333,6 +318,8 @@ static struct cpufreq_driver msm_cpufreq_driver = {
.verify = msm_cpufreq_verify,
.target = msm_cpufreq_target,
.get = msm_cpufreq_get_freq,
.suspend = msm_cpufreq_suspend,
.resume = msm_cpufreq_resume,
.name = "msm",
.attr = msm_freq_attr,
};
@ -348,7 +335,6 @@ static int __init msm_cpufreq_register(void)
register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
register_pm_notifier(&msm_cpufreq_pm_notifier);
return cpufreq_register_driver(&msm_cpufreq_driver);
}

View file

@ -990,10 +990,14 @@ static void dbs_refresh_callback(struct work_struct *unused)
}
if (policy->cur < policy->max) {
policy->cur = policy->max;
/*
* Arch specific cpufreq driver may fail.
* Don't update governor frequency upon failure.
*/
if (__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_L) >= 0)
policy->cur = policy->max;
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_L);
this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
&this_dbs_info->prev_cpu_wall);
}