mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 17:23:36 +00:00
dmaengine: fsl-edma: implement the cleanup path of fsl_edma3_attach_pd()
Current implementation of fsl_edma3_attach_pd() does not provide a
cleanup path, resulting in a memory leak. For example,
dev_pm_domain_detach() is not called after dev_pm_domain_attach_by_id(),
and the device link created with the DL_FLAG_STATELESS is not released
explicitly.
Therefore, provide a cleanup function fsl_edma3_detach_pd() and call it
upon failure. Also add a devm_add_action_or_reset() call with this
function after a successful fsl_edma3_attach_pd().
Fixes: 72f5801a4e
("dmaengine: fsl-edma: integrate v3 support")
Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
Link: https://lore.kernel.org/r/20241221075712.3297200-1-joe@pf.is.s.u-tokyo.ac.jp
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
dcbef0798e
commit
ccfa3131d4
@ -166,6 +166,7 @@ struct fsl_edma_chan {
|
|||||||
struct work_struct issue_worker;
|
struct work_struct issue_worker;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct device *pd_dev;
|
struct device *pd_dev;
|
||||||
|
struct device_link *pd_dev_link;
|
||||||
u32 srcid;
|
u32 srcid;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
int priority;
|
int priority;
|
||||||
|
@ -417,10 +417,33 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
|
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
|
||||||
|
|
||||||
|
static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma)
|
||||||
|
{
|
||||||
|
struct fsl_edma_chan *fsl_chan;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < fsl_edma->n_chans; i++) {
|
||||||
|
if (fsl_edma->chan_masked & BIT(i))
|
||||||
|
continue;
|
||||||
|
fsl_chan = &fsl_edma->chans[i];
|
||||||
|
if (fsl_chan->pd_dev_link)
|
||||||
|
device_link_del(fsl_chan->pd_dev_link);
|
||||||
|
if (fsl_chan->pd_dev) {
|
||||||
|
dev_pm_domain_detach(fsl_chan->pd_dev, false);
|
||||||
|
pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev);
|
||||||
|
pm_runtime_set_suspended(fsl_chan->pd_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void devm_fsl_edma3_detach_pd(void *data)
|
||||||
|
{
|
||||||
|
fsl_edma3_detach_pd(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
|
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
|
||||||
{
|
{
|
||||||
struct fsl_edma_chan *fsl_chan;
|
struct fsl_edma_chan *fsl_chan;
|
||||||
struct device_link *link;
|
|
||||||
struct device *pd_chan;
|
struct device *pd_chan;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int i;
|
int i;
|
||||||
@ -436,15 +459,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
|
|||||||
pd_chan = dev_pm_domain_attach_by_id(dev, i);
|
pd_chan = dev_pm_domain_attach_by_id(dev, i);
|
||||||
if (IS_ERR_OR_NULL(pd_chan)) {
|
if (IS_ERR_OR_NULL(pd_chan)) {
|
||||||
dev_err(dev, "Failed attach pd %d\n", i);
|
dev_err(dev, "Failed attach pd %d\n", i);
|
||||||
return -EINVAL;
|
goto detach;
|
||||||
}
|
}
|
||||||
|
|
||||||
link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
|
fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
|
||||||
DL_FLAG_PM_RUNTIME |
|
DL_FLAG_PM_RUNTIME |
|
||||||
DL_FLAG_RPM_ACTIVE);
|
DL_FLAG_RPM_ACTIVE);
|
||||||
if (!link) {
|
if (!fsl_chan->pd_dev_link) {
|
||||||
dev_err(dev, "Failed to add device_link to %d\n", i);
|
dev_err(dev, "Failed to add device_link to %d\n", i);
|
||||||
return -EINVAL;
|
dev_pm_domain_detach(pd_chan, false);
|
||||||
|
goto detach;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsl_chan->pd_dev = pd_chan;
|
fsl_chan->pd_dev = pd_chan;
|
||||||
@ -455,6 +479,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
detach:
|
||||||
|
fsl_edma3_detach_pd(fsl_edma);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsl_edma_probe(struct platform_device *pdev)
|
static int fsl_edma_probe(struct platform_device *pdev)
|
||||||
@ -544,6 +572,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
|
|||||||
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
|
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drvdata->flags & FSL_EDMA_DRV_TCD64)
|
if (drvdata->flags & FSL_EDMA_DRV_TCD64)
|
||||||
|
Loading…
Reference in New Issue
Block a user