Commit 0324896e2ec7602224b9dcd981b19b1827498cd9

Authored by Krzysztof Kozlowski
Committed by Greg Kroah-Hartman
1 parent 9abaccf3bf

mmc: sdhci: Fix sleep in atomic after inserting SD card

commit 2836766a9d0bd02c66073f8dd44796e6cc23848d upstream.

Sleep in atomic context happened on Trats2 board after inserting or
removing SD card because mmc_gpio_get_cd() was called under spin lock.

Fix this by moving card detection earlier, before acquiring spin lock.
The mmc_gpio_get_cd() call does not have to be protected by spin lock
because it does not access any sdhci internal data.
The sdhci_do_get_cd() call access host flags (SDHCI_DEVICE_DEAD). After
moving it out side of spin lock it could theoretically race with driver
removal but still there is no actual protection against manual card
eject.

Dmesg after inserting SD card:
[   41.663414] BUG: sleeping function called from invalid context at drivers/gpio/gpiolib.c:1511
[   41.670469] in_atomic(): 1, irqs_disabled(): 128, pid: 30, name: kworker/u8:1
[   41.677580] INFO: lockdep is turned off.
[   41.681486] irq event stamp: 61972
[   41.684872] hardirqs last  enabled at (61971): [<c0490ee0>] _raw_spin_unlock_irq+0x24/0x5c
[   41.693118] hardirqs last disabled at (61972): [<c04907ac>] _raw_spin_lock_irq+0x18/0x54
[   41.701190] softirqs last  enabled at (61648): [<c0026fd4>] __do_softirq+0x234/0x2c8
[   41.708914] softirqs last disabled at (61631): [<c00273a0>] irq_exit+0xd0/0x114
[   41.716206] Preemption disabled at:[<  (null)>]   (null)
[   41.721500]
[   41.722985] CPU: 3 PID: 30 Comm: kworker/u8:1 Tainted: G        W      3.18.0-rc5-next-20141121 #883
[   41.732111] Workqueue: kmmcd mmc_rescan
[   41.735945] [<c0014d2c>] (unwind_backtrace) from [<c0011c80>] (show_stack+0x10/0x14)
[   41.743661] [<c0011c80>] (show_stack) from [<c0489d14>] (dump_stack+0x70/0xbc)
[   41.750867] [<c0489d14>] (dump_stack) from [<c0228b74>] (gpiod_get_raw_value_cansleep+0x18/0x30)
[   41.759628] [<c0228b74>] (gpiod_get_raw_value_cansleep) from [<c03646e8>] (mmc_gpio_get_cd+0x38/0x58)
[   41.768821] [<c03646e8>] (mmc_gpio_get_cd) from [<c036d378>] (sdhci_request+0x50/0x1a4)
[   41.776808] [<c036d378>] (sdhci_request) from [<c0357934>] (mmc_start_request+0x138/0x268)
[   41.785051] [<c0357934>] (mmc_start_request) from [<c0357cc8>] (mmc_wait_for_req+0x58/0x1a0)
[   41.793469] [<c0357cc8>] (mmc_wait_for_req) from [<c0357e68>] (mmc_wait_for_cmd+0x58/0x78)
[   41.801714] [<c0357e68>] (mmc_wait_for_cmd) from [<c0361c00>] (mmc_io_rw_direct_host+0x98/0x124)
[   41.810480] [<c0361c00>] (mmc_io_rw_direct_host) from [<c03620f8>] (sdio_reset+0x2c/0x64)
[   41.818641] [<c03620f8>] (sdio_reset) from [<c035a3d8>] (mmc_rescan+0x254/0x2e4)
[   41.826028] [<c035a3d8>] (mmc_rescan) from [<c003a0e0>] (process_one_work+0x180/0x3f4)
[   41.833920] [<c003a0e0>] (process_one_work) from [<c003a3bc>] (worker_thread+0x34/0x4b0)
[   41.841991] [<c003a3bc>] (worker_thread) from [<c003fed8>] (kthread+0xe4/0x104)
[   41.849285] [<c003fed8>] (kthread) from [<c000f268>] (ret_from_fork+0x14/0x2c)
[   42.038276] mmc0: new high speed SDHC card at address 1234

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Fixes: 94144a465dd0 ("mmc: sdhci: add get_cd() implementation")
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 6 additions and 2 deletions Side-by-side Diff

drivers/mmc/host/sdhci.c
... ... @@ -1319,6 +1319,8 @@
1319 1319  
1320 1320 sdhci_runtime_pm_get(host);
1321 1321  
  1322 + present = mmc_gpio_get_cd(host->mmc);
  1323 +
1322 1324 spin_lock_irqsave(&host->lock, flags);
1323 1325  
1324 1326 WARN_ON(host->mrq != NULL);
... ... @@ -1347,7 +1349,6 @@
1347 1349 * zero: cd-gpio is used, and card is removed
1348 1350 * one: cd-gpio is used, and card is present
1349 1351 */
1350   - present = mmc_gpio_get_cd(host->mmc);
1351 1352 if (present < 0) {
1352 1353 /* If polling, assume that the card is always present. */
1353 1354 if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
1354 1355  
1355 1356  
... ... @@ -2072,15 +2073,18 @@
2072 2073 {
2073 2074 struct sdhci_host *host = mmc_priv(mmc);
2074 2075 unsigned long flags;
  2076 + int present;
2075 2077  
2076 2078 /* First check if client has provided their own card event */
2077 2079 if (host->ops->card_event)
2078 2080 host->ops->card_event(host);
2079 2081  
  2082 + present = sdhci_do_get_cd(host);
  2083 +
2080 2084 spin_lock_irqsave(&host->lock, flags);
2081 2085  
2082 2086 /* Check host->mrq first in case we are runtime suspended */
2083   - if (host->mrq && !sdhci_do_get_cd(host)) {
  2087 + if (host->mrq && !present) {
2084 2088 pr_err("%s: Card removed during transfer!\n",
2085 2089 mmc_hostname(host->mmc));
2086 2090 pr_err("%s: Resetting controller.\n",