mmc: host: SD detection flow optimization
authorChuanxiao Dong <chuanxiao.dong@intel.com>
Fri, 11 May 2012 09:43:52 +0000 (17:43 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 30 May 2012 13:07:44 +0000 (06:07 -0700)
BZ: 38199

With continously insert/remove a SD card on Tablet, Fabric error
or kernel panic can happen, which would hang up the system.

As original design, when there happens error during sending command
to device, host controller needs to be reset to go back to a clean
state. This patch will change this. If there error is NOMEDIA, means
SD card is removed, host controller will not be reset until SD card
is plugged again. This makes sense.

This patch cannot workaround Fabric error, but seems can reduce the
kernel panic

Change-Id: I543b118305ee535fbdd9e03f15628b8622edcaa4
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Reviewed-on: http://android.intel.com:8080/50108
Tested-by: Sun, Jianhua <jianhua.sun@intel.com>
Reviewed-by: Tang, Richard <richard.tang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index 6cd3cdc..20c5fc5 100644 (file)
@@ -1259,11 +1259,27 @@ static int sdhci_pci_power_up_host(struct sdhci_host *host)
 #define sdhci_pci_power_up_host        NULL
 #endif
 
+static int sdhci_pci_get_cd(struct sdhci_host *host)
+{
+       bool present;
+
+       /* If nonremovable or polling, assume that the card is always present */
+       if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
+                       (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+               present = true;
+       else
+               present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+                       SDHCI_CARD_PRESENT;
+
+       return present;
+}
+
 static struct sdhci_ops sdhci_pci_ops = {
        .enable_dma     = sdhci_pci_enable_dma,
        .platform_8bit_width    = sdhci_pci_8bit_width,
        .hw_reset               = sdhci_pci_hw_reset,
        .power_up_host  = sdhci_pci_power_up_host,
+       .get_cd         = sdhci_pci_get_cd,
 };
 
 /*****************************************************************************\
index b1b1610..4aa2317 100644 (file)
@@ -2123,6 +2123,20 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
        sdhci_runtime_pm_put(host);
 }
 
+static int sdhci_get_cd(struct mmc_host *mmc)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+       int present = -EOPNOTSUPP;
+
+       if (host->ops->get_cd) {
+               sdhci_runtime_pm_get(host);
+               present = host->ops->get_cd(host);
+               sdhci_runtime_pm_put(host);
+       }
+
+       return present;
+}
+
 static const struct mmc_host_ops sdhci_ops = {
        .request        = sdhci_request,
        .set_ios        = sdhci_set_ios,
@@ -2132,6 +2146,7 @@ static const struct mmc_host_ops sdhci_ops = {
        .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
        .execute_tuning                 = sdhci_execute_tuning,
        .enable_preset_value            = sdhci_enable_preset_value,
+       .get_cd         = sdhci_get_cd,
 };
 
 /*****************************************************************************\
@@ -2147,6 +2162,8 @@ static void sdhci_tasklet_card(unsigned long param)
 
        host = (struct sdhci_host*)param;
 
+       cancel_delayed_work(&host->mmc->detect);
+
        spin_lock_irqsave(&host->lock, flags);
 
        /* Check host->mrq first in case we are runtime suspended */
@@ -2166,7 +2183,7 @@ static void sdhci_tasklet_card(unsigned long param)
 
        spin_unlock_irqrestore(&host->lock, flags);
 
-       mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
 }
 
 static void sdhci_tasklet_finish(unsigned long param)
@@ -2197,7 +2214,7 @@ static void sdhci_tasklet_finish(unsigned long param)
         * upon error conditions.
         */
        if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-           ((mrq->cmd && mrq->cmd->error) ||
+           ((mrq->cmd && mrq->cmd->error && mrq->cmd->error != -ENOMEDIUM) ||
                 (mrq->data && (mrq->data->error ||
                  (mrq->data->stop && mrq->data->stop->error))) ||
                   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
index 6a5914e..fcf0b45 100644 (file)
@@ -275,6 +275,7 @@ struct sdhci_ops {
        int     (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
        void    (*hw_reset)(struct sdhci_host *host);
        int             (*power_up_host)(struct sdhci_host *host);
+       int    (*get_cd)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS