All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow
@ 2012-11-19  3:38 Haijun Zhang
  2012-11-19  3:38 ` [PATCH 2/2] Powerpc/eSDHC: Add limit to data and erase timeout value calculation Haijun Zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Haijun Zhang @ 2012-11-19  3:38 UTC (permalink / raw)
  To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang, Anton Vorontsov

As some mmc cards need large timeout value usually a few seconds,
so data timeout nanosecond will overflow with u32 variable and
give the wrong timeout value, so use u64 will be safe.

Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
---
 drivers/mmc/core/core.c  |   21 ++++++++-------------
 drivers/mmc/host/sdhci.c |    6 +++---
 include/linux/mmc/core.h |    2 +-
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 06c42cf..893144e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -208,10 +208,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 	if (mrq->data) {
 		pr_debug("%s:     blksz %d blocks %d flags %08x "
-			"tsac %d ms nsac %d\n",
+			"tsac %lld ms nsac %d\n",
 			mmc_hostname(host), mrq->data->blksz,
 			mrq->data->blocks, mrq->data->flags,
-			mrq->data->timeout_ns / 1000000,
+			div_u64(mrq->data->timeout_ns, 1000000),
 			mrq->data->timeout_clks);
 	}
 
@@ -659,16 +659,16 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 	if (data->flags & MMC_DATA_WRITE)
 		mult <<= card->csd.r2w_factor;
 
-	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_ns = (u64)card->csd.tacc_ns * mult;
 	data->timeout_clks = card->csd.tacc_clks * mult;
 
 	/*
 	 * SD cards also have an upper limit on the timeout.
 	 */
 	if (mmc_card_sd(card)) {
-		unsigned int timeout_us, limit_us;
+		u64 timeout_us, limit_us;
 
-		timeout_us = data->timeout_ns / 1000;
+		timeout_us = div_u64(data->timeout_ns, 1000);
 		if (mmc_host_clk_rate(card->host))
 			timeout_us += data->timeout_clks * 1000 /
 				(mmc_host_clk_rate(card->host) / 1000);
@@ -1545,14 +1545,9 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 		/* 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;
+		u64 timeout_us;
 
+		timeout_us = (u64)(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.
@@ -1561,7 +1556,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 		timeout_us += (timeout_clks * 1000) /
 			      (mmc_host_clk_rate(card->host) / 1000);
 
-		erase_timeout = timeout_us / 1000;
+		erase_timeout = div_u64(timeout_us, 1000);
 
 		/*
 		 * Theoretically, the calculation could underflow so round up
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f05a377..a5adc9f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -651,7 +651,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	u8 count;
 	struct mmc_data *data = cmd->data;
-	unsigned target_timeout, current_timeout;
+	u64 target_timeout, current_timeout;
 
 	/*
 	 * If the host controller provides us with an incorrect timeout
@@ -668,9 +668,9 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 
 	/* timeout in us */
 	if (!data)
-		target_timeout = cmd->cmd_timeout_ms * 1000;
+		target_timeout = (u64)cmd->cmd_timeout_ms * 1000;
 	else {
-		target_timeout = data->timeout_ns / 1000;
+		target_timeout = div_u64(data->timeout_ns, 1000);
 		if (host->clock)
 			target_timeout += data->timeout_clks / host->clock;
 	}
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 9b9cdaf..a2ff2e9 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -99,7 +99,7 @@ struct mmc_command {
 };
 
 struct mmc_data {
-	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
+	u64			timeout_ns;	/* data timeout (in ns) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
 	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [PATCH 2/2 v3] Powerpc/eSDHC: Add limit to data and erase timeout value calculation
@ 2012-11-19  5:30 Haijun Zhang
  2012-11-19  5:31 ` [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow Haijun Zhang
  0 siblings, 1 reply; 12+ messages in thread
From: Haijun Zhang @ 2012-11-19  5:30 UTC (permalink / raw)
  To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang

Some cards apply too larg timeout value for host to response,
So limit the maximum data transfer timeout value and maximum erase
timeout value to aviod timeout issue.

Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
---
changes for v3:
	- Add limit to data and erase timeout value calculation

 drivers/mmc/core/core.c |   35 +++++++++++++++++++++--------------
 1 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 893144e..edb2964 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -636,6 +636,7 @@ EXPORT_SYMBOL(mmc_read_bkops_status);
  */
 void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 {
+	struct mmc_host *host = card->host;
 	unsigned int mult;
 
 	/*
@@ -669,9 +670,9 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 		u64 timeout_us, limit_us;
 
 		timeout_us = div_u64(data->timeout_ns, 1000);
-		if (mmc_host_clk_rate(card->host))
+		if (mmc_host_clk_rate(host))
 			timeout_us += data->timeout_clks * 1000 /
-				(mmc_host_clk_rate(card->host) / 1000);
+				(mmc_host_clk_rate(host) / 1000);
 
 		if (data->flags & MMC_DATA_WRITE)
 			/*
@@ -712,7 +713,7 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 	 * continuous stream of data until the internal logic
 	 * overflowed.
 	 */
-	if (mmc_host_is_spi(card->host)) {
+	if (mmc_host_is_spi(host)) {
 		if (data->flags & MMC_DATA_WRITE) {
 			if (data->timeout_ns < 1000000000)
 				data->timeout_ns = 1000000000;	/* 1s */
@@ -721,6 +722,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 				data->timeout_ns =  100000000;	/* 100ms */
 		}
 	}
+
+	if (host->max_discard_to &&
+			(host->max_discard_to <
+			 div_u64(data->timeout_ns, 1000000)))
+		data->timeout_ns = (u64)host->max_discard_to * 1000000;
 }
 EXPORT_SYMBOL(mmc_set_data_timeout);
 
@@ -1880,7 +1886,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
 		return 0;
 
 	if (qty == 1)
-		return 1;
+		return 1 << card->erase_shift;
 
 	/* Convert qty to sectors */
 	if (card->erase_shift)
@@ -1898,16 +1904,17 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
 	struct mmc_host *host = card->host;
 	unsigned int max_discard, max_trim;
 
-	if (!host->max_discard_to)
-		return UINT_MAX;
-
-	/*
-	 * Without erase_group_def set, MMC erase timeout depends on clock
-	 * frequence which can change.  In that case, the best choice is
-	 * just the preferred erase size.
-	 */
-	if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
-		return card->pref_erase;
+	if (!host->max_discard_to) {
+		if (mmc_card_sd(card))
+			return UINT_MAX;
+		/*
+		 * Without erase_group_def set, MMC erase timeout depends on
+		 * clock frequence which can change.  In that case, the best
+		 * choice is just the preferred erase size.
+		 */
+		if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
+			return card->pref_erase;
+	}
 
 	max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
 	if (mmc_can_trim(card)) {
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow
@ 2012-11-12  4:45 Haijun Zhang
  2012-11-19  0:39 ` Anton Vorontsov
  0 siblings, 1 reply; 12+ messages in thread
From: Haijun Zhang @ 2012-11-12  4:45 UTC (permalink / raw)
  To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang, Anton Vorontsov

As some mmc cards need large timeout value usually a few seconds,
so data timeout nanosecond will overflow with u32 variable and
give the wrong timeout value, so use u64 will be safe.

Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
CC: Anton Vorontsov <cbouatmailru@gmail.com>
---
 drivers/mmc/core/core.c  |   21 ++++++++-------------
 drivers/mmc/host/sdhci.c |    6 +++---
 include/linux/mmc/core.h |    2 +-
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 06c42cf..c241fc1 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -208,10 +208,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 	if (mrq->data) {
 		pr_debug("%s:     blksz %d blocks %d flags %08x "
-			"tsac %d ms nsac %d\n",
+			"tsac %lld ms nsac %d\n",
 			mmc_hostname(host), mrq->data->blksz,
 			mrq->data->blocks, mrq->data->flags,
-			mrq->data->timeout_ns / 1000000,
+			div_u64(mrq->data->timeout_ns, 1000000),
 			mrq->data->timeout_clks);
 	}
 
@@ -659,16 +659,16 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 	if (data->flags & MMC_DATA_WRITE)
 		mult <<= card->csd.r2w_factor;
 
-	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_ns = (u64)card->csd.tacc_ns * (u64)mult;
 	data->timeout_clks = card->csd.tacc_clks * mult;
 
 	/*
 	 * SD cards also have an upper limit on the timeout.
 	 */
 	if (mmc_card_sd(card)) {
-		unsigned int timeout_us, limit_us;
+		u64 timeout_us, limit_us;
 
-		timeout_us = data->timeout_ns / 1000;
+		timeout_us = div_u64(data->timeout_ns, 1000);
 		if (mmc_host_clk_rate(card->host))
 			timeout_us += data->timeout_clks * 1000 /
 				(mmc_host_clk_rate(card->host) / 1000);
@@ -1545,14 +1545,9 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 		/* 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;
+		u64 timeout_us;
 
+		timeout_us = (u64)(card->csd.tacc_ns / 1000) * (u64)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.
@@ -1561,7 +1556,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 		timeout_us += (timeout_clks * 1000) /
 			      (mmc_host_clk_rate(card->host) / 1000);
 
-		erase_timeout = timeout_us / 1000;
+		erase_timeout = div_u64(timeout_us, 1000);
 
 		/*
 		 * Theoretically, the calculation could underflow so round up
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f05a377..a5adc9f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -651,7 +651,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	u8 count;
 	struct mmc_data *data = cmd->data;
-	unsigned target_timeout, current_timeout;
+	u64 target_timeout, current_timeout;
 
 	/*
 	 * If the host controller provides us with an incorrect timeout
@@ -668,9 +668,9 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 
 	/* timeout in us */
 	if (!data)
-		target_timeout = cmd->cmd_timeout_ms * 1000;
+		target_timeout = (u64)cmd->cmd_timeout_ms * 1000;
 	else {
-		target_timeout = data->timeout_ns / 1000;
+		target_timeout = div_u64(data->timeout_ns, 1000);
 		if (host->clock)
 			target_timeout += data->timeout_clks / host->clock;
 	}
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 9b9cdaf..a2ff2e9 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -99,7 +99,7 @@ struct mmc_command {
 };
 
 struct mmc_data {
-	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
+	u64			timeout_ns;	/* data timeout (in ns) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
 	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-11-25 19:49 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-19  3:38 [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow Haijun Zhang
2012-11-19  3:38 ` [PATCH 2/2] Powerpc/eSDHC: Add limit to data and erase timeout value calculation Haijun Zhang
2012-11-19  5:04   ` Anton Vorontsov
2012-11-19  5:23     ` Zhang Haijun-B42677
2012-11-19  5:33       ` Anton Vorontsov
2012-11-19  5:57         ` Zhang Haijun-B42677
2012-11-19  3:38 ` [PATCH 1/2 v2] Powerpc/eSDHC: Calculate the applicable mmc erase timeout value Haijun Zhang
2012-11-19  5:02 ` [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow Anton Vorontsov
  -- strict thread matches above, loose matches on Subject: below --
2012-11-19  5:30 [PATCH 2/2 v3] Powerpc/eSDHC: Add limit to data and erase timeout value calculation Haijun Zhang
2012-11-19  5:31 ` [PATCH] Powerpc eSDHC: Use u64 to calculate the timeout value to avoid overflow Haijun Zhang
2012-11-25 19:49   ` Chris Ball
2012-11-12  4:45 Haijun Zhang
2012-11-19  0:39 ` Anton Vorontsov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.