summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@nxp.com>2016-01-26 22:20:08 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2016-02-16 18:02:43 +0800
commite9436ad124d83edcd70dbc4cf6fb6a1b892a0d4d (patch)
treec6421013e6a2564229d2011ef6aef69e89854842 /drivers
parent097b88f260b724ce039b47617521fae85e3b0c7f (diff)
MLK-12360-1 mmc: sdhci: add sdio thread irq support
Some special SDIO devices like Broadcom WiFi driver will keep handling SDIO irq even after the driver is already suspended. This weird behavior will block the MMC host suspend during its irq synchronize operation in free_irq(), then the system suspend is blocked too and hanged. We add back sdio thread irq support for such WiFi driver to handle SDIO irqs since the sdio thread is kernel thread which does not block the process freeze operation during suspend. Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> (cherry picked from commit a7e3d205da821c880ab62c21f81e2573c0b621b6)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index be1e445801ce..fd4bf172aba3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2532,6 +2532,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
struct sdhci_host *host = dev_id;
u32 intmask, mask, unexpected = 0;
int max_loops = 16;
+ int cardint = 0;
spin_lock(&host->lock);
@@ -2597,9 +2598,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
mmc_hostname(host->mmc));
if (intmask & SDHCI_INT_CARD_INT) {
- sdhci_enable_sdio_irq_nolock(host, false);
- host->thread_isr |= SDHCI_INT_CARD_INT;
- result = IRQ_WAKE_THREAD;
+ if (host->mmc->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD) {
+ sdhci_enable_sdio_irq_nolock(host, false);
+ host->thread_isr |= SDHCI_INT_CARD_INT;
+ result = IRQ_WAKE_THREAD;
+ } else {
+ cardint = 1;
+ }
}
intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
@@ -2626,6 +2631,9 @@ out:
sdhci_dumpregs(host);
}
+ if (cardint && host->mmc->sdio_irqs)
+ mmc_signal_sdio_irq(host->mmc);
+
return result;
}
@@ -2646,12 +2654,13 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
}
if (isr & SDHCI_INT_CARD_INT) {
- sdio_run_irqs(host->mmc);
-
- spin_lock_irqsave(&host->lock, flags);
- if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
- sdhci_enable_sdio_irq_nolock(host, true);
- spin_unlock_irqrestore(&host->lock, flags);
+ if (host->mmc->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD) {
+ sdio_run_irqs(host->mmc);
+ spin_lock_irqsave(&host->lock, flags);
+ if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
+ sdhci_enable_sdio_irq_nolock(host, true);
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
}
return isr ? IRQ_HANDLED : IRQ_NONE;