From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751535AbdGaTda (ORCPT ); Mon, 31 Jul 2017 15:33:30 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:42150 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751013AbdGaTd3 (ORCPT ); Mon, 31 Jul 2017 15:33:29 -0400 Date: Mon, 31 Jul 2017 21:33:25 +0200 (CEST) From: Thomas Gleixner To: Benjamin Herrenschmidt cc: Daniel Lezcano , "linux-kernel@vger.kernel.org" , Marc Zyngier Subject: [PATCH] genirq: Provide IRQCHIP_ONESHOT_EDGE_SAFE Message-ID: User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If an interrupt chip is marked IRQCHIP_ONESHOT_SAFE it signals that the interrupt chip does not require the ONESHOT mode for threaded interrupts. Unfortunately this is applied independent of the interrupt type (edge/level). The powerpc XPIC wants this functionality only for edge type interrupts. Provide a new flag which provides the same functionality restricted to edge type interrupts. Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 ++ kernel/irq/debugfs.c | 1 + kernel/irq/manage.c | 34 +++++++++++++++++++++------------- 3 files changed, 24 insertions(+), 13 deletions(-) --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -481,6 +481,7 @@ struct irq_chip { * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode + * IRQCHIP_ONESHOT_EDGE_SAFE: Skip the oneshot logic for edge type interrupts */ enum { IRQCHIP_SET_TYPE_MASKED = (1 << 0), @@ -490,6 +491,7 @@ enum { IRQCHIP_SKIP_SET_WAKE = (1 << 4), IRQCHIP_ONESHOT_SAFE = (1 << 5), IRQCHIP_EOI_THREADED = (1 << 6), + IRQCHIP_ONESHOT_EDGE_SAFE = (1 << 7), }; #include --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -56,6 +56,7 @@ static const struct irq_bit_descr irqchi BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), + BIT_MASK_DESCR(IRQCHIP_ONESHOT_EDGE_SAFE), }; static void --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1166,18 +1166,6 @@ static int } /* - * Drivers are often written to work w/o knowledge about the - * underlying irq chip implementation, so a request for a - * threaded irq without a primary hard irq context handler - * requires the ONESHOT flag to be set. Some irq chips like - * MSI based interrupts are per se one shot safe. Check the - * chip flags, so we can avoid the unmask dance at the end of - * the threaded handler for those. - */ - if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) - new->flags &= ~IRQF_ONESHOT; - - /* * Protects against a concurrent __free_irq() call which might wait * for synchronize_irq() to complete without holding the optional * chip bus lock and desc->lock. @@ -1208,6 +1196,25 @@ static int * desc->request_mutex or the optional bus lock. */ raw_spin_lock_irqsave(&desc->lock, flags); + + /* + * Drivers are often written to work w/o knowledge about the + * underlying irq chip implementation, so a request for a + * threaded irq without a primary hard irq context handler + * requires the ONESHOT flag to be set. Some irq chips like + * MSI based interrupts are per se one shot safe. Check the + * chip flags, so we can avoid the unmask dance at the end of + * the threaded handler for those. + */ + if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) + new->flags &= ~IRQF_ONESHOT; + + /* Same as above, but restricted to edge type interrupts */ + if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_EDGE_SAFE) { + if (!irq_settings_is_level(desc)) + new->flags &= ~IRQF_ONESHOT; + } + old_ptr = &desc->action; old = *old_ptr; if (old) { @@ -1281,7 +1288,8 @@ static int new->thread_mask = 1 << ffz(thread_mask); } else if (new->handler == irq_default_primary_handler && - !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { + !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) && + !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_EDGE_SAFE)) { /* * The interrupt was requested with handler = NULL, so * we use the default primary handler for it. But it