Commit ce84d539 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'timers-fixes-for-linus' of...

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
parents bc094757 b5cc8ca1
...@@ -202,17 +202,21 @@ static int __init init_acpi_pm_clocksource(void) ...@@ -202,17 +202,21 @@ static int __init init_acpi_pm_clocksource(void)
printk(KERN_INFO "PM-Timer had inconsistent results:" printk(KERN_INFO "PM-Timer had inconsistent results:"
" 0x%#llx, 0x%#llx - aborting.\n", " 0x%#llx, 0x%#llx - aborting.\n",
value1, value2); value1, value2);
pmtmr_ioport = 0;
return -EINVAL; return -EINVAL;
} }
if (i == ACPI_PM_READ_CHECKS) { if (i == ACPI_PM_READ_CHECKS) {
printk(KERN_INFO "PM-Timer failed consistency check " printk(KERN_INFO "PM-Timer failed consistency check "
" (0x%#llx) - aborting.\n", value1); " (0x%#llx) - aborting.\n", value1);
pmtmr_ioport = 0;
return -ENODEV; return -ENODEV;
} }
} }
if (verify_pmtmr_rate() != 0) if (verify_pmtmr_rate() != 0){
pmtmr_ioport = 0;
return -ENODEV; return -ENODEV;
}
return clocksource_register_hz(&clocksource_acpi_pm, return clocksource_register_hz(&clocksource_acpi_pm,
PMTMR_TICKS_PER_SEC); PMTMR_TICKS_PER_SEC);
......
...@@ -97,18 +97,6 @@ config RTC_INTF_DEV ...@@ -97,18 +97,6 @@ config RTC_INTF_DEV
If unsure, say Y. If unsure, say Y.
config RTC_INTF_DEV_UIE_EMUL
bool "RTC UIE emulation on dev interface"
depends on RTC_INTF_DEV
help
Provides an emulation for RTC_UIE if the underlying rtc chip
driver does not expose RTC_UIE ioctls. Those requests generate
once-per-second update interrupts, used for synchronization.
The emulation code will read the time from the hardware
clock several times per second, please enable this option
only if you know that you really need it.
config RTC_DRV_TEST config RTC_DRV_TEST
tristate "Test driver/device" tristate "Test driver/device"
help help
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{ {
int err; int err;
...@@ -120,12 +123,18 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) ...@@ -120,12 +123,18 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = mutex_lock_interruptible(&rtc->ops_lock); err = mutex_lock_interruptible(&rtc->ops_lock);
if (err) if (err)
return err; return err;
if (rtc->ops == NULL)
err = -ENODEV;
else if (!rtc->ops->read_alarm)
err = -EINVAL;
else {
memset(alarm, 0, sizeof(struct rtc_wkalrm));
alarm->enabled = rtc->aie_timer.enabled; alarm->enabled = rtc->aie_timer.enabled;
if (alarm->enabled)
alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires);
}
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
return 0; return err;
} }
EXPORT_SYMBOL_GPL(rtc_read_alarm); EXPORT_SYMBOL_GPL(rtc_read_alarm);
...@@ -175,16 +184,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) ...@@ -175,16 +184,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
return err; return err;
if (rtc->aie_timer.enabled) { if (rtc->aie_timer.enabled) {
rtc_timer_remove(rtc, &rtc->aie_timer); rtc_timer_remove(rtc, &rtc->aie_timer);
rtc->aie_timer.enabled = 0;
} }
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
rtc->aie_timer.period = ktime_set(0, 0); rtc->aie_timer.period = ktime_set(0, 0);
if (alarm->enabled) { if (alarm->enabled) {
rtc->aie_timer.enabled = 1; err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
rtc_timer_enqueue(rtc, &rtc->aie_timer);
} }
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
return 0; return err;
} }
EXPORT_SYMBOL_GPL(rtc_set_alarm); EXPORT_SYMBOL_GPL(rtc_set_alarm);
...@@ -195,15 +202,15 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) ...@@ -195,15 +202,15 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
return err; return err;
if (rtc->aie_timer.enabled != enabled) { if (rtc->aie_timer.enabled != enabled) {
if (enabled) { if (enabled)
rtc->aie_timer.enabled = 1; err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
rtc_timer_enqueue(rtc, &rtc->aie_timer); else
} else {
rtc_timer_remove(rtc, &rtc->aie_timer); rtc_timer_remove(rtc, &rtc->aie_timer);
rtc->aie_timer.enabled = 0;
}
} }
if (err)
return err;
if (!rtc->ops) if (!rtc->ops)
err = -ENODEV; err = -ENODEV;
else if (!rtc->ops->alarm_irq_enable) else if (!rtc->ops->alarm_irq_enable)
...@@ -235,12 +242,9 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) ...@@ -235,12 +242,9 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
now = rtc_tm_to_ktime(tm); now = rtc_tm_to_ktime(tm);
rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); rtc->uie_rtctimer.node.expires = ktime_add(now, onesec);
rtc->uie_rtctimer.period = ktime_set(1, 0); rtc->uie_rtctimer.period = ktime_set(1, 0);
rtc->uie_rtctimer.enabled = 1; err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer);
rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); } else
} else {
rtc_timer_remove(rtc, &rtc->uie_rtctimer); rtc_timer_remove(rtc, &rtc->uie_rtctimer);
rtc->uie_rtctimer.enabled = 0;
}
out: out:
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
...@@ -488,10 +492,13 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); ...@@ -488,10 +492,13 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
* Enqueues a timer onto the rtc devices timerqueue and sets * Enqueues a timer onto the rtc devices timerqueue and sets
* the next alarm event appropriately. * the next alarm event appropriately.
* *
* Sets the enabled bit on the added timer.
*
* Must hold ops_lock for proper serialization of timerqueue * Must hold ops_lock for proper serialization of timerqueue
*/ */
void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
{ {
timer->enabled = 1;
timerqueue_add(&rtc->timerqueue, &timer->node); timerqueue_add(&rtc->timerqueue, &timer->node);
if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
...@@ -501,7 +508,13 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) ...@@ -501,7 +508,13 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
err = __rtc_set_alarm(rtc, &alarm); err = __rtc_set_alarm(rtc, &alarm);
if (err == -ETIME) if (err == -ETIME)
schedule_work(&rtc->irqwork); schedule_work(&rtc->irqwork);
else if (err) {
timerqueue_del(&rtc->timerqueue, &timer->node);
timer->enabled = 0;
return err;
} }
}
return 0;
} }
/** /**
...@@ -512,13 +525,15 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) ...@@ -512,13 +525,15 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
* Removes a timer onto the rtc devices timerqueue and sets * Removes a timer onto the rtc devices timerqueue and sets
* the next alarm event appropriately. * the next alarm event appropriately.
* *
* Clears the enabled bit on the removed timer.
*
* Must hold ops_lock for proper serialization of timerqueue * Must hold ops_lock for proper serialization of timerqueue
*/ */
void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
{ {
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
timer->enabled = 0;
if (next == &timer->node) { if (next == &timer->node) {
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
int err; int err;
...@@ -626,8 +641,7 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, ...@@ -626,8 +641,7 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
timer->node.expires = expires; timer->node.expires = expires;
timer->period = period; timer->period = period;
timer->enabled = 1; ret = rtc_timer_enqueue(rtc, timer);
rtc_timer_enqueue(rtc, timer);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
return ret; return ret;
...@@ -645,7 +659,6 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer) ...@@ -645,7 +659,6 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer)
mutex_lock(&rtc->ops_lock); mutex_lock(&rtc->ops_lock);
if (timer->enabled) if (timer->enabled)
rtc_timer_remove(rtc, timer); rtc_timer_remove(rtc, timer);
timer->enabled = 0;
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
return ret; return ret;
} }
......
...@@ -235,8 +235,6 @@ extern int rtc_irq_set_freq(struct rtc_device *rtc, ...@@ -235,8 +235,6 @@ extern int rtc_irq_set_freq(struct rtc_device *rtc,
struct rtc_task *task, int freq); struct rtc_task *task, int freq);
extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
unsigned int enabled);
void rtc_aie_update_irq(void *private); void rtc_aie_update_irq(void *private);
void rtc_uie_update_irq(void *private); void rtc_uie_update_irq(void *private);
...@@ -246,8 +244,6 @@ int rtc_register(rtc_task_t *task); ...@@ -246,8 +244,6 @@ int rtc_register(rtc_task_t *task);
int rtc_unregister(rtc_task_t *task); int rtc_unregister(rtc_task_t *task);
int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data); void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data);
int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
ktime_t expires, ktime_t period); ktime_t expires, ktime_t period);
......
...@@ -642,8 +642,7 @@ static void tick_nohz_switch_to_nohz(void) ...@@ -642,8 +642,7 @@ static void tick_nohz_switch_to_nohz(void)
} }
local_irq_enable(); local_irq_enable();
printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
smp_processor_id());
} }
/* /*
...@@ -795,8 +794,10 @@ void tick_setup_sched_timer(void) ...@@ -795,8 +794,10 @@ void tick_setup_sched_timer(void)
} }
#ifdef CONFIG_NO_HZ #ifdef CONFIG_NO_HZ
if (tick_nohz_enabled) if (tick_nohz_enabled) {
ts->nohz_mode = NOHZ_MODE_HIGHRES; ts->nohz_mode = NOHZ_MODE_HIGHRES;
printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
}
#endif #endif
} }
#endif /* HIGH_RES_TIMERS */ #endif /* HIGH_RES_TIMERS */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment