diff options
-rw-r--r-- | drivers/mmc/card/block.c | 42 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 16 |
2 files changed, 55 insertions, 3 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 | ||
250 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | 250 | static 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); | ||
273 | out: | ||
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 | |||
283 | static 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 | ||
511 | static 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 | ||
479 | static inline int mmc_blk_readonly(struct mmc_card *card) | 519 | static inline int mmc_blk_readonly(struct mmc_card *card) |
480 | { | 520 | { |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c77eb49eda0..3b15884e435 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -30,9 +30,9 @@ | |||
30 | static int mmc_prep_request(struct request_queue *q, struct request *req) | 30 | static int mmc_prep_request(struct request_queue *q, struct request *req) |
31 | { | 31 | { |
32 | /* | 32 | /* |
33 | * We only like normal block requests. | 33 | * We only like normal block requests and discards. |
34 | */ | 34 | */ |
35 | if (req->cmd_type != REQ_TYPE_FS) { | 35 | if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) { |
36 | blk_dump_rq_flags(req, "MMC bad request"); | 36 | blk_dump_rq_flags(req, "MMC bad request"); |
37 | return BLKPREP_KILL; | 37 | return BLKPREP_KILL; |
38 | } | 38 | } |
@@ -130,6 +130,18 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); | 130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); |
131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); | 131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); |
132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); | 132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); |
133 | if (mmc_can_erase(card)) { | ||
134 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue); | ||
135 | mq->queue->limits.max_discard_sectors = UINT_MAX; | ||
136 | if (card->erased_byte == 0) | ||
137 | mq->queue->limits.discard_zeroes_data = 1; | ||
138 | if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) { | ||
139 | mq->queue->limits.discard_granularity = | ||
140 | card->erase_size << 9; | ||
141 | mq->queue->limits.discard_alignment = | ||
142 | card->erase_size << 9; | ||
143 | } | ||
144 | } | ||
133 | 145 | ||
134 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 146 | #ifdef CONFIG_MMC_BLOCK_BOUNCE |
135 | if (host->max_hw_segs == 1) { | 147 | if (host->max_hw_segs == 1) { |