Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-drm-fsl-dcu.git] / drivers / rtc / rtc-dev.c
index dcf5f86461f711cbeda9584f4a82c4aef6ac0b54..828b329e08e0ca62a23617863825a325ca3511d7 100644 (file)
@@ -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