diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-07-12 12:03:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-12 15:52:55 -0400 |
commit | 0f74964627e0ece4ac8da0e2cd01906ec322b4fe (patch) | |
tree | a01f8d194ad1d9b3f921826f37b09efaff3a8662 | |
parent | a29b0b74e73b66674d20a170e463fe9032f2272a (diff) |
[PATCH] lockdep: HPET/RTC fix
Joseph Fannin reported that hpet_rtc_interrupt() enables hardirqs
in irq context:
[ 25.628000] [<c014af4e>] trace_hardirqs_on+0xce/0x200
[ 25.628000] [<c036cf21>] _spin_unlock_irq+0x31/0x70
[ 25.628000] [<c0296584>] rtc_get_rtc_time+0x44/0x1a0
[ 25.628000] [<c01198bb>] hpet_rtc_interrupt+0x21b/0x280
[ 25.628000] [<c0161141>] handle_IRQ_event+0x31/0x70
[ 25.628000] [<c0162d37>] handle_edge_irq+0xe7/0x210
[ 25.628000] [<c0106192>] do_IRQ+0x92/0x120
[ 25.628000] [<c0104121>] common_interrupt+0x25/0x2c
the call of rtc_get_rtc_time() is highly suspect. At a minimum we
need the patch below to save/restore hardirq state.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Joseph Fannin <jfannin@gmail.com>
Cc: John Stultz <johnstul@us.ibm.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/char/rtc.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 6ccc364c08df..6e6a7c7a7eff 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -1245,7 +1245,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) | |||
1245 | 1245 | ||
1246 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) | 1246 | void rtc_get_rtc_time(struct rtc_time *rtc_tm) |
1247 | { | 1247 | { |
1248 | unsigned long uip_watchdog = jiffies; | 1248 | unsigned long uip_watchdog = jiffies, flags; |
1249 | unsigned char ctrl; | 1249 | unsigned char ctrl; |
1250 | #ifdef CONFIG_MACH_DECSTATION | 1250 | #ifdef CONFIG_MACH_DECSTATION |
1251 | unsigned int real_year; | 1251 | unsigned int real_year; |
@@ -1272,7 +1272,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) | |||
1272 | * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is | 1272 | * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is |
1273 | * only updated by the RTC when initially set to a non-zero value. | 1273 | * only updated by the RTC when initially set to a non-zero value. |
1274 | */ | 1274 | */ |
1275 | spin_lock_irq(&rtc_lock); | 1275 | spin_lock_irqsave(&rtc_lock, flags); |
1276 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | 1276 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); |
1277 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | 1277 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); |
1278 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | 1278 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); |
@@ -1286,7 +1286,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) | |||
1286 | real_year = CMOS_READ(RTC_DEC_YEAR); | 1286 | real_year = CMOS_READ(RTC_DEC_YEAR); |
1287 | #endif | 1287 | #endif |
1288 | ctrl = CMOS_READ(RTC_CONTROL); | 1288 | ctrl = CMOS_READ(RTC_CONTROL); |
1289 | spin_unlock_irq(&rtc_lock); | 1289 | spin_unlock_irqrestore(&rtc_lock, flags); |
1290 | 1290 | ||
1291 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 1291 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
1292 | { | 1292 | { |