summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@axis.com>2015-06-14 19:26:11 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2015-06-18 09:21:04 +0200
commita8c27c0bea45c6531fbc1e3be79ddd5a9bc1ba3e (patch)
treec1e435d9fc1afbe02aea49f957504cbdce9b0f11 /drivers
parent4b8a43e90ccf88c91475b802d1388c0779be2bda (diff)
mmc: queue: prevent soft lockups on PREEMPT=n
On systems with CONFIG_PREEMPT=n, under certain circumstances, mmcqd can continuously process requests for several seconds without blocking, triggering the soft lockup watchdog. For example, this can happen if mmcqd runs on the CPU which services the controller's interrupt, and a process on a different CPU continuously writes to the MMC block device. NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [mmcqd/0:664] CPU: 0 PID: 664 Comm: mmcqd/0 Not tainted 4.1.0-rc7+ #4 PC is at _raw_spin_unlock_irqrestore+0x24/0x28 LR is at mmc_start_request+0x104/0x134 ... [<805112a8>] (_raw_spin_unlock_irqrestore) from [<803db664>] (mmc_start_request+0x104/0x134) [<803db664>] (mmc_start_request) from [<803dc008>] (mmc_start_req+0x274/0x394) [<803dc008>] (mmc_start_req) from [<803eb2c4>] (mmc_blk_issue_rw_rq+0xd0/0xb98) [<803eb2c4>] (mmc_blk_issue_rw_rq) from [<803ebe8c>] (mmc_blk_issue_rq+0x100/0x470) [<803ebe8c>] (mmc_blk_issue_rq) from [<803ecab8>] (mmc_queue_thread+0xd0/0x170) [<803ecab8>] (mmc_queue_thread) from [<8003fd14>] (kthread+0xe0/0xfc) [<8003fd14>] (kthread) from [<8000f768>] (ret_from_fork+0x14/0x2c) Fix it by adding a cond_resched() in the request handling loop so that other processes get a chance to run. Signed-off-by: Rabin Vincent <rabin.vincent@axis.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/card/queue.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index d34e09b4161e..b5a2b145d89f 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -68,6 +68,7 @@ static int mmc_queue_thread(void *d)
set_current_state(TASK_RUNNING);
cmd_flags = req ? req->cmd_flags : 0;
mq->issue_fn(mq, req);
+ cond_resched();
if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
continue; /* fetch again */