aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/mmc_block.c16
-rw-r--r--drivers/mmc/sdhci.c24
-rw-r--r--drivers/mmc/sdhci.h4
-rw-r--r--drivers/mmc/wbsd.c131
-rw-r--r--drivers/mmc/wbsd.h4
5 files changed, 50 insertions, 129 deletions
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 86439a0bb271..95b0da6abe87 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -223,7 +223,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
223 struct mmc_blk_data *md = mq->data; 223 struct mmc_blk_data *md = mq->data;
224 struct mmc_card *card = md->queue.card; 224 struct mmc_card *card = md->queue.card;
225 struct mmc_blk_request brq; 225 struct mmc_blk_request brq;
226 int ret = 1; 226 int ret = 1, sg_pos, data_size;
227 227
228 if (mmc_card_claim_host(card)) 228 if (mmc_card_claim_host(card))
229 goto flush_queue; 229 goto flush_queue;
@@ -283,6 +283,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
283 brq.data.sg = mq->sg; 283 brq.data.sg = mq->sg;
284 brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg); 284 brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
285 285
286 if (brq.data.blocks !=
287 (req->nr_sectors >> (md->block_bits - 9))) {
288 data_size = brq.data.blocks * brq.data.blksz;
289 for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) {
290 data_size -= mq->sg[sg_pos].length;
291 if (data_size <= 0) {
292 mq->sg[sg_pos].length += data_size;
293 sg_pos++;
294 break;
295 }
296 }
297 brq.data.sg_len = sg_pos;
298 }
299
286 mmc_wait_for_req(card->host, &brq.mrq); 300 mmc_wait_for_req(card->host, &brq.mrq);
287 if (brq.cmd.error) { 301 if (brq.cmd.error) {
288 printk(KERN_ERR "%s: error %d sending read/write command\n", 302 printk(KERN_ERR "%s: error %d sending read/write command\n",
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d749f08601b8..587dccf95f8e 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver 2 * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
3 * 3 *
4 * Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved. 4 * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -247,14 +247,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
247 chunk_remain = min(blksize, 4); 247 chunk_remain = min(blksize, 4);
248 } 248 }
249 249
250 size = min(host->size, host->remain); 250 size = min(host->remain, chunk_remain);
251 size = min(size, chunk_remain);
252 251
253 chunk_remain -= size; 252 chunk_remain -= size;
254 blksize -= size; 253 blksize -= size;
255 host->offset += size; 254 host->offset += size;
256 host->remain -= size; 255 host->remain -= size;
257 host->size -= size; 256
258 while (size) { 257 while (size) {
259 *buffer = data & 0xFF; 258 *buffer = data & 0xFF;
260 buffer++; 259 buffer++;
@@ -289,14 +288,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
289 buffer = sdhci_sg_to_buffer(host) + host->offset; 288 buffer = sdhci_sg_to_buffer(host) + host->offset;
290 289
291 while (blksize) { 290 while (blksize) {
292 size = min(host->size, host->remain); 291 size = min(host->remain, chunk_remain);
293 size = min(size, chunk_remain);
294 292
295 chunk_remain -= size; 293 chunk_remain -= size;
296 blksize -= size; 294 blksize -= size;
297 host->offset += size; 295 host->offset += size;
298 host->remain -= size; 296 host->remain -= size;
299 host->size -= size; 297
300 while (size) { 298 while (size) {
301 data >>= 8; 299 data >>= 8;
302 data |= (u32)*buffer << 24; 300 data |= (u32)*buffer << 24;
@@ -325,7 +323,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
325 323
326 BUG_ON(!host->data); 324 BUG_ON(!host->data);
327 325
328 if (host->size == 0) 326 if (host->num_sg == 0)
329 return; 327 return;
330 328
331 if (host->data->flags & MMC_DATA_READ) 329 if (host->data->flags & MMC_DATA_READ)
@@ -339,10 +337,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
339 else 337 else
340 sdhci_write_block_pio(host); 338 sdhci_write_block_pio(host);
341 339
342 if (host->size == 0) 340 if (host->num_sg == 0)
343 break; 341 break;
344
345 BUG_ON(host->num_sg == 0);
346 } 342 }
347 343
348 DBG("PIO transfer complete.\n"); 344 DBG("PIO transfer complete.\n");
@@ -408,8 +404,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
408 404
409 writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS); 405 writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
410 } else { 406 } else {
411 host->size = data->blksz * data->blocks;
412
413 host->cur_sg = data->sg; 407 host->cur_sg = data->sg;
414 host->num_sg = data->sg_len; 408 host->num_sg = data->sg_len;
415 409
@@ -473,10 +467,6 @@ static void sdhci_finish_data(struct sdhci_host *host)
473 "though there were blocks left.\n", 467 "though there were blocks left.\n",
474 mmc_hostname(host->mmc)); 468 mmc_hostname(host->mmc));
475 data->error = MMC_ERR_FAILED; 469 data->error = MMC_ERR_FAILED;
476 } else if (host->size != 0) {
477 printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
478 mmc_hostname(host->mmc), host->size);
479 data->error = MMC_ERR_FAILED;
480 } 470 }
481 471
482 DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered); 472 DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
index e324f0a623dc..7400f4bc114f 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/sdhci.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver 2 * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
3 * 3 *
4 * Copyright (C) 2005 Pierre Ossman, All Rights Reserved. 4 * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -187,8 +187,6 @@ struct sdhci_host {
187 int offset; /* Offset into current sg */ 187 int offset; /* Offset into current sg */
188 int remain; /* Bytes left in current */ 188 int remain; /* Bytes left in current */
189 189
190 int size; /* Remaining bytes in transfer */
191
192 char slot_descr[20]; /* Name for reservations */ 190 char slot_descr[20]; /* Name for reservations */
193 191
194 int irq; /* Device IRQ */ 192 int irq; /* Device IRQ */
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 05ccfc43168f..7a3e32ec46b8 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver 2 * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
3 * 3 *
4 * Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved. 4 * Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -278,90 +278,36 @@ static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
278 278
279static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) 279static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
280{ 280{
281 unsigned int len, i, size; 281 unsigned int len, i;
282 struct scatterlist *sg; 282 struct scatterlist *sg;
283 char *dmabuf = host->dma_buffer; 283 char *dmabuf = host->dma_buffer;
284 char *sgbuf; 284 char *sgbuf;
285 285
286 size = host->size;
287
288 sg = data->sg; 286 sg = data->sg;
289 len = data->sg_len; 287 len = data->sg_len;
290 288
291 /*
292 * Just loop through all entries. Size might not
293 * be the entire list though so make sure that
294 * we do not transfer too much.
295 */
296 for (i = 0; i < len; i++) { 289 for (i = 0; i < len; i++) {
297 sgbuf = page_address(sg[i].page) + sg[i].offset; 290 sgbuf = page_address(sg[i].page) + sg[i].offset;
298 if (size < sg[i].length) 291 memcpy(dmabuf, sgbuf, sg[i].length);
299 memcpy(dmabuf, sgbuf, size);
300 else
301 memcpy(dmabuf, sgbuf, sg[i].length);
302 dmabuf += sg[i].length; 292 dmabuf += sg[i].length;
303
304 if (size < sg[i].length)
305 size = 0;
306 else
307 size -= sg[i].length;
308
309 if (size == 0)
310 break;
311 } 293 }
312
313 /*
314 * Check that we didn't get a request to transfer
315 * more data than can fit into the SG list.
316 */
317
318 BUG_ON(size != 0);
319
320 host->size -= size;
321} 294}
322 295
323static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) 296static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
324{ 297{
325 unsigned int len, i, size; 298 unsigned int len, i;
326 struct scatterlist *sg; 299 struct scatterlist *sg;
327 char *dmabuf = host->dma_buffer; 300 char *dmabuf = host->dma_buffer;
328 char *sgbuf; 301 char *sgbuf;
329 302
330 size = host->size;
331
332 sg = data->sg; 303 sg = data->sg;
333 len = data->sg_len; 304 len = data->sg_len;
334 305
335 /*
336 * Just loop through all entries. Size might not
337 * be the entire list though so make sure that
338 * we do not transfer too much.
339 */
340 for (i = 0; i < len; i++) { 306 for (i = 0; i < len; i++) {
341 sgbuf = page_address(sg[i].page) + sg[i].offset; 307 sgbuf = page_address(sg[i].page) + sg[i].offset;
342 if (size < sg[i].length) 308 memcpy(sgbuf, dmabuf, sg[i].length);
343 memcpy(sgbuf, dmabuf, size);
344 else
345 memcpy(sgbuf, dmabuf, sg[i].length);
346 dmabuf += sg[i].length; 309 dmabuf += sg[i].length;
347
348 if (size < sg[i].length)
349 size = 0;
350 else
351 size -= sg[i].length;
352
353 if (size == 0)
354 break;
355 } 310 }
356
357 /*
358 * Check that we didn't get a request to transfer
359 * more data than can fit into the SG list.
360 */
361
362 BUG_ON(size != 0);
363
364 host->size -= size;
365} 311}
366 312
367/* 313/*
@@ -484,7 +430,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
484 /* 430 /*
485 * Handle excessive data. 431 * Handle excessive data.
486 */ 432 */
487 if (data->bytes_xfered == host->size) 433 if (host->num_sg == 0)
488 return; 434 return;
489 435
490 buffer = wbsd_sg_to_buffer(host) + host->offset; 436 buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -514,31 +460,14 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
514 data->bytes_xfered++; 460 data->bytes_xfered++;
515 461
516 /* 462 /*
517 * Transfer done?
518 */
519 if (data->bytes_xfered == host->size)
520 return;
521
522 /*
523 * End of scatter list entry? 463 * End of scatter list entry?
524 */ 464 */
525 if (host->remain == 0) { 465 if (host->remain == 0) {
526 /* 466 /*
527 * Get next entry. Check if last. 467 * Get next entry. Check if last.
528 */ 468 */
529 if (!wbsd_next_sg(host)) { 469 if (!wbsd_next_sg(host))
530 /*
531 * We should never reach this point.
532 * It means that we're trying to
533 * transfer more blocks than can fit
534 * into the scatter list.
535 */
536 BUG_ON(1);
537
538 host->size = data->bytes_xfered;
539
540 return; 470 return;
541 }
542 471
543 buffer = wbsd_sg_to_buffer(host); 472 buffer = wbsd_sg_to_buffer(host);
544 } 473 }
@@ -550,7 +479,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
550 * hardware problem. The chip doesn't trigger 479 * hardware problem. The chip doesn't trigger
551 * FIFO threshold interrupts properly. 480 * FIFO threshold interrupts properly.
552 */ 481 */
553 if ((host->size - data->bytes_xfered) < 16) 482 if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
554 tasklet_schedule(&host->fifo_tasklet); 483 tasklet_schedule(&host->fifo_tasklet);
555} 484}
556 485
@@ -564,7 +493,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
564 * Check that we aren't being called after the 493 * Check that we aren't being called after the
565 * entire buffer has been transfered. 494 * entire buffer has been transfered.
566 */ 495 */
567 if (data->bytes_xfered == host->size) 496 if (host->num_sg == 0)
568 return; 497 return;
569 498
570 buffer = wbsd_sg_to_buffer(host) + host->offset; 499 buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -594,31 +523,14 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
594 data->bytes_xfered++; 523 data->bytes_xfered++;
595 524
596 /* 525 /*
597 * Transfer done?
598 */
599 if (data->bytes_xfered == host->size)
600 return;
601
602 /*
603 * End of scatter list entry? 526 * End of scatter list entry?
604 */ 527 */
605 if (host->remain == 0) { 528 if (host->remain == 0) {
606 /* 529 /*
607 * Get next entry. Check if last. 530 * Get next entry. Check if last.
608 */ 531 */
609 if (!wbsd_next_sg(host)) { 532 if (!wbsd_next_sg(host))
610 /*
611 * We should never reach this point.
612 * It means that we're trying to
613 * transfer more blocks than can fit
614 * into the scatter list.
615 */
616 BUG_ON(1);
617
618 host->size = data->bytes_xfered;
619
620 return; 533 return;
621 }
622 534
623 buffer = wbsd_sg_to_buffer(host); 535 buffer = wbsd_sg_to_buffer(host);
624 } 536 }
@@ -638,6 +550,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
638 u16 blksize; 550 u16 blksize;
639 u8 setup; 551 u8 setup;
640 unsigned long dmaflags; 552 unsigned long dmaflags;
553 unsigned int size;
641 554
642 DBGF("blksz %04x blks %04x flags %08x\n", 555 DBGF("blksz %04x blks %04x flags %08x\n",
643 data->blksz, data->blocks, data->flags); 556 data->blksz, data->blocks, data->flags);
@@ -647,7 +560,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
647 /* 560 /*
648 * Calculate size. 561 * Calculate size.
649 */ 562 */
650 host->size = data->blocks * data->blksz; 563 size = data->blocks * data->blksz;
651 564
652 /* 565 /*
653 * Check timeout values for overflow. 566 * Check timeout values for overflow.
@@ -705,8 +618,8 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
705 /* 618 /*
706 * The buffer for DMA is only 64 kB. 619 * The buffer for DMA is only 64 kB.
707 */ 620 */
708 BUG_ON(host->size > 0x10000); 621 BUG_ON(size > 0x10000);
709 if (host->size > 0x10000) { 622 if (size > 0x10000) {
710 data->error = MMC_ERR_INVALID; 623 data->error = MMC_ERR_INVALID;
711 return; 624 return;
712 } 625 }
@@ -729,7 +642,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
729 else 642 else
730 set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40); 643 set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
731 set_dma_addr(host->dma, host->dma_addr); 644 set_dma_addr(host->dma, host->dma_addr);
732 set_dma_count(host->dma, host->size); 645 set_dma_count(host->dma, size);
733 646
734 enable_dma(host->dma); 647 enable_dma(host->dma);
735 release_dma_lock(dmaflags); 648 release_dma_lock(dmaflags);
@@ -812,6 +725,10 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
812 count = get_dma_residue(host->dma); 725 count = get_dma_residue(host->dma);
813 release_dma_lock(dmaflags); 726 release_dma_lock(dmaflags);
814 727
728 data->bytes_xfered = host->mrq->data->blocks *
729 host->mrq->data->blksz - count;
730 data->bytes_xfered -= data->bytes_xfered % data->blksz;
731
815 /* 732 /*
816 * Any leftover data? 733 * Any leftover data?
817 */ 734 */
@@ -820,7 +737,8 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
820 "%d bytes left.\n", 737 "%d bytes left.\n",
821 mmc_hostname(host->mmc), count); 738 mmc_hostname(host->mmc), count);
822 739
823 data->error = MMC_ERR_FAILED; 740 if (data->error == MMC_ERR_NONE)
741 data->error = MMC_ERR_FAILED;
824 } else { 742 } else {
825 /* 743 /*
826 * Transfer data from DMA buffer to 744 * Transfer data from DMA buffer to
@@ -828,8 +746,11 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
828 */ 746 */
829 if (data->flags & MMC_DATA_READ) 747 if (data->flags & MMC_DATA_READ)
830 wbsd_dma_to_sg(host, data); 748 wbsd_dma_to_sg(host, data);
749 }
831 750
832 data->bytes_xfered = host->size; 751 if (data->error != MMC_ERR_NONE) {
752 if (data->bytes_xfered)
753 data->bytes_xfered -= data->blksz;
833 } 754 }
834 } 755 }
835 756
@@ -1167,7 +1088,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
1167 /* 1088 /*
1168 * Done? 1089 * Done?
1169 */ 1090 */
1170 if (host->size == data->bytes_xfered) { 1091 if (host->num_sg == 0) {
1171 wbsd_write_index(host, WBSD_IDX_FIFOEN, 0); 1092 wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
1172 tasklet_schedule(&host->finish_tasklet); 1093 tasklet_schedule(&host->finish_tasklet);
1173 } 1094 }
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index d06718b0e2ab..6fb4fa423219 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver 2 * linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
3 * 3 *
4 * Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved. 4 * Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -158,8 +158,6 @@ struct wbsd_host
158 unsigned int offset; /* Offset into current entry */ 158 unsigned int offset; /* Offset into current entry */
159 unsigned int remain; /* Data left in curren entry */ 159 unsigned int remain; /* Data left in curren entry */
160 160
161 int size; /* Total size of transfer */
162
163 char* dma_buffer; /* ISA DMA buffer */ 161 char* dma_buffer; /* ISA DMA buffer */
164 dma_addr_t dma_addr; /* Physical address for same */ 162 dma_addr_t dma_addr; /* Physical address for same */
165 163