diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-24 14:25:55 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-24 14:25:55 -0500 |
| commit | ce84d539ce47484ff3cbc9c67b3eb69ae88954f9 (patch) | |
| tree | cdba43e845e23a6793ca47857a16fae6032becfb | |
| parent | bc094757f4f3d7b8211a8a1ed7605ffd7c728f75 (diff) | |
| parent | b5cc8ca1c9c3a37eaddf709b2fd3e1699aee41ba (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.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 61 | ||||
| -rw-r--r-- | include/linux/rtc.h | 4 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 7 |
5 files changed, 46 insertions, 44 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index cfb0f5278415..effe7974aa9a 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 4941cade319f..cdd97192dc69 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 | ||
| 100 | config 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 | |||
| 112 | config RTC_DRV_TEST | 100 | config 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 90384b9f6b2c..925006d33109 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 | ||
| 19 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); | ||
| 20 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); | ||
| 21 | |||
| 19 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 22 | static 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 | } |
| 130 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 139 | EXPORT_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 | } |
| 189 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | 196 | EXPORT_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 | ||
| 245 | out: | 249 | out: |
| 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 | */ |
| 493 | void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | 499 | static 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); | ||
