mmc: tegra: error handling if no card
David Yu [Thu, 12 Dec 2013 02:36:40 +0000 (11:36 +0900)]
if sd card removed during tap_delay tuning,
don't exit until trying MAX_TAP_VALUES.
it makes the system un-responsive for 2 sec.
Therefore, adding to check card_present before starting
freq_tuning.
if card is not present, return error
and then exit tuning procedure.

Bug 1422437
Bug 1364449

Change-Id: Ib8dff29a1c1faade2acaa93c3e97ea23d3e3041c
Reviewed-on: http://git-master/r/272902
Signed-off-by: David Yu <davyu@nvidia.com>
Reviewed-on: http://git-master/r/344556
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Harry Hong <hhong@nvidia.com>
Tested-by: Harry Hong <hhong@nvidia.com>

drivers/mmc/host/sdhci-tegra.c

index 5719624..8b9c896 100644 (file)
@@ -1679,6 +1679,7 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
        struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
        int err = 0;
        u8 ctrl;
        u32 mask;
@@ -1686,6 +1687,10 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
        int flags;
        u32 intstatus;
 
+       if (gpio_is_valid(plat->cd_gpio)
+                       && (gpio_get_value(plat->cd_gpio) != 0))
+               return -ENODEV;
+
        mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
        while (sdhci_readl(sdhci, SDHCI_PRESENT_STATE) & mask) {
                if (timeout == 0) {
@@ -1747,7 +1752,7 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
        } else {
                tegra_sdhci_reset(sdhci, SDHCI_RESET_CMD);
                tegra_sdhci_reset(sdhci, SDHCI_RESET_DATA);
-               err = -EIO;
+               err = -EAGAIN;
        }
 
        if (sdhci->tuning_done) {
@@ -1757,7 +1762,7 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
                        (ctrl & SDHCI_CTRL_TUNED_CLK))
                        err = 0;
                else
-                       err = -EIO;
+                       err = -EAGAIN;
        }
        mdelay(1);
 out:
@@ -1777,6 +1782,8 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci,
 
                /* Run frequency tuning */
                err = sdhci_tegra_issue_tuning_cmd(sdhci);
+               if (err == -ENODEV)
+                       return err;
                if (err && retry) {
                        retry--;
                        continue;
@@ -1813,7 +1820,10 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
        /* Get the partial window data */
        tap_value = 0;
        tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, false);
-       if (!tap_value) {
+       if (tap_value < 0) {
+               err = -EIO;
+               goto out;
+       } else if (!tap_value) {
                tap_data->abandon_partial_win = true;
                tap_data->partial_win = 0;
        } else if (tap_value > MAX_TAP_VALUES) {
@@ -1838,7 +1848,10 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
                /* Get the full window start */
                tap_value++;
                tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true);
-               if (tap_value > MAX_TAP_VALUES) {
+               if (tap_value < 0) {
+                       err = -EIO;
+                       goto out;
+               } else if (tap_value > MAX_TAP_VALUES) {
                        /* All tap values exhausted. No full window */
                        tap_data->abandon_full_win = true;
                        goto out;