aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/wbsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/wbsd.c')
-rw-r--r--drivers/mmc/host/wbsd.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index f4233576153b..1e54bbf13d75 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -268,43 +268,29 @@ static inline int wbsd_next_sg(struct wbsd_host *host)
268 return host->num_sg; 268 return host->num_sg;
269} 269}
270 270
271static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) 271static inline char *wbsd_map_sg(struct wbsd_host *host)
272{ 272{
273 return sg_virt(host->cur_sg); 273 return kmap_atomic(sg_page(host->cur_sg)) + host->cur_sg->offset;
274} 274}
275 275
276static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) 276static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
277{ 277{
278 unsigned int len, i; 278 size_t len = 0;
279 struct scatterlist *sg; 279 int i;
280 char *dmabuf = host->dma_buffer; 280
281 char *sgbuf; 281 for (i = 0; i < data->sg_len; i++)
282 282 len += data->sg[i].length;
283 sg = data->sg; 283 sg_copy_to_buffer(data->sg, data->sg_len, host->dma_buffer, len);
284 len = data->sg_len;
285
286 for (i = 0; i < len; i++) {
287 sgbuf = sg_virt(&sg[i]);
288 memcpy(dmabuf, sgbuf, sg[i].length);
289 dmabuf += sg[i].length;
290 }
291} 284}
292 285
293static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) 286static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
294{ 287{
295 unsigned int len, i; 288 size_t len = 0;
296 struct scatterlist *sg; 289 int i;
297 char *dmabuf = host->dma_buffer; 290
298 char *sgbuf; 291 for (i = 0; i < data->sg_len; i++)
299 292 len += data->sg[i].length;
300 sg = data->sg; 293 sg_copy_from_buffer(data->sg, data->sg_len, host->dma_buffer, len);
301 len = data->sg_len;
302
303 for (i = 0; i < len; i++) {
304 sgbuf = sg_virt(&sg[i]);
305 memcpy(sgbuf, dmabuf, sg[i].length);
306 dmabuf += sg[i].length;
307 }
308} 294}
309 295
310/* 296/*
@@ -418,7 +404,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
418{ 404{
419 struct mmc_data *data = host->mrq->cmd->data; 405 struct mmc_data *data = host->mrq->cmd->data;
420 char *buffer; 406 char *buffer;
421 int i, fsr, fifo; 407 int i, idx, fsr, fifo;
422 408
423 /* 409 /*
424 * Handle excessive data. 410 * Handle excessive data.
@@ -426,7 +412,8 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
426 if (host->num_sg == 0) 412 if (host->num_sg == 0)
427 return; 413 return;
428 414
429 buffer = wbsd_sg_to_buffer(host) + host->offset; 415 buffer = wbsd_map_sg(host) + host->offset;
416 idx = 0;
430 417
431 /* 418 /*
432 * Drain the fifo. This has a tendency to loop longer 419 * Drain the fifo. This has a tendency to loop longer
@@ -445,8 +432,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
445 fifo = 1; 432 fifo = 1;
446 433
447 for (i = 0; i < fifo; i++) { 434 for (i = 0; i < fifo; i++) {
448 *buffer = inb(host->base + WBSD_DFR); 435 buffer[idx++] = inb(host->base + WBSD_DFR);
449 buffer++;
450 host->offset++; 436 host->offset++;
451 host->remain--; 437 host->remain--;
452 438
@@ -456,16 +442,19 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
456 * End of scatter list entry? 442 * End of scatter list entry?
457 */ 443 */
458 if (host->remain == 0) { 444 if (host->remain == 0) {
445 kunmap_atomic(buffer);
459 /* 446 /*
460 * Get next entry. Check if last. 447 * Get next entry. Check if last.
461 */ 448 */
462 if (!wbsd_next_sg(host)) 449 if (!wbsd_next_sg(host))
463 return; 450 return;
464 451
465 buffer = wbsd_sg_to_buffer(host); 452 buffer = wbsd_map_sg(host);
453 idx = 0;
466 } 454 }
467 } 455 }
468 } 456 }
457 kunmap_atomic(buffer);
469 458
470 /* 459 /*
471 * This is a very dirty hack to solve a 460 * This is a very dirty hack to solve a
@@ -480,7 +469,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
480{ 469{
481 struct mmc_data *data = host->mrq->cmd->data; 470 struct mmc_data *data = host->mrq->cmd->data;
482 char *buffer; 471 char *buffer;
483 int i, fsr, fifo; 472 int i, idx, fsr, fifo;
484 473
485 /* 474 /*
486 * Check that we aren't being called after the 475 * Check that we aren't being called after the
@@ -489,7 +478,8 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
489 if (host->num_sg == 0) 478 if (host->num_sg == 0)
490 return; 479 return;
491 480
492 buffer = wbsd_sg_to_buffer(host) + host->offset; 481 buffer = wbsd_map_sg(host) + host->offset;
482 idx = 0;
493 483
494 /* 484 /*
495 * Fill the fifo. This has a tendency to loop longer 485 * Fill the fifo. This has a tendency to loop longer
@@ -508,8 +498,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
508 fifo = 15; 498 fifo = 15;
509 499
510 for (i = 16; i > fifo; i--) { 500 for (i = 16; i > fifo; i--) {
511 outb(*buffer, host->base + WBSD_DFR); 501 outb(buffer[idx], host->base + WBSD_DFR);
512 buffer++;
513 host->offset++; 502 host->offset++;
514 host->remain--; 503 host->remain--;
515 504
@@ -519,16 +508,19 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
519 * End of scatter list entry? 508 * End of scatter list entry?
520 */ 509 */
521 if (host->remain == 0) { 510 if (host->remain == 0) {
511 kunmap_atomic(buffer);
522 /* 512 /*
523 * Get next entry. Check if last. 513 * Get next entry. Check if last.
524 */ 514 */
525 if (!wbsd_next_sg(host)) 515 if (!wbsd_next_sg(host))
526 return; 516 return;
527 517
528 buffer = wbsd_sg_to_buffer(host); 518 buffer = wbsd_map_sg(host);
519 idx = 0;
529 } 520 }
530 } 521 }
531 } 522 }
523 kunmap_atomic(buffer);
532 524
533 /* 525 /*
534 * The controller stops sending interrupts for 526 * The controller stops sending interrupts for