diff options
author | Anton Blanchard <anton@samba.org> | 2011-11-23 15:07:22 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-11-24 22:11:26 -0500 |
commit | 7df1027542c9353bef4d027cb4ab8e99f69017b7 (patch) | |
tree | 297c93c0937a05a66235f24fbab1c58e8dd93514 /arch/powerpc/kernel/time.c | |
parent | 621692cb7efb6d0e38c62e41844a6360c6719b20 (diff) |
powerpc/time: Optimise decrementer_check_overflow
decrementer_check_overflow is called from arch_local_irq_restore so
we want to make it as light weight as possible. As such, turn
decrementer_check_overflow into an inline function.
To avoid a circular mess of includes, separate out the two components
of struct decrementer_clock and keep the struct clock_event_device
part local to time.c.
The fast path improves from:
arch_local_irq_restore
0: mflr r0
4: std r0,16(r1)
8: stdu r1,-112(r1)
c: stb r3,578(r13)
10: cmpdi cr7,r3,0
14: beq- cr7,24 <.arch_local_irq_restore+0x24>
...
24: addi r1,r1,112
28: ld r0,16(r1)
2c: mtlr r0
30: blr
to:
arch_local_irq_restore
0: std r30,-16(r1)
4: ld r30,0(r2)
8: stb r3,578(r13)
c: cmpdi cr7,r3,0
10: beq- cr7,6c <.arch_local_irq_restore+0x6c>
...
6c: ld r30,-16(r1)
70: blr
Unfortunately we still setup a local TOC (due to -mminimal-toc). Yet
another sign we should be moving to -mcmodel=medium.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r-- | arch/powerpc/kernel/time.c | 27 |
1 files changed, 7 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index b1990b987e2c..9754743db8b9 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -114,12 +114,8 @@ static struct clock_event_device decrementer_clockevent = { | |||
114 | .features = CLOCK_EVT_FEAT_ONESHOT, | 114 | .features = CLOCK_EVT_FEAT_ONESHOT, |
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct decrementer_clock { | 117 | DEFINE_PER_CPU(u64, decrementers_next_tb); |
118 | struct clock_event_device event; | 118 | static DEFINE_PER_CPU(struct clock_event_device, decrementers); |
119 | u64 next_tb; | ||
120 | }; | ||
121 | |||
122 | static DEFINE_PER_CPU(struct decrementer_clock, decrementers); | ||
123 | 119 | ||
124 | #ifdef CONFIG_PPC_ISERIES | 120 | #ifdef CONFIG_PPC_ISERIES |
125 | static unsigned long __initdata iSeries_recal_titan; | 121 | static unsigned long __initdata iSeries_recal_titan; |
@@ -570,8 +566,8 @@ void arch_irq_work_raise(void) | |||
570 | void timer_interrupt(struct pt_regs * regs) | 566 | void timer_interrupt(struct pt_regs * regs) |
571 | { | 567 | { |
572 | struct pt_regs *old_regs; | 568 | struct pt_regs *old_regs; |
573 | struct decrementer_clock *decrementer = &__get_cpu_var(decrementers); | 569 | u64 *next_tb = &__get_cpu_var(decrementers_next_tb); |
574 | struct clock_event_device *evt = &decrementer->event; | 570 | struct clock_event_device *evt = &__get_cpu_var(decrementers); |
575 | 571 | ||
576 | /* Ensure a positive value is written to the decrementer, or else | 572 | /* Ensure a positive value is written to the decrementer, or else |
577 | * some CPUs will continue to take decrementer exceptions. | 573 | * some CPUs will continue to take decrementer exceptions. |
@@ -606,7 +602,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
606 | get_lppaca()->int_dword.fields.decr_int = 0; | 602 | get_lppaca()->int_dword.fields.decr_int = 0; |
607 | #endif | 603 | #endif |
608 | 604 | ||
609 | decrementer->next_tb = ~(u64)0; | 605 | *next_tb = ~(u64)0; |
610 | if (evt->event_handler) | 606 | if (evt->event_handler) |
611 | evt->event_handler(evt); | 607 | evt->event_handler(evt); |
612 | 608 | ||
@@ -872,19 +868,10 @@ static void __init clocksource_init(void) | |||
872 | clock->name, clock->mult, clock->shift); | 868 | clock->name, clock->mult, clock->shift); |
873 | } | 869 | } |
874 | 870 | ||
875 | void decrementer_check_overflow(void) | ||
876 | { | ||
877 | u64 now = get_tb_or_rtc(); | ||
878 | struct decrementer_clock *decrementer = &__get_cpu_var(decrementers); | ||
879 | |||
880 | if (now >= decrementer->next_tb) | ||
881 | set_dec(1); | ||
882 | } | ||
883 | |||
884 | static int decrementer_set_next_event(unsigned long evt, | 871 | static int decrementer_set_next_event(unsigned long evt, |
885 | struct clock_event_device *dev) | 872 | struct clock_event_device *dev) |
886 | { | 873 | { |
887 | __get_cpu_var(decrementers).next_tb = get_tb_or_rtc() + evt; | 874 | __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt; |
888 | set_dec(evt); | 875 | set_dec(evt); |
889 | return 0; | 876 | return 0; |
890 | } | 877 | } |
@@ -898,7 +885,7 @@ static void decrementer_set_mode(enum clock_event_mode mode, | |||
898 | 885 | ||
899 | static void register_decrementer_clockevent(int cpu) | 886 | static void register_decrementer_clockevent(int cpu) |
900 | { | 887 | { |
901 | struct clock_event_device *dec = &per_cpu(decrementers, cpu).event; | 888 | struct clock_event_device *dec = &per_cpu(decrementers, cpu); |
902 | 889 | ||
903 | *dec = decrementer_clockevent; | 890 | *dec = decrementer_clockevent; |
904 | dec->cpumask = cpumask_of(cpu); | 891 | dec->cpumask = cpumask_of(cpu); |