Commit f662ae48 authored by Ray Jui's avatar Ray Jui Committed by Chris Ball

mmc: fix host release issue after discard operation

Under function mmc_blk_issue_rq, after an MMC discard operation,
the MMC request data structure may be freed in memory. Later in
the same function, the check of req->cmd_flags & MMC_REQ_SPECIAL_MASK
is dangerous and invalid. It causes the MMC host not to be released
when it should.

This patch fixes the issue by marking the special request down before
the discard/flush operation.

Reported by: Harold (SoonYeal) Yang <haroldsy@broadcom.com>
Signed-off-by: default avatarRay Jui <rjui@broadcom.com>
Reviewed-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Acked-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 89d7e5c1
...@@ -1959,6 +1959,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ...@@ -1959,6 +1959,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = md->queue.card; struct mmc_card *card = md->queue.card;
struct mmc_host *host = card->host; struct mmc_host *host = card->host;
unsigned long flags; unsigned long flags;
unsigned int cmd_flags = req ? req->cmd_flags : 0;
if (req && !mq->mqrq_prev->req) if (req && !mq->mqrq_prev->req)
/* claim host only for the first request */ /* claim host only for the first request */
...@@ -1974,7 +1975,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ...@@ -1974,7 +1975,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
} }
mq->flags &= ~MMC_QUEUE_NEW_REQUEST; mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
if (req && req->cmd_flags & REQ_DISCARD) { if (cmd_flags & REQ_DISCARD) {
/* complete ongoing async transfer before issuing discard */ /* complete ongoing async transfer before issuing discard */
if (card->host->areq) if (card->host->areq)
mmc_blk_issue_rw_rq(mq, NULL); mmc_blk_issue_rw_rq(mq, NULL);
...@@ -1983,7 +1984,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ...@@ -1983,7 +1984,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
ret = mmc_blk_issue_secdiscard_rq(mq, req); ret = mmc_blk_issue_secdiscard_rq(mq, req);
else else
ret = mmc_blk_issue_discard_rq(mq, req); ret = mmc_blk_issue_discard_rq(mq, req);
} else if (req && req->cmd_flags & REQ_FLUSH) { } else if (cmd_flags & REQ_FLUSH) {
/* complete ongoing async transfer before issuing flush */ /* complete ongoing async transfer before issuing flush */
if (card->host->areq) if (card->host->areq)
mmc_blk_issue_rw_rq(mq, NULL); mmc_blk_issue_rw_rq(mq, NULL);
...@@ -1999,7 +2000,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ...@@ -1999,7 +2000,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
out: out:
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
(req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) (cmd_flags & MMC_REQ_SPECIAL_MASK))
/* /*
* Release host when there are no more requests * Release host when there are no more requests
* and after special request(discard, flush) is done. * and after special request(discard, flush) is done.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment