diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 063e00517660..7d2ceda7f80e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -3170,6 +3170,16 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_rw_prep( return &mqrq->cmdq_req; } +static void mmc_blk_cmdq_requeue_rw_rq(struct mmc_queue *mq, + struct request *req) +{ + struct mmc_card *card = mq->card; + struct mmc_host *host = card->host; + + blk_requeue_request(req->q, req); + mmc_put_card(host->card); +} + static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req) { struct mmc_queue_req *active_mqrq; @@ -3217,6 +3227,15 @@ static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req) wait_event_interruptible(ctx->queue_empty_wq, (!ctx->active_reqs)); + if (ret) { + /* clear pending request */ + WARN_ON(!test_and_clear_bit(req->tag, + &host->cmdq_ctx.data_active_reqs)); + WARN_ON(!test_and_clear_bit(req->tag, + &host->cmdq_ctx.active_reqs)); + mmc_cmdq_clk_scaling_stop_busy(host, true, false); + } + return ret; } @@ -4042,6 +4061,13 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req) ret = mmc_blk_cmdq_issue_flush_rq(mq, req); } else { ret = mmc_blk_cmdq_issue_rw_rq(mq, req); + /* + * If issuing of the request fails with eitehr EBUSY or + * EAGAIN error, re-queue the request. + * This case would occur with ICE calls. + */ + if (ret == -EBUSY || ret == -EAGAIN) + mmc_blk_cmdq_requeue_rw_rq(mq, req); } }