aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorRay Jui <rjui@broadcom.com>2013-10-26 14:03:44 -0400
committerChris Ball <chris@printf.net>2014-01-13 12:48:10 -0500
commitf662ae48ae67dfd42739e65750274fe8de46240a (patch)
tree0e8d4bf385454dc12f29bcf190553a8defc69732 /drivers/mmc/card
parent89d7e5c131228a8f0d8b0cb48b459c62152bf620 (diff)
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: Ray Jui <rjui@broadcom.com> Reviewed-by: Seungwon Jeon <tgih.jun@samsung.com> Acked-by: Seungwon Jeon <tgih.jun@samsung.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 29d5d988a51c..7b5424f398ac 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1959,6 +1959,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1959 struct mmc_card *card = md->queue.card; 1959 struct mmc_card *card = md->queue.card;
1960 struct mmc_host *host = card->host; 1960 struct mmc_host *host = card->host;
1961 unsigned long flags; 1961 unsigned long flags;
1962 unsigned int cmd_flags = req ? req->cmd_flags : 0;
1962 1963
1963 if (req && !mq->mqrq_prev->req) 1964 if (req && !mq->mqrq_prev->req)
1964 /* claim host only for the first request */ 1965 /* 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 } 1975 }
1975 1976
1976 mq->flags &= ~MMC_QUEUE_NEW_REQUEST; 1977 mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
1977 if (req && req->cmd_flags & REQ_DISCARD) { 1978 if (cmd_flags & REQ_DISCARD) {
1978 /* complete ongoing async transfer before issuing discard */ 1979 /* complete ongoing async transfer before issuing discard */
1979 if (card->host->areq) 1980 if (card->host->areq)
1980 mmc_blk_issue_rw_rq(mq, NULL); 1981 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 ret = mmc_blk_issue_secdiscard_rq(mq, req); 1984 ret = mmc_blk_issue_secdiscard_rq(mq, req);
1984 else 1985 else
1985 ret = mmc_blk_issue_discard_rq(mq, req); 1986 ret = mmc_blk_issue_discard_rq(mq, req);
1986 } else if (req && req->cmd_flags & REQ_FLUSH) { 1987 } else if (cmd_flags & REQ_FLUSH) {
1987 /* complete ongoing async transfer before issuing flush */ 1988 /* complete ongoing async transfer before issuing flush */
1988 if (card->host->areq) 1989 if (card->host->areq)
1989 mmc_blk_issue_rw_rq(mq, NULL); 1990 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 2000
2000out: 2001out:
2001 if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || 2002 if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
2002 (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) 2003 (cmd_flags & MMC_REQ_SPECIAL_MASK))
2003 /* 2004 /*
2004 * Release host when there are no more requests 2005 * Release host when there are no more requests
2005 * and after special request(discard, flush) is done. 2006 * and after special request(discard, flush) is done.