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.zhang@xxxxxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html