mmc: card: fix null pointer deference in cmdq timeout handler

The mmc_queue_req will be present only if the request is issued
to the LLD. The request could be fetched from block layer queue
but could be waiting to be issued (for e.g. clock scaling is
waiting for an empty cmdq queue). Evaluate such cases and reset
the timer to give LLD more time.

Change-Id: Ic5818f5c2b8356bda9b1612d78b65e07dad011d7
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
This commit is contained in:
Venkat Gopalakrishnan 2015-08-28 17:18:54 -07:00 committed by Sahitya Tummala
parent 381320b601
commit d2bfe9d86b
1 changed files with 25 additions and 4 deletions

View File

@ -3041,18 +3041,38 @@ 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;
struct mmc_request *mrq;
struct mmc_cmdq_req *cmdq_req;
BUG_ON(!host);
/*
* The mmc_queue_req will be present only if the request
* is issued to the LLD. The request could be fetched from
* block layer queue but could be waiting to be issued
* (for e.g. clock scaling is waiting for an empty cmdq queue)
* Reset the timer in such cases to give LLD more time
*/
if (!mq_rq) {
pr_warn("%s: restart timer for tag: %d\n", __func__, req->tag);
return BLK_EH_RESET_TIMER;
}
mrq = &mq_rq->cmdq_req.mrq;
cmdq_req = &mq_rq->cmdq_req;
BUG_ON(!mrq || !cmdq_req);
if (cmdq_req->cmdq_req_flags & DCMD)
mrq->cmd->error = -ETIMEDOUT;
else
mrq->data->error = -ETIMEDOUT;
BUG_ON(host->err_mrq != NULL);
host->err_mrq = mrq;
mrq->done(mrq);
return BLK_EH_NOT_HANDLED;
mmc_host_clk_release(mrq->host);
return BLK_EH_HANDLED;
}
static void mmc_blk_cmdq_err(struct mmc_queue *mq)
@ -3131,6 +3151,7 @@ unhalt:
mmc_cmdq_halt(host, false);
out:
host->err_mrq = NULL;
mmc_rpm_release(host, &card->dev);
if (test_and_clear_bit(0, &ctx_info->req_starved))