Hi, all

Could any one help review this patch set for me?

Thanks in advance.

于 2013/9/24 16:12, Haijun Zhang 写道:
> At 50 Mhz SD_CLK period,
> the max timeout value = 2^27 * SD_CLK period ~= 2.69 sec.
>
> If max_discard_to was not designed, for mmc card preferred erase
> size should be used, for sd card just return UINT_MAX. Also add
> limit for data transfer, Use max_discard_to as max data timeout value
> to avoid timeout error in case data timeout was larger than
> 2.69 sec.
>
> For some crappy cards, the timeout value calculate from card was
> larger than UINT_MAX, in this case the timeout value write into
> register was not expected.
>
> This patch can reduce I/O error due to large timeout value for
> erase(CMD38) and write(CMD25) for some crappy cards.
>
> Signed-off-by: Haijun Zhang <haijun.zh...@freescale.com>
> ---
>  drivers/mmc/core/core.c | 45 ++++++++++++++++++++++++++++++---------------
>  1 file changed, 30 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index bf18b6b..b429baa 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -757,6 +757,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;
>  
>       /*
> @@ -780,7 +781,12 @@ 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;
> +     /* Avoid over flow for some crappy cards. */
> +     if ((UINT_MAX / mult) < card->csd.tacc_ns)
> +             data->timeout_ns = UINT_MAX;
> +     else
> +             data->timeout_ns = card->csd.tacc_ns * mult;
> +
>       data->timeout_clks = card->csd.tacc_clks * mult;
>  
>       /*
> @@ -842,6 +848,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 <
> +                      (data->timeout_ns / 1000000)))
> +             data->timeout_ns = host->max_discard_to * 1000000;
>  }
>  EXPORT_SYMBOL(mmc_set_data_timeout);
>  
> @@ -1816,11 +1827,14 @@ static unsigned int mmc_mmc_erase_timeout(struct 
> mmc_card *card,
>               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
> +             /*
> +              * Avoid over flow for some crappy cards.
> +              * e.g. tacc_ns=80000000 mult=1280
> +              */
> +             if ((UINT_MAX / mult) < card->csd.tacc_ns)
>                       timeout_us = (card->csd.tacc_ns / 1000) * mult;
> +             else
> +                     timeout_us = (card->csd.tacc_ns * mult) / 1000;
>  
>               /*
>                * ios.clock is only a target.  The real clock rate might be
> @@ -2185,16 +2199,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) {
> +             /*
> +              * 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;
> +             else
> +                     return UINT_MAX;
> +     }
>  
>       max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
>       if (mmc_can_trim(card)) {

-- 
Thanks & Regards
Haijun.


--
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