Skip to content

Commit

Permalink
cpufreq: speedstep-smi: enable interrupts when waiting
Browse files Browse the repository at this point in the history
On Dell Latitude C600 laptop with Pentium 3 850MHz processor, the
speedstep-smi driver sometimes loads and sometimes doesn't load with
"change to state X failed" message.

The hardware sometimes refuses to change frequency and in this case, we
need to retry later. I found out that we need to enable interrupts while
waiting. When we enable interrupts, the hardware blockage that prevents
frequency transition resolves and the transition is possible. With
disabled interrupts, the blockage doesn't resolve (no matter how long do
we wait). The exact reasons for this hardware behavior are unknown.

This patch enables interrupts in the function speedstep_set_state that can
be called with disabled interrupts. However, this function is called with
disabled interrupts only from speedstep_get_freqs, so it shouldn't cause
any problem.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com
Cc: All applicable <stable@vger.kernel.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Mikulas Patocka authored and rafaeljw committed Feb 12, 2015
1 parent c488ea4 commit d4d4eda
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/cpufreq/speedstep-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,

pr_debug("previous speed is %u\n", prev_speed);

preempt_disable();
local_irq_save(flags);

/* switch to low state */
Expand Down Expand Up @@ -464,6 +465,8 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,

out:
local_irq_restore(flags);
preempt_enable();

return ret;
}
EXPORT_SYMBOL_GPL(speedstep_get_freqs);
Expand Down
12 changes: 12 additions & 0 deletions drivers/cpufreq/speedstep-smi.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static void speedstep_set_state(unsigned int state)
return;

/* Disable IRQs */
preempt_disable();
local_irq_save(flags);

command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
Expand All @@ -166,9 +167,19 @@ static void speedstep_set_state(unsigned int state)

do {
if (retry) {
/*
* We need to enable interrupts, otherwise the blockage
* won't resolve.
*
* We disable preemption so that other processes don't
* run. If other processes were running, they could
* submit more DMA requests, making the blockage worse.
*/
pr_debug("retry %u, previous result %u, waiting...\n",
retry, result);
local_irq_enable();
mdelay(retry * 50);
local_irq_disable();
}
retry++;
__asm__ __volatile__(
Expand All @@ -185,6 +196,7 @@ static void speedstep_set_state(unsigned int state)

/* enable IRQs */
local_irq_restore(flags);
preempt_enable();

if (new_state == state)
pr_debug("change to %u MHz succeeded after %u tries "
Expand Down

0 comments on commit d4d4eda

Please sign in to comment.