]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
speedstep-smi: enable interrupts when waiting
authorMikulas Patocka <mpatocka@redhat.com>
Tue, 14 Jan 2014 22:12:55 +0000 (23:12 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 14 Jan 2014 22:12:55 +0000 (23:12 +0100)
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 <mpatocka@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/speedstep-lib.c
drivers/cpufreq/speedstep-smi.c

index 7047821a7f8a5fd966521ba5a8d48bf7664d2d54..4ab7a215667249326d4b1b81b2144b56767b0dcd 100644 (file)
@@ -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 */
@@ -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);
index 0f5326d6f79ffef866957b26acdd18bf866bd0a9..34bd13c17d1a251660b9225cdbded58fae6f066a 100644 (file)
@@ -188,6 +188,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);
@@ -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();
                }
                retry++;
                __asm__ __volatile__(
@@ -217,6 +228,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 "