@@ -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;
}
}
@@ -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 {
@@ -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)
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@marvell.com> --- 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(+)