From patchwork Thu Mar 17 14:19:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Hunter X-Patchwork-Id: 8611641 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 369B1C0553 for ; Thu, 17 Mar 2016 14:23:18 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 35413201BB for ; Thu, 17 Mar 2016 14:23:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 20B5620123 for ; Thu, 17 Mar 2016 14:23:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031122AbcCQOW7 (ORCPT ); Thu, 17 Mar 2016 10:22:59 -0400 Received: from hqemgate16.nvidia.com ([216.228.121.65]:14044 "EHLO hqemgate16.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031018AbcCQOTq (ORCPT ); Thu, 17 Mar 2016 10:19:46 -0400 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate16.nvidia.com id ; Thu, 17 Mar 2016 07:20:02 -0700 Received: from hqemhub02.nvidia.com ([172.20.150.31]) by hqnvupgp08.nvidia.com (PGP Universal service); Thu, 17 Mar 2016 07:18:54 -0700 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Thu, 17 Mar 2016 07:18:54 -0700 Received: from jonathanh-lm.nvidia.com (172.20.144.16) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.406.0; Thu, 17 Mar 2016 07:19:44 -0700 From: Jon Hunter To: Thomas Gleixner , Jason Cooper , Marc Zyngier , =?UTF-8?q?Beno=C3=AEt=20Cousson?= , Tony Lindgren , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Stephen Warren , Thierry Reding CC: Kevin Hilman , Geert Uytterhoeven , Grygorii Strashko , Lars-Peter Clausen , Linus Walleij , linux-tegra@vger.kernel.org, linux-omap@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jon Hunter Subject: [PATCH 04/15] irqchip/gic: WARN if setting the interrupt type fails Date: Thu, 17 Mar 2016 14:19:08 +0000 Message-ID: <1458224359-32665-5-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1458224359-32665-1-git-send-email-jonathanh@nvidia.com> References: <1458224359-32665-1-git-send-email-jonathanh@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Setting the interrupt type for private peripheral interrupts (PPIs) may not be supported by a given GIC because it is IMPLEMENTATION DEFINED whether this is allowed. There is no way to know if setting the type is supported for a given GIC and so the value written is read back to verify it matches the desired configuration. If it does not match then an error is return. There are cases where the interrupt configuration read from firmware (such as a device-tree blob), has been incorrect and hence gic_configure_irq() has returned an error. This error has gone undetected because the error code returned was ignored but the interrupt still worked fine because the configuration for the interrupt could not be overwritten. Given that this has done undetected and we should only fail to set the type for PPIs whose configuration cannot be changed anyway, don't return an error and simply WARN if this fails. This will allows us to fix up any places in the kernel where we should be checking the return status and maintain back compatibility with firmware images that may have incorrect interrupt configurations. Signed-off-by: Jon Hunter --- drivers/irqchip/irq-gic-common.c | 13 ++++--------- drivers/irqchip/irq-gic-common.h | 2 +- drivers/irqchip/irq-gic-v3.c | 4 +++- drivers/irqchip/irq-gic.c | 4 +++- drivers/irqchip/irq-hip04.c | 5 ++--- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index ffff5a45f1e3..423a345d7b75 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c @@ -32,13 +32,12 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, } } -int gic_configure_irq(unsigned int irq, unsigned int type, +void gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)) { u32 confmask = 0x2 << ((irq % 16) * 2); u32 confoff = (irq / 16) * 4; u32 val, oldval; - int ret = 0; /* * Read current configuration register, and insert the config @@ -52,21 +51,17 @@ int gic_configure_irq(unsigned int irq, unsigned int type, /* If the current configuration is the same, then we are done */ if (val == oldval) - return 0; + return; /* * Write back the new configuration, and possibly re-enable - * the interrupt. If we fail to write a new configuration, - * return an error. + * the interrupt. WARN if we fail to write a new configuration. */ writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); - if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) - ret = -EINVAL; + WARN_ON(readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val); if (sync_access) sync_access(); - - return ret; } void __init gic_dist_config(void __iomem *base, int gic_irqs, diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index fff697db8e22..73dee3bc6bba 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -27,7 +27,7 @@ struct gic_quirk { u32 mask; }; -int gic_configure_irq(unsigned int irq, unsigned int type, +void gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)); void gic_dist_config(void __iomem *base, int gic_irqs, void (*sync_access)(void)); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5b7d3c2129d8..c569c466fa31 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -310,7 +310,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type) rwp_wait = gic_dist_wait_for_rwp; } - return gic_configure_irq(irq, type, base, rwp_wait); + gic_configure_irq(irq, type, base, rwp_wait); + + return 0; } static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 282344b95ec2..6c555a2c5315 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -279,7 +279,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type) type != IRQ_TYPE_EDGE_RISING) return -EINVAL; - return gic_configure_irq(gicirq, type, base, NULL); + gic_configure_irq(gicirq, type, base, NULL); + + return 0; } static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index 9688d2e2a636..12be5906e91a 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c @@ -120,7 +120,6 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type) { void __iomem *base = hip04_dist_base(d); unsigned int irq = hip04_irq(d); - int ret; /* Interrupt configuration for SGIs can't be changed */ if (irq < 16) @@ -133,11 +132,11 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type) raw_spin_lock(&irq_controller_lock); - ret = gic_configure_irq(irq, type, base, NULL); + gic_configure_irq(irq, type, base, NULL); raw_spin_unlock(&irq_controller_lock); - return ret; + return 0; } #ifdef CONFIG_SMP