Commit 7f7e4129c23f0419257184dff6fec89d2d5a8964

Authored by Ulf Hansson
Committed by Chris Ball
1 parent 46cbd56ad4

mmc: core: Fix hangs related to insert/remove of cards

During a rescan operation mmc_attach(sd|mmc|sdio) functions are
called. The error handling in these function can trigger a detach
of the bus, which also meant a power off. This is not notified by
the rescan operation which then continues to the next attach function.

If a power off has been done, the framework must never send any
new commands to the host driver, without first doing a new power up.
This will most likely trigger any host driver to hang.

Moving power off out of detach and instead handle power off
separately when it is actually needed, solves the issue.

Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: <stable@kernel.org>
Signed-off-by: Chris Ball <cjb@laptop.org>

Showing 5 changed files with 9 additions and 5 deletions Side-by-side Diff

drivers/mmc/core/core.c
... ... @@ -1192,7 +1192,7 @@
1192 1192 mmc_host_clk_release(host);
1193 1193 }
1194 1194  
1195   -static void mmc_power_off(struct mmc_host *host)
  1195 +void mmc_power_off(struct mmc_host *host)
1196 1196 {
1197 1197 mmc_host_clk_hold(host);
1198 1198  
... ... @@ -1289,8 +1289,7 @@
1289 1289 }
1290 1290  
1291 1291 /*
1292   - * Remove the current bus handler from a host. Assumes that there are
1293   - * no interesting cards left, so the bus is powered down.
  1292 + * Remove the current bus handler from a host.
1294 1293 */
1295 1294 void mmc_detach_bus(struct mmc_host *host)
1296 1295 {
... ... @@ -1307,8 +1306,6 @@
1307 1306  
1308 1307 spin_unlock_irqrestore(&host->lock, flags);
1309 1308  
1310   - mmc_power_off(host);
1311   -
1312 1309 mmc_bus_put(host);
1313 1310 }
1314 1311  
... ... @@ -1893,6 +1890,7 @@
1893 1890  
1894 1891 mmc_claim_host(host);
1895 1892 mmc_detach_bus(host);
  1893 + mmc_power_off(host);
1896 1894 mmc_release_host(host);
1897 1895 mmc_bus_put(host);
1898 1896 return;
... ... @@ -2022,6 +2020,7 @@
2022 2020 host->bus_ops->remove(host);
2023 2021 mmc_claim_host(host);
2024 2022 mmc_detach_bus(host);
  2023 + mmc_power_off(host);
2025 2024 mmc_release_host(host);
2026 2025 host->pm_flags = 0;
2027 2026 err = 0;
... ... @@ -2109,6 +2108,7 @@
2109 2108 host->bus_ops->remove(host);
2110 2109  
2111 2110 mmc_detach_bus(host);
  2111 + mmc_power_off(host);
2112 2112 mmc_release_host(host);
2113 2113 host->pm_flags = 0;
2114 2114 break;
drivers/mmc/core/core.h
... ... @@ -43,6 +43,7 @@
43 43 bool cmd11);
44 44 void mmc_set_timing(struct mmc_host *host, unsigned int timing);
45 45 void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
  46 +void mmc_power_off(struct mmc_host *host);
46 47  
47 48 static inline void mmc_delay(unsigned int ms)
48 49 {
drivers/mmc/core/mmc.c
... ... @@ -892,6 +892,7 @@
892 892  
893 893 mmc_claim_host(host);
894 894 mmc_detach_bus(host);
  895 + mmc_power_off(host);
895 896 mmc_release_host(host);
896 897 }
897 898 }
drivers/mmc/core/sd.c
... ... @@ -1043,6 +1043,7 @@
1043 1043  
1044 1044 mmc_claim_host(host);
1045 1045 mmc_detach_bus(host);
  1046 + mmc_power_off(host);
1046 1047 mmc_release_host(host);
1047 1048 }
1048 1049 }
drivers/mmc/core/sdio.c
... ... @@ -597,6 +597,7 @@
597 597  
598 598 mmc_claim_host(host);
599 599 mmc_detach_bus(host);
  600 + mmc_power_off(host);
600 601 mmc_release_host(host);
601 602 }
602 603 }