diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-05-26 10:05:52 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-07-01 09:16:02 -0400 |
commit | 06e885b735717d1074dec13ae8b8d15edcd63255 (patch) | |
tree | 5ec195fcd23958ade1b91f9cbae854a86f2791c1 /drivers | |
parent | 18536134abd6b8157d5cb11162606cc264d07232 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/amba-pl08x.c | 61 |
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 */ |