[3.13.y-ckt stable] Patch "cpufreq: speedstep-smi: enable interrupts when waiting" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Tue Mar 31 18:46:11 UTC 2015

This is a note to let you know that I have just added a patch titled

    cpufreq: speedstep-smi: enable interrupts when waiting

to the linux-3.13.y-queue branch of the 3.13.y-ckt extended stable tree 
which can be found at:


This patch is scheduled to be released in version 3.13.11-ckt18.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y-ckt tree, see



>From cf7a7b660e5c61a4d336c60d546cab309918369a Mon Sep 17 00:00:00 2001
From: Mikulas Patocka <mpatocka at redhat.com>
Date: Mon, 9 Feb 2015 13:38:17 -0500
Subject: cpufreq: speedstep-smi: enable interrupts when waiting

commit d4d4eda23794c701442e55129dd4f8f2fefd5e4d upstream.

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 at redhat.com
Acked-by: Viresh Kumar <viresh.kumar at linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
 drivers/cpufreq/speedstep-lib.c |  3 +++
 drivers/cpufreq/speedstep-smi.c | 12 ++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c
index 7047821..4ab7a21 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,

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

+	preempt_disable();

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

+	preempt_enable();
 	return ret;
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index 0f5326d..34bd13c 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -188,6 +188,7 @@ static void speedstep_set_state(unsigned int state)

 	/* Disable IRQs */
+	preempt_disable();

 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
@@ -198,9 +199,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();
 		__asm__ __volatile__(
@@ -217,6 +228,7 @@ static void speedstep_set_state(unsigned int state)

 	/* enable IRQs */
+	preempt_enable();

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

More information about the kernel-team mailing list