aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-08-29 07:33:35 -0400
committerVinod Koul <vinod.koul@intel.com>2011-09-05 07:38:26 -0400
commit82babbb361f207a80cffa8ac34c2b6a0b62acc88 (patch)
tree70bc26dbf87c8d3c82d427903e9dfa6bbcb19c47 /drivers
parent7404368c22b4910ab839238e48d96be45180f6fc (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(). 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>
Diffstat (limited to 'drivers')
-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 92ec0a26401a..467e4dcb20a0 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -177,6 +177,7 @@ struct d40_base;
177 * @pending_queue: Submitted jobs, to be issued by issue_pending() 177 * @pending_queue: Submitted jobs, to be issued by issue_pending()
178 * @active: Active descriptor. 178 * @active: Active descriptor.
179 * @queue: Queued jobs. 179 * @queue: Queued jobs.
180 * @prepare_queue: Prepared jobs.
180 * @dma_cfg: The client configuration of this dma channel. 181 * @dma_cfg: The client configuration of this dma channel.
181 * @configured: whether the dma_cfg configuration is valid 182 * @configured: whether the dma_cfg configuration is valid
182 * @base: Pointer to the device instance struct. 183 * @base: Pointer to the device instance struct.
@@ -204,6 +205,7 @@ struct d40_chan {
204 struct list_head pending_queue; 205 struct list_head pending_queue;
205 struct list_head active; 206 struct list_head active;
206 struct list_head queue; 207 struct list_head queue;
208 struct list_head prepare_queue;
207 struct stedma40_chan_cfg dma_cfg; 209 struct stedma40_chan_cfg dma_cfg;
208 bool configured; 210 bool configured;
209 struct d40_base *base; 211 struct d40_base *base;
@@ -833,6 +835,13 @@ static void d40_term_all(struct d40_chan *d40c)
833 d40_desc_free(d40c, d40d); 835 d40_desc_free(d40c, d40d);
834 } 836 }
835 837
838 /* Release descriptors in prepare queue */
839 if (!list_empty(&d40c->prepare_queue))
840 list_for_each_entry_safe(d40d, _d,
841 &d40c->prepare_queue, node) {
842 d40_desc_remove(d40d);
843 d40_desc_free(d40c, d40d);
844 }
836 845
837 d40c->pending_tx = 0; 846 d40c->pending_tx = 0;
838 d40c->busy = false; 847 d40c->busy = false;
@@ -1911,6 +1920,12 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
1911 goto err; 1920 goto err;
1912 } 1921 }
1913 1922
1923 /*
1924 * add descriptor to the prepare queue in order to be able
1925 * to free them later in terminate_all
1926 */
1927 list_add_tail(&desc->node, &chan->prepare_queue);
1928
1914 spin_unlock_irqrestore(&chan->lock, flags); 1929 spin_unlock_irqrestore(&chan->lock, flags);
1915 1930
1916 return &desc->txd; 1931 return &desc->txd;
@@ -2400,6 +2415,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
2400 INIT_LIST_HEAD(&d40c->queue); 2415 INIT_LIST_HEAD(&d40c->queue);
2401 INIT_LIST_HEAD(&d40c->pending_queue); 2416 INIT_LIST_HEAD(&d40c->pending_queue);
2402 INIT_LIST_HEAD(&d40c->client); 2417 INIT_LIST_HEAD(&d40c->client);
2418 INIT_LIST_HEAD(&d40c->prepare_queue);
2403 2419
2404 tasklet_init(&d40c->tasklet, dma_tasklet, 2420 tasklet_init(&d40c->tasklet, dma_tasklet,
2405 (unsigned long) d40c); 2421 (unsigned long) d40c);