diff options
author | Ulf Hansson <ulf.hansson@stericsson.com> | 2012-02-06 10:42:39 +0100 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-03-27 18:19:58 +0200 |
commit | f0cc9cf99326926fd76f77645c48d16d647802eb (patch) | |
tree | 62ad1c9e51cb27c797acaa5481d93a4306125bcd /drivers | |
parent | mmc: dw_mmc: Regression fix for non-IDMAC DMA (diff) | |
download | linux-f0cc9cf99326926fd76f77645c48d16d647802eb.tar.xz linux-f0cc9cf99326926fd76f77645c48d16d647802eb.zip |
mmc: core: Detect card removal on I/O error
To prevent I/O as soon as possible at card removal, a new detect work is
re-scheduled without a delay to let a rescan remove the card device as
soon as possible.
Additionally, MMC_CAP2_DETECT_ON_ERR can now be used to handle "slowly"
removed cards that a scheduled detect work did not detect as removed.
To prevent further I/O requests for these lingering removed cards,
check if card has been removed and then schedule a detect work to
properly remove it.
Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/core.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index faa0af10d334..436409f7f7bd 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2121,18 +2121,36 @@ int _mmc_detect_card_removed(struct mmc_host *host) int mmc_detect_card_removed(struct mmc_host *host) { struct mmc_card *card = host->card; + int ret; WARN_ON(!host->claimed); + + if (!card) + return 1; + + ret = mmc_card_removed(card); /* * The card will be considered unchanged unless we have been asked to * detect a change or host requires polling to provide card detection. */ - if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) - return mmc_card_removed(card); + if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) && + !(host->caps2 & MMC_CAP2_DETECT_ON_ERR)) + return ret; host->detect_change = 0; + if (!ret) { + ret = _mmc_detect_card_removed(host); + if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) { + /* + * Schedule a detect work as soon as possible to let a + * rescan handle the card removal. + */ + cancel_delayed_work(&host->detect); + mmc_detect_change(host, 0); + } + } - return _mmc_detect_card_removed(host); + return ret; } EXPORT_SYMBOL(mmc_detect_card_removed); |