mmc_calc_max_discard compute a worst case : max(erase, trim). Without this commit, if the erase time is big (2400ms for example) and max_busy_timeout is 1300ms (sdhci running with a clock at 100Mhz and SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK), discard support will be disabled. But trim could be used without exceding max_busy_timeout Also when using secure trim or erase, the max timeout is much bigger, and it is not checked in mmc_calc_max_discard. So we need to check max_busy_timeout in mmc_do_erase to support all case. Note I wonder why we don't check status in spi case. Also why can't we use mmc_send_status ? It that because of the retry ? But what's weird is that in other case of status poll retry is done (for example card_busy_detect in drivers/mmc/card/block.c) --- drivers/mmc/core/core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7dc0c85..12e69e2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1952,6 +1952,16 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.arg = arg; cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; cmd.busy_timeout = mmc_erase_timeout(card, arg, qty); + /* + * Normally we use R1B responses, but in cases where the host + * has specified a max_busy_timeout we need to validate it. A failure + * means we need to prevent the host from doing hw busy detection, which + * is done by converting to a R1 response instead. + */ + if (cmd.busy_timeout > host->max_busy_timeout) { + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + cmd.busy_timeout = 0; + } err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { pr_err("mmc_erase: erase error %d, status %#x\n", @@ -2189,6 +2199,9 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) } else if (max_discard < card->erase_size) { max_discard = 0; } + /* if max_busy_timeout is too small, we can poll */ + if (!max_discard) + max_discard = card->pref_erase; pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", mmc_hostname(host), max_discard, host->max_busy_timeout); return max_discard; -- 2.0.1 -- 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