Re: spin_lock error in arch/i386/kernel/time.c on APM resume

From: George Anzinger
Date: Sat Mar 12 2005 - 11:08:34 EST


J. Bruce Fields wrote:
On APM resume this morning on my Thinkpad X31, I got a "spin_lock is
already locked" error; see below. This doesn't happen on every resume,
though it's happened before. The kernel is 2.6.11 plus a bunch of
(hopefully unrelated...) NFS patches.

Any ideas?

Yesterday's night mare, todays bug :(

Looks like we need the irq on the read clock also. This is true both before and after the prior cmos_time changes.

Andrew,

The attached replaces the patch I sent yesterday.

For those wanting to fix the kernel with out those patches, all that is needed its the chunk that applies, i.e. the _irq on the get_cmos_time() spinlocks.

And more... That this occures implies we are attempting to update the cmos clock on resume seems wrong. One would presume that the time is wrong at this time and we are about to save that wrong time. Possibly the APM code should change time_status to STA_UNSYNC on the way into the sleep (or what ever it is called). Who should we ping with this?
~
Mar 12 07:07:31 puzzle kernel: PCI: Setting latency timer of device 0000:00:1f.5 to 64
Mar 12 07:07:31 puzzle kernel: arch/i386/kernel/time.c:179: spin_lock(arch/i386/kernel/time.c:c0603c28) already locked by arch/i386/kernel/time.c/309
Mar 12 07:07:31 puzzle kernel: arch/i386/kernel/time.c:316: spin_unlock(arch/i386/kernel/time.c:c0603c28) not locked
~
--
George Anzinger george@xxxxxxxxxx
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Source: MontaVista Software, Inc.
Type: Defect Fix
Disposition: Pending
Description:

I was not happy with the locking on this. Two changes:
1) Turn off irq while setting the clock.
2) Call the timer code only through the timer interface
(set a short timer to do it from the ntp call).

Signed-off-by: George Anzinger <george@xxxxxxxxxx>

time.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

Index: linux-2.6.12-rc/arch/i386/kernel/time.c
===================================================================
--- linux-2.6.12-rc.orig/arch/i386/kernel/time.c
+++ linux-2.6.12-rc/arch/i386/kernel/time.c
@@ -176,12 +176,12 @@ static int set_rtc_mmss(unsigned long no
int retval;

/* gets recalled with irq locally disabled */
- spin_lock(&rtc_lock);
+ spin_lock_irq(&rtc_lock);
if (efi_enabled)
retval = efi_set_rtc_mmss(nowtime);
else
retval = mach_set_rtc_mmss(nowtime);
- spin_unlock(&rtc_lock);
+ spin_unlock_irq(&rtc_lock);

return retval;
}
@@ -282,14 +282,14 @@ unsigned long get_cmos_time(void)
{
unsigned long retval;

- spin_lock(&rtc_lock);
+ spin_lock_irq(&rtc_lock);

if (efi_enabled)
retval = efi_get_time();
else
retval = mach_get_cmos_time();

- spin_unlock(&rtc_lock);
+ spin_unlock_irq(&rtc_lock);

return retval;
}
@@ -338,7 +338,7 @@ static void sync_cmos_clock(unsigned lon
}
void notify_arch_cmos_timer(void)
{
- sync_cmos_clock(0);
+ mod_timer(&sync_cmos_timer, jiffies + 1);
}
static long clock_cmos_diff, sleep_start;