From: Jeetesh Burman Date: Tue, 24 Mar 2015 17:46:48 +0000 (+0530) Subject: mmc: tegra: Abort tuning if device is removed X-Git-Tag: tegra-l4t-r21.4~60 X-Git-Url: https://rtime.felk.cvut.cz/gitweb/sojka/nv-tegra/linux-3.10.git/commitdiff_plain/0bb08ee76692a7ded9fb063b3bd77e1848658ced mmc: tegra: Abort tuning if device is removed For removable devices, check for the card presence status before issuing each tuning command. If the device is removed, abort tuning and return -ENOMEDIUM error. bug 1625262 Change-Id: I19d5dfe8e8bf4b9fc7ecc2c00cdfa01343012e68 Signed-off-by: Pavan Kunapuli Reviewed-on: http://git-master/r/398855 (cherry picked from commit 6e82d03dca5b421138e1c4f348efee71df2a865f) Signed-off-by: Jeetesh Burman Reviewed-on: http://git-master/r/721906 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 9c2d1c1508e..7b5eae384cc 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -2168,6 +2168,11 @@ static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci) int flags; u32 intstatus; + if (gpio_is_valid(tegra_host->plat->cd_gpio) && + (gpio_get_value(tegra_host->plat->cd_gpio) != 0)) { + dev_err(mmc_dev(sdhci->mmc), "device removed during tuning\n"); + return -ENOMEDIUM; + } mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; while (sdhci_readl(sdhci, SDHCI_PRESENT_STATE) & mask) { if (timeout == 0) { @@ -2247,7 +2252,7 @@ out: } static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci, - unsigned int starting_tap, bool expect_failure) + unsigned int starting_tap, bool expect_failure, int *status) { unsigned int tap_value = starting_tap; int err; @@ -2259,6 +2264,10 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci, /* Run frequency tuning */ err = sdhci_tegra_issue_tuning_cmd(sdhci); + if (err == -ENOMEDIUM) { + *status = err; + return -1; + } if (err && retry) { retry--; continue; @@ -2271,6 +2280,7 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci, tap_value++; } while (tap_value <= MAX_TAP_VALUES); + *status = 0; return tap_value; } @@ -2594,8 +2604,8 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci, struct sdhci_tegra *tegra_host = pltfm_host->priv; struct tap_window_data *tap_data; struct tuning_ui tuning_ui[10]; - int err = 0, partial_win_start = 0, temp_margin = 0; - unsigned int tap_value, calc_ui = 0; + int err = 0, partial_win_start = 0, temp_margin = 0, tap_value; + unsigned int calc_ui = 0; u8 prev_boundary_end = 0, num_of_wins = 0; u8 num_of_uis = 0, valid_num_uis = 0; u8 ref_ui, first_valid_full_win = 0; @@ -2620,7 +2630,12 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci, do { tap_data = &tuning_data->tap_data[num_of_wins]; /* Get the window start */ - tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true); + tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true, + &err); + if ((tap_value < 0) && (err == -ENOMEDIUM)) { + spin_unlock(&sdhci->lock); + return err; + } tap_data->win_start = min_t(u8, tap_value, MAX_TAP_VALUES); tap_value++; if (tap_value >= MAX_TAP_VALUES) { @@ -2638,7 +2653,11 @@ static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci, /* Get the window end */ tap_value = sdhci_tegra_scan_tap_values(sdhci, - tap_value, false); + tap_value, false, &err); + if ((tap_value < 0) && (err == -ENOMEDIUM)) { + spin_unlock(&sdhci->lock); + return err; + } tap_data->win_end = min_t(u8, (tap_value - 1), MAX_TAP_VALUES); tap_data->win_size = tap_data->win_end - tap_data->win_start; tap_value++;