aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/imx-sdma.c
diff options
context:
space:
mode:
authorHuang Shijie <b32955@freescale.com>2011-12-01 21:16:25 -0500
committerVinod Koul <vinod.koul@linux.intel.com>2011-12-04 21:52:26 -0500
commitab59a510c6ad6b3add5125df64843be754782de6 (patch)
treed0f0bcb04c633885e26daba009a55a7b32c35106 /drivers/dma/imx-sdma.c
parent6d0709d2000ae7dbead759715f57ba381b7057bb (diff)
IMX/SDMA : save the real count for one DMA transaction.
When we use the SDMA in the UART driver(such as imx6q), we will meet one situation: Assume we set 64 bytes for the RX DMA buffer. The RX DMA buffer has received some data, but not full. An Aging DMA request will be received by the SDMA controller if we enable the IDDMAEN(UCR4[6]) in this case. So the UART driver needs to know the count of the real received bytes, and push them to upper layer. Add two new fields to sdmac, and update the `residue` in sdma_tx_status(). Signed-off-by: Huang Shijie <b32955@freescale.com> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r--drivers/dma/imx-sdma.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d9e5933d91eb..f59fd8fffa88 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -268,6 +268,8 @@ struct sdma_channel {
268 struct dma_async_tx_descriptor desc; 268 struct dma_async_tx_descriptor desc;
269 dma_cookie_t last_completed; 269 dma_cookie_t last_completed;
270 enum dma_status status; 270 enum dma_status status;
271 unsigned int chn_count;
272 unsigned int chn_real_count;
271}; 273};
272 274
273#define IMX_DMA_SG_LOOP (1 << 0) 275#define IMX_DMA_SG_LOOP (1 << 0)
@@ -503,6 +505,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
503 struct sdma_buffer_descriptor *bd; 505 struct sdma_buffer_descriptor *bd;
504 int i, error = 0; 506 int i, error = 0;
505 507
508 sdmac->chn_real_count = 0;
506 /* 509 /*
507 * non loop mode. Iterate over all descriptors, collect 510 * non loop mode. Iterate over all descriptors, collect
508 * errors and call callback function 511 * errors and call callback function
@@ -512,6 +515,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
512 515
513 if (bd->mode.status & (BD_DONE | BD_RROR)) 516 if (bd->mode.status & (BD_DONE | BD_RROR))
514 error = -EIO; 517 error = -EIO;
518 sdmac->chn_real_count += bd->mode.count;
515 } 519 }
516 520
517 if (error) 521 if (error)
@@ -519,9 +523,9 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
519 else 523 else
520 sdmac->status = DMA_SUCCESS; 524 sdmac->status = DMA_SUCCESS;
521 525
526 sdmac->last_completed = sdmac->desc.cookie;
522 if (sdmac->desc.callback) 527 if (sdmac->desc.callback)
523 sdmac->desc.callback(sdmac->desc.callback_param); 528 sdmac->desc.callback(sdmac->desc.callback_param);
524 sdmac->last_completed = sdmac->desc.cookie;
525} 529}
526 530
527static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) 531static void mxc_sdma_handle_channel(struct sdma_channel *sdmac)
@@ -941,6 +945,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
941 goto err_out; 945 goto err_out;
942 } 946 }
943 947
948 sdmac->chn_count = 0;
944 for_each_sg(sgl, sg, sg_len, i) { 949 for_each_sg(sgl, sg, sg_len, i) {
945 struct sdma_buffer_descriptor *bd = &sdmac->bd[i]; 950 struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
946 int param; 951 int param;
@@ -957,6 +962,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
957 } 962 }
958 963
959 bd->mode.count = count; 964 bd->mode.count = count;
965 sdmac->chn_count += count;
960 966
961 if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) { 967 if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
962 ret = -EINVAL; 968 ret = -EINVAL;
@@ -1120,7 +1126,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
1120 1126
1121 last_used = chan->cookie; 1127 last_used = chan->cookie;
1122 1128
1123 dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0); 1129 dma_set_tx_state(txstate, sdmac->last_completed, last_used,
1130 sdmac->chn_count - sdmac->chn_real_count);
1124 1131
1125 return sdmac->status; 1132 return sdmac->status;
1126} 1133}