summary refs log tree commit diff
path: root/drivers/rtc/rtc-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-dev.c')
-rw-r--r--drivers/rtc/rtc-dev.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index dcf5f86461f7..828b329e08e0 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -62,7 +62,9 @@ static void rtc_uie_task(struct work_struct *work)
 	int err;
 
 	err = rtc_read_time(&rtc->class_dev, &tm);
-	spin_lock_irq(&rtc->irq_lock);
+
+	local_irq_disable();
+	spin_lock(&rtc->irq_lock);
 	if (rtc->stop_uie_polling || err) {
 		rtc->uie_task_active = 0;
 	} else if (rtc->oldsecs != tm.tm_sec) {
@@ -75,11 +77,11 @@ static void rtc_uie_task(struct work_struct *work)
 	} else if (schedule_work(&rtc->uie_task) == 0) {
 		rtc->uie_task_active = 0;
 	}
-	spin_unlock_irq(&rtc->irq_lock);
+	spin_unlock(&rtc->irq_lock);
 	if (num)
 		rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+	local_irq_enable();
 }
-
 static void rtc_uie_timer(unsigned long data)
 {
 	struct rtc_device *rtc = (struct rtc_device *)data;
@@ -215,7 +217,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 	struct rtc_wkalrm alarm;
 	void __user *uarg = (void __user *) arg;
 
-	/* check that the calles has appropriate permissions
+	/* check that the calling task has appropriate permissions
 	 * for certain ioctls. doing this check here is useful
 	 * to avoid duplicate code in each driver.
 	 */
@@ -239,10 +241,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
 	/* avoid conflicting IRQ users */
 	if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
-		spin_lock(&rtc->irq_task_lock);
+		spin_lock_irq(&rtc->irq_task_lock);
 		if (rtc->irq_task)
 			err = -EBUSY;
-		spin_unlock(&rtc->irq_task_lock);
+		spin_unlock_irq(&rtc->irq_task_lock);
 
 		if (err < 0)
 			return err;
@@ -300,6 +302,17 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 
 		err = rtc_set_time(class_dev, &tm);
 		break;
+
+	case RTC_IRQP_READ:
+		if (ops->irq_set_freq)
+			err = put_user(rtc->irq_freq, (unsigned long *) arg);
+		break;
+
+	case RTC_IRQP_SET:
+		if (ops->irq_set_freq)
+			err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg);
+		break;
+
 #if 0
 	case RTC_EPOCH_SET:
 #ifndef rtc_epoch