[PATCH v7 4/4] dmaengine: pl330: Don't require irq-safe runtime PM
This patch replaces irq-safe runtime PM with non-irq-safe version based on the new approach. Existing, irq-safe runtime PM implementation for PL330 was not bringing much benefits of its own - only clocks were enabled/disabled. Another limitation of irq-safe runtime PM is a fact, that it may prevent the generic PM domain (genpd) from being powered off, particularly in cases when the genpd doesn't have the GENPD_FLAG_IRQ_SAFE set. Till now non-irq-safe runtime PM implementation was only possible by calling pm_runtime_get/put functions from alloc/free_chan_resources. All other DMA engine API functions cannot be called from a context, which permits sleeping. Such implementation, in practice would result in keeping DMA controller's device active almost all the time, because most of the slave device drivers (DMA engine clients) acquire DMA channel in their probe() function and released it during driver removal. This patch provides a new, different approach. It is based on an observation that there can be only one slave device using each DMA channel. PL330 hardware always has dedicated channels for each peripheral device. Using recently introduced device dependencies (links) infrastructure one can ensure proper runtime PM state of PL330 DMA controller basing on the runtime PM state of the slave device. In this approach in pl330_alloc_chan_resources() function a new dependency is being created between PL330 DMA controller device (as a supplier) and given slave device (as a consumer). This way PL330 DMA controller device runtime active counter is increased when the slave device is resumed and decreased the same time when given slave device is put to suspend. This way it has been ensured to keep PL330 DMA controller runtime active if there is an active used of any of its DMA channels. Slave device pointer is initially stored in per-channel data in of_dma_xlate callback. This is similar to what has been already implemented in Exynos IOMMU driver in commit 2f5f44f205cc95 ("iommu/exynos: Use device dependency links to control runtime pm"). If slave device doesn't implement runtime PM or keeps device runtime active all the time, then PL330 DMA controller will be runtime active all the time when channel is being allocated. If one requests memory-to-memory channel, runtime active counter is increased unconditionally. This might be a drawback of this approach, but PL330 is not really used for memory-to-memory operations due to poor performance in such operations compared to the CPU. Removal of irq-safe runtime PM is based on the revert of the following commits: 1. commit 5c9e6c2b2ba3 "dmaengine: pl330: fix runtime pm support" 2. commit 81cc6edc0870 "dmaengine: pl330: Fix hang on dmaengine_terminate_all on certain boards" 3. commit ae43b3289186 "ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12" Introducing non-irq-safe runtime power management finally allows to turn off audio power domain on Exynos5 SoCs. Signed-off-by: Marek SzyprowskiReviewed-by: Krzysztof Kozlowski Reviewed-by: Ulf Hansson Acked-by: Arnd Bergmann --- drivers/dma/pl330.c | 166 +--- 1 file changed, 66 insertions(+), 100 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index c77a3494659c..dff7228198f6 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -268,9 +268,6 @@ enum pl330_byteswap { #define NR_DEFAULT_DESC16 -/* Delay for runtime PM autosuspend, ms */ -#define PL330_AUTOSUSPEND_DELAY 20 - /* Populated by the PL330 core driver for DMA API driver's info */ struct pl330_config { u32 periph_id; @@ -449,8 +446,8 @@ struct dma_pl330_chan { bool cyclic; /* for runtime pm tracking */ - bool active; struct device *slave; + struct device_link *slave_link; }; struct pl330_dmac { @@ -2008,7 +2005,6 @@ static void pl330_tasklet(unsigned long data) struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; struct dma_pl330_desc *desc, *_dt; unsigned long flags; - bool power_down = false; spin_lock_irqsave(>lock, flags); @@ -2023,18 +2019,10 @@ static void pl330_tasklet(unsigned long data) /* Try to submit a req imm. next to the last completed cookie */ fill_queue(pch); - if (list_empty(>work_list)) { - spin_lock(>thread->dmac->lock); - _stop(pch->thread); - spin_unlock(>thread->dmac->lock); - power_down = true; - pch->active = false; - } else { - /* Make sure the PL330 Channel thread is active */ - spin_lock(>thread->dmac->lock); - _start(pch->thread); - spin_unlock(>thread->dmac->lock); - } + /* Make sure the PL330 Channel thread is active */ + spin_lock(>thread->dmac->lock); +
[PATCH v7 4/4] dmaengine: pl330: Don't require irq-safe runtime PM
This patch replaces irq-safe runtime PM with non-irq-safe version based on the new approach. Existing, irq-safe runtime PM implementation for PL330 was not bringing much benefits of its own - only clocks were enabled/disabled. Another limitation of irq-safe runtime PM is a fact, that it may prevent the generic PM domain (genpd) from being powered off, particularly in cases when the genpd doesn't have the GENPD_FLAG_IRQ_SAFE set. Till now non-irq-safe runtime PM implementation was only possible by calling pm_runtime_get/put functions from alloc/free_chan_resources. All other DMA engine API functions cannot be called from a context, which permits sleeping. Such implementation, in practice would result in keeping DMA controller's device active almost all the time, because most of the slave device drivers (DMA engine clients) acquire DMA channel in their probe() function and released it during driver removal. This patch provides a new, different approach. It is based on an observation that there can be only one slave device using each DMA channel. PL330 hardware always has dedicated channels for each peripheral device. Using recently introduced device dependencies (links) infrastructure one can ensure proper runtime PM state of PL330 DMA controller basing on the runtime PM state of the slave device. In this approach in pl330_alloc_chan_resources() function a new dependency is being created between PL330 DMA controller device (as a supplier) and given slave device (as a consumer). This way PL330 DMA controller device runtime active counter is increased when the slave device is resumed and decreased the same time when given slave device is put to suspend. This way it has been ensured to keep PL330 DMA controller runtime active if there is an active used of any of its DMA channels. Slave device pointer is initially stored in per-channel data in of_dma_xlate callback. This is similar to what has been already implemented in Exynos IOMMU driver in commit 2f5f44f205cc95 ("iommu/exynos: Use device dependency links to control runtime pm"). If slave device doesn't implement runtime PM or keeps device runtime active all the time, then PL330 DMA controller will be runtime active all the time when channel is being allocated. If one requests memory-to-memory channel, runtime active counter is increased unconditionally. This might be a drawback of this approach, but PL330 is not really used for memory-to-memory operations due to poor performance in such operations compared to the CPU. Removal of irq-safe runtime PM is based on the revert of the following commits: 1. commit 5c9e6c2b2ba3 "dmaengine: pl330: fix runtime pm support" 2. commit 81cc6edc0870 "dmaengine: pl330: Fix hang on dmaengine_terminate_all on certain boards" 3. commit ae43b3289186 "ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12" Introducing non-irq-safe runtime power management finally allows to turn off audio power domain on Exynos5 SoCs. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Ulf Hansson Acked-by: Arnd Bergmann --- drivers/dma/pl330.c | 166 +--- 1 file changed, 66 insertions(+), 100 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index c77a3494659c..dff7228198f6 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -268,9 +268,6 @@ enum pl330_byteswap { #define NR_DEFAULT_DESC16 -/* Delay for runtime PM autosuspend, ms */ -#define PL330_AUTOSUSPEND_DELAY 20 - /* Populated by the PL330 core driver for DMA API driver's info */ struct pl330_config { u32 periph_id; @@ -449,8 +446,8 @@ struct dma_pl330_chan { bool cyclic; /* for runtime pm tracking */ - bool active; struct device *slave; + struct device_link *slave_link; }; struct pl330_dmac { @@ -2008,7 +2005,6 @@ static void pl330_tasklet(unsigned long data) struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; struct dma_pl330_desc *desc, *_dt; unsigned long flags; - bool power_down = false; spin_lock_irqsave(>lock, flags); @@ -2023,18 +2019,10 @@ static void pl330_tasklet(unsigned long data) /* Try to submit a req imm. next to the last completed cookie */ fill_queue(pch); - if (list_empty(>work_list)) { - spin_lock(>thread->dmac->lock); - _stop(pch->thread); - spin_unlock(>thread->dmac->lock); - power_down = true; - pch->active = false; - } else { - /* Make sure the PL330 Channel thread is active */ - spin_lock(>thread->dmac->lock); - _start(pch->thread); - spin_unlock(>thread->dmac->lock); - } + /* Make sure the PL330 Channel thread is active */ + spin_lock(>thread->dmac->lock); + _start(pch->thread); + spin_unlock(>thread->dmac->lock);