From patchwork Wed Apr 20 09:41:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Hellstrom X-Patchwork-Id: 92128 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 9B2E71007D9 for ; Wed, 20 Apr 2011 19:42:16 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752874Ab1DTJmQ (ORCPT ); Wed, 20 Apr 2011 05:42:16 -0400 Received: from mail168c2.megamailservers.com ([69.49.111.68]:54221 "EHLO mail168c2.megamailservers.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752722Ab1DTJmP (ORCPT ); Wed, 20 Apr 2011 05:42:15 -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 p3K9g4Tv028534; Wed, 20 Apr 2011 05:42:11 -0400 From: Daniel Hellstrom To: davem@davemloft.net Cc: sparclinux@vger.kernel.org, sam@ravnborg.org Subject: [PATCH 7/8] sparc32,leon: implement genirq CPU affinity Date: Wed, 20 Apr 2011 11:41:26 +0200 Message-Id: <1303292487-12623-7-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=qgFiT_ujwqkA:10 a=U62ajLuCel8A:10 a=jXKJviUpWSOlMmIvGrHOfw==:17 a=ebG-ZW-8AAAA:8 a=7gkXJVJtAAAA:8 a=AqA0BgxVnAcN_yStZBsA:9 a=Of9ElwK2PSXu3JAsthMA:7 a=cCYF7-FHeg4A:10 a=JmBWkid0h3cA:10 a=jXKJviUpWSOlMmIvGrHOfw==:117 Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org A simple implementation of CPU affinity, the first CPU in the affinity CPU mask always takes the IRQ. Signed-off-by: Daniel Hellstrom Acked-by: Sam Ravnborg --- arch/sparc/kernel/leon_kernel.c | 64 ++++++++++++++++++++++++++++++++------ 1 files changed, 54 insertions(+), 10 deletions(-) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index d8fafea..ab14584 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -99,25 +99,68 @@ static inline unsigned long get_irqmask(unsigned int irq) return mask; } +#ifdef CONFIG_SMP +static int irq_choose_cpu(const struct cpumask *affinity) +{ + cpumask_t mask; + + cpus_and(mask, cpu_online_map, *affinity); + if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) + return 0; + else + return first_cpu(mask); +} +#else +#define irq_choose_cpu(affinity) 0 +#endif + +static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest, + bool force) +{ + unsigned long mask, oldmask, flags; + int oldcpu, newcpu; + + mask = (unsigned long)data->chip_data; + oldcpu = irq_choose_cpu(data->affinity); + newcpu = irq_choose_cpu(dest); + + if (oldcpu == newcpu) + goto out; + + /* unmask on old CPU first before enabling on the selected CPU */ + spin_lock_irqsave(&leon_irq_lock, flags); + oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu)); + LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask)); + oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu)); + LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask)); + spin_unlock_irqrestore(&leon_irq_lock, flags); +out: + return IRQ_SET_MASK_OK; +} + static void leon_unmask_irq(struct irq_data *data) { unsigned long mask, oldmask, flags; + int cpu; mask = (unsigned long)data->chip_data; + cpu = irq_choose_cpu(data->affinity); spin_lock_irqsave(&leon_irq_lock, flags); - oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); - LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); + oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu)); + LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask)); spin_unlock_irqrestore(&leon_irq_lock, flags); } static void leon_mask_irq(struct irq_data *data) { unsigned long mask, oldmask, flags; + int cpu; mask = (unsigned long)data->chip_data; + cpu = irq_choose_cpu(data->affinity); spin_lock_irqsave(&leon_irq_lock, flags); - oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); - LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask & ~mask)); + oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu)); + LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask)); spin_unlock_irqrestore(&leon_irq_lock, flags); } @@ -144,12 +187,13 @@ static void leon_eoi_irq(struct irq_data *data) } static struct irq_chip leon_irq = { - .name = "leon", - .irq_startup = leon_startup_irq, - .irq_shutdown = leon_shutdown_irq, - .irq_mask = leon_mask_irq, - .irq_unmask = leon_unmask_irq, - .irq_eoi = leon_eoi_irq, + .name = "leon", + .irq_startup = leon_startup_irq, + .irq_shutdown = leon_shutdown_irq, + .irq_mask = leon_mask_irq, + .irq_unmask = leon_unmask_irq, + .irq_eoi = leon_eoi_irq, + .irq_set_affinity = leon_set_affinity, }; /*