[Meego-kernel] [patch v2 2/2]MFLD mmc: Use the mutex to protect eMMC0 host controller
Yunpeng Gao
yunpeng.gao at intel.com
Fri Dec 17 04:36:02 PST 2010
>From 3703642ec143239c6cae348053a11d3d67e8d15e Mon Sep 17 00:00:00 2001
From: Yunpeng Gao <yunpeng.gao at intel.com>
Date: Fri, 17 Dec 2010 19:14:41 +0800
Subject: [PATCH] Use the Medfield eMMC mutex (Dekker Algorithm) acquire/release APIs to protect
eMMC0 host controller accessing operations on IA side.
Signed-off-by: Yunpeng Gao <yunpeng.gao at intel.com>
---
drivers/mmc/card/block.c | 96 ++++++++++++++++++++++++----------------------
drivers/mmc/core/core.c | 20 ++++++++++
drivers/mmc/core/mmc.c | 70 ++++++++++++++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 49 ++++++++++++++++++++++-
4 files changed, 184 insertions(+), 51 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index dcab2c5..ea3b50b 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -295,42 +295,6 @@ out:
return err ? 0 : 1;
}
-static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
- struct request *req)
-{
- struct mmc_blk_data *md = mq->data;
- struct mmc_card *card = md->queue.card;
- unsigned int from, nr, arg;
- int err = 0;
-
- mmc_claim_host(card->host);
-
- if (!mmc_can_secure_erase_trim(card)) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- from = blk_rq_pos(req);
- nr = blk_rq_sectors(req);
-
- if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
- arg = MMC_SECURE_TRIM1_ARG;
- else
- arg = MMC_SECURE_ERASE_ARG;
-
- err = mmc_erase(card, from, nr, arg);
- if (!err && arg == MMC_SECURE_TRIM1_ARG)
- err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
-out:
- spin_lock_irq(&md->lock);
- __blk_end_request(req, err, blk_rq_bytes(req));
- spin_unlock_irq(&md->lock);
-
- mmc_release_host(card->host);
-
- return err ? 0 : 1;
-}
-
static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->data;
@@ -560,14 +524,37 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
{
- if (req->cmd_flags & REQ_DISCARD) {
-// if (req->cmd_flags & REQ_SECURE)
-// return mmc_blk_issue_secdiscard_rq(mq, req);
-// else
- return mmc_blk_issue_discard_rq(mq, req);
- } else {
- return mmc_blk_issue_rw_rq(mq, req);
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+ struct mmc_host *host = card->host;
+ int ret = 0;
+
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY)
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
}
+
+ /* Todo: pm_runtime_get_sync(&card->dev); */
+
+ /* If SCU is last owner, reconfig the host controller */
+ if (ret == 1)
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+
+ if (req->cmd_flags & REQ_DISCARD)
+ ret = mmc_blk_issue_discard_rq(mq, req);
+ else
+ ret = mmc_blk_issue_rw_rq(mq, req);
+
+ /* Todo: pm_runtime_put(&card->dev); */
+
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
+ return ret;
}
static inline int mmc_blk_readonly(struct mmc_card *card)
@@ -666,11 +653,28 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
static int
mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
{
- int err;
+ struct mmc_host *host = card->host;
+ int err, ret;
+
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+ }
+ }
- mmc_claim_host(card->host);
+ mmc_claim_host(host);
err = mmc_set_blocklen(card, 512);
- mmc_release_host(card->host);
+ mmc_release_host(host);
+
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
if (err) {
printk(KERN_ERR "%s: unable to set block size to 512: %d\n",
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d464252..3b60faa 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1439,6 +1439,7 @@ void mmc_rescan(struct work_struct *work)
unsigned long flags;
int i;
const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
+ int ret = 0;
spin_lock_irqsave(&host->lock, flags);
@@ -1449,6 +1450,20 @@ void mmc_rescan(struct work_struct *work)
spin_unlock_irqrestore(&host->lock, flags);
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY)
+ pr_warn("SCU failed to release host in negotiated "
+ "time, ignore this and keep on using "
+ "host controller\n");
+ }
+
+ /* Todo: pm_runtime_get_sync(host->parent); */
+
+ if (ret == 1)
+ /* If SCU is last owner, reconfig the host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
mmc_bus_get(host);
@@ -1544,6 +1559,11 @@ out_fail:
mmc_power_off(host);
}
out:
+ /* Todo: pm_runtime_put(host->parent); */
+
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
if (host->caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host->detect, HZ);
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 91c35fd..ac2f67d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -625,11 +625,24 @@ static void mmc_remove(struct mmc_host *host)
*/
static void mmc_detect(struct mmc_host *host)
{
- int err;
+ int err, ret;
BUG_ON(!host);
BUG_ON(!host->card);
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+ }
+ }
+
mmc_claim_host(host);
/*
@@ -639,6 +652,9 @@ static void mmc_detect(struct mmc_host *host)
mmc_release_host(host);
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
if (err) {
mmc_remove(host);
@@ -653,15 +669,33 @@ static void mmc_detect(struct mmc_host *host)
*/
static int mmc_suspend(struct mmc_host *host)
{
+ int ret;
+
BUG_ON(!host);
BUG_ON(!host->card);
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+ }
+ }
+
mmc_claim_host(host);
if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
host->card->state &= ~MMC_STATE_HIGHSPEED;
mmc_release_host(host);
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
return 0;
}
@@ -673,15 +707,31 @@ static int mmc_suspend(struct mmc_host *host)
*/
static int mmc_resume(struct mmc_host *host)
{
- int err;
+ int err, ret;
BUG_ON(!host);
BUG_ON(!host->card);
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+ }
+ }
+
mmc_claim_host(host);
err = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
return err;
}
@@ -689,11 +739,27 @@ static int mmc_power_restore(struct mmc_host *host)
{
int ret;
+ if (host->ops->acquire_ownership) {
+ ret = host->ops->acquire_ownership(host);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the host controller */
+ if (host->ops->reconfig_host_controller)
+ host->ops->reconfig_host_controller(host);
+ }
+ }
+
host->card->state &= ~MMC_STATE_HIGHSPEED;
mmc_claim_host(host);
ret = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
+ if (host->ops->release_ownership)
+ host->ops->release_ownership(host);
+
return ret;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1aedc3f..52ddd9b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1877,19 +1877,39 @@ out:
int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
{
+ struct mmc_host *mmc = host->mmc;
int ret;
+ if (mmc->ops->acquire_ownership) {
+ ret = mmc->ops->acquire_ownership(mmc);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the HC */
+ if (mmc->ops->reconfig_host_controller)
+ mmc->ops->reconfig_host_controller(mmc);
+ }
+ }
+
sdhci_disable_card_detection(host);
ret = mmc_suspend_host(host->mmc);
- if (ret)
+ if (ret) {
+ if (mmc->ops->release_ownership)
+ mmc->ops->release_ownership(mmc);
return ret;
+ }
free_irq(host->irq, host);
if (host->vmmc)
ret = regulator_disable(host->vmmc);
+ if (mmc->ops->release_ownership)
+ mmc->ops->release_ownership(mmc);
+
return ret;
}
@@ -1897,12 +1917,29 @@ EXPORT_SYMBOL_GPL(sdhci_suspend_host);
int sdhci_resume_host(struct sdhci_host *host)
{
+ struct mmc_host *mmc = host->mmc;
int ret;
+ if (mmc->ops->acquire_ownership) {
+ ret = mmc->ops->acquire_ownership(mmc);
+ if (ret == -EBUSY) {
+ printk(KERN_ERR "SCU failed to release host in "
+ "negotiated time, ignore this and keep on "
+ "using host controller\n");
+ } else if (ret == 1) {
+ /* If SCU is last owner, reconfig the HC */
+ if (mmc->ops->reconfig_host_controller)
+ mmc->ops->reconfig_host_controller(mmc);
+ }
+ }
+
if (host->vmmc) {
int ret = regulator_enable(host->vmmc);
- if (ret)
+ if (ret) {
+ if (mmc->ops->release_ownership)
+ mmc->ops->release_ownership(mmc);
return ret;
+ }
}
@@ -1913,8 +1950,11 @@ int sdhci_resume_host(struct sdhci_host *host)
ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
mmc_hostname(host->mmc), host);
- if (ret)
+ if (ret) {
+ if (mmc->ops->release_ownership)
+ mmc->ops->release_ownership(mmc);
return ret;
+ }
sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
mmiowb();
@@ -1922,6 +1962,9 @@ int sdhci_resume_host(struct sdhci_host *host)
ret = mmc_resume_host(host->mmc);
sdhci_enable_card_detection(host);
+ if (mmc->ops->release_ownership)
+ mmc->ops->release_ownership(mmc);
+
return ret;
}
--
1.5.4.5
More information about the MeeGo-kernel
mailing list