From patchwork Mon Aug 17 08:23:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Courbot X-Patchwork-Id: 507902 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47193140081 for ; Mon, 17 Aug 2015 18:24:10 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750839AbbHQIYJ (ORCPT ); Mon, 17 Aug 2015 04:24:09 -0400 Received: from hqemgate15.nvidia.com ([216.228.121.64]:3205 "EHLO hqemgate15.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750754AbbHQIYI (ORCPT ); Mon, 17 Aug 2015 04:24:08 -0400 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate15.nvidia.com id ; Mon, 17 Aug 2015 01:24:10 -0700 Received: from hqemhub03.nvidia.com ([172.20.150.15]) by hqnvupgp08.nvidia.com (PGP Universal service); Mon, 17 Aug 2015 01:24:07 -0700 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Mon, 17 Aug 2015 01:24:07 -0700 Received: from percival.nvidia.com (172.20.144.16) by hqemhub03.nvidia.com (172.20.150.15) with Microsoft SMTP Server (TLS) id 8.3.342.0; Mon, 17 Aug 2015 01:24:07 -0700 From: Alexandre Courbot To: Linus Walleij CC: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, ldv-project@linuxtesting.org, gnurou@gmail.com, Alexandre Courbot , Alexey Khoroshilov , Andreas Larsson Subject: [PATCH] gpio/grgpio: fix deadlock in grgpio_irq_unmap() Date: Mon, 17 Aug 2015 17:23:52 +0900 Message-ID: <1439799832-13402-1-git-send-email-acourbot@nvidia.com> X-Mailer: git-send-email 2.5.0 X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org As reported by Alexey Khoroshilov: grgpio_irq_unmap() code looks quite suspicious regarding usage of priv->bgc.lock spinlock. It locks the spinlock in line 310: spin_lock_irqsave(&priv->bgc.lock, flags); and then it can call grgpio_set_imask() in line 317: grgpio_set_imask(priv, i, 0); But grgpio_set_imask() unconditionally locks the spinlock by itself. Fix this by moving the spinlock acquisition outside of grgpio_set_imask(). Found by Linux Driver Verification project (linuxtesting.org). Reported-by: Alexey Khoroshilov Signed-off-by: Alexandre Courbot CC: Alexey Khoroshilov CC: Andreas Larsson --- drivers/gpio/gpio-grgpio.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 77053d61466e..801423fe8143 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -104,17 +104,12 @@ static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset, { struct bgpio_chip *bgc = &priv->bgc; unsigned long mask = bgc->pin2mask(bgc, offset); - unsigned long flags; - - spin_lock_irqsave(&bgc->lock, flags); if (val) priv->imask |= mask; else priv->imask &= ~mask; bgc->write_reg(priv->regs + GRGPIO_IMASK, priv->imask); - - spin_unlock_irqrestore(&bgc->lock, flags); } static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -180,16 +175,26 @@ static void grgpio_irq_mask(struct irq_data *d) { struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); int offset = d->hwirq; + unsigned long flags; + + spin_lock_irqsave(&priv->bgc.lock, flags); grgpio_set_imask(priv, offset, 0); + + spin_unlock_irqrestore(&priv->bgc.lock, flags); } static void grgpio_irq_unmask(struct irq_data *d) { struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); int offset = d->hwirq; + unsigned long flags; + + spin_lock_irqsave(&priv->bgc.lock, flags); grgpio_set_imask(priv, offset, 1); + + spin_unlock_irqrestore(&priv->bgc.lock, flags); } static struct irq_chip grgpio_irq_chip = {