mmc: core: Hold a wake lock accross delayed work + mmc rescan
authorSan Mehat <san@android.com>
Mon, 23 Mar 2009 19:20:37 +0000 (12:20 -0700)
committerColin Cross <ccross@android.com>
Thu, 30 Sep 2010 00:49:14 +0000 (17:49 -0700)
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>
drivers/mmc/core/core.c

index e0f55cb88613046016509168f9375b5e15378ab3..a6310368d507711c09d6241175d52e9c4d928707 100644 (file)
@@ -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%)
@@ -69,6 +71,7 @@ MODULE_PARM_DESC(
 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);
 }
 
@@ -1404,6 +1407,7 @@ void mmc_rescan(struct work_struct *work)
        u32 ocr;
        int err;
        unsigned long flags;
+       int extend_wakelock = 0;
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -1464,6 +1468,7 @@ void mmc_rescan(struct work_struct *work)
 
                        if (mmc_attach_sd(host, ocr))
                                mmc_power_off(host);
+                       extend_wakelock = 1;
                }
                goto out;
        }
@@ -1475,6 +1480,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;
        }
 
@@ -1485,6 +1491,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;
        }
 
@@ -1493,6 +1500,11 @@ out_fail:
        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);
 }
@@ -1739,6 +1751,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;
@@ -1773,6 +1787,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);