Skip to content

Commit

Permalink
dmaengine: sprd: Fix the possible memory leak issue
Browse files Browse the repository at this point in the history
If we terminate the channel to free all descriptors associated with this
channel, we will leak the memory of current descriptor if the current
descriptor is not completed, since it had been deteled from the desc_issued
list and have not been added into the desc_completed list.

Thus we should check if current descriptor is completed or not, when freeing
the descriptors associated with one channel, if not, we should free it to
avoid this issue.

Fixes: 9b3b817 ("dmaengine: sprd: Add Spreadtrum DMA driver")
Reported-by: Zhenfang Wang <zhenfang.wang@unisoc.com>
Tested-by: Zhenfang Wang <zhenfang.wang@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Link: https://lore.kernel.org/r/170dbbc6d5366b6fa974ce2d366652e23a334251.1570609788.git.baolin.wang@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
wangbaolin719 authored and vinodkoul committed Oct 15, 2019
1 parent 6c6de1d commit ec1ac30
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions drivers/dma/sprd-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ struct sprd_dma_dev {
struct sprd_dma_chn channels[0];
};

static void sprd_dma_free_desc(struct virt_dma_desc *vd);
static bool sprd_dma_filter_fn(struct dma_chan *chan, void *param);
static struct of_dma_filter_info sprd_dma_info = {
.filter_fn = sprd_dma_filter_fn,
Expand Down Expand Up @@ -613,12 +614,19 @@ static int sprd_dma_alloc_chan_resources(struct dma_chan *chan)
static void sprd_dma_free_chan_resources(struct dma_chan *chan)
{
struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
struct virt_dma_desc *cur_vd = NULL;
unsigned long flags;

spin_lock_irqsave(&schan->vc.lock, flags);
if (schan->cur_desc)
cur_vd = &schan->cur_desc->vd;

sprd_dma_stop(schan);
spin_unlock_irqrestore(&schan->vc.lock, flags);

if (cur_vd)
sprd_dma_free_desc(cur_vd);

vchan_free_chan_resources(&schan->vc);
pm_runtime_put(chan->device->dev);
}
Expand Down Expand Up @@ -1031,15 +1039,22 @@ static int sprd_dma_resume(struct dma_chan *chan)
static int sprd_dma_terminate_all(struct dma_chan *chan)
{
struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
struct virt_dma_desc *cur_vd = NULL;
unsigned long flags;
LIST_HEAD(head);

spin_lock_irqsave(&schan->vc.lock, flags);
if (schan->cur_desc)
cur_vd = &schan->cur_desc->vd;

sprd_dma_stop(schan);

vchan_get_all_descriptors(&schan->vc, &head);
spin_unlock_irqrestore(&schan->vc.lock, flags);

if (cur_vd)
sprd_dma_free_desc(cur_vd);

vchan_dma_desc_free_list(&schan->vc, &head);
return 0;
}
Expand Down

0 comments on commit ec1ac30

Please sign in to comment.