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.hu...@freescale.com>
Signed-off-by: Haijun Zhang <haijun.zh...@freescale.com>
Signed-off-by: Anton Vorontsov <cbouatmai...@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


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to