[PATCH] mmc: core: avoid blocking CPU for long BKOPS
From: MichaÅ MirosÅaw
Date: Sat Dec 14 2019 - 12:59:03 EST
Since the timeout for a command might be 10 minutes (fallback), don't
eat all CPU power spinning for completion (triggering lockup detector).
Implement delay with exponential backoff and a one second limit.
[158480.011769] watchdog: BUG: soft lockup - CPU#3 stuck for 23s! [fsck.f2fs:962]
[158480.014911] Modules linked in: brcmfmac brcmutil cfg80211 mmc_block sdhci_tegra cqhci sdhci_pltfm sdhci pwrseq_simple pwrseq_emmc mmc_core
[158480.018291] CPU: 3 PID: 962 Comm: fsck.f2fs Not tainted 5.5.0-rc1-next-20191209mq-00173-g716e74177313-dirty #95
[158480.021479] Hardware name: NVIDIA Tegra SoC (Flattened Device Tree)
[158480.024934] PC is at sdhci_card_busy+0x28/0x44 [sdhci]
[158480.028858] LR is at __mmc_switch+0x180/0x330 [mmc_core]
[158480.032449] pc : [<af03b118>] lr : [<af009fcc>] psr: 60000013
[158480.036004] sp : e79c9b38 ip : ee01dfd0 fp : 00f23d31
[158480.039339] r10: 00000000 r9 : 0000e020 r8 : b0c04900
[158480.042939] r7 : e763e000 r6 : 00000000 r5 : ee189000 r4 : ee189000
[158480.044909] r3 : f002b600 r2 : af03b0f0 r1 : ee01db00 r0 : 1fe70000
[158480.046857] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[158480.048870] Control: 10c5387d Table: b76ac04a DAC: 00000055
[158480.050807] CPU: 3 PID: 962 Comm: fsck.f2fs Not tainted 5.5.0-rc1-next-20191209mq-00173-g716e74177313-dirty #95
[158480.052913] Hardware name: NVIDIA Tegra SoC (Flattened Device Tree)
[...]
[158480.098604] [<b0101ab8>] (__irq_svc) from [<af03b118>] (sdhci_card_busy+0x28/0x44 [sdhci])
[158480.101406] [<af03b118>] (sdhci_card_busy [sdhci]) from [<af009fcc>] (__mmc_switch+0x180/0x330 [mmc_core])
[158480.104348] [<af009fcc>] (__mmc_switch [mmc_core]) from [<af00a3bc>] (mmc_run_bkops+0xdc/0x114 [mmc_core])
[158480.107209] [<af00a3bc>] (mmc_run_bkops [mmc_core]) from [<af067d88>] (mmc_blk_mq_complete_prev_req.part.4+0x8c/0x21c [mmc_block])
[158480.110043] [<af067d88>] (mmc_blk_mq_complete_prev_req.part.4 [mmc_block]) from [<af067f94>] (mmc_blk_rw_wait+0x7c/0x11c [mmc_block])
[158480.112914] [<af067f94>] (mmc_blk_rw_wait [mmc_block]) from [<af068c34>] (mmc_blk_mq_issue_rq+0x318/0x898 [mmc_block])
[158480.115733] [<af068c34>] (mmc_blk_mq_issue_rq [mmc_block]) from [<af069608>] (mmc_mq_queue_rq+0x124/0x244 [mmc_block])
[158480.118466] [<af069608>] (mmc_mq_queue_rq [mmc_block]) from [<b04560b0>] (__blk_mq_try_issue_directly+0x118/0x1a0)
[158480.121200] [<b04560b0>] (__blk_mq_try_issue_directly) from [<b04571c0>] (blk_mq_request_issue_directly+0x40/0x5c)
[158480.123980] [<b04571c0>] (blk_mq_request_issue_directly) from [<b0457228>] (blk_mq_try_issue_list_directly+0x4c/0xc0)
[158480.126780] [<b0457228>] (blk_mq_try_issue_list_directly) from [<b045bc70>] (blk_mq_sched_insert_requests+0x1b0/0x234)
[158480.129601] [<b045bc70>] (blk_mq_sched_insert_requests) from [<b04570a8>] (blk_mq_flush_plug_list+0x318/0x3f0)
[158480.132446] [<b04570a8>] (blk_mq_flush_plug_list) from [<b044bcb0>] (blk_flush_plug_list+0xc0/0xc8)
[158480.135292] [<b044bcb0>] (blk_flush_plug_list) from [<b044bcec>] (blk_finish_plug+0x34/0x4c)
[158480.138113] [<b044bcec>] (blk_finish_plug) from [<b024104c>] (read_pages+0x60/0x150)
[158480.140988] [<b024104c>] (read_pages) from [<b0241338>] (__do_page_cache_readahead+0x1fc/0x20c)
[158480.143893] [<b0241338>] (__do_page_cache_readahead) from [<b02361f8>] (generic_file_read_iter+0x9ac/0xd28)
[158480.146818] [<b02361f8>] (generic_file_read_iter) from [<b02b6920>] (__vfs_read+0x128/0x1a8)
[158480.149695] [<b02b6920>] (__vfs_read) from [<b02b6a34>] (vfs_read+0x94/0x11c)
[158480.152638] [<b02b6a34>] (vfs_read) from [<b02b6d34>] (ksys_read+0x50/0xbc)
[158480.155601] [<b02b6d34>] (ksys_read) from [<b0101000>] (ret_fast_syscall+0x0/0x50)
[158480.158490] Exception stack(0xe79c9fa8 to 0xe79c9ff0)
[158480.161430] 9fa0: 00000003 01bec3b8 00000003 01bec3b8 00001000 00000000
[158480.164422] 9fc0: 00000003 01bec3b8 00000000 00000003 01bec3b8 01bdf178 a6fc3f70 00000000
[158480.167385] 9fe0: a6f95074 aecadaf8 a6f82c58 a6ef2284
Signed-off-by: MichaÅ MirosÅaw <mirq-linux@xxxxxxxxxxxx>
---
drivers/mmc/core/mmc_ops.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 09113b9ad679..e3005e5b9509 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -20,6 +20,7 @@
#include "mmc_ops.h"
#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+#define MMC_MAX_POLL_MS (1000) /* 1 second */
static const u8 tuning_blk_pattern_4bit[] = {
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
@@ -454,6 +455,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
struct mmc_host *host = card->host;
int err;
unsigned long timeout;
+ unsigned int wait_ms;
u32 status = 0;
bool expired = false;
bool busy = false;
@@ -473,6 +475,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
}
timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
+ wait_ms = 1;
do {
/*
* Due to the possibility of being preempted while polling,
@@ -482,6 +485,11 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
if (host->ops->card_busy) {
busy = host->ops->card_busy(host);
+ if (busy && !expired) {
+ mmc_delay(wait_ms);
+ if (wait_ms < MMC_MAX_POLL_MS)
+ wait_ms *= 2;
+ }
} else {
err = mmc_send_status(card, &status);
if (retry_crc_err && err == -EILSEQ) {
--
2.20.1