From patchwork Wed Jun 13 00:57:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Neri X-Patchwork-Id: 928556 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=sparclinux-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4157q71kt1z9s1R for ; Wed, 13 Jun 2018 11:05:55 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933769AbeFMBBf (ORCPT ); Tue, 12 Jun 2018 21:01:35 -0400 Received: from mga14.intel.com ([192.55.52.115]:64685 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754416AbeFMBBe (ORCPT ); Tue, 12 Jun 2018 21:01:34 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Jun 2018 18:01:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,216,1526367600"; d="scan'208";a="47283461" Received: from voyager.sc.intel.com ([10.3.52.149]) by fmsmga008.fm.intel.com with ESMTP; 12 Jun 2018 18:01:30 -0700 From: Ricardo Neri To: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" Cc: Andi Kleen , Ashok Raj , Borislav Petkov , Tony Luck , "Ravi V. Shankar" , x86@kernel.org, sparclinux@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, Ricardo Neri , Jacob Pan , Daniel Lezcano , Andrew Morton , "Levin, Alexander (Sasha Levin)" , Randy Dunlap , Masami Hiramatsu , Marc Zyngier , Bartosz Golaszewski , Doug Berger , Palmer Dabbelt , iommu@lists.linux-foundation.org Subject: [RFC PATCH 03/23] genirq: Introduce IRQF_DELIVER_AS_NMI Date: Tue, 12 Jun 2018 17:57:23 -0700 Message-Id: <1528851463-21140-4-git-send-email-ricardo.neri-calderon@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1528851463-21140-1-git-send-email-ricardo.neri-calderon@linux.intel.com> References: <1528851463-21140-1-git-send-email-ricardo.neri-calderon@linux.intel.com> Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org Certain interrupt controllers (such as APIC) are capable of delivering interrupts as non-maskable. Likewise, drivers or subsystems (e.g., the hardlockup detector) might be interested in requesting a non-maskable interrupt. The new flag IRQF_DELIVER_AS_NMI serves this purpose. When setting up an interrupt, non-maskable delivery will be set in the interrupt state data only if supported by the underlying interrupt controller chips. Interrupt controller chips can declare that they support non-maskable delivery by using the new flag IRQCHIP_CAN_DELIVER_AS_NMI. Cc: Ashok Raj Cc: Andi Kleen Cc: Tony Luck Cc: Borislav Petkov Cc: Jacob Pan Cc: Daniel Lezcano Cc: Andrew Morton Cc: "Levin, Alexander (Sasha Levin)" Cc: Randy Dunlap Cc: Masami Hiramatsu Cc: Marc Zyngier Cc: Bartosz Golaszewski Cc: Doug Berger Cc: Palmer Dabbelt Cc: "Ravi V. Shankar" Cc: x86@kernel.org Cc: iommu@lists.linux-foundation.org Signed-off-by: Ricardo Neri --- include/linux/interrupt.h | 3 +++ include/linux/irq.h | 3 +++ kernel/irq/manage.c | 22 +++++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5426627..dbc5e02 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -61,6 +61,8 @@ * interrupt handler after suspending interrupts. For system * wakeup devices users need to implement wakeup detection in * their interrupt handlers. + * IRQF_DELIVER_AS_NMI - Configure interrupt to be delivered as non-maskable, if + * supported by the chip. */ #define IRQF_SHARED 0x00000080 #define IRQF_PROBE_SHARED 0x00000100 @@ -74,6 +76,7 @@ #define IRQF_NO_THREAD 0x00010000 #define IRQF_EARLY_RESUME 0x00020000 #define IRQF_COND_SUSPEND 0x00040000 +#define IRQF_DELIVER_AS_NMI 0x00080000 #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD) diff --git a/include/linux/irq.h b/include/linux/irq.h index 7271a2c..d2520ae 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -515,6 +515,8 @@ 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_CAN_DELIVER_AS_NMI Chip can deliver interrupts it receives as non- + * maskable. */ enum { IRQCHIP_SET_TYPE_MASKED = (1 << 0), @@ -524,6 +526,7 @@ enum { IRQCHIP_SKIP_SET_WAKE = (1 << 4), IRQCHIP_ONESHOT_SAFE = (1 << 5), IRQCHIP_EOI_THREADED = (1 << 6), + IRQCHIP_CAN_DELIVER_AS_NMI = (1 << 7), }; #include diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e3336d9..d058aa8 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1137,7 +1137,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) { struct irqaction *old, **old_ptr; unsigned long flags, thread_mask = 0; - int ret, nested, shared = 0; + int ret, nested, shared = 0, deliver_as_nmi = 0; if (!desc) return -EINVAL; @@ -1156,6 +1156,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) if (!(new->flags & IRQF_TRIGGER_MASK)) new->flags |= irqd_get_trigger_type(&desc->irq_data); + /* Only deliver as non-maskable interrupt if supported by chip. */ + if (new->flags & IRQF_DELIVER_AS_NMI) { + if (desc->irq_data.chip->flags & IRQCHIP_CAN_DELIVER_AS_NMI) { + irqd_set_deliver_as_nmi(&desc->irq_data); + deliver_as_nmi = 1; + } else { + return -EINVAL; + } + } + /* * Check whether the interrupt nests into another interrupt * thread. @@ -1166,6 +1176,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ret = -EINVAL; goto out_mput; } + + /* Don't allow nesting if interrupt will be delivered as NMI. */ + if (deliver_as_nmi) { + ret = -EINVAL; + goto out_mput; + } + /* * Replace the primary handler which was provided from * the driver for non nested interrupt handling by the @@ -1186,6 +1203,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) * thread. */ if (new->thread_fn && !nested) { + if (deliver_as_nmi) + goto out_mput; + ret = setup_irq_thread(new, irq, false); if (ret) goto out_mput;