mmc: core: Detect card removal on I/O error
authorUlf Hansson <ulf.hansson@stericsson.com>
Mon, 6 Feb 2012 09:42:39 +0000 (10:42 +0100)
committerChris Ball <cjb@laptop.org>
Tue, 27 Mar 2012 16:19:58 +0000 (12:19 -0400)
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>
drivers/mmc/core/core.c
include/linux/mmc/host.h

index faa0af1..436409f 100644 (file)
@@ -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);
 
index ee2b036..d1d3743 100644 (file)
@@ -258,6 +258,7 @@ struct mmc_host {
 #define MMC_CAP2_HS200         (MMC_CAP2_HS200_1_8V_SDR | \
                                 MMC_CAP2_HS200_1_2V_SDR)
 #define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
+#define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
        unsigned int        power_notify_type;