diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-07-21 07:37:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-21 20:49:15 -0400 |
commit | 18de5bc4c1f1f1fa5e14f354a7603bd6e9d4e3b6 (patch) | |
tree | cb0ff399fb3f368adecf213318e32a499ada6ff9 /arch/i386/kernel/hpet.c | |
parent | 93da56efcf8c6a111f0349f6b7651172d4745ca0 (diff) |
clockevents: fix resume logic
We need to make sure, that the clockevent devices are resumed, before
the tick is resumed. The current resume logic does not guarantee this.
Add CLOCK_EVT_MODE_RESUME and call the set mode functions of the clock
event devices before resuming the tick / oneshot functionality.
Fixup the existing users.
Thanks to Nigel Cunningham for tracking down a long standing thinko,
which affected the jinxed VAIO.
[akpm@linux-foundation.org: xen build fix]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/hpet.c')
-rw-r--r-- | arch/i386/kernel/hpet.c | 71 |
1 files changed, 5 insertions, 66 deletions
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c index 17d73459fc5f..cfbf792a0bf4 100644 --- a/arch/i386/kernel/hpet.c +++ b/arch/i386/kernel/hpet.c | |||
@@ -187,6 +187,10 @@ static void hpet_set_mode(enum clock_event_mode mode, | |||
187 | cfg &= ~HPET_TN_ENABLE; | 187 | cfg &= ~HPET_TN_ENABLE; |
188 | hpet_writel(cfg, HPET_T0_CFG); | 188 | hpet_writel(cfg, HPET_T0_CFG); |
189 | break; | 189 | break; |
190 | |||
191 | case CLOCK_EVT_MODE_RESUME: | ||
192 | hpet_enable_int(); | ||
193 | break; | ||
190 | } | 194 | } |
191 | } | 195 | } |
192 | 196 | ||
@@ -217,6 +221,7 @@ static struct clocksource clocksource_hpet = { | |||
217 | .mask = HPET_MASK, | 221 | .mask = HPET_MASK, |
218 | .shift = HPET_SHIFT, | 222 | .shift = HPET_SHIFT, |
219 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 223 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
224 | .resume = hpet_start_counter, | ||
220 | }; | 225 | }; |
221 | 226 | ||
222 | /* | 227 | /* |
@@ -291,7 +296,6 @@ int __init hpet_enable(void) | |||
291 | 296 | ||
292 | clocksource_register(&clocksource_hpet); | 297 | clocksource_register(&clocksource_hpet); |
293 | 298 | ||
294 | |||
295 | if (id & HPET_ID_LEGSUP) { | 299 | if (id & HPET_ID_LEGSUP) { |
296 | hpet_enable_int(); | 300 | hpet_enable_int(); |
297 | hpet_reserve_platform_timers(id); | 301 | hpet_reserve_platform_timers(id); |
@@ -524,68 +528,3 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | |||
524 | return IRQ_HANDLED; | 528 | return IRQ_HANDLED; |
525 | } | 529 | } |
526 | #endif | 530 | #endif |
527 | |||
528 | |||
529 | /* | ||
530 | * Suspend/resume part | ||
531 | */ | ||
532 | |||
533 | #ifdef CONFIG_PM | ||
534 | |||
535 | static int hpet_suspend(struct sys_device *sys_device, pm_message_t state) | ||
536 | { | ||
537 | unsigned long cfg = hpet_readl(HPET_CFG); | ||
538 | |||
539 | cfg &= ~(HPET_CFG_ENABLE|HPET_CFG_LEGACY); | ||
540 | hpet_writel(cfg, HPET_CFG); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int hpet_resume(struct sys_device *sys_device) | ||
546 | { | ||
547 | unsigned int id; | ||
548 | |||
549 | hpet_start_counter(); | ||
550 | |||
551 | id = hpet_readl(HPET_ID); | ||
552 | |||
553 | if (id & HPET_ID_LEGSUP) | ||
554 | hpet_enable_int(); | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | static struct sysdev_class hpet_class = { | ||
560 | set_kset_name("hpet"), | ||
561 | .suspend = hpet_suspend, | ||
562 | .resume = hpet_resume, | ||
563 | }; | ||
564 | |||
565 | static struct sys_device hpet_device = { | ||
566 | .id = 0, | ||
567 | .cls = &hpet_class, | ||
568 | }; | ||
569 | |||
570 | |||
571 | static __init int hpet_register_sysfs(void) | ||
572 | { | ||
573 | int err; | ||
574 | |||
575 | if (!is_hpet_capable()) | ||
576 | return 0; | ||
577 | |||
578 | err = sysdev_class_register(&hpet_class); | ||
579 | |||
580 | if (!err) { | ||
581 | err = sysdev_register(&hpet_device); | ||
582 | if (err) | ||
583 | sysdev_class_unregister(&hpet_class); | ||
584 | } | ||
585 | |||
586 | return err; | ||
587 | } | ||
588 | |||
589 | device_initcall(hpet_register_sysfs); | ||
590 | |||
591 | #endif | ||