public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Chuanxiao Dong <chuanxiao.dong@intel.com>
To: linux-mmc@vger.kernel.org, adrian.hunter@nokia.com
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH v1 1/2]move erase timeout calculation part to mmc.c and sd.c
Date: Wed, 8 Dec 2010 19:44:52 +0800	[thread overview]
Message-ID: <20101208114452.GA18249@intel.com> (raw)

Hi adrian,
   this 2 patches modify the erase timeout calculation part which added by
   you. Can you help to review that? Thanks.


Since mmc and sd erase timeout calculation only depends on
card registers and host clock, it can be done during card
initialization. No need to calculated the erase timeout value
for erase/trim command before each time sending.

Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
---
 drivers/mmc/core/mmc.c   |   50 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/sd.c    |   19 +++++++++++++++++
 include/linux/mmc/card.h |    4 +++
 3 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 77f93c3..ee2f196 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -118,6 +118,54 @@ static void mmc_set_erase_size(struct mmc_card *card)
 	mmc_init_erase(card);
 }
 
+static void mmc_set_mmc_erase_timeout(struct mmc_card *card)
+{
+	unsigned int erase_timeout;
+
+	if (card->ext_csd.erase_group_def & 1) {
+		/* High Capacity Erase Group Size uses HC timeouts */
+		card->trim_timeout = card->ext_csd.trim_timeout;
+		card->erase_timeout = card->ext_csd.hc_erase_timeout;
+	} else {
+		/* CSD Erase Group Size uses write timeout */
+		unsigned int mult = (10 << card->csd.r2w_factor);
+		unsigned int timeout_clks = card->csd.tacc_clks * mult;
+		unsigned int timeout_us;
+
+		/* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */
+		if (card->csd.tacc_ns < 1000000)
+			timeout_us = (card->csd.tacc_ns * mult) / 1000;
+		else
+			timeout_us = (card->csd.tacc_ns / 1000) * mult;
+
+		/*
+		 * ios.clock is only a target.  The real clock rate might be
+		 * less but not that much less, so fudge it by multiplying by 2.
+		 */
+		timeout_clks <<= 1;
+		timeout_us += (timeout_clks * 1000) /
+			      (card->host->ios.clock / 1000);
+
+		erase_timeout = timeout_us / 1000;
+
+		/*
+		 * Theoretically, the calculation could underflow so round up
+		 * to 1ms in that case.
+		 */
+		if (!erase_timeout)
+			erase_timeout = 1;
+
+		card->trim_timeout = erase_timeout;
+		card->erase_timeout = erase_timeout;
+	}
+
+	/* Multiplier for secure operations */
+	card->sec_trim_timeout = card->erase_timeout *
+		card->ext_csd.sec_trim_mult;
+	card->sec_erase_timeout = card->erase_timeout *
+		card->ext_csd.sec_erase_mult;
+}
+
 /*
  * Given a 128-bit response, decode to our card CSD structure.
  */
@@ -528,6 +576,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			&& (host->caps & (MMC_CAP_1_2V_DDR)))
 				ddr = MMC_1_2V_DDR_MODE;
 	}
+	/* Erase/trim timeout depends on CSD, EXT_CSD and host clock */
+	mmc_set_mmc_erase_timeout(card);
 
 	/*
 	 * Activate wide bus and DDR (if supported).
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 49da4df..f9afff7 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -250,6 +250,20 @@ out:
 	return err;
 }
 
+static void mmc_set_sd_erase_timeout(struct mmc_card *card)
+{
+	if (card->ssr.erase_timeout)
+		/* Erase timeout specified in SD Status Register (SSR) */
+		card->erase_timeout = card->ssr.erase_timeout;
+	else
+		/*
+		 * Erase timeout not specified in SD Status Register (SSR) so
+		 * use 250ms per write block.
+		 */
+		card->erase_timeout = 250;
+}
+
+
 /*
  * Fetches and decodes switch information
  */
@@ -624,6 +638,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	mmc_set_clock(host, mmc_sd_get_max_clock(card));
 
 	/*
+	 * Set erase timeout
+	 * */
+	mmc_set_sd_erase_timeout(card);
+
+	/*
 	 * Switch to wider bus (if supported).
 	 */
 	if ((host->caps & MMC_CAP_4_BIT_DATA) &&
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 8ce0827..e95c770 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -126,6 +126,10 @@ struct mmc_card {
  	unsigned int		erase_shift;	/* if erase unit is power 2 */
  	unsigned int		pref_erase;	/* in sectors */
  	u8			erased_byte;	/* value of erased bytes */
+	unsigned int	erase_timeout; /* erase timeout value in ms per blk */
+	unsigned int	trim_timeout; /* trim timeout value in ms per blk */
+	unsigned int	sec_erase_timeout; /* sec erase timeout in ms per blk */
+	unsigned int	sec_trim_timeout; /* sec trim timeout in ms per blk */
 
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
-- 
1.6.6.1


                 reply	other threads:[~2010-12-08 11:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101208114452.GA18249@intel.com \
    --to=chuanxiao.dong@intel.com \
    --cc=adrian.hunter@nokia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox