diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-06-22 11:55:50 +0100 |
---|---|---|
committer | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-06-23 21:41:20 -0400 |
commit | 54dab05c329c5fb6121d89fddf9b82e0fed35efb (patch) | |
tree | 1824252fbbf9a3e60056b5cb6a8fe385526ae287 /sound/isa/adlib.c | |
parent | d2a8333028558e69d16b4f740e8056528d78fe66 (diff) |
Fix CPU spinlock lockups on secondary CPU bringuplinux-linaro-2.6.39-2011.06-0
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.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: <stable@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.
init/calibrate.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'sound/isa/adlib.c')
0 files changed, 0 insertions, 0 deletions