|
@@ -448,6 +448,9 @@ struct dma_pl330_chan {
|
|
|
|
|
|
/* for cyclic capability */
|
|
/* for cyclic capability */
|
|
bool cyclic;
|
|
bool cyclic;
|
|
|
|
+
|
|
|
|
+ /* for runtime pm tracking */
|
|
|
|
+ bool active;
|
|
};
|
|
};
|
|
|
|
|
|
struct pl330_dmac {
|
|
struct pl330_dmac {
|
|
@@ -2033,6 +2036,7 @@ static void pl330_tasklet(unsigned long data)
|
|
_stop(pch->thread);
|
|
_stop(pch->thread);
|
|
spin_unlock(&pch->thread->dmac->lock);
|
|
spin_unlock(&pch->thread->dmac->lock);
|
|
power_down = true;
|
|
power_down = true;
|
|
|
|
+ pch->active = false;
|
|
} else {
|
|
} else {
|
|
/* Make sure the PL330 Channel thread is active */
|
|
/* Make sure the PL330 Channel thread is active */
|
|
spin_lock(&pch->thread->dmac->lock);
|
|
spin_lock(&pch->thread->dmac->lock);
|
|
@@ -2052,6 +2056,7 @@ static void pl330_tasklet(unsigned long data)
|
|
desc->status = PREP;
|
|
desc->status = PREP;
|
|
list_move_tail(&desc->node, &pch->work_list);
|
|
list_move_tail(&desc->node, &pch->work_list);
|
|
if (power_down) {
|
|
if (power_down) {
|
|
|
|
+ pch->active = true;
|
|
spin_lock(&pch->thread->dmac->lock);
|
|
spin_lock(&pch->thread->dmac->lock);
|
|
_start(pch->thread);
|
|
_start(pch->thread);
|
|
spin_unlock(&pch->thread->dmac->lock);
|
|
spin_unlock(&pch->thread->dmac->lock);
|
|
@@ -2166,6 +2171,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
struct pl330_dmac *pl330 = pch->dmac;
|
|
struct pl330_dmac *pl330 = pch->dmac;
|
|
LIST_HEAD(list);
|
|
LIST_HEAD(list);
|
|
|
|
+ bool power_down = false;
|
|
|
|
|
|
pm_runtime_get_sync(pl330->ddma.dev);
|
|
pm_runtime_get_sync(pl330->ddma.dev);
|
|
spin_lock_irqsave(&pch->lock, flags);
|
|
spin_lock_irqsave(&pch->lock, flags);
|
|
@@ -2176,6 +2182,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
|
pch->thread->req[0].desc = NULL;
|
|
pch->thread->req[0].desc = NULL;
|
|
pch->thread->req[1].desc = NULL;
|
|
pch->thread->req[1].desc = NULL;
|
|
pch->thread->req_running = -1;
|
|
pch->thread->req_running = -1;
|
|
|
|
+ power_down = pch->active;
|
|
|
|
+ pch->active = false;
|
|
|
|
|
|
/* Mark all desc done */
|
|
/* Mark all desc done */
|
|
list_for_each_entry(desc, &pch->submitted_list, node) {
|
|
list_for_each_entry(desc, &pch->submitted_list, node) {
|
|
@@ -2193,6 +2201,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
|
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
|
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
|
spin_unlock_irqrestore(&pch->lock, flags);
|
|
spin_unlock_irqrestore(&pch->lock, flags);
|
|
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
|
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
|
|
|
+ if (power_down)
|
|
|
|
+ pm_runtime_put_autosuspend(pl330->ddma.dev);
|
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -2357,6 +2367,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
|
|
* updated on work_list emptiness status.
|
|
* updated on work_list emptiness status.
|
|
*/
|
|
*/
|
|
WARN_ON(list_empty(&pch->submitted_list));
|
|
WARN_ON(list_empty(&pch->submitted_list));
|
|
|
|
+ pch->active = true;
|
|
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
|
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
|
}
|
|
}
|
|
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
|
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|