summaryrefslogtreecommitdiff
path: root/drivers/dma/ste_dma40.c
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-08-29 13:33:35 +0200
committerJonas ABERG <jonas.aberg@stericsson.com>2011-10-24 11:32:12 +0200
commit6eaad6cd7669151bda6c080c3f736df726b33bc6 (patch)
tree6011ba636d3fe074f3b129c09ab0ee8def64eff2 /drivers/dma/ste_dma40.c
parent63662563b36bf493c540a84bea7ddd64aa9b3be7 (diff)
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(). ST-Ericsson ID: 362972 ST-Ericsson FOSS-OUT ID: NA ST-Ericsson Linux next: NA Change-Id: I93bb2bd072851c435c0dcf0a50deab63d9c1b735 Signed-off-by: Per Forlin <per.forlin@linaro.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34968 Tested-by: Narayanan GOPALAKRISHNAN <narayanan.gopalakrishnan@stericsson.com> Reviewed-by: Per FORLIN <per.forlin@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r--drivers/dma/ste_dma40.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 78eb58c6dc3..047a7de76c7 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -240,6 +240,7 @@ struct d40_base;
* @active: Active descriptor.
* @done: Completed jobs
* @queue: Queued jobs.
+ * @prepare_queue: Prepared jobs.
* @dma_cfg: The client configuration of this dma channel.
* @configured: whether the dma_cfg configuration is valid
* @base: Pointer to the device instance struct.
@@ -270,6 +271,7 @@ struct d40_chan {
struct list_head active;
struct list_head done;
struct list_head queue;
+ struct list_head prepare_queue;
struct stedma40_chan_cfg dma_cfg;
bool configured;
struct d40_base *base;
@@ -1055,6 +1057,13 @@ static void d40_term_all(struct d40_chan *d40c)
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;
}
@@ -2152,6 +2161,12 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
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);
return &desc->txd;
@@ -2901,6 +2916,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
INIT_LIST_HEAD(&d40c->queue);
INIT_LIST_HEAD(&d40c->pending_queue);
INIT_LIST_HEAD(&d40c->client);
+ INIT_LIST_HEAD(&d40c->prepare_queue);
tasklet_init(&d40c->tasklet, dma_tasklet,
(unsigned long) d40c);