diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/sdio_irq.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 7502ba3ebda..ff6bdaef680 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -104,9 +104,13 @@ static void sdio_irq_work_func(struct work_struct *work) */ mmc_claim_host(host); - ret = process_sdio_pending_irqs(host->card); + /* Check if there are any subscribers to IRQ:s */ + if (!host->sdio_irqs) { + mmc_release_host(host); + return; + } - mmc_release_host(host); + ret = process_sdio_pending_irqs(host->card); if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, true); @@ -127,6 +131,8 @@ static void sdio_irq_work_func(struct work_struct *work) &host->sdio_irq_work, msecs_to_jiffies(host->sdio_poll_period)); } + + mmc_release_host(host); } static int sdio_card_irq_get(struct mmc_card *card) @@ -173,9 +179,25 @@ static int sdio_card_irq_put(struct mmc_card *card) if (!--host->sdio_irqs) { host->ops->enable_sdio_irq(host, false); + + /* + * Temporarily release the host in order to complete + * any pending work before destroying the work queue. + * + * There is a theroetical chance of messing up here, + * if a calling driver is waiting to claim the host + * in order to claim an SDIO IRQ, and that call falls through + * while releasing the IRQ:s here, there is no guarantee + * that that IRQ:s will be reliably turned on or off. + * This will be fixed in a coming patch, but this solution + * is deemed good enough for now since it fixes an obvious + * error and the failing case deemed not likely to happen. + */ + mmc_release_host(card->host); cancel_delayed_work_sync(&host->sdio_irq_work); destroy_workqueue(host->sdio_irq_workqueue); host->sdio_irq_workqueue = NULL; + mmc_claim_host(card->host); } return 0; |