diff options
Diffstat (limited to 'drivers/mmc/host/wbsd.c')
-rw-r--r-- | drivers/mmc/host/wbsd.c | 68 |
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 | ||
271 | static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) | 271 | static 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 | ||
276 | static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) | 276 | static 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 | ||
293 | static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) | 286 | static 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 |