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