This is a note to let you know that I've just added the patch titled

    Fix CPU spinlock lockups on secondary CPU bringup

to the 2.6.39-stable tree which can be found at:
    
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     fix-cpu-spinlock-lockups-on-secondary-cpu-bringup.patch
and it can be found in the queue-2.6.39 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <sta...@kernel.org> know about it.


>From 1b19ca9f0bdab7d5035821e1ec8f39df9a6e3ee0 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+ker...@arm.linux.org.uk>
Date: Wed, 22 Jun 2011 11:55:50 +0100
Subject: Fix CPU spinlock lockups on secondary CPU bringup

From: Russell King <rmk+ker...@arm.linux.org.uk>

commit 1b19ca9f0bdab7d5035821e1ec8f39df9a6e3ee0 upstream.

Secondary CPU bringup typically calls calibrate_delay() during its
initialization.  However, calibrate_delay() modifies a global variable
(loops_per_jiffy) used for udelay() and __delay().

A side effect of 71c696b1 ("calibrate: extract fall-back calculation
into own helper") introduced in the 2.6.39 merge window means that we
end up with a substantial period where loops_per_jiffy is zero.  This
causes the spinlock debugging code to malfunction:

        u64 loops = loops_per_jiffy * HZ;
        for (;;) {
                for (i = 0; i < loops; i++) {
                        if (arch_spin_trylock(&lock->raw_lock))
                                return;
                        __delay(1);
                }
                ...
        }

by never calling arch_spin_trylock() - resulting in the CPU locking
up in an infinite loop inside __spin_lock_debug().

Work around this by only writing to loops_per_jiffy only once we have
completed all the calibration decisions.

Tested-by: Santosh Shilimkar <santosh.shilim...@ti.com>
Signed-off-by: Russell King <rmk+ker...@arm.linux.org.uk>
Cc: <sta...@kernel.org> (2.6.39-stable)
--
Better solutions (such as omitting the calibration for secondary CPUs,
or arranging for calibrate_delay() to return the LPJ value and leave
it to the caller to decide where to store it) are a possibility, but
would be much more invasive into each architecture.

I think this is the best solution for -rc and stable, but it should be
revisited for the next merge window.

Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gre...@suse.de>

---
 init/calibrate.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -185,30 +185,32 @@ recalibrate:
 
 void __cpuinit calibrate_delay(void)
 {
+       unsigned long lpj;
        static bool printed;
 
        if (preset_lpj) {
-               loops_per_jiffy = preset_lpj;
+               lpj = preset_lpj;
                if (!printed)
                        pr_info("Calibrating delay loop (skipped) "
                                "preset value.. ");
        } else if ((!printed) && lpj_fine) {
-               loops_per_jiffy = lpj_fine;
+               lpj = lpj_fine;
                pr_info("Calibrating delay loop (skipped), "
                        "value calculated using timer frequency.. ");
-       } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
+       } else if ((lpj = calibrate_delay_direct()) != 0) {
                if (!printed)
                        pr_info("Calibrating delay using timer "
                                "specific routine.. ");
        } else {
                if (!printed)
                        pr_info("Calibrating delay loop... ");
-               loops_per_jiffy = calibrate_delay_converge();
+               lpj = calibrate_delay_converge();
        }
        if (!printed)
                pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
-                       loops_per_jiffy/(500000/HZ),
-                       (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
+                       lpj/(500000/HZ),
+                       (lpj/(5000/HZ)) % 100, lpj);
 
+       loops_per_jiffy = lpj;
        printed = true;
 }


Patches currently in stable-queue which might be from 
rmk+ker...@arm.linux.org.uk are

queue-2.6.39/fix-cpu-spinlock-lockups-on-secondary-cpu-bringup.patch

_______________________________________________
stable mailing list
stable@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to