diff options
author | James Hogan <james.hogan@imgtec.com> | 2011-06-29 04:28:43 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-07-20 17:21:05 -0400 |
commit | 03e8cb534e7cc3f71a07528a44da7ce68e5b5708 (patch) | |
tree | 989d0a96a03d8838de7617f6eb0062ed2a7065e6 /drivers/mmc/host/dw_mmc.c | |
parent | 65d13516b2358c38ac56a5f83e989a6837dcf825 (diff) |
mmc: dw_mmc: fix stop when fallen back to PIO
There are several situations when dw_mci_submit_data_dma() decides to
fall back to PIO mode instead of using DMA, due to a short (to avoid
overhead) or "complex" (e.g. with unaligned buffers) transaction, even
though host->use_dma is set. However dw_mci_stop_dma() decides whether
to stop DMA or set the EVENT_XFER_COMPLETE event based on host->use_dma.
When falling back to PIO mode this results in data timeout errors
getting missed and the driver locking up.
Therefore add host->using_dma to indicate whether the current
transaction is using dma or not, and adjust dw_mci_stop_dma() to use
that instead.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Acked-by: Will Newton <will.newton@imgtec.com>
Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 10b697986283..fcff3c042f69 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -287,7 +287,7 @@ static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) | |||
287 | /* DMA interface functions */ | 287 | /* DMA interface functions */ |
288 | static void dw_mci_stop_dma(struct dw_mci *host) | 288 | static void dw_mci_stop_dma(struct dw_mci *host) |
289 | { | 289 | { |
290 | if (host->use_dma) { | 290 | if (host->using_dma) { |
291 | host->dma_ops->stop(host); | 291 | host->dma_ops->stop(host); |
292 | host->dma_ops->cleanup(host); | 292 | host->dma_ops->cleanup(host); |
293 | } else { | 293 | } else { |
@@ -435,6 +435,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
435 | unsigned int i, direction, sg_len; | 435 | unsigned int i, direction, sg_len; |
436 | u32 temp; | 436 | u32 temp; |
437 | 437 | ||
438 | host->using_dma = 0; | ||
439 | |||
438 | /* If we don't have a channel, we can't do DMA */ | 440 | /* If we don't have a channel, we can't do DMA */ |
439 | if (!host->use_dma) | 441 | if (!host->use_dma) |
440 | return -ENODEV; | 442 | return -ENODEV; |
@@ -454,6 +456,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
454 | return -EINVAL; | 456 | return -EINVAL; |
455 | } | 457 | } |
456 | 458 | ||
459 | host->using_dma = 1; | ||
460 | |||
457 | if (data->flags & MMC_DATA_READ) | 461 | if (data->flags & MMC_DATA_READ) |
458 | direction = DMA_FROM_DEVICE; | 462 | direction = DMA_FROM_DEVICE; |
459 | else | 463 | else |