@@ -1206,11 +1206,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
}
head_desc = list_first_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_desc = list_last_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_axidma_tx_segment, node);
+ struct xilinx_dma_tx_descriptor, node);
if (chan->has_sg && !chan->xdev->mcdma) {
old_head = list_first_entry(&head_desc->segments,
@@ -1223,8 +1219,18 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
list_replace_init(&old_head->node, &new_head->node);
chan->seg_v = old_head;
+ tail_desc = list_last_entry(&chan->pending_list,
+ struct xilinx_dma_tx_descriptor, node);
+ tail_segment = list_last_entry(&tail_desc->segments,
+ struct xilinx_axidma_tx_segment, node);
+
tail_segment->hw.next_desc = chan->seg_v->phys;
head_desc->async_tx.phys = new_head->phys;
+ } else {
+ tail_desc = list_last_entry(&chan->pending_list,
+ struct xilinx_dma_tx_descriptor, node);
+ tail_segment = list_last_entry(&tail_desc->segments,
+ struct xilinx_axidma_tx_segment, node);
}
reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
xilinx_dma_start_transfer() locally buffered the tail segment of the pending list, then it operated over the head. However In case of a 1-length descriptor list, where head and tail are the same, the tail segment changes. The local buffering at the beginning is thus broken. This patch fixes this. Signed-off-by: Andrea Merello <andrea.merello@gmail.com> --- drivers/dma/xilinx/xilinx_dma.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)