OSDN Git Service

mmc: card: Requeue the request if it fails during issuing
authorVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
Mon, 9 Oct 2017 15:55:05 +0000 (21:25 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 24 Nov 2017 14:03:15 +0000 (06:03 -0800)
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 <vbadigan@codeaurora.org>
drivers/mmc/card/block.c

index 063e005..7d2ceda 100644 (file)
@@ -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);
                }
        }