Commit 503473ac authored by Per Forlin's avatar Per Forlin Committed by Vinod Koul

dmaengine/ste_dma40: fix memory leak due to prepared descriptors

Prepared descriptors that are not submitted will not be freed. Add
prepared descriptor to a list to be able to release them upon
dmaengine_terminate_all().
Signed-off-by: default avatarPer Forlin <per.forlin@linaro.org>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 70a207ad
...@@ -177,6 +177,7 @@ struct d40_base; ...@@ -177,6 +177,7 @@ struct d40_base;
* @pending_queue: Submitted jobs, to be issued by issue_pending() * @pending_queue: Submitted jobs, to be issued by issue_pending()
* @active: Active descriptor. * @active: Active descriptor.
* @queue: Queued jobs. * @queue: Queued jobs.
* @prepare_queue: Prepared jobs.
* @dma_cfg: The client configuration of this dma channel. * @dma_cfg: The client configuration of this dma channel.
* @configured: whether the dma_cfg configuration is valid * @configured: whether the dma_cfg configuration is valid
* @base: Pointer to the device instance struct. * @base: Pointer to the device instance struct.
...@@ -204,6 +205,7 @@ struct d40_chan { ...@@ -204,6 +205,7 @@ struct d40_chan {
struct list_head pending_queue; struct list_head pending_queue;
struct list_head active; struct list_head active;
struct list_head queue; struct list_head queue;
struct list_head prepare_queue;
struct stedma40_chan_cfg dma_cfg; struct stedma40_chan_cfg dma_cfg;
bool configured; bool configured;
struct d40_base *base; struct d40_base *base;
...@@ -833,6 +835,13 @@ static void d40_term_all(struct d40_chan *d40c) ...@@ -833,6 +835,13 @@ static void d40_term_all(struct d40_chan *d40c)
d40_desc_free(d40c, d40d); d40_desc_free(d40c, d40d);
} }
/* Release descriptors in prepare queue */
if (!list_empty(&d40c->prepare_queue))
list_for_each_entry_safe(d40d, _d,
&d40c->prepare_queue, node) {
d40_desc_remove(d40d);
d40_desc_free(d40c, d40d);
}
d40c->pending_tx = 0; d40c->pending_tx = 0;
d40c->busy = false; d40c->busy = false;
...@@ -1911,6 +1920,12 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, ...@@ -1911,6 +1920,12 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
goto err; goto err;
} }
/*
* add descriptor to the prepare queue in order to be able
* to free them later in terminate_all
*/
list_add_tail(&desc->node, &chan->prepare_queue);
spin_unlock_irqrestore(&chan->lock, flags); spin_unlock_irqrestore(&chan->lock, flags);
return &desc->txd; return &desc->txd;
...@@ -2400,6 +2415,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, ...@@ -2400,6 +2415,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
INIT_LIST_HEAD(&d40c->queue); INIT_LIST_HEAD(&d40c->queue);
INIT_LIST_HEAD(&d40c->pending_queue); INIT_LIST_HEAD(&d40c->pending_queue);
INIT_LIST_HEAD(&d40c->client); INIT_LIST_HEAD(&d40c->client);
INIT_LIST_HEAD(&d40c->prepare_queue);
tasklet_init(&d40c->tasklet, dma_tasklet, tasklet_init(&d40c->tasklet, dma_tasklet,
(unsigned long) d40c); (unsigned long) d40c);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment