aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2016-12-20 14:51:10 -0500
committerHelge Deller <deller@gmx.de>2016-12-20 15:39:40 -0500
commit160494d381373cfa21208484aea4e5db2d3cb0a8 (patch)
tree436b9f2b94eca1f48a0484c91838219dd022635e
parent82cbd568bc5aa4c70f2a694f169d39ddef3b1aba (diff)
parisc: Optimize timer interrupt function
Restructure the timer interrupt function to better cope with missed timer irqs. Optimize the calculation when the next interrupt should happen and skip irqs if they would happen too shortly after exit of the irq function. The update_process_times() call is done anyway at every timer irq, so we can safely drop the prof_counter and prof_multiplier variables from the per_cpu structure. Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--arch/parisc/include/asm/processor.h4
-rw-r--r--arch/parisc/kernel/processor.c5
-rw-r--r--arch/parisc/kernel/time.c112
3 files changed, 29 insertions, 92 deletions
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 2e674e13e005..e4396304d545 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -93,9 +93,7 @@ struct system_cpuinfo_parisc {
93/* Per CPU data structure - ie varies per CPU. */ 93/* Per CPU data structure - ie varies per CPU. */
94struct cpuinfo_parisc { 94struct cpuinfo_parisc {
95 unsigned long it_value; /* Interval Timer at last timer Intr */ 95 unsigned long it_value; /* Interval Timer at last timer Intr */
96 unsigned long it_delta; /* Interval delta (tic_10ms / HZ * 100) */
97 unsigned long irq_count; /* number of IRQ's since boot */ 96 unsigned long irq_count; /* number of IRQ's since boot */
98 unsigned long irq_max_cr16; /* longest time to handle a single IRQ */
99 unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */ 97 unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */
100 unsigned long hpa; /* Host Physical address */ 98 unsigned long hpa; /* Host Physical address */
101 unsigned long txn_addr; /* MMIO addr of EIR or id_eid */ 99 unsigned long txn_addr; /* MMIO addr of EIR or id_eid */
@@ -103,8 +101,6 @@ struct cpuinfo_parisc {
103 unsigned long pending_ipi; /* bitmap of type ipi_message_type */ 101 unsigned long pending_ipi; /* bitmap of type ipi_message_type */
104#endif 102#endif
105 unsigned long bh_count; /* number of times bh was invoked */ 103 unsigned long bh_count; /* number of times bh was invoked */
106 unsigned long prof_counter; /* per CPU profiling support */
107 unsigned long prof_multiplier; /* per CPU profiling support */
108 unsigned long fp_rev; 104 unsigned long fp_rev;
109 unsigned long fp_model; 105 unsigned long fp_model;
110 unsigned int state; 106 unsigned int state;
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index c1c08b5f0cf2..85de47f4eb59 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -78,11 +78,6 @@ DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data);
78static void 78static void
79init_percpu_prof(unsigned long cpunum) 79init_percpu_prof(unsigned long cpunum)
80{ 80{
81 struct cpuinfo_parisc *p;
82
83 p = &per_cpu(cpu_data, cpunum);
84 p->prof_counter = 1;
85 p->prof_multiplier = 1;
86} 81}
87 82
88 83
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 325f30d82b64..4215f5596c8b 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -59,10 +59,9 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */
59 */ 59 */
60irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) 60irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
61{ 61{
62 unsigned long now, now2; 62 unsigned long now;
63 unsigned long next_tick; 63 unsigned long next_tick;
64 unsigned long cycles_elapsed, ticks_elapsed = 1; 64 unsigned long ticks_elapsed = 0;
65 unsigned long cycles_remainder;
66 unsigned int cpu = smp_processor_id(); 65 unsigned int cpu = smp_processor_id();
67 struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); 66 struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
68 67
@@ -71,102 +70,49 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
71 70
72 profile_tick(CPU_PROFILING); 71 profile_tick(CPU_PROFILING);
73 72
74 /* Initialize next_tick to the expected tick time. */ 73 /* Initialize next_tick to the old expected tick time. */
75 next_tick = cpuinfo->it_value; 74 next_tick = cpuinfo->it_value;
76 75
77 /* Get current cycle counter (Control Register 16). */ 76 /* Calculate how many ticks have elapsed. */
78 now = mfctl(16); 77 do {
79 78 ++ticks_elapsed;
80 cycles_elapsed = now - next_tick; 79 next_tick += cpt;
81 80 now = mfctl(16);
82 if ((cycles_elapsed >> 6) < cpt) { 81 } while (next_tick - now > cpt);
83 /* use "cheap" math (add/subtract) instead
84 * of the more expensive div/mul method
85 */
86 cycles_remainder = cycles_elapsed;
87 while (cycles_remainder > cpt) {
88 cycles_remainder -= cpt;
89 ticks_elapsed++;
90 }
91 } else {
92 /* TODO: Reduce this to one fdiv op */
93 cycles_remainder = cycles_elapsed % cpt;
94 ticks_elapsed += cycles_elapsed / cpt;
95 }
96
97 /* convert from "division remainder" to "remainder of clock tick" */
98 cycles_remainder = cpt - cycles_remainder;
99
100 /* Determine when (in CR16 cycles) next IT interrupt will fire.
101 * We want IT to fire modulo clocktick even if we miss/skip some.
102 * But those interrupts don't in fact get delivered that regularly.
103 */
104 next_tick = now + cycles_remainder;
105 82
83 /* Store (in CR16 cycles) up to when we are accounting right now. */
106 cpuinfo->it_value = next_tick; 84 cpuinfo->it_value = next_tick;
107 85
108 /* Program the IT when to deliver the next interrupt. 86 /* Go do system house keeping. */
109 * Only bottom 32-bits of next_tick are writable in CR16! 87 if (cpu == 0)
110 */ 88 xtime_update(ticks_elapsed);
111 mtctl(next_tick, 16); 89
90 update_process_times(user_mode(get_irq_regs()));
112 91
113 /* Skip one clocktick on purpose if we missed next_tick. 92 /* Skip clockticks on purpose if we know we would miss those.
114 * The new CR16 must be "later" than current CR16 otherwise 93 * The new CR16 must be "later" than current CR16 otherwise
115 * itimer would not fire until CR16 wrapped - e.g 4 seconds 94 * itimer would not fire until CR16 wrapped - e.g 4 seconds
116 * later on a 1Ghz processor. We'll account for the missed 95 * later on a 1Ghz processor. We'll account for the missed
117 * tick on the next timer interrupt. 96 * ticks on the next timer interrupt.
97 * We want IT to fire modulo clocktick even if we miss/skip some.
98 * But those interrupts don't in fact get delivered that regularly.
118 * 99 *
119 * "next_tick - now" will always give the difference regardless 100 * "next_tick - now" will always give the difference regardless
120 * if one or the other wrapped. If "now" is "bigger" we'll end up 101 * if one or the other wrapped. If "now" is "bigger" we'll end up
121 * with a very large unsigned number. 102 * with a very large unsigned number.
122 */ 103 */
123 now2 = mfctl(16); 104 while (next_tick - mfctl(16) > cpt)
124 if (next_tick - now2 > cpt) 105 next_tick += cpt;
125 mtctl(next_tick+cpt, 16);
126 106
127#if 1 107 /* Program the IT when to deliver the next interrupt.
128/* 108 * Only bottom 32-bits of next_tick are writable in CR16!
129 * GGG: DEBUG code for how many cycles programming CR16 used. 109 * Timer interrupt will be delivered at least a few hundred cycles
130 */ 110 * after the IT fires, so if we are too close (<= 500 cycles) to the
131 if (unlikely(now2 - now > 0x3000)) /* 12K cycles */ 111 * next cycle, simply skip it.
132 printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!"
133 " cyc %lX rem %lX "
134 " next/now %lX/%lX\n",
135 cpu, now2 - now, cycles_elapsed, cycles_remainder,
136 next_tick, now );
137#endif
138
139 /* Can we differentiate between "early CR16" (aka Scenario 1) and
140 * "long delay" (aka Scenario 3)? I don't think so.
141 *
142 * Timer_interrupt will be delivered at least a few hundred cycles
143 * after the IT fires. But it's arbitrary how much time passes
144 * before we call it "late". I've picked one second.
145 *
146 * It's important NO printk's are between reading CR16 and
147 * setting up the next value. May introduce huge variance.
148 */
149 if (unlikely(ticks_elapsed > HZ)) {
150 /* Scenario 3: very long delay? bad in any case */
151 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
152 " cycles %lX rem %lX "
153 " next/now %lX/%lX\n",
154 cpu,
155 cycles_elapsed, cycles_remainder,
156 next_tick, now );
157 }
158
159 /* Done mucking with unreliable delivery of interrupts.
160 * Go do system house keeping.
161 */ 112 */
162 113 if (next_tick - mfctl(16) <= 500)
163 if (!--cpuinfo->prof_counter) { 114 next_tick += cpt;
164 cpuinfo->prof_counter = cpuinfo->prof_multiplier; 115 mtctl(next_tick, 16);
165 update_process_times(user_mode(get_irq_regs()));
166 }
167
168 if (cpu == 0)
169 xtime_update(ticks_elapsed);
170 116
171 return IRQ_HANDLED; 117 return IRQ_HANDLED;
172} 118}