aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40.c
diff options
context:
space:
mode:
authorFabio Baltieri <fabio.baltieri@linaro.org>2012-12-13 07:46:16 -0500
committerFabio Baltieri <fabio.baltieri@linaro.org>2013-01-14 04:50:53 -0500
commit4226dd86b10ac44f8e98599f6a73e3a1b929f8eb (patch)
tree236280805bf3db2b81911303e4b429f7bda79368 /drivers/dma/ste_dma40.c
parent3cb645dc85a050c8a6b5c2cbdcbe4b8f39dba1b8 (diff)
dmaengine: ste_dma40: add a done queue for completed descriptors
This is to keep the active queue for only those transfers which are actually active in the hardware. Descriptors will be moved to the done queue after they are completed in the hardware (interrupt handler) but before all the cleanup work has been completed (tasklet). Mostly based on a previous patch by Rabin Vincent. Cc: Rabin Vincent <rabin.vincent@stericsson.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r--drivers/dma/ste_dma40.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 67e565bffe16..ff21dcbd8208 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -382,6 +382,7 @@ struct d40_base;
382 * @client: Cliented owned descriptor list. 382 * @client: Cliented owned descriptor list.
383 * @pending_queue: Submitted jobs, to be issued by issue_pending() 383 * @pending_queue: Submitted jobs, to be issued by issue_pending()
384 * @active: Active descriptor. 384 * @active: Active descriptor.
385 * @done: Completed jobs
385 * @queue: Queued jobs. 386 * @queue: Queued jobs.
386 * @prepare_queue: Prepared jobs. 387 * @prepare_queue: Prepared jobs.
387 * @dma_cfg: The client configuration of this dma channel. 388 * @dma_cfg: The client configuration of this dma channel.
@@ -407,6 +408,7 @@ struct d40_chan {
407 struct list_head client; 408 struct list_head client;
408 struct list_head pending_queue; 409 struct list_head pending_queue;
409 struct list_head active; 410 struct list_head active;
411 struct list_head done;
410 struct list_head queue; 412 struct list_head queue;
411 struct list_head prepare_queue; 413 struct list_head prepare_queue;
412 struct stedma40_chan_cfg dma_cfg; 414 struct stedma40_chan_cfg dma_cfg;
@@ -754,6 +756,11 @@ static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc)
754 writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK); 756 writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK);
755} 757}
756 758
759static void d40_desc_done(struct d40_chan *d40c, struct d40_desc *desc)
760{
761 list_add_tail(&desc->node, &d40c->done);
762}
763
757static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) 764static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
758{ 765{
759 struct d40_lcla_pool *pool = &chan->base->lcla_pool; 766 struct d40_lcla_pool *pool = &chan->base->lcla_pool;
@@ -914,6 +921,14 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c)
914 return d; 921 return d;
915} 922}
916 923
924static struct d40_desc *d40_first_done(struct d40_chan *d40c)
925{
926 if (list_empty(&d40c->done))
927 return NULL;
928
929 return list_first_entry(&d40c->done, struct d40_desc, node);
930}
931
917static int d40_psize_2_burst_size(bool is_log, int psize) 932static int d40_psize_2_burst_size(bool is_log, int psize)
918{ 933{
919 if (is_log) { 934 if (is_log) {
@@ -1104,6 +1119,12 @@ static void d40_term_all(struct d40_chan *d40c)
1104 struct d40_desc *d40d; 1119 struct d40_desc *d40d;
1105 struct d40_desc *_d; 1120 struct d40_desc *_d;
1106 1121
1122 /* Release completed descriptors */
1123 while ((d40d = d40_first_done(d40c))) {
1124 d40_desc_remove(d40d);
1125 d40_desc_free(d40c, d40d);
1126 }
1127
1107 /* Release active descriptors */ 1128 /* Release active descriptors */
1108 while ((d40d = d40_first_active_get(d40c))) { 1129 while ((d40d = d40_first_active_get(d40c))) {
1109 d40_desc_remove(d40d); 1130 d40_desc_remove(d40d);
@@ -1541,6 +1562,9 @@ static void dma_tc_handle(struct d40_chan *d40c)
1541 pm_runtime_put_autosuspend(d40c->base->dev); 1562 pm_runtime_put_autosuspend(d40c->base->dev);
1542 } 1563 }
1543 1564
1565 d40_desc_remove(d40d);
1566 d40_desc_done(d40c, d40d);
1567
1544 d40c->pending_tx++; 1568 d40c->pending_tx++;
1545 tasklet_schedule(&d40c->tasklet); 1569 tasklet_schedule(&d40c->tasklet);
1546 1570
@@ -1556,10 +1580,14 @@ static void dma_tasklet(unsigned long data)
1556 1580
1557 spin_lock_irqsave(&d40c->lock, flags); 1581 spin_lock_irqsave(&d40c->lock, flags);
1558 1582
1559 /* Get first active entry from list */ 1583 /* Get first entry from the done list */
1560 d40d = d40_first_active_get(d40c); 1584 d40d = d40_first_done(d40c);
1561 if (d40d == NULL) 1585 if (d40d == NULL) {
1562 goto err; 1586 /* Check if we have reached here for cyclic job */
1587 d40d = d40_first_active_get(d40c);
1588 if (d40d == NULL || !d40d->cyclic)
1589 goto err;
1590 }
1563 1591
1564 if (!d40d->cyclic) 1592 if (!d40d->cyclic)
1565 dma_cookie_complete(&d40d->txd); 1593 dma_cookie_complete(&d40d->txd);
@@ -2823,6 +2851,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
2823 2851
2824 d40c->log_num = D40_PHY_CHAN; 2852 d40c->log_num = D40_PHY_CHAN;
2825 2853
2854 INIT_LIST_HEAD(&d40c->done);
2826 INIT_LIST_HEAD(&d40c->active); 2855 INIT_LIST_HEAD(&d40c->active);
2827 INIT_LIST_HEAD(&d40c->queue); 2856 INIT_LIST_HEAD(&d40c->queue);
2828 INIT_LIST_HEAD(&d40c->pending_queue); 2857 INIT_LIST_HEAD(&d40c->pending_queue);