From patchwork Wed Apr 20 09:41:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Hellstrom X-Patchwork-Id: 92131 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 081801007D9 for ; Wed, 20 Apr 2011 19:42:19 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752973Ab1DTJmR (ORCPT ); Wed, 20 Apr 2011 05:42:17 -0400 Received: from mail168c2.megamailservers.com ([69.49.111.68]:54225 "EHLO mail168c2.megamailservers.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752913Ab1DTJmQ (ORCPT ); Wed, 20 Apr 2011 05:42:16 -0400 X-POP-User: ekergarn.gaisler.com Received: from localhost.localdomain (gaisler.se [92.33.28.242]) by mail168c2.megamailservers.com (8.13.6/8.13.1) with ESMTP id p3K9g4Ts028534; Wed, 20 Apr 2011 05:42:08 -0400 From: Daniel Hellstrom To: davem@davemloft.net Cc: sparclinux@vger.kernel.org, sam@ravnborg.org Subject: [PATCH 4/8] sparc32, leon: per-cpu ticker use genirq per-cpu handler Date: Wed, 20 Apr 2011 11:41:23 +0200 Message-Id: <1303292487-12623-4-git-send-email-daniel@gaisler.com> X-Mailer: git-send-email 1.5.4 In-Reply-To: <1303292487-12623-1-git-send-email-daniel@gaisler.com> References: <1303292487-12623-1-git-send-email-daniel@gaisler.com> X-CSC: 0 X-CHA: v=1.1 cv=6CA6lOutKNv3S0yVbd4vJ0+Coro52Wh1FxrCWVcgkas= c=1 sm=1 a=XA5yD2Dl1woA:10 a=U62ajLuCel8A:10 a=jXKJviUpWSOlMmIvGrHOfw==:17 a=ebG-ZW-8AAAA:8 a=7gkXJVJtAAAA:8 a=fenn5-jDWcgumkV2GCAA:9 a=PNNagKmTkQFXj8SLQFoA:7 a=cCYF7-FHeg4A:10 a=JmBWkid0h3cA:10 a=kb-E8dydEizAPhL5:21 a=kpoDX-jfpQQUslfw:21 a=jXKJviUpWSOlMmIvGrHOfw==:117 Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org Signed-off-by: Daniel Hellstrom Acked-by: Sam Ravnborg --- arch/sparc/include/asm/leon.h | 6 ++++-- arch/sparc/kernel/entry.S | 16 ---------------- arch/sparc/kernel/leon_kernel.c | 39 ++++++++++++++------------------------- 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 1271254..204dc0f 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) #ifdef CONFIG_SMP # define LEON3_IRQ_RESCHEDULE 13 -# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) +# define LEON3_IRQ_TICKER (leon3_ticker_irq) # define LEON3_IRQ_CROSS_CALL 15 #endif @@ -357,6 +357,7 @@ extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); extern int leon_flush_needed(void); extern void leon_switch_mm(void); extern int srmmu_swprobe_trace; +extern int leon3_ticker_irq; #ifdef CONFIG_SMP extern int leon_smp_nrcpus(void); @@ -371,8 +372,9 @@ extern void init_IRQ(void); extern void cpu_panic(void); extern int __leon_processor_id(void); void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); +extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused); -extern unsigned int real_irq_entry[], smpleon_ticker[]; +extern unsigned int real_irq_entry[]; extern unsigned int patchme_maybe_smp_msg[]; extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; extern unsigned int linux_trap_ipi15_sun4m[]; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 6da784a..1879739 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -401,22 +401,6 @@ linux_trap_ipi15_sun4d: 1: b,a 1b #ifdef CONFIG_SPARC_LEON - - .globl smpleon_ticker - /* SMP per-cpu ticker interrupts are handled specially. */ -smpleon_ticker: - SAVE_ALL - or %l0, PSR_PIL, %g2 - wr %g2, 0x0, %psr - WRITE_PAUSE - wr %g2, PSR_ET, %psr - WRITE_PAUSE - call leon_percpu_timer_interrupt - add %sp, STACKFRAME_SZ, %o0 - wr %l0, PSR_ET, %psr - WRITE_PAUSE - RESTORE_ALL - .align 4 .globl linux_trap_ipi15_leon linux_trap_ipi15_leon: diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 210f4a0..d867543 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -26,7 +26,6 @@ struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ -struct amba_apb_device leon_percpu_timer_dev[16]; int leondebug_irq_disable; int leon_debug_irqout; @@ -36,6 +35,7 @@ static DEFINE_SPINLOCK(leon_irq_lock); unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ +int leon3_ticker_irq; /* Timer ticker IRQ */ unsigned int sparc_leon_eirq; #define LEON_IMASK (&leon3_irqctrl_regs->mask[0]) #define LEON_IACK (&leon3_irqctrl_regs->iclear) @@ -271,9 +271,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); #ifdef CONFIG_SMP - leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; - leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 + - leon3_gptimer_idx; + leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & (1<inst_three += smpleon_ticker - real_irq_entry; - - local_flush_cache_all(); - local_irq_restore(flags); - } -# endif - if (leon3_gptimer_regs) { LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, LEON3_GPTIMER_EN | @@ -350,6 +327,18 @@ void __init leon_init_timers(irq_handler_t counter_fn) LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); #ifdef CONFIG_SMP + /* Install per-cpu IRQ handler for broadcasted ticker */ + irq = leon_build_device_irq(leon3_ticker_irq, + handle_percpu_irq, "per-cpu", + 0); + err = request_irq(irq, leon_percpu_timer_interrupt, + IRQF_PERCPU | IRQF_TIMER, "ticker", + NULL); + if (err) { + printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); + prom_halt(); + } + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 8f5de4a..053eca9 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) ccall_info.processors_out[i] = 1; } -void leon_percpu_timer_interrupt(struct pt_regs *regs) +irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) { - struct pt_regs *old_regs; int cpu = smp_processor_id(); - old_regs = set_irq_regs(regs); - leon_clear_profile_irq(cpu); profile_tick(CPU_PROFILING); if (!--prof_counter(cpu)) { - int user = user_mode(regs); + int user = user_mode(get_irq_regs()); - irq_enter(); update_process_times(user); - irq_exit(); prof_counter(cpu) = prof_multiplier(cpu); } - set_irq_regs(old_regs); + + return IRQ_HANDLED; } static void __init smp_setup_percpu_timer(void)