summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-02-08 12:42:24 +0100
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 16:07:31 +0200
commit358e88553925f93389afbcc6dc4257bad1c7740e (patch)
treeb9cfe9f4e3060fbf36b1cc239c7f4fbf4c166771 /drivers/mmc
parentb309c69967efd2fc1476fb2018062090dafcec47 (diff)
mmc: Fixup wakelock handling
Wakelocks was not used correctly in mmc core. A suspend operation could be triggered even though there was an ongoing mmc operation. Instead now one wakelock exist per mmc host. Once the host is enabled the wakelock is retrieved. When the host is ready to be disabled the wakelock is released. Change-Id: I72e1fb80e47e9bc181766dc84bafb006a71ff6b4 Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/14668 Reviewed-by: Stefan NILSSON9 <stefan.xk.nilsson@stericsson.com> Reviewed-by: QATOOLS Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30726
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c21
-rw-r--r--drivers/mmc/core/host.c5
2 files changed, 12 insertions, 14 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 6d1ec650c04..85514a0bb73 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -40,7 +40,6 @@
#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%)
@@ -73,7 +72,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);
}
@@ -485,6 +483,8 @@ int mmc_host_enable(struct mmc_host *host)
if (host->ops->enable) {
int err;
+ wake_lock(&host->wakelock);
+
host->en_dis_recurs = 1;
err = host->ops->enable(host);
host->en_dis_recurs = 0;
@@ -492,6 +492,7 @@ int mmc_host_enable(struct mmc_host *host)
if (err) {
pr_debug("%s: enable error %d\n",
mmc_hostname(host), err);
+ wake_unlock(&host->wakelock);
return err;
}
}
@@ -519,6 +520,8 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy)
mmc_schedule_delayed_work(&host->disable, delay);
}
+ if (err == 0)
+ wake_unlock(&host->wakelock);
}
host->enabled = 0;
return 0;
@@ -652,12 +655,9 @@ void mmc_host_deeper_disable(struct work_struct *work)
/* If the host is claimed then we do not want to disable it anymore */
if (!mmc_try_claim_host(host))
- goto out;
+ return;
mmc_host_do_disable(host, 1);
mmc_do_release_host(host);
-
-out:
- wake_unlock(&mmc_delayed_work_wake_lock);
}
/**
@@ -1829,9 +1829,7 @@ void mmc_rescan(struct work_struct *work)
out:
if (extend_wakelock)
- wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2);
- else
- wake_unlock(&mmc_delayed_work_wake_lock);
+ wake_lock_timeout(&host->wakelock, HZ / 2);
if (host->caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host->detect, HZ);
}
@@ -2142,9 +2140,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;
@@ -2165,7 +2160,6 @@ unregister_bus:
mmc_unregister_bus();
destroy_workqueue:
destroy_workqueue(workqueue);
- wake_lock_destroy(&mmc_delayed_work_wake_lock);
return ret;
}
@@ -2176,7 +2170,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);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 84694a9410d..33eee273959 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -290,6 +290,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->pm_notify.notifier_call = mmc_pm_notify;
#endif
+ snprintf(host->wakelock_name, sizeof(host->wakelock_name),
+ "mmc%d_delay_work", host->index);
+ wake_lock_init(&host->wakelock, WAKE_LOCK_SUSPEND, host->wakelock_name);
+
/*
* By default, hosts do not support SGIO or large requests.
* They have to set these according to their abilities.
@@ -380,6 +384,7 @@ EXPORT_SYMBOL(mmc_remove_host);
*/
void mmc_free_host(struct mmc_host *host)
{
+ wake_lock_destroy(&host->wakelock);
spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index);
spin_unlock(&mmc_host_lock);