From: Jisheng Zhang Date: Fri, 23 Jan 2015 10:08:21 +0000 (+0800) Subject: mmc: sdhci-pxav3: fix race between runtime pm and irq X-Git-Tag: v3.16.35~2775 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=44baa458dcdf872ebd51c1c44276e5d1bdf8a92f;p=thirdparty%2Fkernel%2Fstable.git mmc: sdhci-pxav3: fix race between runtime pm and irq commit 3bb10f60933e84abfe2be69f60b3486f9b96348b upstream. This patch is to fix a race condition that may cause an unhandled irq, which results in big sdhci interrupt numbers and endless "mmc1: got irq while runtime suspended" msgs before v3.15. Consider following scenario: CPU0 CPU1 sdhci_pxav3_runtime_suspend() spin_lock_irqsave(&host->lock, flags); sdhci_irq() spining on the &host->lock host->runtime_suspended = true; spin_unlock_irqrestore(&host->lock, flags); get the &host->lock runtime_suspended is true now return IRQ_NONE; Fix this race by using the core sdhci.c supplied sdhci_runtime_suspend_host() in runtime suspend hook which will disable card interrupts. We also use the sdhci_runtime_resume_host() in the runtime resume hook accordingly. Signed-off-by: Jisheng Zhang Signed-off-by: Ulf Hansson [ luis: backported to 3.16: adjusted context ] Signed-off-by: Luis Henriques --- diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index f62655bc1604f..a30f42003fb80 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -448,11 +448,11 @@ static int sdhci_pxav3_runtime_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - unsigned long flags; + int ret; - spin_lock_irqsave(&host->lock, flags); - host->runtime_suspended = true; - spin_unlock_irqrestore(&host->lock, flags); + ret = sdhci_runtime_suspend_host(host); + if (ret) + return ret; clk_disable_unprepare(pltfm_host->clk); @@ -463,15 +463,10 @@ static int sdhci_pxav3_runtime_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - unsigned long flags; clk_prepare_enable(pltfm_host->clk); - spin_lock_irqsave(&host->lock, flags); - host->runtime_suspended = false; - spin_unlock_irqrestore(&host->lock, flags); - - return 0; + return sdhci_runtime_resume_host(host); } #endif