]> git.openpandora.org Git - pandora-kernel.git/commitdiff
[PATCH] rtc class locking bugfixes
authorDavid Brownell <david-b@pacbell.net>
Sat, 25 Nov 2006 19:09:28 +0000 (11:09 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Sat, 25 Nov 2006 21:28:33 +0000 (13:28 -0800)
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>
drivers/rtc/interface.c
drivers/rtc/rtc-at91.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-test.c

index 4783ec68fb3c92127ed631963baf8b8982282b25..6f11f6dfdd9dccc699b5a1a958132d55dec5daa6 100644 (file)
@@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
 }
 EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
+/**
+ * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
+ * @class_dev: the rtc's class device
+ * @num: how many irqs are being reported (usually one)
+ * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
+ * Context: in_interrupt(), irqs blocked
+ */
 void rtc_update_irq(struct class_device *class_dev,
                unsigned long num, unsigned long events)
 {
@@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
        if (task == NULL || task->func == NULL)
                return -EINVAL;
 
-       spin_lock(&rtc->irq_task_lock);
+       spin_lock_irq(&rtc->irq_task_lock);
        if (rtc->irq_task == NULL) {
                rtc->irq_task = task;
                retval = 0;
        }
-       spin_unlock(&rtc->irq_task_lock);
+       spin_unlock_irq(&rtc->irq_task_lock);
 
        return retval;
 }
@@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
 {
        struct rtc_device *rtc = to_rtc_device(class_dev);
 
-       spin_lock(&rtc->irq_task_lock);
+       spin_lock_irq(&rtc->irq_task_lock);
        if (rtc->irq_task == task)
                rtc->irq_task = NULL;
-       spin_unlock(&rtc->irq_task_lock);
+       spin_unlock_irq(&rtc->irq_task_lock);
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
Simple merge
Simple merge
Simple merge
Simple merge