/[linux-patches]/genpatches-2.6/tags/2.6.14-5/1021_3_alsa-rtc-soft-lockup.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.14-5/1021_3_alsa-rtc-soft-lockup.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 226 - (show annotations) (download)
Fri Dec 2 12:14:55 2005 UTC (12 years, 2 months ago) by dsd
File size: 5152 byte(s)
2.6.14-5 release
1 From stable-bounces@linux.kernel.org Fri Nov 11 10:47:39 2005
2 Date: Fri, 11 Nov 2005 19:47:28 +0100
3 From: Takashi Iwai <tiwai@suse.de>
4 To: stable@kernel.org
5 Cc:
6 Subject: [PATCH] Fix soft lockup with ALSA rtc-timer
7
8 Fixed the soft lockup of ALSA rtc-timer due to the wrong irq
9 handling in rtc_control(). The call of rtc_control() can be atomic.
10
11 Signed-off-by: Takashi Iwai <tiwai@suse.de>
12 Signed-off-by: Chris Wright <chrisw@osdl.org>
13 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
14 ---
15 drivers/char/rtc.c | 65 ++++++++++++++++++++++++++++++-----------------------
16 1 file changed, 38 insertions(+), 27 deletions(-)
17
18 --- linux-2.6.14.2.orig/drivers/char/rtc.c
19 +++ linux-2.6.14.2/drivers/char/rtc.c
20 @@ -149,8 +149,22 @@ static void get_rtc_alm_time (struct rtc
21 #ifdef RTC_IRQ
22 static void rtc_dropped_irq(unsigned long data);
23
24 -static void set_rtc_irq_bit(unsigned char bit);
25 -static void mask_rtc_irq_bit(unsigned char bit);
26 +static void set_rtc_irq_bit_locked(unsigned char bit);
27 +static void mask_rtc_irq_bit_locked(unsigned char bit);
28 +
29 +static inline void set_rtc_irq_bit(unsigned char bit)
30 +{
31 + spin_lock_irq(&rtc_lock);
32 + set_rtc_irq_bit_locked(bit);
33 + spin_unlock_irq(&rtc_lock);
34 +}
35 +
36 +static void mask_rtc_irq_bit(unsigned char bit)
37 +{
38 + spin_lock_irq(&rtc_lock);
39 + mask_rtc_irq_bit_locked(bit);
40 + spin_unlock_irq(&rtc_lock);
41 +}
42 #endif
43
44 static int rtc_proc_open(struct inode *inode, struct file *file);
45 @@ -401,18 +415,19 @@ static int rtc_do_ioctl(unsigned int cmd
46 }
47 case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
48 {
49 - mask_rtc_irq_bit(RTC_PIE);
50 + unsigned long flags; /* can be called from isr via rtc_control() */
51 + spin_lock_irqsave (&rtc_lock, flags);
52 + mask_rtc_irq_bit_locked(RTC_PIE);
53 if (rtc_status & RTC_TIMER_ON) {
54 - spin_lock_irq (&rtc_lock);
55 rtc_status &= ~RTC_TIMER_ON;
56 del_timer(&rtc_irq_timer);
57 - spin_unlock_irq (&rtc_lock);
58 }
59 + spin_unlock_irqrestore (&rtc_lock, flags);
60 return 0;
61 }
62 case RTC_PIE_ON: /* Allow periodic ints */
63 {
64 -
65 + unsigned long flags; /* can be called from isr via rtc_control() */
66 /*
67 * We don't really want Joe User enabling more
68 * than 64Hz of interrupts on a multi-user machine.
69 @@ -421,14 +436,14 @@ static int rtc_do_ioctl(unsigned int cmd
70 (!capable(CAP_SYS_RESOURCE)))
71 return -EACCES;
72
73 + spin_lock_irqsave (&rtc_lock, flags);
74 if (!(rtc_status & RTC_TIMER_ON)) {
75 - spin_lock_irq (&rtc_lock);
76 rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
77 add_timer(&rtc_irq_timer);
78 rtc_status |= RTC_TIMER_ON;
79 - spin_unlock_irq (&rtc_lock);
80 }
81 - set_rtc_irq_bit(RTC_PIE);
82 + set_rtc_irq_bit_locked(RTC_PIE);
83 + spin_unlock_irqrestore (&rtc_lock, flags);
84 return 0;
85 }
86 case RTC_UIE_OFF: /* Mask ints from RTC updates. */
87 @@ -609,6 +624,7 @@ static int rtc_do_ioctl(unsigned int cmd
88 {
89 int tmp = 0;
90 unsigned char val;
91 + unsigned long flags; /* can be called from isr via rtc_control() */
92
93 /*
94 * The max we can do is 8192Hz.
95 @@ -631,9 +647,9 @@ static int rtc_do_ioctl(unsigned int cmd
96 if (arg != (1<<tmp))
97 return -EINVAL;
98
99 - spin_lock_irq(&rtc_lock);
100 + spin_lock_irqsave(&rtc_lock, flags);
101 if (hpet_set_periodic_freq(arg)) {
102 - spin_unlock_irq(&rtc_lock);
103 + spin_unlock_irqrestore(&rtc_lock, flags);
104 return 0;
105 }
106 rtc_freq = arg;
107 @@ -641,7 +657,7 @@ static int rtc_do_ioctl(unsigned int cmd
108 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
109 val |= (16 - tmp);
110 CMOS_WRITE(val, RTC_FREQ_SELECT);
111 - spin_unlock_irq(&rtc_lock);
112 + spin_unlock_irqrestore(&rtc_lock, flags);
113 return 0;
114 }
115 #endif
116 @@ -844,12 +860,15 @@ int rtc_control(rtc_task_t *task, unsign
117 #ifndef RTC_IRQ
118 return -EIO;
119 #else
120 - spin_lock_irq(&rtc_task_lock);
121 + unsigned long flags;
122 + if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET)
123 + return -EINVAL;
124 + spin_lock_irqsave(&rtc_task_lock, flags);
125 if (rtc_callback != task) {
126 - spin_unlock_irq(&rtc_task_lock);
127 + spin_unlock_irqrestore(&rtc_task_lock, flags);
128 return -ENXIO;
129 }
130 - spin_unlock_irq(&rtc_task_lock);
131 + spin_unlock_irqrestore(&rtc_task_lock, flags);
132 return rtc_do_ioctl(cmd, arg, 1);
133 #endif
134 }
135 @@ -1306,40 +1325,32 @@ static void get_rtc_alm_time(struct rtc_
136 * meddles with the interrupt enable/disable bits.
137 */
138
139 -static void mask_rtc_irq_bit(unsigned char bit)
140 +static void mask_rtc_irq_bit_locked(unsigned char bit)
141 {
142 unsigned char val;
143
144 - spin_lock_irq(&rtc_lock);
145 - if (hpet_mask_rtc_irq_bit(bit)) {
146 - spin_unlock_irq(&rtc_lock);
147 + if (hpet_mask_rtc_irq_bit(bit))
148 return;
149 - }
150 val = CMOS_READ(RTC_CONTROL);
151 val &= ~bit;
152 CMOS_WRITE(val, RTC_CONTROL);
153 CMOS_READ(RTC_INTR_FLAGS);
154
155 rtc_irq_data = 0;
156 - spin_unlock_irq(&rtc_lock);
157 }
158
159 -static void set_rtc_irq_bit(unsigned char bit)
160 +static void set_rtc_irq_bit_locked(unsigned char bit)
161 {
162 unsigned char val;
163
164 - spin_lock_irq(&rtc_lock);
165 - if (hpet_set_rtc_irq_bit(bit)) {
166 - spin_unlock_irq(&rtc_lock);
167 + if (hpet_set_rtc_irq_bit(bit))
168 return;
169 - }
170 val = CMOS_READ(RTC_CONTROL);
171 val |= bit;
172 CMOS_WRITE(val, RTC_CONTROL);
173 CMOS_READ(RTC_INTR_FLAGS);
174
175 rtc_irq_data = 0;
176 - spin_unlock_irq(&rtc_lock);
177 }
178 #endif
179

  ViewVC Help
Powered by ViewVC 1.1.20