diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2017-11-14 09:32:10 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2017-12-04 12:03:51 -0500 |
commit | 397c59bce6cbda05dc862b691e15ac2ef0ba1948 (patch) | |
tree | a8c6cf73e3c18df6436cd35c19e828bf91f8e67a | |
parent | 47d71bc75d072ce25c1063aa629e55e1cfb961b2 (diff) |
dmaengine: img-mdc-dma: Use vchan_terminate_vdesc() instead of desc_free
To avoid race with vchan_complete, use the race free way to terminate
running transfer.
Implement the device_synchronize callback to make sure that the terminated
descriptor is freed.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/img-mdc-dma.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c index 0391f930aecc..25cec9c243e1 100644 --- a/drivers/dma/img-mdc-dma.c +++ b/drivers/dma/img-mdc-dma.c | |||
@@ -694,7 +694,6 @@ static unsigned int mdc_get_new_events(struct mdc_chan *mchan) | |||
694 | static int mdc_terminate_all(struct dma_chan *chan) | 694 | static int mdc_terminate_all(struct dma_chan *chan) |
695 | { | 695 | { |
696 | struct mdc_chan *mchan = to_mdc_chan(chan); | 696 | struct mdc_chan *mchan = to_mdc_chan(chan); |
697 | struct mdc_tx_desc *mdesc; | ||
698 | unsigned long flags; | 697 | unsigned long flags; |
699 | LIST_HEAD(head); | 698 | LIST_HEAD(head); |
700 | 699 | ||
@@ -703,21 +702,28 @@ static int mdc_terminate_all(struct dma_chan *chan) | |||
703 | mdc_chan_writel(mchan, MDC_CONTROL_AND_STATUS_CANCEL, | 702 | mdc_chan_writel(mchan, MDC_CONTROL_AND_STATUS_CANCEL, |
704 | MDC_CONTROL_AND_STATUS); | 703 | MDC_CONTROL_AND_STATUS); |
705 | 704 | ||
706 | mdesc = mchan->desc; | 705 | if (mchan->desc) { |
707 | mchan->desc = NULL; | 706 | vchan_terminate_vdesc(&mchan->desc->vd); |
707 | mchan->desc = NULL; | ||
708 | } | ||
708 | vchan_get_all_descriptors(&mchan->vc, &head); | 709 | vchan_get_all_descriptors(&mchan->vc, &head); |
709 | 710 | ||
710 | mdc_get_new_events(mchan); | 711 | mdc_get_new_events(mchan); |
711 | 712 | ||
712 | spin_unlock_irqrestore(&mchan->vc.lock, flags); | 713 | spin_unlock_irqrestore(&mchan->vc.lock, flags); |
713 | 714 | ||
714 | if (mdesc) | ||
715 | mdc_desc_free(&mdesc->vd); | ||
716 | vchan_dma_desc_free_list(&mchan->vc, &head); | 715 | vchan_dma_desc_free_list(&mchan->vc, &head); |
717 | 716 | ||
718 | return 0; | 717 | return 0; |
719 | } | 718 | } |
720 | 719 | ||
720 | static void mdc_synchronize(struct dma_chan *chan) | ||
721 | { | ||
722 | struct mdc_chan *mchan = to_mdc_chan(chan); | ||
723 | |||
724 | vchan_synchronize(&mchan->vc); | ||
725 | } | ||
726 | |||
721 | static int mdc_slave_config(struct dma_chan *chan, | 727 | static int mdc_slave_config(struct dma_chan *chan, |
722 | struct dma_slave_config *config) | 728 | struct dma_slave_config *config) |
723 | { | 729 | { |
@@ -952,6 +958,7 @@ static int mdc_dma_probe(struct platform_device *pdev) | |||
952 | mdma->dma_dev.device_tx_status = mdc_tx_status; | 958 | mdma->dma_dev.device_tx_status = mdc_tx_status; |
953 | mdma->dma_dev.device_issue_pending = mdc_issue_pending; | 959 | mdma->dma_dev.device_issue_pending = mdc_issue_pending; |
954 | mdma->dma_dev.device_terminate_all = mdc_terminate_all; | 960 | mdma->dma_dev.device_terminate_all = mdc_terminate_all; |
961 | mdma->dma_dev.device_synchronize = mdc_synchronize; | ||
955 | mdma->dma_dev.device_config = mdc_slave_config; | 962 | mdma->dma_dev.device_config = mdc_slave_config; |
956 | 963 | ||
957 | mdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); | 964 | mdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); |