Skip to content

Commit ccfa313

Browse files
joehattorivinodkoul
authored andcommitted
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: 72f5801 ("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>
1 parent dcbef07 commit ccfa313

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

drivers/dma/fsl-edma-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ struct fsl_edma_chan {
166166
struct work_struct issue_worker;
167167
struct platform_device *pdev;
168168
struct device *pd_dev;
169+
struct device_link *pd_dev_link;
169170
u32 srcid;
170171
struct clk *clk;
171172
int priority;

drivers/dma/fsl-edma-main.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,33 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
417417
};
418418
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
419419

420+
static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma)
421+
{
422+
struct fsl_edma_chan *fsl_chan;
423+
int i;
424+
425+
for (i = 0; i < fsl_edma->n_chans; i++) {
426+
if (fsl_edma->chan_masked & BIT(i))
427+
continue;
428+
fsl_chan = &fsl_edma->chans[i];
429+
if (fsl_chan->pd_dev_link)
430+
device_link_del(fsl_chan->pd_dev_link);
431+
if (fsl_chan->pd_dev) {
432+
dev_pm_domain_detach(fsl_chan->pd_dev, false);
433+
pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev);
434+
pm_runtime_set_suspended(fsl_chan->pd_dev);
435+
}
436+
}
437+
}
438+
439+
static void devm_fsl_edma3_detach_pd(void *data)
440+
{
441+
fsl_edma3_detach_pd(data);
442+
}
443+
420444
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
421445
{
422446
struct fsl_edma_chan *fsl_chan;
423-
struct device_link *link;
424447
struct device *pd_chan;
425448
struct device *dev;
426449
int i;
@@ -436,15 +459,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
436459
pd_chan = dev_pm_domain_attach_by_id(dev, i);
437460
if (IS_ERR_OR_NULL(pd_chan)) {
438461
dev_err(dev, "Failed attach pd %d\n", i);
439-
return -EINVAL;
462+
goto detach;
440463
}
441464

442-
link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
465+
fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
443466
DL_FLAG_PM_RUNTIME |
444467
DL_FLAG_RPM_ACTIVE);
445-
if (!link) {
468+
if (!fsl_chan->pd_dev_link) {
446469
dev_err(dev, "Failed to add device_link to %d\n", i);
447-
return -EINVAL;
470+
dev_pm_domain_detach(pd_chan, false);
471+
goto detach;
448472
}
449473

450474
fsl_chan->pd_dev = pd_chan;
@@ -455,6 +479,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
455479
}
456480

457481
return 0;
482+
483+
detach:
484+
fsl_edma3_detach_pd(fsl_edma);
485+
return -EINVAL;
458486
}
459487

460488
static int fsl_edma_probe(struct platform_device *pdev)
@@ -544,6 +572,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
544572
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
545573
if (ret)
546574
return ret;
575+
ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma);
576+
if (ret)
577+
return ret;
547578
}
548579

549580
if (drvdata->flags & FSL_EDMA_DRV_TCD64)

0 commit comments

Comments
 (0)