diff options
| author | Asutosh Das <asutoshd@codeaurora.org> | 2015-03-02 23:14:05 +0530 |
|---|---|---|
| committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-31 15:26:33 -0700 |
| commit | eb2587ce536bffd12bc2cd2a59e3331ba34d4d68 (patch) | |
| tree | e0db4b2a9007a76a4aedd1681df25665e9591431 | |
| parent | f446730be194afa78404fd8d1e474305218a000c (diff) | |
mmc: queue: add timeout capability to requests
Individual requests can have timeouts defined. The default
timeout is set to 120 seconds. On a timeout, the block layer
notifies the driver and error can be handled thereafter.
Change-Id: Ifcd690411770ab266c12a01bb0993f92b0f18bc6
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
| -rw-r--r-- | drivers/mmc/card/block.c | 21 | ||||
| -rw-r--r-- | drivers/mmc/card/queue.c | 12 | ||||
| -rw-r--r-- | drivers/mmc/card/queue.h | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/cmdq_hci.c | 8 | ||||
| -rw-r--r-- | include/linux/mmc/host.h | 1 |
5 files changed, 43 insertions, 0 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index fc98eea77fe7..daccedcb7f58 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2735,6 +2735,26 @@ reset: clear_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state); } +static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) +{ + struct mmc_queue *mq = req->q->queuedata; + struct mmc_host *host = mq->card->host; + struct mmc_queue_req *mq_rq = req->special; + struct mmc_request *mrq = &mq_rq->cmdq_req.mrq; + struct mmc_cmdq_req *cmdq_req = &mq_rq->cmdq_req; + + host->cmdq_ops->dumpstate(host); + if (cmdq_req->cmdq_req_flags & DCMD) + mrq->cmd->error = -ETIMEDOUT; + else + mrq->data->error = -ETIMEDOUT; + + host->err_mrq = mrq; + mrq->done(mrq); + + return BLK_EH_NOT_HANDLED; +} + static void mmc_blk_cmdq_err(struct mmc_queue *mq) { int err; @@ -3319,6 +3339,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, md->queue.cmdq_complete_fn = mmc_blk_cmdq_complete_rq; md->queue.cmdq_issue_fn = mmc_blk_cmdq_issue_rq; md->queue.cmdq_error_fn = mmc_blk_cmdq_err; + md->queue.cmdq_req_timed_out = mmc_blk_cmdq_req_timed_out; } if (mmc_card_mmc(card) && !card->cmdq_init && diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 676e080550f8..be417461f44b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -577,6 +577,16 @@ static void mmc_cmdq_error_work(struct work_struct *work) mq->cmdq_error_fn(mq); } +enum blk_eh_timer_return mmc_cmdq_rq_timed_out(struct request *req) +{ + struct mmc_queue *mq = req->q->queuedata; + + pr_err("%s: request with tag: %d flags: 0x%llx timed out\n", + mmc_hostname(mq->card->host), req->tag, req->cmd_flags); + + return mq->cmdq_req_timed_out(req); +} + int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) { int i, ret = 0; @@ -619,6 +629,8 @@ int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done); INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work); + blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out); + blk_queue_rq_timeout(mq->queue, 120 * HZ); card->cmdq_init = true; goto out; diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index c4acab9bff27..388f099a06f5 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -58,6 +58,7 @@ struct mmc_queue { struct request *); void (*cmdq_complete_fn)(struct request *); void (*cmdq_error_fn)(struct mmc_queue *); + enum blk_eh_timer_return (*cmdq_req_timed_out)(struct request *); void *data; struct request_queue *queue; struct mmc_queue_req mqrq[2]; diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c index affc92756c0b..08ba2546cf37 100644 --- a/drivers/mmc/host/cmdq_hci.c +++ b/drivers/mmc/host/cmdq_hci.c @@ -715,6 +715,13 @@ static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, } } +static void cmdq_dumpstate(struct mmc_host *mmc) +{ + struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); + + cmdq_dumpregs(cq_host); +} + static const struct mmc_cmdq_host_ops cmdq_host_ops = { .enable = cmdq_enable, .disable = cmdq_disable, @@ -722,6 +729,7 @@ static const struct mmc_cmdq_host_ops cmdq_host_ops = { .post_req = cmdq_post_req, .halt = cmdq_halt, .reset = cmdq_reset, + .dumpstate = cmdq_dumpstate, }; struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 18d041f85f95..6c6a699abea9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -96,6 +96,7 @@ struct mmc_cmdq_host_ops { int err); int (*halt)(struct mmc_host *host, bool halt); void (*reset)(struct mmc_host *host, bool soft); + void (*dumpstate)(struct mmc_host *host); }; struct mmc_host_ops { |
