diff mbox

[v4] mmc: sdio: add wakeup event for suspend/resume

Message ID 1359422142-9686-1-git-send-email-kliu5@marvell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kevin Liu Jan. 29, 2013, 1:15 a.m. UTC
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   |   12 ++++++++++++
 include/linux/mmc/sdio_func.h |    6 ++++++
 3 files changed, 22 insertions(+)
diff mbox

Patch

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..3bae8aa 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -28,6 +28,14 @@ 
 
 #include "sdio_ops.h"
 
+static inline bool sdio_irq_wakeup(struct sdio_func *func)
+{
+	struct mmc_host *host = func->card->host;
+
+	return mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)
+		&& func->func_status == FUNC_SUSPENDED;
+}
+
 static int process_sdio_pending_irqs(struct mmc_host *host)
 {
 	struct mmc_card *card = host->card;
@@ -42,6 +50,8 @@  static int process_sdio_pending_irqs(struct mmc_host *host)
 	 */
 	func = card->sdio_single_irq;
 	if (func && host->sdio_irq_pending) {
+		if (sdio_irq_wakeup(func))
+			pm_wakeup_event(mmc_dev(host), 0);
 		func->irq_handler(func);
 		return 1;
 	}
@@ -63,6 +73,8 @@  static int process_sdio_pending_irqs(struct mmc_host *host)
 					mmc_card_id(card));
 				ret = -EINVAL;
 			} else if (func->irq_handler) {
+				if (sdio_irq_wakeup(func))
+					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)