Skip to content

Commit bc3415a

Browse files
committed
dmaengine: fsl-edma: implement the cleanup path of fsl_edma3_attach_pd()
JIRA: https://issues.redhat.com/browse/RHEL-115725 commit ccfa313 Author: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> Date: Sat Dec 21 16:57:12 2024 +0900 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> Signed-off-by: Jared Kangas <jkangas@redhat.com>
1 parent 992a754 commit bc3415a

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
@@ -168,6 +168,7 @@ struct fsl_edma_chan {
168168
struct work_struct issue_worker;
169169
struct platform_device *pdev;
170170
struct device *pd_dev;
171+
struct device_link *pd_dev_link;
171172
u32 srcid;
172173
struct clk *clk;
173174
int priority;

drivers/dma/fsl-edma-main.c

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

527+
static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma)
528+
{
529+
struct fsl_edma_chan *fsl_chan;
530+
int i;
531+
532+
for (i = 0; i < fsl_edma->n_chans; i++) {
533+
if (fsl_edma->chan_masked & BIT(i))
534+
continue;
535+
fsl_chan = &fsl_edma->chans[i];
536+
if (fsl_chan->pd_dev_link)
537+
device_link_del(fsl_chan->pd_dev_link);
538+
if (fsl_chan->pd_dev) {
539+
dev_pm_domain_detach(fsl_chan->pd_dev, false);
540+
pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev);
541+
pm_runtime_set_suspended(fsl_chan->pd_dev);
542+
}
543+
}
544+
}
545+
546+
static void devm_fsl_edma3_detach_pd(void *data)
547+
{
548+
fsl_edma3_detach_pd(data);
549+
}
550+
527551
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
528552
{
529553
struct fsl_edma_chan *fsl_chan;
530-
struct device_link *link;
531554
struct device *pd_chan;
532555
struct device *dev;
533556
int i;
@@ -543,15 +566,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
543566
pd_chan = dev_pm_domain_attach_by_id(dev, i);
544567
if (IS_ERR_OR_NULL(pd_chan)) {
545568
dev_err(dev, "Failed attach pd %d\n", i);
546-
return -EINVAL;
569+
goto detach;
547570
}
548571

549-
link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
572+
fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
550573
DL_FLAG_PM_RUNTIME |
551574
DL_FLAG_RPM_ACTIVE);
552-
if (!link) {
575+
if (!fsl_chan->pd_dev_link) {
553576
dev_err(dev, "Failed to add device_link to %d\n", i);
554-
return -EINVAL;
577+
dev_pm_domain_detach(pd_chan, false);
578+
goto detach;
555579
}
556580

557581
fsl_chan->pd_dev = pd_chan;
@@ -562,6 +586,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
562586
}
563587

564588
return 0;
589+
590+
detach:
591+
fsl_edma3_detach_pd(fsl_edma);
592+
return -EINVAL;
565593
}
566594

567595
static int fsl_edma_probe(struct platform_device *pdev)
@@ -647,6 +675,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
647675
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
648676
if (ret)
649677
return ret;
678+
ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma);
679+
if (ret)
680+
return ret;
650681
}
651682

652683
if (drvdata->flags & FSL_EDMA_DRV_TCD64)

0 commit comments

Comments
 (0)