[PATCH 1/2 v4] mmc: core: enhance card removal judgement for slow removal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Function _mmc_detect_card_removed will be called to know whether
the card is still present when host->bus_ops->detect is called.
In current code, the return value of this function generally only
depend on the result of sending cmd13 to card, which may not safe
for card with detection support like slot gpio detection.
Because the communication status between host and card may out of
sync with the detect status if remove the card slowly or hands shake
during the process. The direct reason is the async between card
detect switch and card/slot pad contaction in hardware, which is
defined by spec.

The spec define card insert/remove sequence as below (both standard size
SD card and MicroSD card have the same sequence):
"Part 1 Standard Size SD Card Mechanical Addendum Ver4.00 Final,
Appendix C: Card Detection Switch" (Take normally open type as example)
a)SD card insertion sequence:
  The card detection switch should be turned on after all SD card
  contact pads are connected to the host connector contact pads.
b)SD removal sequence:
  The card detection switch should be turned off when the SD card
  is just going to be removed and before any SD card contact pad is
  disconnected from the host connector contact pad.

Below is the sequence when this issue occur (Take slot gpio detection
as example and remove the card slowly during the process):
1. gpio level changed and card detect interrupt triggered.
2. mmc_rescan was launched.
3. the card pads were still contacted with the slot pads because of slow
   removal. So _mmc_detect_card_removed and mmc_rescan think card was
   still present (cmd13 succeed).
4. card pads were discontacted from the card slot pads.
So the card was actually removed finally but the card removal event
has been missed by system.
The interval length between step 1 and step 4 depends on the
card removal speed. If it's longer than the detect work schedule
delay which is 200ms, this issue will likely happen.

This patch add the card detect status check in function
_mmc_detect_card_removed if host->ops->get_cd existed.
If the card detect status and cmd13 result are out of sync then schedule
another detect work 200ms later.

Signed-off-by: Kevin Liu <kliu5@xxxxxxxxxxx>
---
 drivers/mmc/core/core.c |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b8c3d41..ad927ad 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"
@@ -2282,6 +2283,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 detected;
 
 	if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
 		return 0;
@@ -2290,6 +2292,23 @@ int _mmc_detect_card_removed(struct mmc_host *host)
 		return 1;
 
 	ret = host->bus_ops->alive(host);
+	/*
+	 * Card detect status and alive check may out of sync because of
+	 * the async between card detect switch and card/slot pad contaction
+	 * in hardware.(refer to "SD Card Mechanical Addendum, Appendix C:
+	 * Card Detection Switch") So reschedule a detect work 200ms later
+	 * for this case.
+	 */
+	if (host->ops->get_cd &&
+		!(host->caps & MMC_CAP_NEEDS_POLL)) {
+		detected = host->ops->get_cd(host);
+		if (!IS_ERR_VALUE(detected) && (!ret ^ !!detected)) {
+			mmc_detect_change(host, msecs_to_jiffies(200));
+			pr_warn("%s: card insert/remove too slowly\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


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux