aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common/rtctime.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common/rtctime.c')
-rw-r--r--arch/arm/common/rtctime.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 72b03f2..e851d86 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -17,7 +17,9 @@
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
+#include <linux/capability.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/rtc.h>
#include <asm/semaphore.h>
@@ -34,7 +36,7 @@ static unsigned long rtc_irq_data;
/*
* rtc_sem protects rtc_inuse and rtc_ops
*/
-static DECLARE_MUTEX(rtc_sem);
+static DEFINE_MUTEX(rtc_mutex);
static unsigned long rtc_inuse;
static struct rtc_ops *rtc_ops;
@@ -126,19 +128,27 @@ EXPORT_SYMBOL(rtc_tm_to_time);
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
- *
- * FIXME: for now, we just copy the alarm time because we're lazy (and
- * is therefore buggy - setting a 10am alarm at 8pm will not result in
- * the alarm triggering.)
*/
void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
{
+ unsigned long next_time;
+ unsigned long now_time;
+
next->tm_year = now->tm_year;
next->tm_mon = now->tm_mon;
next->tm_mday = now->tm_mday;
next->tm_hour = alrm->tm_hour;
next->tm_min = alrm->tm_min;
next->tm_sec = alrm->tm_sec;
+
+ rtc_tm_to_time(now, &now_time);
+ rtc_tm_to_time(next, &next_time);
+
+ if (next_time < now_time) {
+ /* Advance one day */
+ next_time += 60 * 60 * 24;
+ rtc_time_to_tm(next_time, next);
+ }
}
static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
@@ -355,7 +365,7 @@ static int rtc_open(struct inode *inode, struct file *file)
{
int ret;
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc_inuse) {
ret = -EBUSY;
@@ -373,7 +383,7 @@ static int rtc_open(struct inode *inode, struct file *file)
rtc_inuse = 1;
}
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
return ret;
}
@@ -479,7 +489,7 @@ int register_rtc(struct rtc_ops *ops)
{
int ret = -EBUSY;
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc_ops == NULL) {
rtc_ops = ops;
@@ -488,7 +498,7 @@ int register_rtc(struct rtc_ops *ops)
create_proc_read_entry("driver/rtc", 0, NULL,
rtc_read_proc, ops);
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
return ret;
}
@@ -496,12 +506,12 @@ EXPORT_SYMBOL(register_rtc);
void unregister_rtc(struct rtc_ops *rtc)
{
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc == rtc_ops) {
remove_proc_entry("driver/rtc", NULL);
misc_deregister(&rtc_miscdev);
rtc_ops = NULL;
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
}
EXPORT_SYMBOL(unregister_rtc);