diff mbox

[FIX] dmaengine: virt-dma: Free descriptor after callback

Message ID 1397782610-7370-1-git-send-email-joelf@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Joel Fernandes April 18, 2014, 12:56 a.m. UTC
Free the vd (virt descriptor) after the callback is called.  In EDMA driver
atleast which uses virt-dma, we make use of the desc during the callback and if
its dangerously freed before the callback is called. I also noticed this in
omap-dma dmaengine driver.

Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Joel Fernandes <joelf@ti.com>
---
 drivers/dma/virt-dma.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Russell King - ARM Linux April 18, 2014, 8:50 a.m. UTC | #1
On Thu, Apr 17, 2014 at 07:56:50PM -0500, Joel Fernandes wrote:
> Free the vd (virt descriptor) after the callback is called.  In EDMA driver
> atleast which uses virt-dma, we make use of the desc during the callback and if
> its dangerously freed before the callback is called. I also noticed this in
> omap-dma dmaengine driver.

You've missed the vital bit of information: why do you make use of the
descriptor afterwards?  You shouldn't.  omap-dma doesn't either.

Once clients submit their request to DMA engine, they must not hold any
kind of reference to the descriptor other than the cookie.
Joel Fernandes April 18, 2014, 4:34 p.m. UTC | #2
On 04/18/2014 03:50 AM, Russell King - ARM Linux wrote:
> On Thu, Apr 17, 2014 at 07:56:50PM -0500, Joel Fernandes wrote:
>> Free the vd (virt descriptor) after the callback is called.  In EDMA driver
>> atleast which uses virt-dma, we make use of the desc during the callback and if
>> its dangerously freed before the callback is called. I also noticed this in
>> omap-dma dmaengine driver.
> 
> You've missed the vital bit of information: why do you make use of the
> descriptor afterwards?  You shouldn't.  omap-dma doesn't either.
> 
> Once clients submit their request to DMA engine, they must not hold any
> kind of reference to the descriptor other than the cookie.
> 

Sorry, I confused edma/omap-dma callbacks for virt dma callbacks.

Anyway, I think there is still a chance in edma that we refer to the
echan->edesc pointer later on after virt-dma calls the free (in
edma_execute), so I'll just NULL that out to be safe and submit a patch.
Thanks.

regards,
  -Joel
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vinod Koul April 22, 2014, 4:14 p.m. UTC | #3
On Fri, Apr 18, 2014 at 11:34:50AM -0500, Joel Fernandes wrote:
> On 04/18/2014 03:50 AM, Russell King - ARM Linux wrote:
> > On Thu, Apr 17, 2014 at 07:56:50PM -0500, Joel Fernandes wrote:
> >> Free the vd (virt descriptor) after the callback is called.  In EDMA driver
> >> atleast which uses virt-dma, we make use of the desc during the callback and if
> >> its dangerously freed before the callback is called. I also noticed this in
> >> omap-dma dmaengine driver.
> > 
> > You've missed the vital bit of information: why do you make use of the
> > descriptor afterwards?  You shouldn't.  omap-dma doesn't either.
> > 
> > Once clients submit their request to DMA engine, they must not hold any
> > kind of reference to the descriptor other than the cookie.
> > 
> 
> Sorry, I confused edma/omap-dma callbacks for virt dma callbacks.
> 
> Anyway, I think there is still a chance in edma that we refer to the
> echan->edesc pointer later on after virt-dma calls the free (in
> edma_execute), so I'll just NULL that out to be safe and submit a patch.

Yes, that would be the right way :)

While looking at this, I see it is not called out specfically in documentation, will update
that as well
diff mbox

Patch

diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c
index 6f80432..98aeb7f 100644
--- a/drivers/dma/virt-dma.c
+++ b/drivers/dma/virt-dma.c
@@ -84,10 +84,10 @@  static void vchan_complete(unsigned long arg)
 
 		list_del(&vd->node);
 
-		vc->desc_free(vd);
-
 		if (cb)
 			cb(cb_data);
+
+		vc->desc_free(vd);
 	}
 }