From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753452AbbBRRK5 (ORCPT ); Wed, 18 Feb 2015 12:10:57 -0500 Received: from terminus.zytor.com ([198.137.202.10]:39142 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752450AbbBRRKz (ORCPT ); Wed, 18 Feb 2015 12:10:55 -0500 Date: Wed, 18 Feb 2015 09:08:42 -0800 From: tip-bot for Peter Zijlstra Message-ID: Cc: lambert.quentin@gmail.com, arnd@arndb.de, peterz@infradead.org, mingo@kernel.org, rdunlap@infradead.org, sd@queasysnail.net, linux-kernel@vger.kernel.org, linux@arm.linux.org.uk, paulmck@linux.vnet.ibm.com, hpa@zytor.com, tglx@linutronix.de, davem@davemloft.net, torvalds@linux-foundation.org, eyalpe@mellanox.com Reply-To: mingo@kernel.org, rdunlap@infradead.org, sd@queasysnail.net, arnd@arndb.de, lambert.quentin@gmail.com, peterz@infradead.org, hpa@zytor.com, tglx@linutronix.de, paulmck@linux.vnet.ibm.com, torvalds@linux-foundation.org, davem@davemloft.net, eyalpe@mellanox.com, linux-kernel@vger.kernel.org, linux@arm.linux.org.uk In-Reply-To: <20150205130623.GH5029@twins.programming.kicks-ass.net> References: <20150205130623.GH5029@twins.programming.kicks-ass.net> To: linux-tip-commits@vger.kernel.org Subject: [tip:irq/core] genirq: Provide disable_hardirq() Git-Commit-ID: 02cea3958664723a5d2236f0f0058de97c7e4693 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 02cea3958664723a5d2236f0f0058de97c7e4693 Gitweb: http://git.kernel.org/tip/02cea3958664723a5d2236f0f0058de97c7e4693 Author: Peter Zijlstra AuthorDate: Thu, 5 Feb 2015 14:06:23 +0100 Committer: Ingo Molnar CommitDate: Wed, 18 Feb 2015 15:08:33 +0100 genirq: Provide disable_hardirq() For things like netpoll there is a need to disable an interrupt from atomic context. Currently netpoll uses disable_irq() which will sleep-wait on threaded handlers and thus forced_irqthreads breaks things. Provide disable_hardirq(), which uses synchronize_hardirq() to only wait for active hardirq handlers; also change synchronize_hardirq() to return the status of threaded handlers. This will allow one to try-disable an interrupt from atomic context, or in case of request_threaded_irq() to only wait for the hardirq part. Suggested-by: Sabrina Dubroca Signed-off-by: Peter Zijlstra (Intel) Cc: Arnd Bergmann Cc: David Miller Cc: Eyal Perry Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Quentin Lambert Cc: Randy Dunlap Cc: Russell King Link: http://lkml.kernel.org/r/20150205130623.GH5029@twins.programming.kicks-ass.net [ Fixed typos and such. ] Signed-off-by: Ingo Molnar --- include/linux/hardirq.h | 2 +- include/linux/interrupt.h | 1 + kernel/irq/manage.c | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index cba442e..f4af034 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -9,7 +9,7 @@ extern void synchronize_irq(unsigned int irq); -extern void synchronize_hardirq(unsigned int irq); +extern bool synchronize_hardirq(unsigned int irq); #if defined(CONFIG_TINY_RCU) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index d9b05b5..3bb01b9 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -184,6 +184,7 @@ extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id); #endif extern void disable_irq_nosync(unsigned int irq); +extern bool disable_hardirq(unsigned int irq); extern void disable_irq(unsigned int irq); extern void disable_percpu_irq(unsigned int irq); extern void enable_irq(unsigned int irq); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 196a06f..03329c2 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -68,14 +68,20 @@ static void __synchronize_hardirq(struct irq_desc *desc) * Do not use this for shutdown scenarios where you must be sure * that all parts (hardirq and threaded handler) have completed. * + * Returns: false if a threaded handler is active. + * * This function may be called - with care - from IRQ context. */ -void synchronize_hardirq(unsigned int irq) +bool synchronize_hardirq(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); - if (desc) + if (desc) { __synchronize_hardirq(desc); + return !atomic_read(&desc->threads_active); + } + + return true; } EXPORT_SYMBOL(synchronize_hardirq); @@ -440,6 +446,32 @@ void disable_irq(unsigned int irq) } EXPORT_SYMBOL(disable_irq); +/** + * disable_hardirq - disables an irq and waits for hardirq completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Enables and Disables are + * nested. + * This function waits for any pending hard IRQ handlers for this + * interrupt to complete before returning. If you use this function while + * holding a resource the hard IRQ handler may need you will deadlock. + * + * When used to optimistically disable an interrupt from atomic context + * the return value must be checked. + * + * Returns: false if a threaded handler is active. + * + * This function may be called - with care - from IRQ context. + */ +bool disable_hardirq(unsigned int irq) +{ + if (!__disable_irq_nosync(irq)) + return synchronize_hardirq(irq); + + return false; +} +EXPORT_SYMBOL_GPL(disable_hardirq); + void __enable_irq(struct irq_desc *desc, unsigned int irq) { switch (desc->depth) {