diff options
author | Per Forlin <per.forlin@linaro.org> | 2011-08-29 07:33:35 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2011-09-05 07:41:38 -0400 |
commit | 503473ac2a3952e6af254b0769fe788a67d797e5 (patch) | |
tree | 9b089ea8636b3a8b26a9534b7e1ccf1790c093aa | |
parent | 70a207ad4db2f0c60308b3f32086263c438c67a3 (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>
-rw-r--r-- | drivers/dma/ste_dma40.c | 16 |
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); |