aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2006-10-04 17:12:52 -0400
committerMatthew Wilcox <willy@hera.kernel.org>2006-10-04 21:48:18 -0400
commit1604f31895dcdb42edf6511ce7ef0546ff92c8e5 (patch)
tree406ed0e9d1004eaccb7aa194145a4035183c0de2 /arch/parisc
parent1070c9655b90016ec4c9b59c402292e57ee15885 (diff)
[PA-RISC] Fix time.c for new do_timer() calling convention
do_timer now wants to know how many ticks have elapsed. Now that we have to calculate that, we can eliminate some of the clever code that avoided having to calculate that. Also add some more documentation. I'd like to thank Grant Grundler for helping me with this. Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/kernel/time.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index b3496b592a2d..1d58ce0e37ad 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -38,11 +38,28 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */
38extern void smp_do_timer(struct pt_regs *regs); 38extern void smp_do_timer(struct pt_regs *regs);
39#endif 39#endif
40 40
41/*
42 * We keep time on PA-RISC Linux by using the Interval Timer which is
43 * a pair of registers; one is read-only and one is write-only; both
44 * accessed through CR16. The read-only register is 32 or 64 bits wide,
45 * and increments by 1 every CPU clock tick. The architecture only
46 * guarantees us a rate between 0.5 and 2, but all implementations use a
47 * rate of 1. The write-only register is 32-bits wide. When the lowest
48 * 32 bits of the read-only register compare equal to the write-only
49 * register, it raises a maskable external interrupt. Each processor has
50 * an Interval Timer of its own and they are not synchronised.
51 *
52 * We want to generate an interrupt every 1/HZ seconds. So we program
53 * CR16 to interrupt every @clocktick cycles. The it_value in cpu_data
54 * is programmed with the intended time of the next tick. We can be
55 * held off for an arbitrarily long period of time by interrupts being
56 * disabled, so we may miss one or more ticks.
57 */
41irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 58irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
42{ 59{
43 unsigned long now; 60 unsigned long now;
44 unsigned long next_tick; 61 unsigned long next_tick;
45 unsigned long cycles_elapsed; 62 unsigned long cycles_elapsed, ticks_elapsed;
46 unsigned long cycles_remainder; 63 unsigned long cycles_remainder;
47 unsigned int cpu = smp_processor_id(); 64 unsigned int cpu = smp_processor_id();
48 65
@@ -67,11 +84,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
67 * of the more expensive div/mul method 84 * of the more expensive div/mul method
68 */ 85 */
69 cycles_remainder = cycles_elapsed; 86 cycles_remainder = cycles_elapsed;
87 ticks_elapsed = 1;
70 while (cycles_remainder > cpt) { 88 while (cycles_remainder > cpt) {
71 cycles_remainder -= cpt; 89 cycles_remainder -= cpt;
90 ticks_elapsed++;
72 } 91 }
73 } else { 92 } else {
74 cycles_remainder = cycles_elapsed % cpt; 93 cycles_remainder = cycles_elapsed % cpt;
94 ticks_elapsed = 1 + cycles_elapsed / cpt;
75 } 95 }
76 96
77 /* Can we differentiate between "early CR16" (aka Scenario 1) and 97 /* Can we differentiate between "early CR16" (aka Scenario 1) and
@@ -81,18 +101,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
81 * cycles after the IT fires. But it's arbitrary how much time passes 101 * cycles after the IT fires. But it's arbitrary how much time passes
82 * before we call it "late". I've picked one second. 102 * before we call it "late". I've picked one second.
83 */ 103 */
84/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */ 104 if (ticks_elapsed > HZ) {
85#if HZ == 1000
86 if (cycles_elapsed > (cpt << 10) )
87#elif HZ == 250
88 if (cycles_elapsed > (cpt << 8) )
89#elif HZ == 100
90 if (cycles_elapsed > (cpt << 7) )
91#else
92#warn WTF is HZ set to anyway?
93 if (cycles_elapsed > (HZ * cpt) )
94#endif
95 {
96 /* Scenario 3: very long delay? bad in any case */ 105 /* Scenario 3: very long delay? bad in any case */
97 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" 106 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
98 " cycles %lX rem %lX " 107 " cycles %lX rem %lX "
@@ -136,7 +145,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
136#endif 145#endif
137 if (cpu == 0) { 146 if (cpu == 0) {
138 write_seqlock(&xtime_lock); 147 write_seqlock(&xtime_lock);
139 do_timer(regs); 148 do_timer(ticks_elapsed);
140 write_sequnlock(&xtime_lock); 149 write_sequnlock(&xtime_lock);
141 } 150 }
142 151