aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card/block.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2010-08-11 17:17:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 11:43:30 -0400
commitbd788c9665fb7c543aac21317059375632343337 (patch)
tree8d4a2a629cafefa2e0f2a9a44a558d10d3c7bddd /drivers/mmc/card/block.c
parentdfe86cba7676d58db8de7e623f5e72f1b0d3ca35 (diff)
mmc_block: add discard support
Enable MMC to service discard requests. In the case of SD and MMC cards that do not support trim, discards become erases. In the case of cards (MMC) that only allow erases in multiples of erase group size, round to the nearest completely discarded erase group. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Acked-by: Jens Axboe <axboe@kernel.dk> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Madhusudhan Chikkature <madhu.cr@ti.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Ben Gardiner <bengardiner@nanometrics.ca> Cc: <linux-mmc@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc/card/block.c')
-rw-r--r--drivers/mmc/card/block.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 8433cde29c8..03f96e975fe 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -247,7 +247,40 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
247 return cmd.resp[0]; 247 return cmd.resp[0];
248} 248}
249 249
250static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 250static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
251{
252 struct mmc_blk_data *md = mq->data;
253 struct mmc_card *card = md->queue.card;
254 unsigned int from, nr, arg;
255 int err = 0;
256
257 mmc_claim_host(card->host);
258
259 if (!mmc_can_erase(card)) {
260 err = -EOPNOTSUPP;
261 goto out;
262 }
263
264 from = blk_rq_pos(req);
265 nr = blk_rq_sectors(req);
266
267 if (mmc_can_trim(card))
268 arg = MMC_TRIM_ARG;
269 else
270 arg = MMC_ERASE_ARG;
271
272 err = mmc_erase(card, from, nr, arg);
273out:
274 spin_lock_irq(&md->lock);
275 __blk_end_request(req, err, blk_rq_bytes(req));
276 spin_unlock_irq(&md->lock);
277
278 mmc_release_host(card->host);
279
280 return err ? 0 : 1;
281}
282
283static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
251{ 284{
252 struct mmc_blk_data *md = mq->data; 285 struct mmc_blk_data *md = mq->data;
253 struct mmc_card *card = md->queue.card; 286 struct mmc_card *card = md->queue.card;
@@ -475,6 +508,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
475 return 0; 508 return 0;
476} 509}
477 510
511static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
512{
513 if (req->cmd_flags & REQ_DISCARD)
514 return mmc_blk_issue_discard_rq(mq, req);
515 else
516 return mmc_blk_issue_rw_rq(mq, req);
517}
478 518
479static inline int mmc_blk_readonly(struct mmc_card *card) 519static inline int mmc_blk_readonly(struct mmc_card *card)
480{ 520{