diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/xilinx/xilinx_dma.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index fe265d942ed2..d81f387cfcc7 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -300,12 +300,16 @@ struct xilinx_cdma_tx_segment { * @segments: TX segments list * @node: Node in the channel descriptors list * @cyclic: Check for cyclic transfers. + * @err: Whether the descriptor has an error. + * @residue: Residue of the completed descriptor */ struct xilinx_dma_tx_descriptor { struct dma_async_tx_descriptor async_tx; struct list_head segments; struct list_head node; bool cyclic; + bool err; + u32 residue; }; /** @@ -856,6 +860,8 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan) spin_lock_irqsave(&chan->lock, flags); list_for_each_entry_safe(desc, next, &chan->done_list, node) { + struct dmaengine_result result; + if (desc->cyclic) { xilinx_dma_chan_handle_cyclic(chan, desc, &flags); break; @@ -864,9 +870,20 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan) /* Remove from the list of running transactions */ list_del(&desc->node); + if (unlikely(desc->err)) { + if (chan->direction == DMA_DEV_TO_MEM) + result.result = DMA_TRANS_READ_FAILED; + else + result.result = DMA_TRANS_WRITE_FAILED; + } else { + result.result = DMA_TRANS_NOERROR; + } + + result.residue = desc->residue; + /* Run the link descriptor callback function */ spin_unlock_irqrestore(&chan->lock, flags); - dmaengine_desc_get_callback_invoke(&desc->async_tx, NULL); + dmaengine_desc_get_callback_invoke(&desc->async_tx, &result); spin_lock_irqsave(&chan->lock, flags); /* Run any dependencies, then free the descriptor */ @@ -1421,6 +1438,13 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan) return; list_for_each_entry_safe(desc, next, &chan->active_list, node) { + if (chan->has_sg && chan->xdev->dma_config->dmatype != + XDMA_TYPE_VDMA) + desc->residue = xilinx_dma_get_residue(chan, desc); + else + desc->residue = 0; + desc->err = chan->err; + list_del(&desc->node); if (!desc->cyclic) dma_cookie_complete(&desc->async_tx); |