Skip to content

Commit

Permalink
dmaengine: xilinx: dpdma: Fix descriptor issuing on video group
Browse files Browse the repository at this point in the history
[ Upstream commit 1cbd446 ]

When multiple channels are part of a video group, the transfer is
triggered only when all channels in the group are ready. The logic to do
so is incorrect, as it causes the descriptors for all channels but the
last one in a group to not being pushed to the hardware. Fix it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://lore.kernel.org/r/20210307040629.29308-2-laurent.pinchart@ideasonboard.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
pinchartl authored and gregkh committed Apr 28, 2021
1 parent 77ac7b2 commit cea1e22
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions drivers/dma/xilinx/xilinx_dpdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,7 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
struct xilinx_dpdma_tx_desc *desc;
struct virt_dma_desc *vdesc;
u32 reg, channels;
bool first_frame;

lockdep_assert_held(&chan->lock);

Expand All @@ -852,14 +853,6 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
chan->running = true;
}

if (chan->video_group)
channels = xilinx_dpdma_chan_video_group_ready(chan);
else
channels = BIT(chan->id);

if (!channels)
return;

vdesc = vchan_next_desc(&chan->vchan);
if (!vdesc)
return;
Expand All @@ -884,13 +877,26 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan)
FIELD_PREP(XILINX_DPDMA_CH_DESC_START_ADDRE_MASK,
upper_32_bits(sw_desc->dma_addr)));

if (chan->first_frame)
first_frame = chan->first_frame;
chan->first_frame = false;

if (chan->video_group) {
channels = xilinx_dpdma_chan_video_group_ready(chan);
/*
* Trigger the transfer only when all channels in the group are
* ready.
*/
if (!channels)
return;
} else {
channels = BIT(chan->id);
}

if (first_frame)
reg = XILINX_DPDMA_GBL_TRIG_MASK(channels);
else
reg = XILINX_DPDMA_GBL_RETRIG_MASK(channels);

chan->first_frame = false;

dpdma_write(xdev->reg, XILINX_DPDMA_GBL, reg);
}

Expand Down

0 comments on commit cea1e22

Please sign in to comment.