aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-24 14:25:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-24 14:25:55 -0500
commitce84d539ce47484ff3cbc9c67b3eb69ae88954f9 (patch)
treecdba43e845e23a6793ca47857a16fae6032becfb
parentbc094757f4f3d7b8211a8a1ed7605ffd7c728f75 (diff)
parentb5cc8ca1c9c3a37eaddf709b2fd3e1699aee41ba (diff)
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: RTC: Remove Kconfig symbol for UIE emulation RTC: Properly handle rtc_read_alarm error propagation and fix bug RTC: Propagate error handling via rtc_timer_enqueue properly acpi_pm: Clear pmtmr_ioport if acpi_pm initialization fails rtc: Cleanup removed UIE emulation declaration hrtimers: Notify hrtimer users of switches to NOHZ mode
-rw-r--r--drivers/clocksource/acpi_pm.c6
-rw-r--r--drivers/rtc/Kconfig12
-rw-r--r--drivers/rtc/interface.c61
-rw-r--r--include/linux/rtc.h4
-rw-r--r--kernel/time/tick-sched.c7
5 files changed, 46 insertions, 44 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index cfb0f527841..effe7974aa9 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -202,17 +202,21 @@ static int __init init_acpi_pm_clocksource(void)
202 printk(KERN_INFO "PM-Timer had inconsistent results:" 202 printk(KERN_INFO "PM-Timer had inconsistent results:"
203 " 0x%#llx, 0x%#llx - aborting.\n", 203 " 0x%#llx, 0x%#llx - aborting.\n",
204 value1, value2); 204 value1, value2);
205 pmtmr_ioport = 0;
205 return -EINVAL; 206 return -EINVAL;
206 } 207 }
207 if (i == ACPI_PM_READ_CHECKS) { 208 if (i == ACPI_PM_READ_CHECKS) {
208 printk(KERN_INFO "PM-Timer failed consistency check " 209 printk(KERN_INFO "PM-Timer failed consistency check "
209 " (0x%#llx) - aborting.\n", value1); 210 " (0x%#llx) - aborting.\n", value1);
211 pmtmr_ioport = 0;
210 return -ENODEV; 212 return -ENODEV;
211 } 213 }
212 } 214 }
213 215
214 if (verify_pmtmr_rate() != 0) 216 if (verify_pmtmr_rate() != 0){
217 pmtmr_ioport = 0;
215 return -ENODEV; 218 return -ENODEV;
219 }
216 220
217 return clocksource_register_hz(&clocksource_acpi_pm, 221 return clocksource_register_hz(&clocksource_acpi_pm,
218 PMTMR_TICKS_PER_SEC); 222 PMTMR_TICKS_PER_SEC);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4941cade319..cdd97192dc6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -97,18 +97,6 @@ config RTC_INTF_DEV
97 97
98 If unsure, say Y. 98 If unsure, say Y.
99 99
100config RTC_INTF_DEV_UIE_EMUL
101 bool "RTC UIE emulation on dev interface"
102 depends on RTC_INTF_DEV
103 help
104 Provides an emulation for RTC_UIE if the underlying rtc chip
105 driver does not expose RTC_UIE ioctls. Those requests generate
106 once-per-second update interrupts, used for synchronization.
107
108 The emulation code will read the time from the hardware
109 clock several times per second, please enable this option
110 only if you know that you really need it.
111
112config RTC_DRV_TEST 100config RTC_DRV_TEST
113 tristate "Test driver/device" 101 tristate "Test driver/device"
114 help 102 help
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 90384b9f6b2..925006d3310 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -16,6 +16,9 @@
16#include <linux/log2.h> 16#include <linux/log2.h>
17#include <linux/workqueue.h> 17#include <linux/workqueue.h>
18 18
19static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
20static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
21
19static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) 22static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
20{ 23{
21 int err; 24 int err;
@@ -120,12 +123,18 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
120 err = mutex_lock_interruptible(&rtc->ops_lock); 123 err = mutex_lock_interruptible(&rtc->ops_lock);
121 if (err) 124 if (err)
122 return err; 125 return err;
123 alarm->enabled = rtc->aie_timer.enabled; 126 if (rtc->ops == NULL)
124 if (alarm->enabled) 127 err = -ENODEV;
128 else if (!rtc->ops->read_alarm)
129 err = -EINVAL;
130 else {
131 memset(alarm, 0, sizeof(struct rtc_wkalrm));
132 alarm->enabled = rtc->aie_timer.enabled;
125 alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); 133 alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires);
134 }
126 mutex_unlock(&rtc->ops_lock); 135 mutex_unlock(&rtc->ops_lock);
127 136
128 return 0; 137 return err;
129} 138}
130EXPORT_SYMBOL_GPL(rtc_read_alarm); 139EXPORT_SYMBOL_GPL(rtc_read_alarm);
131 140
@@ -175,16 +184,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
175 return err; 184 return err;
176 if (rtc->aie_timer.enabled) { 185 if (rtc->aie_timer.enabled) {
177 rtc_timer_remove(rtc, &rtc->aie_timer); 186 rtc_timer_remove(rtc, &rtc->aie_timer);
178 rtc->aie_timer.enabled = 0;
179 } 187 }
180 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); 188 rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
181 rtc->aie_timer.period = ktime_set(0, 0); 189 rtc->aie_timer.period = ktime_set(0, 0);
182 if (alarm->enabled) { 190 if (alarm->enabled) {
183 rtc->aie_timer.enabled = 1; 191 err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
184 rtc_timer_enqueue(rtc, &rtc->aie_timer);
185 } 192 }
186 mutex_unlock(&rtc->ops_lock); 193 mutex_unlock(&rtc->ops_lock);
187 return 0; 194 return err;
188} 195}
189EXPORT_SYMBOL_GPL(rtc_set_alarm); 196EXPORT_SYMBOL_GPL(rtc_set_alarm);
190 197
@@ -195,15 +202,15 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
195 return err; 202 return err;
196 203
197 if (rtc->aie_timer.enabled != enabled) { 204 if (rtc->aie_timer.enabled != enabled) {
198 if (enabled) { 205 if (enabled)
199 rtc->aie_timer.enabled = 1; 206 err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
200 rtc_timer_enqueue(rtc, &rtc->aie_timer); 207 else
201 } else {
202 rtc_timer_remove(rtc, &rtc->aie_timer); 208 rtc_timer_remove(rtc, &rtc->aie_timer);
203 rtc->aie_timer.enabled = 0;
204 }
205 } 209 }
206 210
211 if (err)
212 return err;
213
207 if (!rtc->ops) 214 if (!rtc->ops)
208 err = -ENODEV; 215 err = -ENODEV;
209 else if (!rtc->ops->alarm_irq_enable) 216 else if (!rtc->ops->alarm_irq_enable)
@@ -235,12 +242,9 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
235 now = rtc_tm_to_ktime(tm); 242 now = rtc_tm_to_ktime(tm);
236 rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); 243 rtc->uie_rtctimer.node.expires = ktime_add(now, onesec);
237 rtc->uie_rtctimer.period = ktime_set(1, 0); 244 rtc->uie_rtctimer.period = ktime_set(1, 0);
238 rtc->uie_rtctimer.enabled = 1; 245 err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer);
239 rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); 246 } else
240 } else {
241 rtc_timer_remove(rtc, &rtc->uie_rtctimer); 247 rtc_timer_remove(rtc, &rtc->uie_rtctimer);
242 rtc->uie_rtctimer.enabled = 0;
243 }
244 248
245out: 249out:
246 mutex_unlock(&rtc->ops_lock); 250 mutex_unlock(&rtc->ops_lock);
@@ -488,10 +492,13 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
488 * Enqueues a timer onto the rtc devices timerqueue and sets 492 * Enqueues a timer onto the rtc devices timerqueue and sets
489 * the next alarm event appropriately. 493 * the next alarm event appropriately.
490 * 494 *
495 * Sets the enabled bit on the added timer.
496 *
491 * Must hold ops_lock for proper serialization of timerqueue 497 * Must hold ops_lock for proper serialization of timerqueue
492 */ 498 */
493void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) 499static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
494{ 500{
501 timer->enabled = 1;
495 timerqueue_add(&rtc->timerqueue, &timer->node); 502 timerqueue_add(&rtc->timerqueue, &timer->node);
496 if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { 503 if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
497 struct rtc_wkalrm alarm; 504 struct rtc_wkalrm alarm;
@@ -501,7 +508,13 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
501 err = __rtc_set_alarm(rtc, &alarm); 508 err = __rtc_set_alarm(rtc, &alarm);
502 if (err == -ETIME) 509 if (err == -ETIME)
503 schedule_work(&rtc->irqwork); 510 schedule_work(&rtc->irqwork);
511 else if (err) {
512 timerqueue_del(&rtc->timerqueue, &timer->node);
513 timer->enabled = 0;
514 return err;
515 }
504 } 516 }
517 return 0;
505} 518}
506 519
507/** 520/**
@@ -512,13 +525,15 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
512 * Removes a timer onto the rtc devices timerqueue and sets 525 * Removes a timer onto the rtc devices timerqueue and sets
513 * the next alarm event appropriately. 526 * the next alarm event appropriately.
514 * 527 *
528 * Clears the enabled bit on the removed timer.
529 *
515 * Must hold ops_lock for proper serialization of timerqueue 530 * Must hold ops_lock for proper serialization of timerqueue
516 */ 531 */
517void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) 532static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
518{ 533{
519 struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); 534 struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
520 timerqueue_del(&rtc->timerqueue, &timer->node); 535 timerqueue_del(&rtc->timerqueue, &timer->node);
521 536 timer->enabled = 0;
522 if (next == &timer->node) { 537 if (next == &timer->node) {
523 struct rtc_wkalrm alarm; 538 struct rtc_wkalrm alarm;
524 int err; 539 int err;
@@ -626,8 +641,7 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
626 timer->node.expires = expires; 641 timer->node.expires = expires;
627 timer->period = period; 642 timer->period = period;
628 643
629 timer->enabled = 1; 644 ret = rtc_timer_enqueue(rtc, timer);
630 rtc_timer_enqueue(rtc, timer);
631 645
632 mutex_unlock(&rtc->ops_lock); 646 mutex_unlock(&rtc->ops_lock);
633 return ret; 647 return ret;
@@ -645,7 +659,6 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer)
645 mutex_lock(&rtc->ops_lock); 659 mutex_lock(&rtc->ops_lock);
646 if (timer->enabled) 660 if (timer->enabled)
647 rtc_timer_remove(rtc, timer); 661 rtc_timer_remove(rtc, timer);
648 timer->enabled = 0;
649 mutex_unlock(&rtc->ops_lock); 662 mutex_unlock(&rtc->ops_lock);
650 return ret; 663 return ret;
651} 664}
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 3c995b4d742..a0b639f8e80 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -235,8 +235,6 @@ extern int rtc_irq_set_freq(struct rtc_device *rtc,
235 struct rtc_task *task, int freq); 235 struct rtc_task *task, int freq);
236extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); 236extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
237extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); 237extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
238extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
239 unsigned int enabled);
240 238
241void rtc_aie_update_irq(void *private); 239void rtc_aie_update_irq(void *private);
242void rtc_uie_update_irq(void *private); 240void rtc_uie_update_irq(void *private);
@@ -246,8 +244,6 @@ int rtc_register(rtc_task_t *task);
246int rtc_unregister(rtc_task_t *task); 244int rtc_unregister(rtc_task_t *task);
247int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); 245int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
248 246
249void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
250void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
251void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data); 247void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data);
252int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, 248int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
253 ktime_t expires, ktime_t period); 249 ktime_t expires, ktime_t period);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 3e216e01bbd..c55ea243347 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -642,8 +642,7 @@ static void tick_nohz_switch_to_nohz(void)
642 } 642 }
643 local_irq_enable(); 643 local_irq_enable();
644 644
645 printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", 645 printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
646 smp_processor_id());
647} 646}
648 647
649/* 648/*
@@ -795,8 +794,10 @@ void tick_setup_sched_timer(void)
795 } 794 }
796 795
797#ifdef CONFIG_NO_HZ 796#ifdef CONFIG_NO_HZ
798 if (tick_nohz_enabled) 797 if (tick_nohz_enabled) {
799 ts->nohz_mode = NOHZ_MODE_HIGHRES; 798 ts->nohz_mode = NOHZ_MODE_HIGHRES;
799 printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
800 }
800#endif 801#endif
801} 802}
802#endif /* HIGH_RES_TIMERS */ 803#endif /* HIGH_RES_TIMERS */