]>
Commit | Line | Data |
---|---|---|
c6af9cf9 GKH |
1 | From f662ae48ae67dfd42739e65750274fe8de46240a Mon Sep 17 00:00:00 2001 |
2 | From: Ray Jui <rjui@broadcom.com> | |
3 | Date: Sat, 26 Oct 2013 11:03:44 -0700 | |
4 | Subject: mmc: fix host release issue after discard operation | |
5 | ||
6 | From: Ray Jui <rjui@broadcom.com> | |
7 | ||
8 | commit f662ae48ae67dfd42739e65750274fe8de46240a upstream. | |
9 | ||
10 | Under function mmc_blk_issue_rq, after an MMC discard operation, | |
11 | the MMC request data structure may be freed in memory. Later in | |
12 | the same function, the check of req->cmd_flags & MMC_REQ_SPECIAL_MASK | |
13 | is dangerous and invalid. It causes the MMC host not to be released | |
14 | when it should. | |
15 | ||
16 | This patch fixes the issue by marking the special request down before | |
17 | the discard/flush operation. | |
18 | ||
19 | Reported by: Harold (SoonYeal) Yang <haroldsy@broadcom.com> | |
20 | Signed-off-by: Ray Jui <rjui@broadcom.com> | |
21 | Reviewed-by: Seungwon Jeon <tgih.jun@samsung.com> | |
22 | Acked-by: Seungwon Jeon <tgih.jun@samsung.com> | |
23 | Signed-off-by: Chris Ball <cjb@laptop.org> | |
24 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
25 | ||
26 | --- | |
27 | drivers/mmc/card/block.c | 7 ++++--- | |
28 | 1 file changed, 4 insertions(+), 3 deletions(-) | |
29 | ||
30 | --- a/drivers/mmc/card/block.c | |
31 | +++ b/drivers/mmc/card/block.c | |
32 | @@ -1931,6 +1931,7 @@ static int mmc_blk_issue_rq(struct mmc_q | |
33 | struct mmc_card *card = md->queue.card; | |
34 | struct mmc_host *host = card->host; | |
35 | unsigned long flags; | |
36 | + unsigned int cmd_flags = req ? req->cmd_flags : 0; | |
37 | ||
38 | if (req && !mq->mqrq_prev->req) | |
39 | /* claim host only for the first request */ | |
40 | @@ -1946,7 +1947,7 @@ static int mmc_blk_issue_rq(struct mmc_q | |
41 | } | |
42 | ||
43 | mq->flags &= ~MMC_QUEUE_NEW_REQUEST; | |
44 | - if (req && req->cmd_flags & REQ_DISCARD) { | |
45 | + if (cmd_flags & REQ_DISCARD) { | |
46 | /* complete ongoing async transfer before issuing discard */ | |
47 | if (card->host->areq) | |
48 | mmc_blk_issue_rw_rq(mq, NULL); | |
49 | @@ -1955,7 +1956,7 @@ static int mmc_blk_issue_rq(struct mmc_q | |
50 | ret = mmc_blk_issue_secdiscard_rq(mq, req); | |
51 | else | |
52 | ret = mmc_blk_issue_discard_rq(mq, req); | |
53 | - } else if (req && req->cmd_flags & REQ_FLUSH) { | |
54 | + } else if (cmd_flags & REQ_FLUSH) { | |
55 | /* complete ongoing async transfer before issuing flush */ | |
56 | if (card->host->areq) | |
57 | mmc_blk_issue_rw_rq(mq, NULL); | |
58 | @@ -1971,7 +1972,7 @@ static int mmc_blk_issue_rq(struct mmc_q | |
59 | ||
60 | out: | |
61 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || | |
62 | - (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) | |
63 | + (cmd_flags & MMC_REQ_SPECIAL_MASK)) | |
64 | /* | |
65 | * Release host when there are no more requests | |
66 | * and after special request(discard, flush) is done. |