> -----Original Message----- > From: Vinod Koul <vkoul@xxxxxxxxxx> > Sent: 2024年12月24日 17:30 > To: Joy Zou <joy.zou@xxxxxxx> > Cc: Frank Li <frank.li@xxxxxxx>; S.J. Wang <shengjiu.wang@xxxxxxx>; > imx@xxxxxxxxxxxxxxx; dmaengine@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx > Subject: Re: [PATCH v1] dmaengine: fsl-edma: add runtime > suspend/resume support > > > > On 20-12-24, 10:11, Joy Zou wrote: > > Introduce runtime suspend and resume support for FSL eDMA. Enable > > per-channel power domain management to facilitate runtime suspend and > > resume operations. > > > > Implement runtime suspend and resume functions for the eDMA engine and > > individual channels. > > > > Link per-channel power domain device to eDMA per-channel device > > instead of eDMA engine device. So Power Manage framework manage power > > state of linked domain device when per-channel device request runtime > resume/suspend. > > > > Trigger the eDMA engine's runtime suspend when all channels are > > suspended, disabling all common clocks through the runtime PM framework. > > > > Signed-off-by: Joy Zou <joy.zou@xxxxxxx> > > Signed-off-by: Frank Li <Frank.Li@xxxxxxx> > > --- > > drivers/dma/fsl-edma-common.c | 15 ++--- > > drivers/dma/fsl-edma-main.c | 115 > ++++++++++++++++++++++++++++++---- > > 2 files changed, 110 insertions(+), 20 deletions(-) > > > > diff --git a/drivers/dma/fsl-edma-common.c > > b/drivers/dma/fsl-edma-common.c index b7f15ab96855..fcdb53b21f38 > > 100644 > > --- a/drivers/dma/fsl-edma-common.c > > +++ b/drivers/dma/fsl-edma-common.c > > @@ -243,9 +243,6 @@ int fsl_edma_terminate_all(struct dma_chan *chan) > > spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); > > vchan_dma_desc_free_list(&fsl_chan->vchan, &head); > > > > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_PD) > > - pm_runtime_allow(fsl_chan->pd_dev); > > - > > return 0; > > } > > > > @@ -805,8 +802,12 @@ int fsl_edma_alloc_chan_resources(struct > dma_chan *chan) > > struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); > > int ret; > > > > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) > > - clk_prepare_enable(fsl_chan->clk); > > + ret = pm_runtime_get_sync(&fsl_chan->vchan.chan.dev->device); > > + if (ret < 0) { > > + dev_err(&fsl_chan->vchan.chan.dev->device, > "pm_runtime_get_sync() failed\n"); > > + pm_runtime_disable(&fsl_chan->vchan.chan.dev->device); > > + return ret; > > + } > > > > fsl_chan->tcd_pool = dma_pool_create("tcd_pool", > chan->device->dev, > > fsl_edma_drvflags(fsl_chan) & > FSL_EDMA_DRV_TCD64 ? > > @@ -819,6 +820,7 @@ int fsl_edma_alloc_chan_resources(struct dma_chan > > *chan) > > > > if (ret) { > > dma_pool_destroy(fsl_chan->tcd_pool); > > + > > + pm_runtime_put_sync_suspend(&fsl_chan->vchan.chan.dev->device); > > return ret; > > } > > } > > @@ -851,8 +853,7 @@ void fsl_edma_free_chan_resources(struct > dma_chan *chan) > > fsl_chan->is_sw = false; > > fsl_chan->srcid = 0; > > fsl_chan->is_remote = false; > > - if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK) > > - clk_disable_unprepare(fsl_chan->clk); > > + pm_runtime_put_sync_suspend(&fsl_chan->vchan.chan.dev->device); > > } > > > > void fsl_edma_cleanup_vchan(struct dma_device *dmadev) diff --git > > a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c index > > 60de1003193a..75d6c8984c8e 100644 > > --- a/drivers/dma/fsl-edma-main.c > > +++ b/drivers/dma/fsl-edma-main.c > > @@ -420,7 +420,6 @@ MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids); > static > > int fsl_edma3_attach_pd(struct platform_device *pdev, struct > > fsl_edma_engine *fsl_edma) { > > struct fsl_edma_chan *fsl_chan; > > - struct device_link *link; > > struct device *pd_chan; > > struct device *dev; > > int i; > > @@ -439,24 +438,39 @@ static int fsl_edma3_attach_pd(struct > platform_device *pdev, struct fsl_edma_eng > > return -EINVAL; > > } > > > > - link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS | > > - DL_FLAG_PM_RUNTIME | > > - DL_FLAG_RPM_ACTIVE); > > - if (!link) { > > - dev_err(dev, "Failed to add device_link to %d\n", i); > > - return -EINVAL; > > - } > > - > > fsl_chan->pd_dev = pd_chan; > > - > > - pm_runtime_use_autosuspend(fsl_chan->pd_dev); > > - pm_runtime_set_autosuspend_delay(fsl_chan->pd_dev, > 200); > > - pm_runtime_set_active(fsl_chan->pd_dev); > > } > > > > return 0; > > } > > > > +/* Per channel dma power domain */ > > +static int fsl_edma_chan_runtime_suspend(struct device *dev) { > > + struct fsl_edma_chan *fsl_chan = dev_get_drvdata(dev); > > + int ret = 0; > > + > > + clk_disable_unprepare(fsl_chan->clk); > > + > > + return ret; > > Unused ret! drop it Thanks for your comments! Will drop it! > > > +} > > + > > +static int fsl_edma_chan_runtime_resume(struct device *dev) { > > + struct fsl_edma_chan *fsl_chan = dev_get_drvdata(dev); > > + int ret; > > + > > + ret = clk_prepare_enable(fsl_chan->clk); > > + > > + return ret; > > how about return clk_prepare_enable() Yeah! It's better! Will change it. Thank you very much! Merry Christmas! BR Joy Zou > > -- > ~Vinod