>From 3703642ec143239c6cae348053a11d3d67e8d15e Mon Sep 17 00:00:00 2001
From: Yunpeng Gao <[email protected]>
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 <[email protected]>
---
 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

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to