aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2015-02-09 13:38:17 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-11 20:02:52 -0500
commitd4d4eda23794c701442e55129dd4f8f2fefd5e4d (patch)
tree26b68b8c7413e3bf9503a101414e9fd2f6fecf12
parentc488ea461359483976ff7d4838cce5c0138c6b3e (diff)
cpufreq: 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. 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>
-rw-r--r--drivers/cpufreq/speedstep-lib.c3
-rw-r--r--drivers/cpufreq/speedstep-smi.c12
2 files changed, 15 insertions, 0 deletions
diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c
index 7047821a7f8a..4ab7a2156672 100644
--- a/drivers/cpufreq/speedstep-lib.c
+++ b/drivers/cpufreq/speedstep-lib.c
@@ -400,6 +400,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
400 400
401 pr_debug("previous speed is %u\n", prev_speed); 401 pr_debug("previous speed is %u\n", prev_speed);
402 402
403 preempt_disable();
403 local_irq_save(flags); 404 local_irq_save(flags);
404 405
405 /* switch to low state */ 406 /* switch to low state */
@@ -464,6 +465,8 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor,
464 465
465out: 466out:
466 local_irq_restore(flags); 467 local_irq_restore(flags);
468 preempt_enable();
469
467 return ret; 470 return ret;
468} 471}
469EXPORT_SYMBOL_GPL(speedstep_get_freqs); 472EXPORT_SYMBOL_GPL(speedstep_get_freqs);
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index 5fc96d5d656b..819229e824fb 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -156,6 +156,7 @@ static void speedstep_set_state(unsigned int state)
156 return; 156 return;
157 157
158 /* Disable IRQs */ 158 /* Disable IRQs */
159 preempt_disable();
159 local_irq_save(flags); 160 local_irq_save(flags);
160 161
161 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); 162 command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
@@ -166,9 +167,19 @@ static void speedstep_set_state(unsigned int state)
166 167
167 do { 168 do {
168 if (retry) { 169 if (retry) {
170 /*
171 * We need to enable interrupts, otherwise the blockage
172 * won't resolve.
173 *
174 * We disable preemption so that other processes don't
175 * run. If other processes were running, they could
176 * submit more DMA requests, making the blockage worse.
177 */
169 pr_debug("retry %u, previous result %u, waiting...\n", 178 pr_debug("retry %u, previous result %u, waiting...\n",
170 retry, result); 179 retry, result);
180 local_irq_enable();
171 mdelay(retry * 50); 181 mdelay(retry * 50);
182 local_irq_disable();
172 } 183 }
173 retry++; 184 retry++;
174 __asm__ __volatile__( 185 __asm__ __volatile__(
@@ -185,6 +196,7 @@ static void speedstep_set_state(unsigned int state)
185 196
186 /* enable IRQs */ 197 /* enable IRQs */
187 local_irq_restore(flags); 198 local_irq_restore(flags);
199 preempt_enable();
188 200
189 if (new_state == state) 201 if (new_state == state)
190 pr_debug("change to %u MHz succeeded after %u tries " 202 pr_debug("change to %u MHz succeeded after %u tries "