From 97144c67566241db46633727f2860e6428373fe4 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 16 Oct 2007 01:28:16 -0700 Subject: [PATCH] rtc_irq_set_freq() requires power-of-two and associated kerneldoc RTC periodic IRQs are only defined to work for 2^N Hz values. This patch moves that validity check into the infrastructure, so drivers don't need to check it; and adds kerneldoc for the two interface functions related to periodic IRQs. (One of which was quite mysterious until its first use was recently checked in!) Signed-off-by: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 24 ++++++++++++++++++++++++ drivers/rtc/rtc-cmos.c | 8 +++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index a43afa54f0..8adcab3c36 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -12,6 +12,7 @@ */ #include +#include int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) { @@ -236,6 +237,16 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) } EXPORT_SYMBOL_GPL(rtc_irq_unregister); +/** + * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs + * @rtc: the rtc device + * @task: currently registered with rtc_irq_register() + * @enabled: true to enable periodic IRQs + * Context: any + * + * Note that rtc_irq_set_freq() should previously have been used to + * specify the desired frequency of periodic IRQ task->func() callbacks. + */ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) { int err = 0; @@ -258,6 +269,16 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled } EXPORT_SYMBOL_GPL(rtc_irq_set_state); +/** + * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ + * @rtc: the rtc device + * @task: currently registered with rtc_irq_register() + * @freq: positive frequency with which task->func() will be called + * Context: any + * + * Note that rtc_irq_set_state() is used to enable or disable the + * periodic IRQs. + */ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) { int err = 0; @@ -266,6 +287,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) if (rtc->ops->irq_set_freq == NULL) return -ENXIO; + if (!is_power_of_2(freq)) + return -EINVAL; + spin_lock_irqsave(&rtc->irq_task_lock, flags); if (rtc->irq_task != NULL && task == NULL) err = -EBUSY; diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5d760bb6c2..6d0c35397b 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -246,11 +246,9 @@ static int cmos_irq_set_freq(struct device *dev, int freq) /* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */ f = ffs(freq); - if (f != 0) { - if (f-- > 16 || freq != (1 << f)) - return -EINVAL; - f = 16 - f; - } + if (f-- > 16) + return -EINVAL; + f = 16 - f; spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); -- 2.39.5