aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-04-19 19:41:23 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-21 18:31:30 -0400
commit2cf9530420e446bb61f665d02afeb81070106900 (patch)
tree157ee818554017ed8495a0556d30d38e662d2be9 /arch
parent4c6773c3954cb1192f70a63e2dc61adc55bb0948 (diff)
sparc32,leon: per-cpu ticker use genirq per-cpu handler
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/include/asm/leon.h6
-rw-r--r--arch/sparc/kernel/entry.S16
-rw-r--r--arch/sparc/kernel/leon_kernel.c39
-rw-r--r--arch/sparc/kernel/leon_smp.c12
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);
357extern int leon_flush_needed(void); 357extern int leon_flush_needed(void);
358extern void leon_switch_mm(void); 358extern void leon_switch_mm(void);
359extern int srmmu_swprobe_trace; 359extern int srmmu_swprobe_trace;
360extern int leon3_ticker_irq;
360 361
361#ifdef CONFIG_SMP 362#ifdef CONFIG_SMP
362extern int leon_smp_nrcpus(void); 363extern int leon_smp_nrcpus(void);
@@ -371,8 +372,9 @@ extern void init_IRQ(void);
371extern void cpu_panic(void); 372extern void cpu_panic(void);
372extern int __leon_processor_id(void); 373extern int __leon_processor_id(void);
373void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); 374void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
375extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
374 376
375extern unsigned int real_irq_entry[], smpleon_ticker[]; 377extern unsigned int real_irq_entry[];
376extern unsigned int patchme_maybe_smp_msg[]; 378extern unsigned int patchme_maybe_smp_msg[];
377extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; 379extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
378extern unsigned int linux_trap_ipi15_sun4m[]; 380extern 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:
4011: b,a 1b 4011: 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. */
407smpleon_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
422linux_trap_ipi15_leon: 406linux_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
27struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ 27struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
28struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ 28struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
29struct amba_apb_device leon_percpu_timer_dev[16];
30 29
31int leondebug_irq_disable; 30int leondebug_irq_disable;
32int leon_debug_irqout; 31int leon_debug_irqout;
@@ -36,6 +35,7 @@ static DEFINE_SPINLOCK(leon_irq_lock);
36 35
37unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ 36unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
38unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ 37unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
38int leon3_ticker_irq; /* Timer ticker IRQ */
39unsigned int sparc_leon_eirq; 39unsigned 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
389void leon_percpu_timer_interrupt(struct pt_regs *regs) 389irqreturn_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
412static void __init smp_setup_percpu_timer(void) 408static void __init smp_setup_percpu_timer(void)