diff options
| -rw-r--r-- | arch/parisc/kernel/time.c | 37 |
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 */ | |||
| 38 | extern void smp_do_timer(struct pt_regs *regs); | 38 | extern 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 | */ | ||
| 41 | irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 58 | irqreturn_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 | ||
