aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-05-26 10:05:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-01 09:16:02 -0400
commit06e885b735717d1074dec13ae8b8d15edcd63255 (patch)
tree5ec195fcd23958ade1b91f9cbae854a86f2791c1
parent18536134abd6b8157d5cb11162606cc264d07232 (diff)
dmaengine: PL08x: fix tx_status function to return correct residue
Now that we're converted to use the generic vchan support, we can fix the residue return from tx_status to be compliant with dmaengine. This returns the number of bytes remaining for the _specified_ cookie, not the number of bytes in all pending transfers on the channel. Acked-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/dma/amba-pl08x.c61
1 files changed, 34 insertions, 27 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 6a35e37d14bc..c42c7ef6b93a 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -473,10 +473,8 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
473{ 473{
474 struct pl08x_phy_chan *ch; 474 struct pl08x_phy_chan *ch;
475 struct pl08x_txd *txd; 475 struct pl08x_txd *txd;
476 unsigned long flags;
477 size_t bytes = 0; 476 size_t bytes = 0;
478 477
479 spin_lock_irqsave(&plchan->vc.lock, flags);
480 ch = plchan->phychan; 478 ch = plchan->phychan;
481 txd = plchan->at; 479 txd = plchan->at;
482 480
@@ -516,27 +514,6 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
516 } 514 }
517 } 515 }
518 516
519 /* Sum up all queued transactions */
520 if (!list_empty(&plchan->vc.desc_issued)) {
521 struct pl08x_txd *txdi;
522 list_for_each_entry(txdi, &plchan->vc.desc_issued, vd.node) {
523 struct pl08x_sg *dsg;
524 list_for_each_entry(dsg, &txd->dsg_list, node)
525 bytes += dsg->len;
526 }
527 }
528
529 if (!list_empty(&plchan->vc.desc_submitted)) {
530 struct pl08x_txd *txdi;
531 list_for_each_entry(txdi, &plchan->vc.desc_submitted, vd.node) {
532 struct pl08x_sg *dsg;
533 list_for_each_entry(dsg, &txd->dsg_list, node)
534 bytes += dsg->len;
535 }
536 }
537
538 spin_unlock_irqrestore(&plchan->vc.lock, flags);
539
540 return bytes; 517 return bytes;
541} 518}
542 519
@@ -1171,23 +1148,53 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
1171 dma_cookie_t cookie, struct dma_tx_state *txstate) 1148 dma_cookie_t cookie, struct dma_tx_state *txstate)
1172{ 1149{
1173 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); 1150 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1151 struct virt_dma_desc *vd;
1152 unsigned long flags;
1174 enum dma_status ret; 1153 enum dma_status ret;
1154 size_t bytes = 0;
1175 1155
1176 ret = dma_cookie_status(chan, cookie, txstate); 1156 ret = dma_cookie_status(chan, cookie, txstate);
1177 if (ret == DMA_SUCCESS) 1157 if (ret == DMA_SUCCESS)
1178 return ret; 1158 return ret;
1179 1159
1180 /* 1160 /*
1161 * There's no point calculating the residue if there's
1162 * no txstate to store the value.
1163 */
1164 if (!txstate) {
1165 if (plchan->state == PL08X_CHAN_PAUSED)
1166 ret = DMA_PAUSED;
1167 return ret;
1168 }
1169
1170 spin_lock_irqsave(&plchan->vc.lock, flags);
1171 ret = dma_cookie_status(chan, cookie, txstate);
1172 if (ret != DMA_SUCCESS) {
1173 vd = vchan_find_desc(&plchan->vc, cookie);
1174 if (vd) {
1175 /* On the issued list, so hasn't been processed yet */
1176 struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
1177 struct pl08x_sg *dsg;
1178
1179 list_for_each_entry(dsg, &txd->dsg_list, node)
1180 bytes += dsg->len;
1181 } else {
1182 bytes = pl08x_getbytes_chan(plchan);
1183 }
1184 }
1185 spin_unlock_irqrestore(&plchan->vc.lock, flags);
1186
1187 /*
1181 * This cookie not complete yet 1188 * This cookie not complete yet
1182 * Get number of bytes left in the active transactions and queue 1189 * Get number of bytes left in the active transactions and queue
1183 */ 1190 */
1184 dma_set_residue(txstate, pl08x_getbytes_chan(plchan)); 1191 dma_set_residue(txstate, bytes);
1185 1192
1186 if (plchan->state == PL08X_CHAN_PAUSED) 1193 if (plchan->state == PL08X_CHAN_PAUSED && ret == DMA_IN_PROGRESS)
1187 return DMA_PAUSED; 1194 ret = DMA_PAUSED;
1188 1195
1189 /* Whether waiting or running, we're in progress */ 1196 /* Whether waiting or running, we're in progress */
1190 return DMA_IN_PROGRESS; 1197 return ret;
1191} 1198}
1192 1199
1193/* PrimeCell DMA extension */ 1200/* PrimeCell DMA extension */