Skip to content

Commit 34d2c9c

Browse files
joehattorigregkh
authored andcommitted
dmaengine: fsl-edma: implement the cleanup path of fsl_edma3_attach_pd()
commit ccfa313 upstream. 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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f270535 commit 34d2c9c

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
@@ -151,6 +151,7 @@ struct fsl_edma_chan {
151151
struct work_struct issue_worker;
152152
struct platform_device *pdev;
153153
struct device *pd_dev;
154+
struct device_link *pd_dev_link;
154155
u32 srcid;
155156
struct clk *clk;
156157
int priority;

drivers/dma/fsl-edma-main.c

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

387+
static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma)
388+
{
389+
struct fsl_edma_chan *fsl_chan;
390+
int i;
391+
392+
for (i = 0; i < fsl_edma->n_chans; i++) {
393+
if (fsl_edma->chan_masked & BIT(i))
394+
continue;
395+
fsl_chan = &fsl_edma->chans[i];
396+
if (fsl_chan->pd_dev_link)
397+
device_link_del(fsl_chan->pd_dev_link);
398+
if (fsl_chan->pd_dev) {
399+
dev_pm_domain_detach(fsl_chan->pd_dev, false);
400+
pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev);
401+
pm_runtime_set_suspended(fsl_chan->pd_dev);
402+
}
403+
}
404+
}
405+
406+
static void devm_fsl_edma3_detach_pd(void *data)
407+
{
408+
fsl_edma3_detach_pd(data);
409+
}
410+
387411
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
388412
{
389413
struct fsl_edma_chan *fsl_chan;
390-
struct device_link *link;
391414
struct device *pd_chan;
392415
struct device *dev;
393416
int i;
@@ -403,15 +426,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
403426
pd_chan = dev_pm_domain_attach_by_id(dev, i);
404427
if (IS_ERR_OR_NULL(pd_chan)) {
405428
dev_err(dev, "Failed attach pd %d\n", i);
406-
return -EINVAL;
429+
goto detach;
407430
}
408431

409-
link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
432+
fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
410433
DL_FLAG_PM_RUNTIME |
411434
DL_FLAG_RPM_ACTIVE);
412-
if (!link) {
435+
if (!fsl_chan->pd_dev_link) {
413436
dev_err(dev, "Failed to add device_link to %d\n", i);
414-
return -EINVAL;
437+
dev_pm_domain_detach(pd_chan, false);
438+
goto detach;
415439
}
416440

417441
fsl_chan->pd_dev = pd_chan;
@@ -422,6 +446,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
422446
}
423447

424448
return 0;
449+
450+
detach:
451+
fsl_edma3_detach_pd(fsl_edma);
452+
return -EINVAL;
425453
}
426454

427455
static int fsl_edma_probe(struct platform_device *pdev)
@@ -522,6 +550,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
522550
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
523551
if (ret)
524552
return ret;
553+
ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma);
554+
if (ret)
555+
return ret;
525556
}
526557

527558
INIT_LIST_HEAD(&fsl_edma->dma_dev.channels);

0 commit comments

Comments
 (0)