diff options
author | Dong Aisheng <aisheng.dong@nxp.com> | 2016-01-26 22:20:08 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2016-02-16 18:02:43 +0800 |
commit | e9436ad124d83edcd70dbc4cf6fb6a1b892a0d4d (patch) | |
tree | c6421013e6a2564229d2011ef6aef69e89854842 /drivers | |
parent | 097b88f260b724ce039b47617521fae85e3b0c7f (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.c | 27 |
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; |