On 09/12/2019 9.48, Peter Ujfalusi wrote: > Hi Sascha, > > > On 06/12/2019 15.53, Sascha Hauer wrote: >> vchan_vdesc_fini() shouldn't be called under a spin_lock. This is done >> in two places, once in vchan_terminate_vdesc() and once in >> vchan_synchronize(). Instead of freeing the vdesc right away, collect >> the aborted vdescs on a separate list and free them along with the other >> vdescs. >> >> Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> >> --- >> drivers/dma/virt-dma.c | 1 + >> drivers/dma/virt-dma.h | 17 +++-------------- >> 2 files changed, 4 insertions(+), 14 deletions(-) >> >> diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c >> index ec4adf4260a0..87d5bd53c98b 100644 >> --- a/drivers/dma/virt-dma.c >> +++ b/drivers/dma/virt-dma.c >> @@ -135,6 +135,7 @@ void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev) >> INIT_LIST_HEAD(&vc->desc_submitted); >> INIT_LIST_HEAD(&vc->desc_issued); >> INIT_LIST_HEAD(&vc->desc_completed); >> + INIT_LIST_HEAD(&vc->desc_aborted); > > Can we keep the terminated term instead of aborted: desc_terminated > >> >> tasklet_init(&vc->task, vchan_complete, (unsigned long)vc); >> >> diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h >> index 41883ee2c29f..6cae93624f0d 100644 >> --- a/drivers/dma/virt-dma.h >> +++ b/drivers/dma/virt-dma.h >> @@ -31,9 +31,9 @@ struct virt_dma_chan { >> struct list_head desc_submitted; >> struct list_head desc_issued; >> struct list_head desc_completed; >> + struct list_head desc_aborted; >> >> struct virt_dma_desc *cyclic; >> - struct virt_dma_desc *vd_terminated; >> }; >> >> static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) >> @@ -146,11 +146,8 @@ static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) >> { >> struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); >> >> - /* free up stuck descriptor */ >> - if (vc->vd_terminated) >> - vchan_vdesc_fini(vc->vd_terminated); >> + list_add_tail(&vd->node, &vc->desc_aborted); >> >> - vc->vd_terminated = vd; >> if (vc->cyclic == vd) >> vc->cyclic = NULL; >> } >> @@ -184,6 +181,7 @@ static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, >> list_splice_tail_init(&vc->desc_submitted, head); >> list_splice_tail_init(&vc->desc_issued, head); >> list_splice_tail_init(&vc->desc_completed, head); >> + list_splice_tail_init(&vc->desc_aborted, head); >> } >> >> static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) >> @@ -212,16 +210,7 @@ static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) >> */ >> static inline void vchan_synchronize(struct virt_dma_chan *vc) >> { >> - unsigned long flags; >> - >> tasklet_kill(&vc->task); >> - >> - spin_lock_irqsave(&vc->lock, flags); >> - if (vc->vd_terminated) { >> - vchan_vdesc_fini(vc->vd_terminated); >> - vc->vd_terminated = NULL; >> - } >> - spin_unlock_irqrestore(&vc->lock, flags); > > We don't want the terminated descriptors to accumulate until the channel > is freed up. Well, most DMA driver will clean it up in their terminate_all, but it is better to do it in synchronize as well. > > spin_lock_irqsave(&vc->lock, flags); > list_splice_tail_init(&vc->desc_terminated, &head); > spin_unlock_irqrestore(&vc->lock, flags); > > list_for_each_entry_safe(vd, _vd, &head, node) { > list_del(&vd->node); > vchan_vdesc_fini(vd); > } > > >> } >> >> #endif >> > > - Péter > > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. > Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki