diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r-- | arch/powerpc/kernel/time.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index d20947cf1735..9368da371f36 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -108,7 +108,7 @@ static void decrementer_set_mode(enum clock_event_mode mode, | |||
108 | static struct clock_event_device decrementer_clockevent = { | 108 | static struct clock_event_device decrementer_clockevent = { |
109 | .name = "decrementer", | 109 | .name = "decrementer", |
110 | .rating = 200, | 110 | .rating = 200, |
111 | .shift = 32, | 111 | .shift = 16, |
112 | .mult = 0, /* To be filled in */ | 112 | .mult = 0, /* To be filled in */ |
113 | .irq = 0, | 113 | .irq = 0, |
114 | .set_next_event = decrementer_set_next_event, | 114 | .set_next_event = decrementer_set_next_event, |
@@ -118,6 +118,7 @@ static struct clock_event_device decrementer_clockevent = { | |||
118 | 118 | ||
119 | static DEFINE_PER_CPU(struct clock_event_device, decrementers); | 119 | static DEFINE_PER_CPU(struct clock_event_device, decrementers); |
120 | void init_decrementer_clockevent(void); | 120 | void init_decrementer_clockevent(void); |
121 | static DEFINE_PER_CPU(u64, decrementer_next_tb); | ||
121 | 122 | ||
122 | #ifdef CONFIG_PPC_ISERIES | 123 | #ifdef CONFIG_PPC_ISERIES |
123 | static unsigned long __initdata iSeries_recal_titan; | 124 | static unsigned long __initdata iSeries_recal_titan; |
@@ -541,6 +542,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
541 | struct pt_regs *old_regs; | 542 | struct pt_regs *old_regs; |
542 | int cpu = smp_processor_id(); | 543 | int cpu = smp_processor_id(); |
543 | struct clock_event_device *evt = &per_cpu(decrementers, cpu); | 544 | struct clock_event_device *evt = &per_cpu(decrementers, cpu); |
545 | u64 now; | ||
544 | 546 | ||
545 | /* Ensure a positive value is written to the decrementer, or else | 547 | /* Ensure a positive value is written to the decrementer, or else |
546 | * some CPUs will continuue to take decrementer exceptions */ | 548 | * some CPUs will continuue to take decrementer exceptions */ |
@@ -551,6 +553,14 @@ void timer_interrupt(struct pt_regs * regs) | |||
551 | do_IRQ(regs); | 553 | do_IRQ(regs); |
552 | #endif | 554 | #endif |
553 | 555 | ||
556 | now = get_tb_or_rtc(); | ||
557 | if (now < per_cpu(decrementer_next_tb, cpu)) { | ||
558 | /* not time for this event yet */ | ||
559 | now = per_cpu(decrementer_next_tb, cpu) - now; | ||
560 | if (now <= DECREMENTER_MAX) | ||
561 | set_dec((unsigned int)now - 1); | ||
562 | return; | ||
563 | } | ||
554 | old_regs = set_irq_regs(regs); | 564 | old_regs = set_irq_regs(regs); |
555 | irq_enter(); | 565 | irq_enter(); |
556 | 566 | ||
@@ -797,6 +807,10 @@ void __init clocksource_init(void) | |||
797 | static int decrementer_set_next_event(unsigned long evt, | 807 | static int decrementer_set_next_event(unsigned long evt, |
798 | struct clock_event_device *dev) | 808 | struct clock_event_device *dev) |
799 | { | 809 | { |
810 | __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt; | ||
811 | /* The decrementer interrupts on the 0 -> -1 transition */ | ||
812 | if (evt) | ||
813 | --evt; | ||
800 | set_dec(evt); | 814 | set_dec(evt); |
801 | return 0; | 815 | return 0; |
802 | } | 816 | } |