From 4b14afb224e2788cd77b4ac6c4f8e2b5029be428 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Sun, 13 Nov 2005 19:26:07 -0800 Subject: [PATCH] Add ALSA soft lockup fix to rtc from Takashi Iwai --- .../fix-soft-lockup-with-ALSA-rtc-timer.patch | 180 ++++++++++++++++++ queue/series | 1 + 2 files changed, 181 insertions(+) create mode 100644 queue/fix-soft-lockup-with-ALSA-rtc-timer.patch diff --git a/queue/fix-soft-lockup-with-ALSA-rtc-timer.patch b/queue/fix-soft-lockup-with-ALSA-rtc-timer.patch new file mode 100644 index 00000000000..43cb0c01a3d --- /dev/null +++ b/queue/fix-soft-lockup-with-ALSA-rtc-timer.patch @@ -0,0 +1,180 @@ +From stable-bounces@linux.kernel.org Fri Nov 11 10:47:39 2005 +Date: Fri, 11 Nov 2005 19:47:28 +0100 +From: Takashi Iwai +To: stable@kernel.org +Cc: +Subject: [PATCH] Fix soft lockup with ALSA rtc-timer + +Fixed the soft lockup of ALSA rtc-timer due to the wrong irq +handling in rtc_control(). The call of rtc_control() can be atomic. + +Signed-off-by: Takashi Iwai +Signed-off-by: Chris Wright +--- + drivers/char/rtc.c | 65 ++++++++++++++++++++++++++++++----------------------- + 1 files changed, 38 insertions(+), 27 deletions(-) + +Index: linux-2.6.14.y/drivers/char/rtc.c +=================================================================== +--- linux-2.6.14.y.orig/drivers/char/rtc.c ++++ linux-2.6.14.y/drivers/char/rtc.c +@@ -149,8 +149,22 @@ static void get_rtc_alm_time (struct rtc + #ifdef RTC_IRQ + static void rtc_dropped_irq(unsigned long data); + +-static void set_rtc_irq_bit(unsigned char bit); +-static void mask_rtc_irq_bit(unsigned char bit); ++static void set_rtc_irq_bit_locked(unsigned char bit); ++static void mask_rtc_irq_bit_locked(unsigned char bit); ++ ++static inline void set_rtc_irq_bit(unsigned char bit) ++{ ++ spin_lock_irq(&rtc_lock); ++ set_rtc_irq_bit_locked(bit); ++ spin_unlock_irq(&rtc_lock); ++} ++ ++static void mask_rtc_irq_bit(unsigned char bit) ++{ ++ spin_lock_irq(&rtc_lock); ++ mask_rtc_irq_bit_locked(bit); ++ spin_unlock_irq(&rtc_lock); ++} + #endif + + static int rtc_proc_open(struct inode *inode, struct file *file); +@@ -401,18 +415,19 @@ static int rtc_do_ioctl(unsigned int cmd + } + case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ + { +- mask_rtc_irq_bit(RTC_PIE); ++ unsigned long flags; /* can be called from isr via rtc_control() */ ++ spin_lock_irqsave (&rtc_lock, flags); ++ mask_rtc_irq_bit_locked(RTC_PIE); + if (rtc_status & RTC_TIMER_ON) { +- spin_lock_irq (&rtc_lock); + rtc_status &= ~RTC_TIMER_ON; + del_timer(&rtc_irq_timer); +- spin_unlock_irq (&rtc_lock); + } ++ spin_unlock_irqrestore (&rtc_lock, flags); + return 0; + } + case RTC_PIE_ON: /* Allow periodic ints */ + { +- ++ unsigned long flags; /* can be called from isr via rtc_control() */ + /* + * We don't really want Joe User enabling more + * than 64Hz of interrupts on a multi-user machine. +@@ -421,14 +436,14 @@ static int rtc_do_ioctl(unsigned int cmd + (!capable(CAP_SYS_RESOURCE))) + return -EACCES; + ++ spin_lock_irqsave (&rtc_lock, flags); + if (!(rtc_status & RTC_TIMER_ON)) { +- spin_lock_irq (&rtc_lock); + rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; + add_timer(&rtc_irq_timer); + rtc_status |= RTC_TIMER_ON; +- spin_unlock_irq (&rtc_lock); + } +- set_rtc_irq_bit(RTC_PIE); ++ set_rtc_irq_bit_locked(RTC_PIE); ++ spin_unlock_irqrestore (&rtc_lock, flags); + return 0; + } + case RTC_UIE_OFF: /* Mask ints from RTC updates. */ +@@ -609,6 +624,7 @@ static int rtc_do_ioctl(unsigned int cmd + { + int tmp = 0; + unsigned char val; ++ unsigned long flags; /* can be called from isr via rtc_control() */ + + /* + * The max we can do is 8192Hz. +@@ -631,9 +647,9 @@ static int rtc_do_ioctl(unsigned int cmd + if (arg != (1<