From e8dce7e56dfc825a43fd775fe81d54cae21d2232 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Mon, 9 Oct 2017 21:25:05 +0530 Subject: [PATCH] mmc: card: Requeue the request if it fails during issuing In the cmdq request issuing path, cq driver invokes ICE driver calls to get the configuration for encrypting/decrypting the data requests. The ice driver in-turn makes calls to secure world (TZ) which can process only single task at a time. If TZ is busy in servicing something else when ICE driver invokes it, ICE driver would return -EBUSY to cmdq driver. The requests which failed due to ice error are neither issued to h/w nor errored out, so resulting in filesystem corruptions. We must re-queue the requests which failed with -EBUSY error, so that it will be re-issued again as very next request. Change-Id: I4557a5c3aca8dd53740e48e516e6011787df50d8 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/card/block.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) 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); } }