From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qt0-f195.google.com ([209.85.216.195]:36334 "EHLO mail-qt0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753357AbeCUT2k (ORCPT ); Wed, 21 Mar 2018 15:28:40 -0400 Received: by mail-qt0-f195.google.com with SMTP id a20so6513587qtj.3 for ; Wed, 21 Mar 2018 12:28:39 -0700 (PDT) From: Ezequiel Garcia To: Mathieu Malaterre , Ulf Hansson , Paul Cercueil Cc: linux-mmc@vger.kernel.org, linux-mips@linux-mips.org, James Hogan , kernel@collabora.com, Alex Smith , stable@vger.kernel.org Subject: [PATCH 01/14] mmc: jz4740: Fix race condition in IRQ mask update Date: Wed, 21 Mar 2018 16:27:28 -0300 Message-Id: <20180321192741.25872-2-ezequiel@vanguardiasur.com.ar> In-Reply-To: <20180321192741.25872-1-ezequiel@vanguardiasur.com.ar> References: <20180321192741.25872-1-ezequiel@vanguardiasur.com.ar> Sender: stable-owner@vger.kernel.org List-ID: From: Alex Smith A spinlock is held while updating the internal copy of the IRQ mask, but not while writing it to the actual IMASK register. After the lock is released, an IRQ can occur before the IMASK register is written. If handling this IRQ causes the mask to be changed, when the handler returns back to the middle of the first mask update, a stale value will be written to the mask register. If this causes an IRQ to become unmasked that cannot have its status cleared by writing a 1 to it in the IREG register, e.g. the SDIO IRQ, then we can end up stuck with the same IRQ repeatedly being fired but not handled. Normally the MMC IRQ handler attempts to clear any unexpected IRQs by writing IREG, but for those that cannot be cleared in this way then the IRQ will just repeatedly fire. This was resulting in lockups after a while of using Wi-Fi on the CI20 (GitHub issue #19). Resolve by holding the spinlock until after the IMASK register has been updated. Cc: stable@vger.kernel.org Link: https://github.com/MIPS/CI20_linux/issues/19 Fixes: 61bfbdb85687 ("MMC: Add support for the controller on JZ4740 SoCs.") Tested-by: Mathieu Malaterre Signed-off-by: Alex Smith --- drivers/mmc/host/jz4740_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 712e08d9a45e..a0168e9e4fce 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -362,9 +362,9 @@ static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host, host->irq_mask &= ~irq; else host->irq_mask |= irq; - spin_unlock_irqrestore(&host->lock, flags); writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK); + spin_unlock_irqrestore(&host->lock, flags); } static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host, -- 2.16.2