From bc238d51bbb2c2c7f5ea76106ac951d38884663d Mon Sep 17 00:00:00 2001 From: Junjie Wu Date: Fri, 15 Aug 2014 16:20:54 -0700 Subject: [PATCH] cpufreq: interactive: Use del_timer/add_timer_on to rearm timers Replace mod_timer_pinned() with del_timer(), add_timer_on(). mod_timer_pinned() always adds timer onto current CPU. Interactive governor expects each CPU's timers to be running on the same CPU. If cpufreq_interactive_timer_resched() is called from another CPU, the timer will be armed on the wrong CPU. Replacing mod_timer_pinned() with del_timer() and add_timer_on() guarantees timers are still run on the right CPU even if another CPU reschedules the timer. This would provide more flexibility for future changes. Change-Id: I3a10be37632afc0ea4e0cc9c86323b9783b216b1 Signed-off-by: Junjie Wu --- drivers/cpufreq/cpufreq_interactive.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 264fee412f5..4629878d671 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -177,9 +177,9 @@ static inline cputime64_t get_cpu_idle_time( return idle_time; } -static void cpufreq_interactive_timer_resched( - struct cpufreq_interactive_cpuinfo *pcpu) +static void cpufreq_interactive_timer_resched(unsigned long cpu) { + struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); struct cpufreq_interactive_tunables *tunables = pcpu->policy->governor_data; unsigned long expires; @@ -196,12 +196,16 @@ static void cpufreq_interactive_timer_resched( pcpu->cputime_speedadj = 0; pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; expires = jiffies + usecs_to_jiffies(tunables->timer_rate); - mod_timer_pinned(&pcpu->cpu_timer, expires); + del_timer(&pcpu->cpu_timer); + pcpu->cpu_timer.expires = expires; + add_timer_on(&pcpu->cpu_timer, cpu); if (tunables->timer_slack_val >= 0 && pcpu->target_freq > pcpu->policy->min) { expires += usecs_to_jiffies(tunables->timer_slack_val); - mod_timer_pinned(&pcpu->cpu_slack_timer, expires); + del_timer(&pcpu->cpu_slack_timer); + pcpu->cpu_slack_timer.expires = expires; + add_timer_on(&pcpu->cpu_slack_timer, cpu); } spin_unlock_irqrestore(&pcpu->load_lock, flags); @@ -222,6 +226,7 @@ static void cpufreq_interactive_timer_start( if (!tunables->speedchange_task) return; + spin_lock_irqsave(&pcpu->load_lock, flags); pcpu->cpu_timer.expires = expires; add_timer_on(&pcpu->cpu_timer, cpu); if (tunables->timer_slack_val >= 0 && @@ -231,7 +236,6 @@ static void cpufreq_interactive_timer_start( add_timer_on(&pcpu->cpu_slack_timer, cpu); } - spin_lock_irqsave(&pcpu->load_lock, flags); pcpu->time_in_idle = get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp, tunables->io_is_busy); @@ -526,7 +530,7 @@ rearm_if_notmax: rearm: if (!timer_pending(&pcpu->cpu_timer)) - cpufreq_interactive_timer_resched(pcpu); + cpufreq_interactive_timer_resched(data); exit: up_read(&pcpu->enable_sem); @@ -558,7 +562,7 @@ static void cpufreq_interactive_idle_start(void) * the CPUFreq driver. */ if (!pending) - cpufreq_interactive_timer_resched(pcpu); + cpufreq_interactive_timer_resched(smp_processor_id()); } up_read(&pcpu->enable_sem); @@ -578,7 +582,7 @@ static void cpufreq_interactive_idle_end(void) /* Arm the timer for 1-2 ticks later if not already. */ if (!timer_pending(&pcpu->cpu_timer)) { - cpufreq_interactive_timer_resched(pcpu); + cpufreq_interactive_timer_resched(smp_processor_id()); } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) { del_timer(&pcpu->cpu_timer); del_timer(&pcpu->cpu_slack_timer); @@ -1457,7 +1461,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); - cpufreq_interactive_timer_start(tunables, j); + cpufreq_interactive_timer_resched(j); up_write(&pcpu->enable_sem); pcpu->max_freq = policy->max; -- 2.20.1