[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