From patchwork Mon Apr 22 14:21:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 2472191 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id 1BABDDF23A for ; Mon, 22 Apr 2013 14:22:15 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUHcr-0005D5-3U; Mon, 22 Apr 2013 14:21:49 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUHcd-0001SO-2C; Mon, 22 Apr 2013 14:21:35 +0000 Received: from galois.linutronix.de ([2001:470:1f0b:db:abcd:42:0:1]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUHcY-0001S1-Bq for linux-arm-kernel@lists.infradead.org; Mon, 22 Apr 2013 14:21:31 +0000 Received: from localhost ([127.0.0.1]) by Galois.linutronix.de with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1UUHcS-0004Y2-Rv; Mon, 22 Apr 2013 16:21:25 +0200 Date: Mon, 22 Apr 2013 16:21:23 +0200 (CEST) From: Thomas Gleixner To: =?ISO-8859-15?Q?Uwe_Kleine-K=F6nig?= Subject: Re: [PATCH v3] irqchip: Add support for ARMv7-M's NVIC In-Reply-To: <20130422100219.GH15233@pengutronix.de> Message-ID: References: <1366214540-31166-1-git-send-email-u.kleine-koenig@pengutronix.de> <20130419150927.GE15233@pengutronix.de> <20130422100219.GH15233@pengutronix.de> User-Agent: Alpine 2.02 (LFD 1266 2009-07-14) MIME-Version: 1.0 X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1, SHORTCIRCUIT=-0.0001 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130422_102130_831685_D82108EA X-CRM114-Status: GOOD ( 17.16 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Jonathan Austin , Arnd Bergmann , linux-sh@vger.kernel.org, Catalin Marinas , linux-kernel@vger.kernel.org, Paul Mundt , kernel@pengutronix.de, Benjamin Herrenschmidt , Grant Likely , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org On Mon, 22 Apr 2013, Uwe Kleine-König wrote: > The options I see are: > > - introduce a new set of functions > Do you have a nice naming scheme? > irq_gc_unmask_enable_reg_hwirqmod32? Or should I rename the existing > ones to irq_gc_unmask_enable_reg_irqbaseoffset? Shudder. We do not need new functions at all, we just need to think a bit. > - use > u32 mask = 1 << (d->hwirq - gc->irq_base) % 32; > This is ugly but might work assuming irq_base == 0 for chips with irq > domain support and hwirq == irq for the others. Which is not correct, as hwirq is always 0 for !irqdomain users. And no, we don't set it to irq. Calculating the mask over and over is stupid to begin with. We can precompute it and store it in irq_data->mask. For the existing generic chip users we simply precompute it with 1 << (d->hwirq - gc->irq_base) and let the irqdomain code calculate it for everything else. Hmm? Thanks, tglx diff --git a/include/linux/irq.h b/include/linux/irq.h index bc4e066..03fd64a 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -119,6 +119,7 @@ struct irq_domain; /** * struct irq_data - per irq and irq chip data passed down to chip functions + * @mask: precomputed bitmask for accessing the chip registers * @irq: interrupt number * @hwirq: hardware interrupt number, local to the interrupt domain * @node: node index useful for balancing @@ -138,6 +139,7 @@ struct irq_domain; * irq_data. */ struct irq_data { + u32 mask; unsigned int irq; unsigned long hwirq; unsigned int node; @@ -700,10 +702,14 @@ struct irq_chip_generic { * @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for * irq chips which need to call irq_set_wake() on * the parent irq. Usually GPIO implementations + * @IRQ_GC_NO_MASK: Do not calculate irq_data->mask + * @IRQ_GC_MASK_FROM_HWIRQ: Calculate irq_data->mask from the hwirq number */ enum irq_gc_flags { IRQ_GC_INIT_MASK_CACHE = 1 << 0, IRQ_GC_INIT_NESTED_LOCK = 1 << 1, + IRQ_GC_NO_MASK = 1 << 2, + IRQ_GC_MASK_FROM_HWIRQ = 1 << 4, }; /* Generic chip callback functions */ diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index c89295a..a013a35 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c @@ -39,7 +39,7 @@ void irq_gc_noop(struct irq_data *d) void irq_gc_mask_disable_reg(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable); @@ -57,7 +57,7 @@ void irq_gc_mask_disable_reg(struct irq_data *d) void irq_gc_mask_set_bit(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); gc->mask_cache |= mask; @@ -75,7 +75,7 @@ void irq_gc_mask_set_bit(struct irq_data *d) void irq_gc_mask_clr_bit(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); gc->mask_cache &= ~mask; @@ -93,7 +93,7 @@ void irq_gc_mask_clr_bit(struct irq_data *d) void irq_gc_unmask_enable_reg(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable); @@ -108,7 +108,7 @@ void irq_gc_unmask_enable_reg(struct irq_data *d) void irq_gc_ack_set_bit(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); @@ -122,7 +122,7 @@ void irq_gc_ack_set_bit(struct irq_data *d) void irq_gc_ack_clr_bit(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = ~(1 << (d->irq - gc->irq_base)); + u32 mask = ~d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); @@ -136,7 +136,7 @@ void irq_gc_ack_clr_bit(struct irq_data *d) void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask); @@ -151,7 +151,7 @@ void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) void irq_gc_eoi(struct irq_data *d) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; irq_gc_lock(gc); irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi); @@ -169,7 +169,7 @@ void irq_gc_eoi(struct irq_data *d) int irq_gc_set_wake(struct irq_data *d, unsigned int on) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - u32 mask = 1 << (d->irq - gc->irq_base); + u32 mask = d->mask; if (!(mask & gc->wake_enabled)) return -EINVAL; @@ -254,6 +254,15 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, if (flags & IRQ_GC_INIT_NESTED_LOCK) irq_set_lockdep_class(i, &irq_nested_lock_class); + if (!(flags & IRQ_GC_NO_MASK)) { + struct irq_data *d = irq_get_irq_data(i); + u32 mask; + + if (flags & IRQ_GC_MASK_FROM_HWIRQ) + d->mask = 1 << (d->hwirq % 32); + else + d->mask = 1 << (i - gc->irq_base); + } irq_set_chip_and_handler(i, &ct->chip, ct->handler); irq_set_chip_data(i, gc); irq_modify_status(i, clr, set);