diff options
| -rw-r--r-- | drivers/rtc/interface.c | 49 | ||||
| -rw-r--r-- | include/linux/rtc.h | 2 |
2 files changed, 28 insertions, 23 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 90384b9f6b2..f1ba2c69652 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; |
| @@ -175,16 +178,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 175 | return err; | 178 | return err; |
| 176 | if (rtc->aie_timer.enabled) { | 179 | if (rtc->aie_timer.enabled) { |
| 177 | rtc_timer_remove(rtc, &rtc->aie_timer); | 180 | rtc_timer_remove(rtc, &rtc->aie_timer); |
| 178 | rtc->aie_timer.enabled = 0; | ||
| 179 | } | 181 | } |
| 180 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); | 182 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
| 181 | rtc->aie_timer.period = ktime_set(0, 0); | 183 | rtc->aie_timer.period = ktime_set(0, 0); |
| 182 | if (alarm->enabled) { | 184 | if (alarm->enabled) { |
| 183 | rtc->aie_timer.enabled = 1; | 185 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); |
| 184 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | ||
| 185 | } | 186 | } |
| 186 | mutex_unlock(&rtc->ops_lock); | 187 | mutex_unlock(&rtc->ops_lock); |
| 187 | return 0; | 188 | return err; |
| 188 | } | 189 | } |
| 189 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | 190 | EXPORT_SYMBOL_GPL(rtc_set_alarm); |
| 190 | 191 | ||
| @@ -195,15 +196,15 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
| 195 | return err; | 196 | return err; |
| 196 | 197 | ||
| 197 | if (rtc->aie_timer.enabled != enabled) { | 198 | if (rtc->aie_timer.enabled != enabled) { |
| 198 | if (enabled) { | 199 | if (enabled) |
| 199 | rtc->aie_timer.enabled = 1; | 200 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); |
| 200 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | 201 | else |
| 201 | } else { | ||
| 202 | rtc_timer_remove(rtc, &rtc->aie_timer); | 202 | rtc_timer_remove(rtc, &rtc->aie_timer); |
| 203 | rtc->aie_timer.enabled = 0; | ||
| 204 | } | ||
| 205 | } | 203 | } |
| 206 | 204 | ||
| 205 | if (err) | ||
| 206 | return err; | ||
| 207 | |||
| 207 | if (!rtc->ops) | 208 | if (!rtc->ops) |
| 208 | err = -ENODEV; | 209 | err = -ENODEV; |
| 209 | else if (!rtc->ops->alarm_irq_enable) | 210 | else if (!rtc->ops->alarm_irq_enable) |
| @@ -235,12 +236,9 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
| 235 | now = rtc_tm_to_ktime(tm); | 236 | now = rtc_tm_to_ktime(tm); |
| 236 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); | 237 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); |
| 237 | rtc->uie_rtctimer.period = ktime_set(1, 0); | 238 | rtc->uie_rtctimer.period = ktime_set(1, 0); |
| 238 | rtc->uie_rtctimer.enabled = 1; | 239 | err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); |
| 239 | rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); | 240 | } else |
| 240 | } else { | ||
| 241 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); | 241 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); |
| 242 | rtc->uie_rtctimer.enabled = 0; | ||
| 243 | } | ||
| 244 | 242 | ||
| 245 | out: | 243 | out: |
| 246 | mutex_unlock(&rtc->ops_lock); | 244 | mutex_unlock(&rtc->ops_lock); |
| @@ -488,10 +486,13 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); | |||
| 488 | * Enqueues a timer onto the rtc devices timerqueue and sets | 486 | * Enqueues a timer onto the rtc devices timerqueue and sets |
| 489 | * the next alarm event appropriately. | 487 | * the next alarm event appropriately. |
| 490 | * | 488 | * |
| 489 | * Sets the enabled bit on the added timer. | ||
| 490 | * | ||
| 491 | * Must hold ops_lock for proper serialization of timerqueue | 491 | * Must hold ops_lock for proper serialization of timerqueue |
| 492 | */ | 492 | */ |
| 493 | void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | 493 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) |
| 494 | { | 494 | { |
| 495 | timer->enabled = 1; | ||
| 495 | timerqueue_add(&rtc->timerqueue, &timer->node); | 496 | timerqueue_add(&rtc->timerqueue, &timer->node); |
| 496 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { | 497 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { |
| 497 | struct rtc_wkalrm alarm; | 498 | struct rtc_wkalrm alarm; |
| @@ -501,7 +502,13 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
| 501 | err = __rtc_set_alarm(rtc, &alarm); | 502 | err = __rtc_set_alarm(rtc, &alarm); |
| 502 | if (err == -ETIME) | 503 | if (err == -ETIME) |
| 503 | schedule_work(&rtc->irqwork); | 504 | schedule_work(&rtc->irqwork); |
| 505 | else if (err) { | ||
| 506 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
| 507 | timer->enabled = 0; | ||
| 508 | return err; | ||
| 509 | } | ||
| 504 | } | 510 | } |
| 511 | return 0; | ||
| 505 | } | 512 | } |
| 506 | 513 | ||
| 507 | /** | 514 | /** |
| @@ -512,13 +519,15 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
| 512 | * Removes a timer onto the rtc devices timerqueue and sets | 519 | * Removes a timer onto the rtc devices timerqueue and sets |
| 513 | * the next alarm event appropriately. | 520 | * the next alarm event appropriately. |
| 514 | * | 521 | * |
| 522 | * Clears the enabled bit on the removed timer. | ||
| 523 | * | ||
| 515 | * Must hold ops_lock for proper serialization of timerqueue | 524 | * Must hold ops_lock for proper serialization of timerqueue |
| 516 | */ | 525 | */ |
| 517 | void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | 526 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) |
| 518 | { | 527 | { |
| 519 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | 528 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); |
| 520 | timerqueue_del(&rtc->timerqueue, &timer->node); | 529 | timerqueue_del(&rtc->timerqueue, &timer->node); |
| 521 | 530 | timer->enabled = 0; | |
| 522 | if (next == &timer->node) { | 531 | if (next == &timer->node) { |
| 523 | struct rtc_wkalrm alarm; | 532 | struct rtc_wkalrm alarm; |
| 524 | int err; | 533 | int err; |
| @@ -626,8 +635,7 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, | |||
| 626 | timer->node.expires = expires; | 635 | timer->node.expires = expires; |
| 627 | timer->period = period; | 636 | timer->period = period; |
| 628 | 637 | ||
| 629 | timer->enabled = 1; | 638 | ret = rtc_timer_enqueue(rtc, timer); |
| 630 | rtc_timer_enqueue(rtc, timer); | ||
| 631 | 639 | ||
| 632 | mutex_unlock(&rtc->ops_lock); | 640 | mutex_unlock(&rtc->ops_lock); |
| 633 | return ret; | 641 | return ret; |
| @@ -645,7 +653,6 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer) | |||
| 645 | mutex_lock(&rtc->ops_lock); | 653 | mutex_lock(&rtc->ops_lock); |
| 646 | if (timer->enabled) | 654 | if (timer->enabled) |
| 647 | rtc_timer_remove(rtc, timer); | 655 | rtc_timer_remove(rtc, timer); |
| 648 | timer->enabled = 0; | ||
| 649 | mutex_unlock(&rtc->ops_lock); | 656 | mutex_unlock(&rtc->ops_lock); |
| 650 | return ret; | 657 | return ret; |
| 651 | } | 658 | } |
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index ea760698e6f..a0b639f8e80 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
| @@ -244,8 +244,6 @@ int rtc_register(rtc_task_t *task); | |||
| 244 | int rtc_unregister(rtc_task_t *task); | 244 | int rtc_unregister(rtc_task_t *task); |
| 245 | int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); | 245 | int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); |
| 246 | 246 | ||
| 247 | void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); | ||
| 248 | void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); | ||
| 249 | void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data); | 247 | void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data); |
| 250 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, | 248 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, |
| 251 | ktime_t expires, ktime_t period); | 249 | ktime_t expires, ktime_t period); |
