aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/block.c3
-rw-r--r--drivers/mmc/core/queue.c125
-rw-r--r--drivers/mmc/core/queue.h6
-rw-r--r--drivers/mmc/host/cavium.c2
-rw-r--r--drivers/mmc/host/pxamci.c6
-rw-r--r--include/linux/mmc/host.h2
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
1641static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, 1639static 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
153static 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 */
371unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) 313unsigned 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 */
399void 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 */
415void 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 {
49struct mmc_queue_req { 49struct 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 *,
81extern void mmc_cleanup_queue(struct mmc_queue *); 78extern void mmc_cleanup_queue(struct mmc_queue *);
82extern void mmc_queue_suspend(struct mmc_queue *); 79extern void mmc_queue_suspend(struct mmc_queue *);
83extern void mmc_queue_resume(struct mmc_queue *); 80extern void mmc_queue_resume(struct mmc_queue *);
84
85extern unsigned int mmc_queue_map_sg(struct mmc_queue *, 81extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
86 struct mmc_queue_req *); 82 struct mmc_queue_req *);
87extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
88extern void mmc_queue_bounce_post(struct mmc_queue_req *);
89 83
90extern int mmc_access_rpmb(struct mmc_queue *); 84extern 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 */