#include <linux/module.h>
#include <linux/rtc.h>
-#include <linux/smp_lock.h>
#include "rtc-core.h"
static dev_t rtc_devt;
struct rtc_device, char_dev);
const struct rtc_class_ops *ops = rtc->ops;
- lock_kernel();
- if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) {
- err = -EBUSY;
- goto out;
- }
+ if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
+ return -EBUSY;
file->private_data = rtc;
rtc->irq_data = 0;
spin_unlock_irq(&rtc->irq_lock);
- goto out;
+ return 0;
}
/* something has gone wrong */
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
-out:
- unlock_kernel();
return err;
}
spin_unlock_irqrestore(&rtc->irq_lock, flags);
}
-static void clear_uie(struct rtc_device *rtc)
+static int clear_uie(struct rtc_device *rtc)
{
spin_lock_irq(&rtc->irq_lock);
- if (rtc->irq_active) {
+ if (rtc->uie_irq_active) {
rtc->stop_uie_polling = 1;
if (rtc->uie_timer_active) {
spin_unlock_irq(&rtc->irq_lock);
flush_scheduled_work();
spin_lock_irq(&rtc->irq_lock);
}
- rtc->irq_active = 0;
+ rtc->uie_irq_active = 0;
}
spin_unlock_irq(&rtc->irq_lock);
+ return 0;
}
static int set_uie(struct rtc_device *rtc)
if (err)
return err;
spin_lock_irq(&rtc->irq_lock);
- if (!rtc->irq_active) {
- rtc->irq_active = 1;
+ if (!rtc->uie_irq_active) {
+ rtc->uie_irq_active = 1;
rtc->stop_uie_polling = 0;
rtc->oldsecs = tm.tm_sec;
rtc->uie_task_active = 1;
spin_unlock_irq(&rtc->irq_lock);
return 0;
}
+
+int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled)
+{
+ if (enabled)
+ return set_uie(rtc);
+ else
+ return clear_uie(rtc);
+}
+EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul);
+
#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
static ssize_t
err = rtc_irq_set_state(rtc, NULL, 0);
break;
+ case RTC_AIE_ON:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_alarm_irq_enable(rtc, 1);
+
+ case RTC_AIE_OFF:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_alarm_irq_enable(rtc, 0);
+
+ case RTC_UIE_ON:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_update_irq_enable(rtc, 1);
+
+ case RTC_UIE_OFF:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_update_irq_enable(rtc, 0);
+
case RTC_IRQP_SET:
err = rtc_irq_set_freq(rtc, NULL, arg);
break;
err = -EFAULT;
return err;
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
- case RTC_UIE_OFF:
- clear_uie(rtc);
- break;
-
- case RTC_UIE_ON:
- err = set_uie(rtc);
-#endif
default:
err = -ENOTTY;
break;
return err;
}
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+ struct rtc_device *rtc = file->private_data;
+ return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
static int rtc_dev_release(struct inode *inode, struct file *file)
{
struct rtc_device *rtc = file->private_data;
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
- clear_uie(rtc);
-#endif
+ /* We shut down the repeating IRQs that userspace enabled,
+ * since nothing is listening to them.
+ * - Update (UIE) ... currently only managed through ioctls
+ * - Periodic (PIE) ... also used through rtc_*() interface calls
+ *
+ * Leave the alarm alone; it may be set to trigger a system wakeup
+ * later, or be used by kernel code, and is a one-shot event anyway.
+ */
+
+ /* Keep ioctl until all drivers are converted */
+ rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
+ rtc_update_irq_enable(rtc, 0);
rtc_irq_set_state(rtc, NULL, 0);
if (rtc->ops->release)
return 0;
}
-static int rtc_dev_fasync(int fd, struct file *file, int on)
-{
- struct rtc_device *rtc = file->private_data;
- return fasync_helper(fd, file, on, &rtc->async_queue);
-}
-
static const struct file_operations rtc_dev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,