From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753020AbcBKNUL (ORCPT ); Thu, 11 Feb 2016 08:20:11 -0500 Received: from comal.ext.ti.com ([198.47.26.152]:57090 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752157AbcBKNUJ (ORCPT ); Thu, 11 Feb 2016 08:20:09 -0500 From: Peter Ujfalusi To: CC: , , , , , Subject: [PATCH] dmaengine: edma: Fetch echan->edesc while holding lock in edma_comletion_handler Date: Thu, 11 Feb 2016 15:17:48 +0200 Message-ID: <1455196668-9327-1-git-send-email-peter.ujfalusi@ti.com> X-Mailer: git-send-email 2.7.1 MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to avoid possible race condition when client drivers are using dmaengine_terminate_sync() call to disable the channel. Signed-off-by: Peter Ujfalusi Suggested-by: Lars-Peter Clausen --- drivers/dma/edma.c | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 290e1a721c5b..13b6a23dc06b 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -1372,36 +1372,36 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic( static void edma_completion_handler(struct edma_chan *echan) { struct device *dev = echan->vchan.chan.device->dev; - struct edma_desc *edesc = echan->edesc; - - if (!edesc) - return; + struct edma_desc *edesc; spin_lock(&echan->vchan.lock); - if (edesc->cyclic) { - vchan_cyclic_callback(&edesc->vdesc); - spin_unlock(&echan->vchan.lock); - return; - } else if (edesc->processed == edesc->pset_nr) { - edesc->residue = 0; - edma_stop(echan); - vchan_cookie_complete(&edesc->vdesc); - echan->edesc = NULL; - - dev_dbg(dev, "Transfer completed on channel %d\n", - echan->ch_num); - } else { - dev_dbg(dev, "Sub transfer completed on channel %d\n", - echan->ch_num); - - edma_pause(echan); - - /* Update statistics for tx_status */ - edesc->residue -= edesc->sg_len; - edesc->residue_stat = edesc->residue; - edesc->processed_stat = edesc->processed; + edesc = echan->edesc; + if (edesc) { + if (edesc->cyclic) { + vchan_cyclic_callback(&edesc->vdesc); + spin_unlock(&echan->vchan.lock); + return; + } else if (edesc->processed == edesc->pset_nr) { + edesc->residue = 0; + edma_stop(echan); + vchan_cookie_complete(&edesc->vdesc); + echan->edesc = NULL; + + dev_dbg(dev, "Transfer completed on channel %d\n", + echan->ch_num); + } else { + dev_dbg(dev, "Sub transfer completed on channel %d\n", + echan->ch_num); + + edma_pause(echan); + + /* Update statistics for tx_status */ + edesc->residue -= edesc->sg_len; + edesc->residue_stat = edesc->residue; + edesc->processed_stat = edesc->processed; + } + edma_execute(echan); } - edma_execute(echan); spin_unlock(&echan->vchan.lock); } -- 2.7.1