diff options
author | Jack Steiner <steiner@sgi.com> | 2007-05-08 17:50:43 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-05-08 17:50:43 -0400 |
commit | 3be44b9cc33d26930cb3bb014f35f582c6522481 (patch) | |
tree | 09225c5f0fb4c6caa81bbdff216ec83a093e4d12 /arch/ia64/kernel/irq_ia64.c | |
parent | 8737d59579c5e61ea3d5da4bd63303159fd1cf7e (diff) |
[IA64] Optional method to purge the TLB on SN systems
This patch adds an optional method for purging the TLB on SN IA64 systems.
The change should not affect any non-SN system.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/irq_ia64.c')
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 456f57b087ca..9a5f41be760b 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/machvec.h> | 39 | #include <asm/machvec.h> |
40 | #include <asm/pgtable.h> | 40 | #include <asm/pgtable.h> |
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/tlbflush.h> | ||
42 | 43 | ||
43 | #ifdef CONFIG_PERFMON | 44 | #ifdef CONFIG_PERFMON |
44 | # include <asm/perfmon.h> | 45 | # include <asm/perfmon.h> |
@@ -127,8 +128,10 @@ void destroy_irq(unsigned int irq) | |||
127 | 128 | ||
128 | #ifdef CONFIG_SMP | 129 | #ifdef CONFIG_SMP |
129 | # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) | 130 | # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) |
131 | # define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH) | ||
130 | #else | 132 | #else |
131 | # define IS_RESCHEDULE(vec) (0) | 133 | # define IS_RESCHEDULE(vec) (0) |
134 | # define IS_LOCAL_TLB_FLUSH(vec) (0) | ||
132 | #endif | 135 | #endif |
133 | /* | 136 | /* |
134 | * That's where the IVT branches when we get an external | 137 | * That's where the IVT branches when we get an external |
@@ -180,8 +183,11 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) | |||
180 | saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); | 183 | saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); |
181 | ia64_srlz_d(); | 184 | ia64_srlz_d(); |
182 | while (vector != IA64_SPURIOUS_INT_VECTOR) { | 185 | while (vector != IA64_SPURIOUS_INT_VECTOR) { |
183 | if (unlikely(IS_RESCHEDULE(vector))) | 186 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { |
184 | kstat_this_cpu.irqs[vector]++; | 187 | smp_local_flush_tlb(); |
188 | kstat_this_cpu.irqs[vector]++; | ||
189 | } else if (unlikely(IS_RESCHEDULE(vector))) | ||
190 | kstat_this_cpu.irqs[vector]++; | ||
185 | else { | 191 | else { |
186 | ia64_setreg(_IA64_REG_CR_TPR, vector); | 192 | ia64_setreg(_IA64_REG_CR_TPR, vector); |
187 | ia64_srlz_d(); | 193 | ia64_srlz_d(); |
@@ -227,8 +233,11 @@ void ia64_process_pending_intr(void) | |||
227 | * Perform normal interrupt style processing | 233 | * Perform normal interrupt style processing |
228 | */ | 234 | */ |
229 | while (vector != IA64_SPURIOUS_INT_VECTOR) { | 235 | while (vector != IA64_SPURIOUS_INT_VECTOR) { |
230 | if (unlikely(IS_RESCHEDULE(vector))) | 236 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { |
231 | kstat_this_cpu.irqs[vector]++; | 237 | smp_local_flush_tlb(); |
238 | kstat_this_cpu.irqs[vector]++; | ||
239 | } else if (unlikely(IS_RESCHEDULE(vector))) | ||
240 | kstat_this_cpu.irqs[vector]++; | ||
232 | else { | 241 | else { |
233 | struct pt_regs *old_regs = set_irq_regs(NULL); | 242 | struct pt_regs *old_regs = set_irq_regs(NULL); |
234 | 243 | ||
@@ -260,12 +269,12 @@ void ia64_process_pending_intr(void) | |||
260 | 269 | ||
261 | 270 | ||
262 | #ifdef CONFIG_SMP | 271 | #ifdef CONFIG_SMP |
263 | extern irqreturn_t handle_IPI (int irq, void *dev_id); | ||
264 | 272 | ||
265 | static irqreturn_t dummy_handler (int irq, void *dev_id) | 273 | static irqreturn_t dummy_handler (int irq, void *dev_id) |
266 | { | 274 | { |
267 | BUG(); | 275 | BUG(); |
268 | } | 276 | } |
277 | extern irqreturn_t handle_IPI (int irq, void *dev_id); | ||
269 | 278 | ||
270 | static struct irqaction ipi_irqaction = { | 279 | static struct irqaction ipi_irqaction = { |
271 | .handler = handle_IPI, | 280 | .handler = handle_IPI, |
@@ -278,6 +287,13 @@ static struct irqaction resched_irqaction = { | |||
278 | .flags = IRQF_DISABLED, | 287 | .flags = IRQF_DISABLED, |
279 | .name = "resched" | 288 | .name = "resched" |
280 | }; | 289 | }; |
290 | |||
291 | static struct irqaction tlb_irqaction = { | ||
292 | .handler = dummy_handler, | ||
293 | .flags = SA_INTERRUPT, | ||
294 | .name = "tlb_flush" | ||
295 | }; | ||
296 | |||
281 | #endif | 297 | #endif |
282 | 298 | ||
283 | void | 299 | void |
@@ -303,6 +319,7 @@ init_IRQ (void) | |||
303 | #ifdef CONFIG_SMP | 319 | #ifdef CONFIG_SMP |
304 | register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); | 320 | register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); |
305 | register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); | 321 | register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); |
322 | register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); | ||
306 | #endif | 323 | #endif |
307 | #ifdef CONFIG_PERFMON | 324 | #ifdef CONFIG_PERFMON |
308 | pfm_init_percpu(); | 325 | pfm_init_percpu(); |