diff options
-rw-r--r-- | drivers/mmc/core/block.c | 3 | ||||
-rw-r--r-- | drivers/mmc/core/queue.c | 125 | ||||
-rw-r--r-- | drivers/mmc/core/queue.h | 6 | ||||
-rw-r--r-- | drivers/mmc/host/cavium.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/pxamci.c | 6 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 2 |
6 files changed, 12 insertions, 132 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 29fc1e662891..2ad7b5c69156 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c | |||
@@ -1634,8 +1634,6 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, | |||
1634 | } | 1634 | } |
1635 | 1635 | ||
1636 | mqrq->areq.mrq = &brq->mrq; | 1636 | mqrq->areq.mrq = &brq->mrq; |
1637 | |||
1638 | mmc_queue_bounce_pre(mqrq); | ||
1639 | } | 1637 | } |
1640 | 1638 | ||
1641 | static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, | 1639 | static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, |
@@ -1829,7 +1827,6 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req) | |||
1829 | brq = &mq_rq->brq; | 1827 | brq = &mq_rq->brq; |
1830 | old_req = mmc_queue_req_to_req(mq_rq); | 1828 | old_req = mmc_queue_req_to_req(mq_rq); |
1831 | type = rq_data_dir(old_req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; | 1829 | type = rq_data_dir(old_req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; |
1832 | mmc_queue_bounce_post(mq_rq); | ||
1833 | 1830 | ||
1834 | switch (status) { | 1831 | switch (status) { |
1835 | case MMC_BLK_SUCCESS: | 1832 | case MMC_BLK_SUCCESS: |
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 74c663b1c0a7..0a4e77a5ba33 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include "core.h" | 23 | #include "core.h" |
24 | #include "card.h" | 24 | #include "card.h" |
25 | 25 | ||
26 | #define MMC_QUEUE_BOUNCESZ 65536 | ||
27 | |||
28 | /* | 26 | /* |
29 | * Prepare a MMC request. This just filters out odd stuff. | 27 | * Prepare a MMC request. This just filters out odd stuff. |
30 | */ | 28 | */ |
@@ -150,26 +148,6 @@ static void mmc_queue_setup_discard(struct request_queue *q, | |||
150 | queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q); | 148 | queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q); |
151 | } | 149 | } |
152 | 150 | ||
153 | static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host) | ||
154 | { | ||
155 | unsigned int bouncesz = MMC_QUEUE_BOUNCESZ; | ||
156 | |||
157 | if (host->max_segs != 1 || (host->caps & MMC_CAP_NO_BOUNCE_BUFF)) | ||
158 | return 0; | ||
159 | |||
160 | if (bouncesz > host->max_req_size) | ||
161 | bouncesz = host->max_req_size; | ||
162 | if (bouncesz > host->max_seg_size) | ||
163 | bouncesz = host->max_seg_size; | ||
164 | if (bouncesz > host->max_blk_count * 512) | ||
165 | bouncesz = host->max_blk_count * 512; | ||
166 | |||
167 | if (bouncesz <= 512) | ||
168 | return 0; | ||
169 | |||
170 | return bouncesz; | ||
171 | } | ||
172 | |||
173 | /** | 151 | /** |
174 | * mmc_init_request() - initialize the MMC-specific per-request data | 152 | * mmc_init_request() - initialize the MMC-specific per-request data |
175 | * @q: the request queue | 153 | * @q: the request queue |
@@ -184,26 +162,9 @@ static int mmc_init_request(struct request_queue *q, struct request *req, | |||
184 | struct mmc_card *card = mq->card; | 162 | struct mmc_card *card = mq->card; |
185 | struct mmc_host *host = card->host; | 163 | struct mmc_host *host = card->host; |
186 | 164 | ||
187 | if (card->bouncesz) { | 165 | mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp); |
188 | mq_rq->bounce_buf = kmalloc(card->bouncesz, gfp); | 166 | if (!mq_rq->sg) |
189 | if (!mq_rq->bounce_buf) | 167 | return -ENOMEM; |
190 | return -ENOMEM; | ||
191 | if (card->bouncesz > 512) { | ||
192 | mq_rq->sg = mmc_alloc_sg(1, gfp); | ||
193 | if (!mq_rq->sg) | ||
194 | return -ENOMEM; | ||
195 | mq_rq->bounce_sg = mmc_alloc_sg(card->bouncesz / 512, | ||
196 | gfp); | ||
197 | if (!mq_rq->bounce_sg) | ||
198 | return -ENOMEM; | ||
199 | } | ||
200 | } else { | ||
201 | mq_rq->bounce_buf = NULL; | ||
202 | mq_rq->bounce_sg = NULL; | ||
203 | mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp); | ||
204 | if (!mq_rq->sg) | ||
205 | return -ENOMEM; | ||
206 | } | ||
207 | 168 | ||
208 | return 0; | 169 | return 0; |
209 | } | 170 | } |
@@ -212,13 +173,6 @@ static void mmc_exit_request(struct request_queue *q, struct request *req) | |||
212 | { | 173 | { |
213 | struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req); | 174 | struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req); |
214 | 175 | ||
215 | /* It is OK to kfree(NULL) so this will be smooth */ | ||
216 | kfree(mq_rq->bounce_sg); | ||
217 | mq_rq->bounce_sg = NULL; | ||
218 | |||
219 | kfree(mq_rq->bounce_buf); | ||
220 | mq_rq->bounce_buf = NULL; | ||
221 | |||
222 | kfree(mq_rq->sg); | 176 | kfree(mq_rq->sg); |
223 | mq_rq->sg = NULL; | 177 | mq_rq->sg = NULL; |
224 | } | 178 | } |
@@ -242,12 +196,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, | |||
242 | if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) | 196 | if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) |
243 | limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; | 197 | limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; |
244 | 198 | ||
245 | /* | ||
246 | * mmc_init_request() depends on card->bouncesz so it must be calculated | ||
247 | * before blk_init_allocated_queue() starts allocating requests. | ||
248 | */ | ||
249 | card->bouncesz = mmc_queue_calc_bouncesz(host); | ||
250 | |||
251 | mq->card = card; | 199 | mq->card = card; |
252 | mq->queue = blk_alloc_queue(GFP_KERNEL); | 200 | mq->queue = blk_alloc_queue(GFP_KERNEL); |
253 | if (!mq->queue) | 201 | if (!mq->queue) |
@@ -271,17 +219,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, | |||
271 | if (mmc_can_erase(card)) | 219 | if (mmc_can_erase(card)) |
272 | mmc_queue_setup_discard(mq->queue, card); | 220 | mmc_queue_setup_discard(mq->queue, card); |
273 | 221 | ||
274 | if (card->bouncesz) { | 222 | blk_queue_bounce_limit(mq->queue, limit); |
275 | blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512); | 223 | blk_queue_max_hw_sectors(mq->queue, |
276 | blk_queue_max_segments(mq->queue, card->bouncesz / 512); | 224 | min(host->max_blk_count, host->max_req_size / 512)); |
277 | blk_queue_max_segment_size(mq->queue, card->bouncesz); | 225 | blk_queue_max_segments(mq->queue, host->max_segs); |
278 | } else { | 226 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
279 | blk_queue_bounce_limit(mq->queue, limit); | ||
280 | blk_queue_max_hw_sectors(mq->queue, | ||
281 | min(host->max_blk_count, host->max_req_size / 512)); | ||
282 | blk_queue_max_segments(mq->queue, host->max_segs); | ||
283 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | ||
284 | } | ||
285 | 227 | ||
286 | sema_init(&mq->thread_sem, 1); | 228 | sema_init(&mq->thread_sem, 1); |
287 | 229 | ||
@@ -370,56 +312,7 @@ void mmc_queue_resume(struct mmc_queue *mq) | |||
370 | */ | 312 | */ |
371 | unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) | 313 | unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) |
372 | { | 314 | { |
373 | unsigned int sg_len; | ||
374 | size_t buflen; | ||
375 | struct scatterlist *sg; | ||
376 | struct request *req = mmc_queue_req_to_req(mqrq); | 315 | struct request *req = mmc_queue_req_to_req(mqrq); |
377 | int i; | ||
378 | |||
379 | if (!mqrq->bounce_buf) | ||
380 | return blk_rq_map_sg(mq->queue, req, mqrq->sg); | ||
381 | |||
382 | sg_len = blk_rq_map_sg(mq->queue, req, mqrq->bounce_sg); | ||
383 | |||
384 | mqrq->bounce_sg_len = sg_len; | ||
385 | |||
386 | buflen = 0; | ||
387 | for_each_sg(mqrq->bounce_sg, sg, sg_len, i) | ||
388 | buflen += sg->length; | ||
389 | |||
390 | sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen); | ||
391 | |||
392 | return 1; | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * If writing, bounce the data to the buffer before the request | ||
397 | * is sent to the host driver | ||
398 | */ | ||
399 | void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq) | ||
400 | { | ||
401 | if (!mqrq->bounce_buf) | ||
402 | return; | ||
403 | |||
404 | if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != WRITE) | ||
405 | return; | ||
406 | |||
407 | sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, | ||
408 | mqrq->bounce_buf, mqrq->sg[0].length); | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * If reading, bounce the data from the buffer after the request | ||
413 | * has been handled by the host driver | ||
414 | */ | ||
415 | void mmc_queue_bounce_post(struct mmc_queue_req *mqrq) | ||
416 | { | ||
417 | if (!mqrq->bounce_buf) | ||
418 | return; | ||
419 | |||
420 | if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != READ) | ||
421 | return; | ||
422 | 316 | ||
423 | sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, | 317 | return blk_rq_map_sg(mq->queue, req, mqrq->sg); |
424 | mqrq->bounce_buf, mqrq->sg[0].length); | ||
425 | } | 318 | } |
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 04fc89360a7a..f18d3f656baa 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h | |||
@@ -49,9 +49,6 @@ enum mmc_drv_op { | |||
49 | struct mmc_queue_req { | 49 | struct mmc_queue_req { |
50 | struct mmc_blk_request brq; | 50 | struct mmc_blk_request brq; |
51 | struct scatterlist *sg; | 51 | struct scatterlist *sg; |
52 | char *bounce_buf; | ||
53 | struct scatterlist *bounce_sg; | ||
54 | unsigned int bounce_sg_len; | ||
55 | struct mmc_async_req areq; | 52 | struct mmc_async_req areq; |
56 | enum mmc_drv_op drv_op; | 53 | enum mmc_drv_op drv_op; |
57 | int drv_op_result; | 54 | int drv_op_result; |
@@ -81,11 +78,8 @@ extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, | |||
81 | extern void mmc_cleanup_queue(struct mmc_queue *); | 78 | extern void mmc_cleanup_queue(struct mmc_queue *); |
82 | extern void mmc_queue_suspend(struct mmc_queue *); | 79 | extern void mmc_queue_suspend(struct mmc_queue *); |
83 | extern void mmc_queue_resume(struct mmc_queue *); | 80 | extern void mmc_queue_resume(struct mmc_queue *); |
84 | |||
85 | extern unsigned int mmc_queue_map_sg(struct mmc_queue *, | 81 | extern unsigned int mmc_queue_map_sg(struct mmc_queue *, |
86 | struct mmc_queue_req *); | 82 | struct mmc_queue_req *); |
87 | extern void mmc_queue_bounce_pre(struct mmc_queue_req *); | ||
88 | extern void mmc_queue_bounce_post(struct mmc_queue_req *); | ||
89 | 83 | ||
90 | extern int mmc_access_rpmb(struct mmc_queue *); | 84 | extern int mmc_access_rpmb(struct mmc_queue *); |
91 | 85 | ||
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index 27fb625cbcf3..fbd29f00fca0 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c | |||
@@ -1038,7 +1038,7 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host) | |||
1038 | */ | 1038 | */ |
1039 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 1039 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
1040 | MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD | | 1040 | MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD | |
1041 | MMC_CAP_3_3V_DDR | MMC_CAP_NO_BOUNCE_BUFF; | 1041 | MMC_CAP_3_3V_DDR; |
1042 | 1042 | ||
1043 | if (host->use_sg) | 1043 | if (host->use_sg) |
1044 | mmc->max_segs = 16; | 1044 | mmc->max_segs = 16; |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 59ab194cb009..c763b404510f 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -702,11 +702,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
702 | 702 | ||
703 | pxamci_init_ocr(host); | 703 | pxamci_init_ocr(host); |
704 | 704 | ||
705 | /* | 705 | mmc->caps = 0; |
706 | * This architecture used to disable bounce buffers through its | ||
707 | * defconfig, now it is done at runtime as a host property. | ||
708 | */ | ||
709 | mmc->caps = MMC_CAP_NO_BOUNCE_BUFF; | ||
710 | host->cmdat = 0; | 706 | host->cmdat = 0; |
711 | if (!cpu_is_pxa25x()) { | 707 | if (!cpu_is_pxa25x()) { |
712 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 708 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index f3f2d07feb2a..9a43763a68ad 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -316,7 +316,7 @@ struct mmc_host { | |||
316 | #define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */ | 316 | #define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */ |
317 | #define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */ | 317 | #define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */ |
318 | #define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */ | 318 | #define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */ |
319 | #define MMC_CAP_NO_BOUNCE_BUFF (1 << 21) /* Disable bounce buffers on host */ | 319 | /* (1 << 21) is free for reuse */ |
320 | #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ | 320 | #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ |
321 | #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ | 321 | #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ |
322 | #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ | 322 | #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ |