We need to free the ld_active list head before jumping into the callback routine. Otherwise the callback could run into issue_pending and change our ld_active list head we just going to free. This will run the channel list into an currupted and undefined state.
Unified · Split
| @@ -627,13 +627,11 @@ static void imxdma_tasklet(unsigned long data) · 626 unmodified lines | ||
| 627 | 627 | |
| 628 | 628 | if (list_empty(&imxdmac->ld_active)) { |
| 629 | 629 | /* Someone might have called terminate all */ |
| 630 | − goto out; | |
| 630 | + spin_unlock_irqrestore(&imxdma->lock, flags); | |
| 631 | + return; | |
| 631 | 632 | } |
| 632 | 633 | desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); |
| 633 | 634 | |
| 634 | − if (desc->desc.callback) | |
| 635 | − desc->desc.callback(desc->desc.callback_param); | |
| 636 | − | |
| 637 | 635 | /* If we are dealing with a cyclic descriptor, keep it on ld_active |
| 638 | 636 | * and dont mark the descriptor as complete. |
| 639 | 637 | * Only in non-cyclic cases it would be marked as complete |
| @@ -661,6 +659,10 @@ static void imxdma_tasklet(unsigned long data) · 21 unmodified lines | ||
| 661 | 659 | } |
| 662 | 660 | out: |
| 663 | 661 | spin_unlock_irqrestore(&imxdma->lock, flags); |
| 662 | + | |
| 663 | + if (desc->desc.callback) | |
| 664 | + desc->desc.callback(desc->desc.callback_param); | |
| 665 | + | |
| 664 | 666 | } |
| 665 | 667 | |
| 666 | 668 | static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |