summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSan Mehat <san@android.com>2009-03-23 12:20:37 -0700
committerArve Hjønnevåg <arve@android.com>2010-02-08 15:08:24 -0800
commit126f493e6b281b802471ce475c83c5a6ae58e26d (patch)
tree86037428a043a17d8437baf1d3d871e80cda928f /drivers/mmc
parent5b23a96fd66d13f00315d5d46f2b399464707a90 (diff)
mmc: core: Hold a wake lock accross delayed work + mmc rescan
Signed-off-by: San Mehat <san@android.com> mmc: core: Rework mmc_delayed_work wakelock so that the wakelock is only extended if a card is added or removed. Signed-off-by: San Mehat <san@google.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index e543f85deb79..08d08e4699e7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -22,6 +22,7 @@
#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
+#include <linux/wakelock.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -38,6 +39,7 @@
#include "sdio_ops.h"
static struct workqueue_struct *workqueue;
+static struct wake_lock mmc_delayed_work_wake_lock;
/*
* Enabling software CRCs on the data blocks can be a significant (30%)
@@ -53,6 +55,7 @@ module_param(use_spi_crc, bool, 0);
static int mmc_schedule_delayed_work(struct delayed_work *work,
unsigned long delay)
{
+ wake_lock(&mmc_delayed_work_wake_lock);
return queue_delayed_work(workqueue, work, delay);
}
@@ -1041,6 +1044,7 @@ void mmc_rescan(struct work_struct *work)
container_of(work, struct mmc_host, detect.work);
u32 ocr;
int err;
+ int extend_wakelock = 0;
mmc_bus_get(host);
@@ -1084,6 +1088,7 @@ void mmc_rescan(struct work_struct *work)
if (!err) {
if (mmc_attach_sdio(host, ocr))
mmc_power_off(host);
+ extend_wakelock = 1;
goto out;
}
@@ -1094,6 +1099,7 @@ void mmc_rescan(struct work_struct *work)
if (!err) {
if (mmc_attach_sd(host, ocr))
mmc_power_off(host);
+ extend_wakelock = 1;
goto out;
}
@@ -1104,6 +1110,7 @@ void mmc_rescan(struct work_struct *work)
if (!err) {
if (mmc_attach_mmc(host, ocr))
mmc_power_off(host);
+ extend_wakelock = 1;
goto out;
}
@@ -1111,6 +1118,11 @@ void mmc_rescan(struct work_struct *work)
mmc_power_off(host);
out:
+ if (extend_wakelock)
+ wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2);
+ else
+ wake_unlock(&mmc_delayed_work_wake_lock);
+
if (host->caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host->detect, HZ);
}
@@ -1332,6 +1344,8 @@ static int __init mmc_init(void)
{
int ret;
+ wake_lock_init(&mmc_delayed_work_wake_lock, WAKE_LOCK_SUSPEND, "mmc_delayed_work");
+
workqueue = create_singlethread_workqueue("kmmcd");
if (!workqueue)
return -ENOMEM;
@@ -1366,6 +1380,7 @@ static void __exit mmc_exit(void)
mmc_unregister_host_class();
mmc_unregister_bus();
destroy_workqueue(workqueue);
+ wake_lock_destroy(&mmc_delayed_work_wake_lock);
}
subsys_initcall(mmc_init);