On 06/06/17 10:51, Mikko Perttunen wrote: > On 06.06.2017 11:59, Jon Hunter wrote: >> Commit edd3bdbe9db1 ("dmaengine: tegra-apb: Correct runtime-pm usage") >> added pm_runtime_get/put() calls to the tegra-apb DMA system suspend >> callbacks. Runtime PM is disabled during system suspend and so these >> APIs cannot be used. Fix the suspend handling for the tegra-apb DMA by >> moving the save and restore of the DMA register context into the >> runtime PM suspend and resume callbacks, and then use the >> pm_runtime_force_suspend/resume() APIs to invoke the runtime PM >> callbacks during system suspend. >> >> Fixes: edd3bdbe9db1 ("dmaengine: tegra-apb: Correct runtime-pm usage") >> >> Signed-off-by: Jon Hunter <jonathanh@xxxxxxxxxx> >> --- >> drivers/dma/tegra20-apb-dma.c | 57 >> +++++++++++++++---------------------------- >> 1 file changed, 19 insertions(+), 38 deletions(-) >> >> diff --git a/drivers/dma/tegra20-apb-dma.c >> b/drivers/dma/tegra20-apb-dma.c >> index 3722b9d8d9fe..5c3ddd61dc3b 100644 >> --- a/drivers/dma/tegra20-apb-dma.c >> +++ b/drivers/dma/tegra20-apb-dma.c >> @@ -1494,35 +1494,7 @@ static int tegra_dma_remove(struct >> platform_device *pdev) >> static int tegra_dma_runtime_suspend(struct device *dev) >> { >> struct tegra_dma *tdma = dev_get_drvdata(dev); >> - >> - clk_disable_unprepare(tdma->dma_clk); >> - return 0; >> -} >> - >> -static int tegra_dma_runtime_resume(struct device *dev) >> -{ >> - struct tegra_dma *tdma = dev_get_drvdata(dev); >> - int ret; >> - >> - ret = clk_prepare_enable(tdma->dma_clk); >> - if (ret < 0) { >> - dev_err(dev, "clk_enable failed: %d\n", ret); >> - return ret; >> - } >> - return 0; >> -} >> - >> -#ifdef CONFIG_PM_SLEEP >> -static int tegra_dma_pm_suspend(struct device *dev) >> -{ >> - struct tegra_dma *tdma = dev_get_drvdata(dev); >> int i; >> - int ret; >> - >> - /* Enable clock before accessing register */ >> - ret = pm_runtime_get_sync(dev); >> - if (ret < 0) >> - return ret; >> >> tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); >> for (i = 0; i < tdma->chip_data->nr_channels; i++) { >> @@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device >> *dev) >> TEGRA_APBDMA_CHAN_WCOUNT); >> } >> >> - /* Disable clock */ >> - pm_runtime_put(dev); >> + clk_disable_unprepare(tdma->dma_clk); >> + >> return 0; >> } >> >> -static int tegra_dma_pm_resume(struct device *dev) >> +static int tegra_dma_runtime_resume(struct device *dev) >> { >> struct tegra_dma *tdma = dev_get_drvdata(dev); >> - int i; >> - int ret; >> + int i, ret; >> >> - /* Enable clock before accessing register */ >> - ret = pm_runtime_get_sync(dev); >> - if (ret < 0) >> + ret = clk_prepare_enable(tdma->dma_clk); >> + if (ret < 0) { >> + dev_err(dev, "clk_enable failed: %d\n", ret); >> return ret; >> + } >> >> tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); >> tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); >> @@ -1582,10 +1554,19 @@ static int tegra_dma_pm_resume(struct device >> *dev) >> (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB)); >> } >> >> - /* Disable clock */ >> - pm_runtime_put(dev); >> return 0; >> } >> + >> +#ifdef CONFIG_PM_SLEEP >> +static int tegra_dma_pm_suspend(struct device *dev) >> +{ >> + return pm_runtime_force_suspend(dev); >> +} >> + >> +static int tegra_dma_pm_resume(struct device *dev) >> +{ >> + return pm_runtime_force_resume(dev); >> +} >> #endif > > You could just have SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, > pm_runtime_force_resume) Yes indeed! Will update. Cheers Jon -- nvpublic -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html