From: Dong Aisheng Date: Tue, 26 Jan 2016 14:20:08 +0000 (+0800) Subject: MLK-12360-1 mmc: sdhci: add sdio thread irq support X-Git-Tag: C0P2-H0.0--20200415~3701 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=be72844d1e22ea76c91a6964271f59b18b6d1eb8;p=linux.git 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 --- diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index dc4f170a099a..d215d3b9f04b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2661,6 +2661,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); @@ -2729,9 +2730,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if ((intmask & SDHCI_INT_CARD_INT) && (host->ier & 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 | @@ -2758,6 +2763,9 @@ out: sdhci_dumpregs(host); } + if (cardint && host->mmc->sdio_irqs) + mmc_signal_sdio_irq(host->mmc); + return result; } @@ -2780,12 +2788,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;