mmc: core: host: only use wakelock for detect work
authorColin Cross <ccross@android.com>
Thu, 8 Sep 2011 00:28:58 +0000 (17:28 -0700)
committerArve Hjønnevåg <arve@android.com>
Mon, 1 Jul 2013 20:40:25 +0000 (13:40 -0700)
There is no need to take a wakelock for delayed lazy disable
work, it will be cancelled in the suspend handler and force
disabled.  Only take the wakelock when the detect work is
queued, and make sure to drop the wakelock if the work is
cancelled.

Change-Id: I1e507a5f98848954ea21d45e23b6192c3132a349
Signed-off-by: Colin Cross <ccross@android.com>
drivers/mmc/core/core.c
drivers/mmc/core/host.c
include/linux/mmc/host.h

index 297367ab5486c129ed9e219f5365d9d2fd53183e..812f3d98bfc87a67bf3324f0e6b2f017f4513a89 100644 (file)
@@ -53,7 +53,6 @@
 #define MMC_BKOPS_MAX_TIMEOUT  (4 * 60 * 1000) /* max time to wait in ms */
 
 static struct workqueue_struct *workqueue;
-static struct wake_lock mmc_delayed_work_wake_lock;
 static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 
 /*
@@ -87,7 +86,6 @@ 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);
 }
 
@@ -1689,6 +1687,8 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
        spin_unlock_irqrestore(&host->lock, flags);
 #endif
        host->detect_change = 1;
+
+       wake_lock(&host->detect_wake_lock);
        mmc_schedule_delayed_work(&host->detect, delay);
 }
 
@@ -2451,11 +2451,13 @@ void mmc_rescan(struct work_struct *work)
 
  out:
        if (extend_wakelock)
-               wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2);
+               wake_lock_timeout(&host->detect_wake_lock, HZ / 2);
        else
-               wake_unlock(&mmc_delayed_work_wake_lock);
-       if (host->caps & MMC_CAP_NEEDS_POLL)
+               wake_unlock(&host->detect_wake_lock);
+       if (host->caps & MMC_CAP_NEEDS_POLL) {
+               wake_lock(&host->detect_wake_lock);
                mmc_schedule_delayed_work(&host->detect, HZ);
+       }
 }
 
 void mmc_start_host(struct mmc_host *host)
@@ -2479,7 +2481,8 @@ void mmc_stop_host(struct mmc_host *host)
 #endif
 
        host->rescan_disable = 1;
-       cancel_delayed_work_sync(&host->detect);
+       if (cancel_delayed_work_sync(&host->detect))
+               wake_unlock(&host->detect_wake_lock);
        mmc_flush_scheduled_work();
 
        /* clear pm flags now and let card drivers set them as needed */
@@ -2677,7 +2680,8 @@ int mmc_suspend_host(struct mmc_host *host)
        if (mmc_bus_needs_resume(host))
                return 0;
 
-       cancel_delayed_work(&host->detect);
+       if (cancel_delayed_work(&host->detect))
+               wake_unlock(&host->detect_wake_lock);
        mmc_flush_scheduled_work();
 
        mmc_bus_get(host);
@@ -2800,7 +2804,8 @@ int mmc_pm_notify(struct notifier_block *notify_block,
                }
                host->rescan_disable = 1;
                spin_unlock_irqrestore(&host->lock, flags);
-               cancel_delayed_work_sync(&host->detect);
+               if (cancel_delayed_work_sync(&host->detect))
+                       wake_unlock(&host->detect_wake_lock);
 
                if (!host->bus_ops || host->bus_ops->suspend)
                        break;
@@ -2876,9 +2881,6 @@ static int __init mmc_init(void)
        if (!workqueue)
                return -ENOMEM;
 
-       wake_lock_init(&mmc_delayed_work_wake_lock, WAKE_LOCK_SUSPEND,
-                      "mmc_delayed_work");
-
        ret = mmc_register_bus();
        if (ret)
                goto destroy_workqueue;
@@ -2899,7 +2901,6 @@ unregister_bus:
        mmc_unregister_bus();
 destroy_workqueue:
        destroy_workqueue(workqueue);
-       wake_lock_destroy(&mmc_delayed_work_wake_lock);
 
        return ret;
 }
@@ -2910,7 +2911,6 @@ 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);
index f5bb7c769c3e7a7ede4471e9175c9da71c724515..56dadd667ec1505bf81862cefea8e5fb6816897c 100644 (file)
@@ -459,6 +459,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 
        spin_lock_init(&host->lock);
        init_waitqueue_head(&host->wq);
+       wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND,
+               kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host)));
        INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 #ifdef CONFIG_PM
        host->pm_notify.notifier_call = mmc_pm_notify;
@@ -558,6 +560,7 @@ void mmc_free_host(struct mmc_host *host)
        spin_lock(&mmc_host_lock);
        idr_remove(&mmc_host_idr, host->index);
        spin_unlock(&mmc_host_lock);
+       wake_lock_destroy(&host->detect_wake_lock);
 
        put_device(&host->class_dev);
 }
index d286d7ecaee41dbbe68698d1d8a564657d0271a9..66b4659276026e3769d859573007c2d1f06ac294 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/fault-inject.h>
+#include <linux/wakelock.h>
 
 #include <linux/mmc/core.h>
 #include <linux/mmc/pm.h>
@@ -329,6 +330,7 @@ struct mmc_host {
        int                     claim_cnt;      /* "claim" nesting count */
 
        struct delayed_work     detect;
+       struct wake_lock        detect_wake_lock;
        int                     detect_change;  /* card detect flag */
        struct mmc_slot         slot;