>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
