aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/sdhci.c
diff options
context:
space:
mode:
authorAlex Dubov <oakad@yahoo.com>2007-04-13 13:04:38 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-05-01 07:04:12 -0400
commit14d836e7499c53a1f6a65086c3d11600e871a971 (patch)
tree37d1cb767422bd498a13654ecabd6f891b27b0e3 /drivers/mmc/sdhci.c
parentdc87c3985e9b442c60994308a96f887579addc39 (diff)
mmc: cull sg list to match mmc request size
mmc layer may introduce additional (compared to block layer) limits on request size. Culling of the sg list to match adjusted request size simplifies the handling of such cases in the low level driver, allowing it to skip block count checks while processing sg entries. (fixes for wbsd and sdhci by Pierre Ossman) Signed-off-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/sdhci.c')
-rw-r--r--drivers/mmc/sdhci.c24
1 files changed, 7 insertions, 17 deletions
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);