aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 13:32:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 13:32:09 -0400
commit161f7a7161191ab9c2e97f787829ef8dd2b95771 (patch)
tree9776d3f963c7f0d247b7fb324eab4811a1302f67 /drivers/rtc
parent2ba68940c893c8f0bfc8573c041254251bb6aeab (diff)
parenta078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 (diff)
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer changes for v3.4 from Ingo Molnar * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (32 commits) ntp: Fix integer overflow when setting time math: Introduce div64_long cs5535-clockevt: Allow the MFGPT IRQ to be shared cs5535-clockevt: Don't ignore MFGPT on SMP-capable kernels x86/time: Eliminate unused irq0_irqs counter clocksource: scx200_hrt: Fix the build x86/tsc: Reduce the TSC sync check time for core-siblings timer: Fix bad idle check on irq entry nohz: Remove ts->Einidle checks before restarting the tick nohz: Remove update_ts_time_stat from tick_nohz_start_idle clockevents: Leave the broadcast device in shutdown mode when not needed clocksource: Load the ACPI PM clocksource asynchronously clocksource: scx200_hrt: Convert scx200 to use clocksource_register_hz clocksource: Get rid of clocksource_calc_mult_shift() clocksource: dbx500: convert to clocksource_register_hz() clocksource: scx200_hrt: use pr_<level> instead of printk time: Move common updates to a function time: Reorder so the hot data is together time: Remove most of xtime_lock usage in timekeeping.c ntp: Add ntp_lock to replace xtime_locking ...
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/interface.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 8a1c031391d6..dc87eda65814 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -73,6 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
73 err = -EINVAL; 73 err = -EINVAL;
74 74
75 mutex_unlock(&rtc->ops_lock); 75 mutex_unlock(&rtc->ops_lock);
76 /* A timer might have just expired */
77 schedule_work(&rtc->irqwork);
76 return err; 78 return err;
77} 79}
78EXPORT_SYMBOL_GPL(rtc_set_time); 80EXPORT_SYMBOL_GPL(rtc_set_time);
@@ -112,6 +114,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
112 err = -EINVAL; 114 err = -EINVAL;
113 115
114 mutex_unlock(&rtc->ops_lock); 116 mutex_unlock(&rtc->ops_lock);
117 /* A timer might have just expired */
118 schedule_work(&rtc->irqwork);
115 119
116 return err; 120 return err;
117} 121}
@@ -380,18 +384,27 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm);
380int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) 384int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
381{ 385{
382 int err; 386 int err;
387 struct rtc_time now;
383 388
384 err = rtc_valid_tm(&alarm->time); 389 err = rtc_valid_tm(&alarm->time);
385 if (err != 0) 390 if (err != 0)
386 return err; 391 return err;
387 392
393 err = rtc_read_time(rtc, &now);
394 if (err)
395 return err;
396
388 err = mutex_lock_interruptible(&rtc->ops_lock); 397 err = mutex_lock_interruptible(&rtc->ops_lock);
389 if (err) 398 if (err)
390 return err; 399 return err;
391 400
392 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); 401 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
393 rtc->aie_timer.period = ktime_set(0, 0); 402 rtc->aie_timer.period = ktime_set(0, 0);
394 if (alarm->enabled) { 403
404 /* Alarm has to be enabled & in the futrure for us to enqueue it */
405 if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
406 rtc->aie_timer.node.expires.tv64)) {
407
395 rtc->aie_timer.enabled = 1; 408 rtc->aie_timer.enabled = 1;
396 timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); 409 timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
397 } 410 }
@@ -763,6 +776,14 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
763 return 0; 776 return 0;
764} 777}
765 778
779static void rtc_alarm_disable(struct rtc_device *rtc)
780{
781 if (!rtc->ops || !rtc->ops->alarm_irq_enable)
782 return;
783
784 rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
785}
786
766/** 787/**
767 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue 788 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
768 * @rtc rtc device 789 * @rtc rtc device
@@ -784,8 +805,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
784 struct rtc_wkalrm alarm; 805 struct rtc_wkalrm alarm;
785 int err; 806 int err;
786 next = timerqueue_getnext(&rtc->timerqueue); 807 next = timerqueue_getnext(&rtc->timerqueue);
787 if (!next) 808 if (!next) {
809 rtc_alarm_disable(rtc);
788 return; 810 return;
811 }
789 alarm.time = rtc_ktime_to_tm(next->expires); 812 alarm.time = rtc_ktime_to_tm(next->expires);
790 alarm.enabled = 1; 813 alarm.enabled = 1;
791 err = __rtc_set_alarm(rtc, &alarm); 814 err = __rtc_set_alarm(rtc, &alarm);
@@ -847,7 +870,8 @@ again:
847 err = __rtc_set_alarm(rtc, &alarm); 870 err = __rtc_set_alarm(rtc, &alarm);
848 if (err == -ETIME) 871 if (err == -ETIME)
849 goto again; 872 goto again;
850 } 873 } else
874 rtc_alarm_disable(rtc);
851 875
852 mutex_unlock(&rtc->ops_lock); 876 mutex_unlock(&rtc->ops_lock);
853} 877}