diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/leon.h | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/entry.S | 16 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 39 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_smp.c | 12 |
4 files changed, 22 insertions, 51 deletions
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 12712541e9ee..204dc0f0243f 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h | |||
@@ -239,7 +239,7 @@ static inline int sparc_leon3_cpuid(void) | |||
239 | 239 | ||
240 | #ifdef CONFIG_SMP | 240 | #ifdef CONFIG_SMP |
241 | # define LEON3_IRQ_RESCHEDULE 13 | 241 | # define LEON3_IRQ_RESCHEDULE 13 |
242 | # define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) | 242 | # define LEON3_IRQ_TICKER (leon3_ticker_irq) |
243 | # define LEON3_IRQ_CROSS_CALL 15 | 243 | # define LEON3_IRQ_CROSS_CALL 15 |
244 | #endif | 244 | #endif |
245 | 245 | ||
@@ -357,6 +357,7 @@ extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); | |||
357 | extern int leon_flush_needed(void); | 357 | extern int leon_flush_needed(void); |
358 | extern void leon_switch_mm(void); | 358 | extern void leon_switch_mm(void); |
359 | extern int srmmu_swprobe_trace; | 359 | extern int srmmu_swprobe_trace; |
360 | extern int leon3_ticker_irq; | ||
360 | 361 | ||
361 | #ifdef CONFIG_SMP | 362 | #ifdef CONFIG_SMP |
362 | extern int leon_smp_nrcpus(void); | 363 | extern int leon_smp_nrcpus(void); |
@@ -371,8 +372,9 @@ extern void init_IRQ(void); | |||
371 | extern void cpu_panic(void); | 372 | extern void cpu_panic(void); |
372 | extern int __leon_processor_id(void); | 373 | extern int __leon_processor_id(void); |
373 | void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); | 374 | void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); |
375 | extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused); | ||
374 | 376 | ||
375 | extern unsigned int real_irq_entry[], smpleon_ticker[]; | 377 | extern unsigned int real_irq_entry[]; |
376 | extern unsigned int patchme_maybe_smp_msg[]; | 378 | extern unsigned int patchme_maybe_smp_msg[]; |
377 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; | 379 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; |
378 | extern unsigned int linux_trap_ipi15_sun4m[]; | 380 | extern unsigned int linux_trap_ipi15_sun4m[]; |
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 6da784a5612b..1879739c9588 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -401,22 +401,6 @@ linux_trap_ipi15_sun4d: | |||
401 | 1: b,a 1b | 401 | 1: b,a 1b |
402 | 402 | ||
403 | #ifdef CONFIG_SPARC_LEON | 403 | #ifdef CONFIG_SPARC_LEON |
404 | |||
405 | .globl smpleon_ticker | ||
406 | /* SMP per-cpu ticker interrupts are handled specially. */ | ||
407 | smpleon_ticker: | ||
408 | SAVE_ALL | ||
409 | or %l0, PSR_PIL, %g2 | ||
410 | wr %g2, 0x0, %psr | ||
411 | WRITE_PAUSE | ||
412 | wr %g2, PSR_ET, %psr | ||
413 | WRITE_PAUSE | ||
414 | call leon_percpu_timer_interrupt | ||
415 | add %sp, STACKFRAME_SZ, %o0 | ||
416 | wr %l0, PSR_ET, %psr | ||
417 | WRITE_PAUSE | ||
418 | RESTORE_ALL | ||
419 | |||
420 | .align 4 | 404 | .align 4 |
421 | .globl linux_trap_ipi15_leon | 405 | .globl linux_trap_ipi15_leon |
422 | linux_trap_ipi15_leon: | 406 | linux_trap_ipi15_leon: |
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 210f4a0a8457..d867543edfe1 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ | 27 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ |
28 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ | 28 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ |
29 | struct amba_apb_device leon_percpu_timer_dev[16]; | ||
30 | 29 | ||
31 | int leondebug_irq_disable; | 30 | int leondebug_irq_disable; |
32 | int leon_debug_irqout; | 31 | int leon_debug_irqout; |
@@ -36,6 +35,7 @@ static DEFINE_SPINLOCK(leon_irq_lock); | |||
36 | 35 | ||
37 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | 36 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
38 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | 37 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ |
38 | int leon3_ticker_irq; /* Timer ticker IRQ */ | ||
39 | unsigned int sparc_leon_eirq; | 39 | unsigned int sparc_leon_eirq; |
40 | #define LEON_IMASK (&leon3_irqctrl_regs->mask[0]) | 40 | #define LEON_IMASK (&leon3_irqctrl_regs->mask[0]) |
41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) | 41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) |
@@ -271,9 +271,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
271 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); | 271 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); |
272 | 272 | ||
273 | #ifdef CONFIG_SMP | 273 | #ifdef CONFIG_SMP |
274 | leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; | 274 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; |
275 | leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 + | ||
276 | leon3_gptimer_idx; | ||
277 | 275 | ||
278 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | 276 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & |
279 | (1<<LEON3_GPTIMER_SEPIRQ))) { | 277 | (1<<LEON3_GPTIMER_SEPIRQ))) { |
@@ -322,27 +320,6 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
322 | prom_halt(); | 320 | prom_halt(); |
323 | } | 321 | } |
324 | 322 | ||
325 | # ifdef CONFIG_SMP | ||
326 | { | ||
327 | unsigned long flags; | ||
328 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; | ||
329 | |||
330 | /* For SMP we use the level 14 ticker, however the bootup code | ||
331 | * has copied the firmwares level 14 vector into boot cpu's | ||
332 | * trap table, we must fix this now or we get squashed. | ||
333 | */ | ||
334 | local_irq_save(flags); | ||
335 | |||
336 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ | ||
337 | |||
338 | /* Adjust so that we jump directly to smpleon_ticker */ | ||
339 | trap_table->inst_three += smpleon_ticker - real_irq_entry; | ||
340 | |||
341 | local_flush_cache_all(); | ||
342 | local_irq_restore(flags); | ||
343 | } | ||
344 | # endif | ||
345 | |||
346 | if (leon3_gptimer_regs) { | 323 | if (leon3_gptimer_regs) { |
347 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, | 324 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, |
348 | LEON3_GPTIMER_EN | | 325 | LEON3_GPTIMER_EN | |
@@ -350,6 +327,18 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
350 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); | 327 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); |
351 | 328 | ||
352 | #ifdef CONFIG_SMP | 329 | #ifdef CONFIG_SMP |
330 | /* Install per-cpu IRQ handler for broadcasted ticker */ | ||
331 | irq = leon_build_device_irq(leon3_ticker_irq, | ||
332 | handle_percpu_irq, "per-cpu", | ||
333 | 0); | ||
334 | err = request_irq(irq, leon_percpu_timer_interrupt, | ||
335 | IRQF_PERCPU | IRQF_TIMER, "ticker", | ||
336 | NULL); | ||
337 | if (err) { | ||
338 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); | ||
339 | prom_halt(); | ||
340 | } | ||
341 | |||
353 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | 342 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, |
354 | LEON3_GPTIMER_EN | | 343 | LEON3_GPTIMER_EN | |
355 | LEON3_GPTIMER_RL | | 344 | LEON3_GPTIMER_RL | |
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 8f5de4aa3c0a..053eca9f78e9 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
@@ -386,27 +386,23 @@ void leon_cross_call_irq(void) | |||
386 | ccall_info.processors_out[i] = 1; | 386 | ccall_info.processors_out[i] = 1; |
387 | } | 387 | } |
388 | 388 | ||
389 | void leon_percpu_timer_interrupt(struct pt_regs *regs) | 389 | irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) |
390 | { | 390 | { |
391 | struct pt_regs *old_regs; | ||
392 | int cpu = smp_processor_id(); | 391 | int cpu = smp_processor_id(); |
393 | 392 | ||
394 | old_regs = set_irq_regs(regs); | ||
395 | |||
396 | leon_clear_profile_irq(cpu); | 393 | leon_clear_profile_irq(cpu); |
397 | 394 | ||
398 | profile_tick(CPU_PROFILING); | 395 | profile_tick(CPU_PROFILING); |
399 | 396 | ||
400 | if (!--prof_counter(cpu)) { | 397 | if (!--prof_counter(cpu)) { |
401 | int user = user_mode(regs); | 398 | int user = user_mode(get_irq_regs()); |
402 | 399 | ||
403 | irq_enter(); | ||
404 | update_process_times(user); | 400 | update_process_times(user); |
405 | irq_exit(); | ||
406 | 401 | ||
407 | prof_counter(cpu) = prof_multiplier(cpu); | 402 | prof_counter(cpu) = prof_multiplier(cpu); |
408 | } | 403 | } |
409 | set_irq_regs(old_regs); | 404 | |
405 | return IRQ_HANDLED; | ||
410 | } | 406 | } |
411 | 407 | ||
412 | static void __init smp_setup_percpu_timer(void) | 408 | static void __init smp_setup_percpu_timer(void) |