mmc: SDHCI: fix the issue related with SD card insert/remove
authorChuanxiao Dong <chuanxiao.dong@intel.com>
Mon, 24 Oct 2011 05:01:52 +0000 (13:01 +0800)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:21:14 +0000 (13:21 -0800)
BZ 1605

insert/remove a SD card quickly while the card is inusing, can cause
MMC driver print timeout error message. This is reasonable. But should
not cause system getting slow. This patch will fix this.

Change-Id: Iffb1fe615603f2cd5ab74d28120d38167d317cb7
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Reviewed-on: http://android.intel.com:8080/23125
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Tested-by: Gross, Mark <mark.gross@intel.com>
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c

index 2706cd3..3be533c 100644 (file)
@@ -196,12 +196,27 @@ static int mfd_emmc_gpio_parse(struct sfi_table_header *table)
 
 #ifdef CONFIG_PM_RUNTIME
 
+/*
+ * MFLD SD card insert/remove handler
+ * When removing a SD card, there may be still requests
+ * transferring. But removing a SD card can cause MFLD
+ * host controller reset its power register automatically
+ * which causes host cannot generate interrupts for the
+ * current transferring requests. That will trigger timeout
+ * timer.
+ * So before start to detect a card, finish the current
+ * request first.
+ */
 static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
 {
        struct sdhci_pci_slot *slot = dev_id;
        struct sdhci_host *host = slot->host;
 
-       mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+       if (host->card_tasklet.func == NULL)
+               return IRQ_NONE;
+
+       tasklet_schedule(&host->card_tasklet);
+
        return IRQ_HANDLED;
 }
 
index 012bac0..8c4c99d 100644 (file)
@@ -1484,6 +1484,14 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        else
                present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
                                SDHCI_CARD_PRESENT;
+       /*
+        * If user insert/remove card too quickly, host may send
+        * command before host power up. That is bad, which can
+        * lead host generate no interrupts.
+        * So before sending command, check power control register
+        */
+       if (!(sdhci_readb(host, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON))
+               present = false;
 
        if (!present || host->flags & SDHCI_DEVICE_DEAD) {
                host->mrq->cmd->error = -ENOMEDIUM;