[PATCH] mmc: avoid unnecessary rescan in PM_POST_SUSPEND

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With this patch, we call rescan only when card insert/remove
happens during rescan_disabled is set to avoid unnecessary mmc
command transaction and realted wakelock holding.

This patch fix below suspend retry issue on Android:
1. System trigger suspend procedure for all wakelock are released
2. A wakelock is hold again and suspend is aborted as a result.
3. pm subsystem post PM_POST_SUSPEND event when exiting suspend.
4. mmc rescan is schedlued on every mmc host when handling the event
5. The wakelock is released just after it block suspend
6. System trigger another suspend retry
7. mmc rescan thread hold wakelock to dectect card
8. System go to state 2 and enter suspend retry loop

Signed-off-by: Jun Nie <njun@xxxxxxxxxxx>
---
 drivers/mmc/core/core.c  |   16 ++++++++++++++--
 include/linux/mmc/host.h |    1 +
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe..ded7686 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1568,9 +1568,15 @@ void mmc_rescan(struct work_struct *work)
 	struct mmc_host *host =
 		container_of(work, struct mmc_host, detect.work);
 	int i;
+	unsigned long flags;

-	if (host->rescan_disable)
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->rescan_disable) {
+		host->rescan_delayed = 1;
+		spin_unlock_irqrestore(&host->lock, flags);
 		return;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);

 	mmc_bus_get(host);

@@ -1836,6 +1842,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 	struct mmc_host *host = container_of(
 		notify_block, struct mmc_host, pm_notify);
 	unsigned long flags;
+	unsigned long rescan_needed = 0;


 	switch (mode) {
@@ -1866,8 +1873,13 @@ int mmc_pm_notify(struct notifier_block *notify_block,

 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 0;
+		if (host->rescan_delayed) {
+			rescan_needed = 1;
+			host->rescan_delayed = 0;
+		}
 		spin_unlock_irqrestore(&host->lock, flags);
-		mmc_detect_change(host, 0);
+		if (rescan_needed)
+			mmc_detect_change(host, 0);

 	}

diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1ee4424..f05e619 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -249,6 +249,7 @@ struct mmc_host {
 	/* Only used with MMC_CAP_DISABLE */
 	int			enabled;	/* host is enabled */
 	int			rescan_disable;	/* disable card detection */
+	int			rescan_delayed;	/* card detection is delayed */
 	int			nesting_cnt;	/* "enable" nesting count */
 	int			en_dis_recurs;	/* detect recursion */
 	unsigned int		disable_delay;	/* disable delay in msecs */
-- 
1.7.0.4
From 8976e67c50fee9eaad742ad097b84fd5523effee Mon Sep 17 00:00:00 2001
From: Jun Nie <njun@xxxxxxxxxxx>
Date: Fri, 1 Jul 2011 10:01:51 +0800
Subject: [PATCH] mmc: avoid unnecessary rescan in PM_POST_SUSPEND

With this patch, we call rescan only when card insert/remove
happens during rescan_disabled is set to avoid unnecessary mmc
command transaction and realted wakelock holding.

This patch fix below suspend retry issue on Android:
1. System trigger suspend procedure for all wakelock are released
2. A wakelock is hold again and suspend is aborted as a result.
3. pm subsystem post PM_POST_SUSPEND event when exiting suspend.
4. mmc rescan is schedlued on every mmc host when handling the event
5. The wakelock is released just after it block suspend
6. System trigger another suspend retry
7. mmc rescan thread hold wakelock to dectect card
8. System go to state 2 and enter suspend retry loop

Signed-off-by: Jun Nie <njun@xxxxxxxxxxx>
---
 drivers/mmc/core/core.c  |   16 ++++++++++++++--
 include/linux/mmc/host.h |    1 +
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe..ded7686 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1568,9 +1568,15 @@ void mmc_rescan(struct work_struct *work)
 	struct mmc_host *host =
 		container_of(work, struct mmc_host, detect.work);
 	int i;
+	unsigned long flags;
 
-	if (host->rescan_disable)
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->rescan_disable) {
+		host->rescan_delayed = 1;
+		spin_unlock_irqrestore(&host->lock, flags);
 		return;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
 
 	mmc_bus_get(host);
 
@@ -1836,6 +1842,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 	struct mmc_host *host = container_of(
 		notify_block, struct mmc_host, pm_notify);
 	unsigned long flags;
+	unsigned long rescan_needed = 0;
 
 
 	switch (mode) {
@@ -1866,8 +1873,13 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 0;
+		if (host->rescan_delayed) {
+			rescan_needed = 1;
+			host->rescan_delayed = 0;
+		}
 		spin_unlock_irqrestore(&host->lock, flags);
-		mmc_detect_change(host, 0);
+		if (rescan_needed)
+			mmc_detect_change(host, 0);
 
 	}
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1ee4424..f05e619 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -249,6 +249,7 @@ struct mmc_host {
 	/* Only used with MMC_CAP_DISABLE */
 	int			enabled;	/* host is enabled */
 	int			rescan_disable;	/* disable card detection */
+	int			rescan_delayed;	/* card detection is delayed */
 	int			nesting_cnt;	/* "enable" nesting count */
 	int			en_dis_recurs;	/* detect recursion */
 	unsigned int		disable_delay;	/* disable delay in msecs */
-- 
1.7.0.4


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux