From: Thomas Pfaff <tpfaff@xxxxxxx> In kernel 6.1, atc_advance_work and atc_handle_error are checking for the next dma transfer inside active list, but the descriptor is taken from the queue instead. Signed-off-by: Thomas Pfaff <tpfaff@xxxxxxx> --- diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 858bd64f1313..68c1bfbefc5c 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -490,6 +490,27 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) } } +/** + * atc_start_next - start next pending transaction if any + * @atchan: channel where the transaction ended + * + * Called with atchan->lock held + */ +static void atc_start_next(struct at_dma_chan *atchan) +{ + struct at_desc *desc = NULL; + + if (!list_empty(&atchan->active_list)) + desc = atc_first_active(atchan); + else if (!list_empty(&atchan->queue)) { + desc = atc_first_queued(atchan); + list_move_tail(&desc->desc_node, &atchan->active_list); + } + + if (desc) + atc_dostart(atchan, desc); +} + /** * atc_advance_work - at the end of a transaction, move forward * @atchan: channel where the transaction ended @@ -513,11 +534,7 @@ static void atc_advance_work(struct at_dma_chan *atchan) /* advance work */ spin_lock_irqsave(&atchan->lock, flags); - if (!list_empty(&atchan->active_list)) { - desc = atc_first_queued(atchan); - list_move_tail(&desc->desc_node, &atchan->active_list); - atc_dostart(atchan, desc); - } + atc_start_next(atchan); spin_unlock_irqrestore(&atchan->lock, flags); } @@ -529,7 +546,6 @@ 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; @@ -543,11 +559,7 @@ static void atc_handle_error(struct at_dma_chan *atchan) list_del_init(&bad_desc->desc_node); /* Try to restart the controller */ - if (!list_empty(&atchan->active_list)) { - desc = atc_first_queued(atchan); - list_move_tail(&desc->desc_node, &atchan->active_list); - atc_dostart(atchan, desc); - } + atc_start_next(atchan); /* * KERN_CRITICAL may seem harsh, but since this only happens