aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/interface.c
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-11-25 14:09:28 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-11-25 16:28:33 -0500
commitd728b1e69fd5829ec2ab2434381e5a268d4f684a (patch)
treee11b3dea35247074628f04f5441e4a458bdbd86b /drivers/rtc/interface.c
parent2601a46474db2dcbc08ee690e56f08a10abe65cb (diff)
[PATCH] rtc class locking bugfixes
I got a lockdep warning when running "rtctest" so I though it'd be good to see what was up. - The warning was for rtc->irq_task_lock, gotten from rtc_update_irq() by irq handlerss ... but in a handful of other cases, grabbed without blocking IRQs. - Some callers to rtc_update_irq() were not ensuring IRQs were blocked, yet the routine expects that; make sure all callers block IRQs. It would appear that RTC API tests haven't been part of anyone's kernel regression test suite recently, at least not with lockdep running. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r--drivers/rtc/interface.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 4783ec68fb3c..6f11f6dfdd9d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
145} 145}
146EXPORT_SYMBOL_GPL(rtc_set_alarm); 146EXPORT_SYMBOL_GPL(rtc_set_alarm);
147 147
148/**
149 * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
150 * @class_dev: the rtc's class device
151 * @num: how many irqs are being reported (usually one)
152 * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
153 * Context: in_interrupt(), irqs blocked
154 */
148void rtc_update_irq(struct class_device *class_dev, 155void rtc_update_irq(struct class_device *class_dev,
149 unsigned long num, unsigned long events) 156 unsigned long num, unsigned long events)
150{ 157{
@@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
201 if (task == NULL || task->func == NULL) 208 if (task == NULL || task->func == NULL)
202 return -EINVAL; 209 return -EINVAL;
203 210
204 spin_lock(&rtc->irq_task_lock); 211 spin_lock_irq(&rtc->irq_task_lock);
205 if (rtc->irq_task == NULL) { 212 if (rtc->irq_task == NULL) {
206 rtc->irq_task = task; 213 rtc->irq_task = task;
207 retval = 0; 214 retval = 0;
208 } 215 }
209 spin_unlock(&rtc->irq_task_lock); 216 spin_unlock_irq(&rtc->irq_task_lock);
210 217
211 return retval; 218 return retval;
212} 219}
@@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
216{ 223{
217 struct rtc_device *rtc = to_rtc_device(class_dev); 224 struct rtc_device *rtc = to_rtc_device(class_dev);
218 225
219 spin_lock(&rtc->irq_task_lock); 226 spin_lock_irq(&rtc->irq_task_lock);
220 if (rtc->irq_task == task) 227 if (rtc->irq_task == task)
221 rtc->irq_task = NULL; 228 rtc->irq_task = NULL;
222 spin_unlock(&rtc->irq_task_lock); 229 spin_unlock_irq(&rtc->irq_task_lock);
223} 230}
224EXPORT_SYMBOL_GPL(rtc_irq_unregister); 231EXPORT_SYMBOL_GPL(rtc_irq_unregister);
225 232