From 2601a46474db2dcbc08ee690e56f08a10abe65cb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 25 Nov 2006 11:09:27 -0800 Subject: [PATCH] rtc framework handles periodic irqs The RTC framework has an irq_set_freq() method that should be used to manage the periodic IRQ frequency, but the current ioctl logic doesn't know how to do that. This patch teaches it how. This means that drivers implementing irq_set_freq() will automatically support RTC_IRQP_{READ,SET} ioctls; that logic doesn't need duplication within the driver. [akpm@osdl.org: export rtc_irq_set_freq] Signed-off-by: David Brownell Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/rtc/interface.c') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 579cd667b16f..4783ec68fb3c 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -265,3 +265,4 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int } return err; } +EXPORT_SYMBOL_GPL(rtc_irq_set_freq); -- cgit v1.2.2 From d728b1e69fd5829ec2ab2434381e5a268d4f684a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 25 Nov 2006 11:09:28 -0800 Subject: [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 Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/rtc/interface.c') 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) } 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); -- cgit v1.2.2