Current code detect card removal only by judging the result of
sending cmd13 to card, which is not safe for card with external
gpio detection. The communication status between host and card
may out of sync with the external gpio status if remove slowly
or hand shake during card removal.

For a card with external gpio detection, this patch add the
gpio detection into consideration when detect card removal.
The judgement result won't return until both the gpio status
and cmd13 result are synced or wait more than 1 second.

This patch won't impact to cards not using gpio detection.

Signed-off-by: Kevin Liu <kl...@marvell.com>
---
 drivers/mmc/core/core.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b8c3d41..61ec354 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -32,6 +32,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include "core.h"
 #include "bus.h"
@@ -2281,7 +2282,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, 
unsigned freq)
 
 int _mmc_detect_card_removed(struct mmc_host *host)
 {
-       int ret;
+       int ret, gpio_cd, retries = 10;
 
        if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
                return 0;
@@ -2290,6 +2291,17 @@ int _mmc_detect_card_removed(struct mmc_host *host)
                return 1;
 
        ret = host->bus_ops->alive(host);
+       gpio_cd = mmc_gpio_get_cd(host);
+       if (gpio_cd >= 0) {
+               while (((ret && gpio_cd) || (!ret && !gpio_cd)) && --retries) {
+                       msleep(100);
+                       ret = host->bus_ops->alive(host);
+                       gpio_cd = mmc_gpio_get_cd(host);
+               }
+               if (!retries)
+                       pr_warn("%s: card insert/remove too slow\n",
+                                       mmc_hostname(host));
+       }
        if (ret) {
                mmc_card_set_removed(host->card);
                pr_debug("%s: card remove detected\n", mmc_hostname(host));
-- 
1.7.9.5

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