diff options
author | Alex Dubov <oakad@yahoo.com> | 2007-04-13 13:04:38 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-05-01 07:04:12 -0400 |
commit | 14d836e7499c53a1f6a65086c3d11600e871a971 (patch) | |
tree | 37d1cb767422bd498a13654ecabd6f891b27b0e3 /drivers/mmc/sdhci.c | |
parent | dc87c3985e9b442c60994308a96f887579addc39 (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.c | 24 |
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); |