If sdio can wakeup host, the card interrupts received after suspend while before resume back should be regard as wakeup event. So set a wakeup event at that point. All sdio functions should set the wakeup event individually according to its suspending status. Signed-off-by: Kevin Liu <kliu5@xxxxxxxxxxx> --- drivers/mmc/core/sdio.c | 4 ++++ drivers/mmc/core/sdio_irq.c | 10 ++++++++++ include/linux/mmc/sdio_func.h | 6 ++++++ 3 files changed, 20 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 3a64933..06675cb 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -904,6 +904,8 @@ static int mmc_sdio_suspend(struct mmc_host *host) err = pmops->suspend(&func->dev); if (err) break; + else + func->func_status = FUNC_SUSPENDED; } } while (err && --i >= 0) { @@ -911,6 +913,7 @@ static int mmc_sdio_suspend(struct mmc_host *host) if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; pmops->resume(&func->dev); + func->func_status = FUNC_RESUMED; } } @@ -967,6 +970,7 @@ static int mmc_sdio_resume(struct mmc_host *host) if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; err = pmops->resume(&func->dev); + func->func_status = FUNC_RESUMED; } } diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4..b1f3a3b 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -42,6 +42,11 @@ static int process_sdio_pending_irqs(struct mmc_host *host) */ func = card->sdio_single_irq; if (func && host->sdio_irq_pending) { + if (mmc_card_keep_power(host) && + mmc_card_wake_sdio_irq(host) && + (func->func_status == FUNC_SUSPENDED)) { + pm_wakeup_event(mmc_dev(host), 0); + } func->irq_handler(func); return 1; } @@ -63,6 +68,11 @@ static int process_sdio_pending_irqs(struct mmc_host *host) mmc_card_id(card)); ret = -EINVAL; } else if (func->irq_handler) { + if (mmc_card_keep_power(host) && + mmc_card_wake_sdio_irq(host) && + (func->func_status == FUNC_SUSPENDED)) { + pm_wakeup_event(mmc_dev(host), 0); + } func->irq_handler(func); count++; } else { diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index 50f0bc9..59f4c23 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -32,6 +32,11 @@ struct sdio_func_tuple { unsigned char data[0]; }; +enum sdio_func_status { + FUNC_RESUMED = 0, /* default value */ + FUNC_SUSPENDED, +}; + /* * SDIO function devices */ @@ -59,6 +64,7 @@ struct sdio_func { const char **info; /* info strings */ struct sdio_func_tuple *tuples; + enum sdio_func_status func_status; /* SDIO function driver state */ }; #define sdio_func_present(f) ((f)->state & SDIO_STATE_PRESENT) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html