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-Url: https://git.stricted.de/?a=commitdiff_plain;h=3bb10f60933e84abfe2be69f60b3486f9b96348b;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git mmc: sdhci-pxav3: fix race between runtime pm and irq 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 Cc: # v3.9+ Signed-off-by: Ulf Hansson --- diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 63967b85dc42..c5db5d271ee7 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -458,11 +458,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); struct sdhci_pxa *pxa = pltfm_host->priv; - 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(pxa->clk_io); if (!IS_ERR(pxa->clk_core)) @@ -476,17 +476,12 @@ 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); struct sdhci_pxa *pxa = pltfm_host->priv; - unsigned long flags; clk_prepare_enable(pxa->clk_io); if (!IS_ERR(pxa->clk_core)) clk_prepare_enable(pxa->clk_core); - 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