Commit ba242363 authored by Tudor Ambarus's avatar Tudor Ambarus Committed by Vinod Koul
Browse files

dmaengine: at_hdmac: Fix descriptor handling when issuing it to hardware



As it was before, the descriptor was issued to the hardware without adding
it to the active (issued) list. This could result in a completion of other
descriptor, or/and in the descriptor never being completed.

Fixes: dc78baa2 ("dmaengine: at_hdmac: new driver for the Atmel AHB DMA Controller")
Reported-by: default avatarPeter Rosin <peda@axentia.se>
Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/lkml/13c6c9a2-6db5-c3bf-349b-4c127ad3496a@axentia.se/


Acked-by: default avatarNicolas Ferre <nicolas.ferre@microchip.com>
Link: https://lore.kernel.org/r/20221025090306.297886-1-tudor.ambarus@microchip.com
Link: https://lore.kernel.org/r/20221025090306.297886-12-tudor.ambarus@microchip.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 03ed9ba3
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -510,8 +510,11 @@ static void atc_advance_work(struct at_dma_chan *atchan)

	/* advance work */
	spin_lock_irqsave(&atchan->lock, flags);
	if (!list_empty(&atchan->active_list))
		atc_dostart(atchan, atc_first_active(atchan));
	if (!list_empty(&atchan->active_list)) {
		desc = atc_first_queued(atchan);
		list_move_tail(&desc->desc_node, &atchan->active_list);
		atc_dostart(atchan, desc);
	}
	spin_unlock_irqrestore(&atchan->lock, flags);
}

@@ -523,6 +526,7 @@ static void atc_advance_work(struct at_dma_chan *atchan)
static void atc_handle_error(struct at_dma_chan *atchan)
{
	struct at_desc *bad_desc;
	struct at_desc *desc;
	struct at_desc *child;
	unsigned long flags;

@@ -540,8 +544,11 @@ static void atc_handle_error(struct at_dma_chan *atchan)
	list_splice_init(&atchan->queue, atchan->active_list.prev);

	/* Try to restart the controller */
	if (!list_empty(&atchan->active_list))
		atc_dostart(atchan, atc_first_active(atchan));
	if (!list_empty(&atchan->active_list)) {
		desc = atc_first_queued(atchan);
		list_move_tail(&desc->desc_node, &atchan->active_list);
		atc_dostart(atchan, desc);
	}

	/*
	 * KERN_CRITICAL may seem harsh, but since this only happens