From 24e1937b23867a55404eb2dc98fa618bc9851ea7 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 11 Dec 2013 19:55:40 -0500 Subject: [PATCH] speedstep-smi: enable interrupts when waiting 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. I found out that we need to enable interrupts while waiting. When we enable interrupts, the 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). 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 Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/speedstep-lib.c | 1 + drivers/cpufreq/speedstep-smi.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 7047821a7f8a..0b12ab9ae0e6 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -464,6 +464,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, out: local_irq_restore(flags); + preempt_check_resched(); return ret; } EXPORT_SYMBOL_GPL(speedstep_get_freqs); diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index 0f5326d6f79f..4d04770cf4f2 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -200,7 +200,19 @@ static void speedstep_set_state(unsigned int state) if (retry) { pr_debug("retry %u, previous result %u, waiting...\n", retry, result); + /* + * 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. + */ + preempt_disable(); + local_irq_enable(); mdelay(retry * 50); + local_irq_disable(); + preempt_enable_no_resched(); } retry++; __asm__ __volatile__( @@ -217,6 +229,7 @@ static void speedstep_set_state(unsigned int state) /* enable IRQs */ local_irq_restore(flags); + preempt_check_resched(); if (new_state == state) pr_debug("change to %u MHz succeeded after %u tries " -- 2.39.5