diff options
author | Per Forlin <per.forlin@linaro.org> | 2011-06-26 17:29:52 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2011-07-13 18:32:08 -0400 |
commit | a8f3067bce60b96215f3169d2c71e21f784ef507 (patch) | |
tree | e2a999995a3439cc1342843b69946a491f914f07 /drivers/dma | |
parent | 70f18915846f092e0e1c988f1726a532fa3ab3a1 (diff) |
dmaengine/ste_dma40: add a separate queue for pending requests
tx_submit will add descriptors to the pending queue. Issue pending
will then move the pending descriptors to the transfer queue.
Signed-off-by: Per Forlin <per.forlin@linaro.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ste_dma40.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 8f222d4db7de..91d5ed7c79ba 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -199,6 +199,7 @@ struct d40_chan { | |||
199 | struct dma_chan chan; | 199 | struct dma_chan chan; |
200 | struct tasklet_struct tasklet; | 200 | struct tasklet_struct tasklet; |
201 | struct list_head client; | 201 | struct list_head client; |
202 | struct list_head pending_queue; | ||
202 | struct list_head active; | 203 | struct list_head active; |
203 | struct list_head queue; | 204 | struct list_head queue; |
204 | struct stedma40_chan_cfg dma_cfg; | 205 | struct stedma40_chan_cfg dma_cfg; |
@@ -644,7 +645,20 @@ static struct d40_desc *d40_first_active_get(struct d40_chan *d40c) | |||
644 | 645 | ||
645 | static void d40_desc_queue(struct d40_chan *d40c, struct d40_desc *desc) | 646 | static void d40_desc_queue(struct d40_chan *d40c, struct d40_desc *desc) |
646 | { | 647 | { |
647 | list_add_tail(&desc->node, &d40c->queue); | 648 | list_add_tail(&desc->node, &d40c->pending_queue); |
649 | } | ||
650 | |||
651 | static struct d40_desc *d40_first_pending(struct d40_chan *d40c) | ||
652 | { | ||
653 | struct d40_desc *d; | ||
654 | |||
655 | if (list_empty(&d40c->pending_queue)) | ||
656 | return NULL; | ||
657 | |||
658 | d = list_first_entry(&d40c->pending_queue, | ||
659 | struct d40_desc, | ||
660 | node); | ||
661 | return d; | ||
648 | } | 662 | } |
649 | 663 | ||
650 | static struct d40_desc *d40_first_queued(struct d40_chan *d40c) | 664 | static struct d40_desc *d40_first_queued(struct d40_chan *d40c) |
@@ -801,6 +815,11 @@ static void d40_term_all(struct d40_chan *d40c) | |||
801 | d40_desc_free(d40c, d40d); | 815 | d40_desc_free(d40c, d40d); |
802 | } | 816 | } |
803 | 817 | ||
818 | /* Release pending descriptors */ | ||
819 | while ((d40d = d40_first_pending(d40c))) { | ||
820 | d40_desc_remove(d40d); | ||
821 | d40_desc_free(d40c, d40d); | ||
822 | } | ||
804 | 823 | ||
805 | d40c->pending_tx = 0; | 824 | d40c->pending_tx = 0; |
806 | d40c->busy = false; | 825 | d40c->busy = false; |
@@ -2151,7 +2170,9 @@ static void d40_issue_pending(struct dma_chan *chan) | |||
2151 | 2170 | ||
2152 | spin_lock_irqsave(&d40c->lock, flags); | 2171 | spin_lock_irqsave(&d40c->lock, flags); |
2153 | 2172 | ||
2154 | /* Busy means that pending jobs are already being processed */ | 2173 | list_splice_tail_init(&d40c->pending_queue, &d40c->queue); |
2174 | |||
2175 | /* Busy means that queued jobs are already being processed */ | ||
2155 | if (!d40c->busy) | 2176 | if (!d40c->busy) |
2156 | (void) d40_queue_start(d40c); | 2177 | (void) d40_queue_start(d40c); |
2157 | 2178 | ||
@@ -2340,6 +2361,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, | |||
2340 | 2361 | ||
2341 | INIT_LIST_HEAD(&d40c->active); | 2362 | INIT_LIST_HEAD(&d40c->active); |
2342 | INIT_LIST_HEAD(&d40c->queue); | 2363 | INIT_LIST_HEAD(&d40c->queue); |
2364 | INIT_LIST_HEAD(&d40c->pending_queue); | ||
2343 | INIT_LIST_HEAD(&d40c->client); | 2365 | INIT_LIST_HEAD(&d40c->client); |
2344 | 2366 | ||
2345 | tasklet_init(&d40c->tasklet, dma_tasklet, | 2367 | tasklet_init(&d40c->tasklet, dma_tasklet, |