aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorRay Jui <rjui@broadcom.com>2013-10-26 14:03:44 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-13 16:48:00 -0500
commit1e06335d339132ecbb4196ede2cf1c2b618b0121 (patch)
treee71c8b075b122f0191a645a212e04cfb90f76299 /drivers/mmc/card
parent48526149964e69fc54a06c409e13d36990386464 (diff)
mmc: fix host release issue after discard operation
commit f662ae48ae67dfd42739e65750274fe8de46240a upstream. 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> Signed-off-by: Chris Ball <cjb@laptop.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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 76a3d3a752d8..9aca9462a12f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1931,6 +1931,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1931 struct mmc_card *card = md->queue.card; 1931 struct mmc_card *card = md->queue.card;
1932 struct mmc_host *host = card->host; 1932 struct mmc_host *host = card->host;
1933 unsigned long flags; 1933 unsigned long flags;
1934 unsigned int cmd_flags = req ? req->cmd_flags : 0;
1934 1935
1935 if (req && !mq->mqrq_prev->req) 1936 if (req && !mq->mqrq_prev->req)
1936 /* claim host only for the first request */ 1937 /* claim host only for the first request */
@@ -1946,7 +1947,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1946 } 1947 }
1947 1948
1948 mq->flags &= ~MMC_QUEUE_NEW_REQUEST; 1949 mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
1949 if (req && req->cmd_flags & REQ_DISCARD) { 1950 if (cmd_flags & REQ_DISCARD) {
1950 /* complete ongoing async transfer before issuing discard */ 1951 /* complete ongoing async transfer before issuing discard */
1951 if (card->host->areq) 1952 if (card->host->areq)
1952 mmc_blk_issue_rw_rq(mq, NULL); 1953 mmc_blk_issue_rw_rq(mq, NULL);
@@ -1955,7 +1956,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1955 ret = mmc_blk_issue_secdiscard_rq(mq, req); 1956 ret = mmc_blk_issue_secdiscard_rq(mq, req);
1956 else 1957 else
1957 ret = mmc_blk_issue_discard_rq(mq, req); 1958 ret = mmc_blk_issue_discard_rq(mq, req);
1958 } else if (req && req->cmd_flags & REQ_FLUSH) { 1959 } else if (cmd_flags & REQ_FLUSH) {
1959 /* complete ongoing async transfer before issuing flush */ 1960 /* complete ongoing async transfer before issuing flush */
1960 if (card->host->areq) 1961 if (card->host->areq)
1961 mmc_blk_issue_rw_rq(mq, NULL); 1962 mmc_blk_issue_rw_rq(mq, NULL);
@@ -1971,7 +1972,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1971 1972
1972out: 1973out:
1973 if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || 1974 if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
1974 (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) 1975 (cmd_flags & MMC_REQ_SPECIAL_MASK))
1975 /* 1976 /*
1976 * Release host when there are no more requests 1977 * Release host when there are no more requests
1977 * and after special request(discard, flush) is done. 1978 * and after special request(discard, flush) is done.