Skip to content

Commit 2610acf

Browse files
andiplaVinod Koul
authored andcommitted
dmaengine: fsl-edma: disable clks on all error paths
Previously enabled clks are only disabled if clk_prepare_enable() fails. However, there are other error paths were the previously enabled clocks are not disabled. To fix the problem, fsl_disable_clocks() now takes the number of clocks that shall be disabled + unprepared. For existing calls were all clocks were already successfully prepared + enabled, DMAMUX_NR is passed to disable + unprepare all clocks. In error paths were only some clocks were successfully prepared + enabled the loop counter is passed, in order to disable + unprepare all successfully prepared + enabled clocks. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Andreas Platschek <andreas.platschek@opentech.at> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
1 parent eb94369 commit 2610acf

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

drivers/dma/fsl-edma.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -863,11 +863,11 @@ static void fsl_edma_irq_exit(
863863
}
864864
}
865865

866-
static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma)
866+
static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
867867
{
868868
int i;
869869

870-
for (i = 0; i < DMAMUX_NR; i++)
870+
for (i = 0; i < nr_clocks; i++)
871871
clk_disable_unprepare(fsl_edma->muxclk[i]);
872872
}
873873

@@ -904,25 +904,25 @@ static int fsl_edma_probe(struct platform_device *pdev)
904904

905905
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
906906
fsl_edma->muxbase[i] = devm_ioremap_resource(&pdev->dev, res);
907-
if (IS_ERR(fsl_edma->muxbase[i]))
907+
if (IS_ERR(fsl_edma->muxbase[i])) {
908+
/* on error: disable all previously enabled clks */
909+
fsl_disable_clocks(fsl_edma, i);
908910
return PTR_ERR(fsl_edma->muxbase[i]);
911+
}
909912

910913
sprintf(clkname, "dmamux%d", i);
911914
fsl_edma->muxclk[i] = devm_clk_get(&pdev->dev, clkname);
912915
if (IS_ERR(fsl_edma->muxclk[i])) {
913916
dev_err(&pdev->dev, "Missing DMAMUX block clock.\n");
917+
/* on error: disable all previously enabled clks */
918+
fsl_disable_clocks(fsl_edma, i);
914919
return PTR_ERR(fsl_edma->muxclk[i]);
915920
}
916921

917922
ret = clk_prepare_enable(fsl_edma->muxclk[i]);
918-
if (ret) {
919-
/* disable only clks which were enabled on error */
920-
for (; i >= 0; i--)
921-
clk_disable_unprepare(fsl_edma->muxclk[i]);
922-
923-
dev_err(&pdev->dev, "DMAMUX clk block failed.\n");
924-
return ret;
925-
}
923+
if (ret)
924+
/* on error: disable all previously enabled clks */
925+
fsl_disable_clocks(fsl_edma, i);
926926

927927
}
928928

@@ -976,7 +976,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
976976
if (ret) {
977977
dev_err(&pdev->dev,
978978
"Can't register Freescale eDMA engine. (%d)\n", ret);
979-
fsl_disable_clocks(fsl_edma);
979+
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
980980
return ret;
981981
}
982982

@@ -985,7 +985,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
985985
dev_err(&pdev->dev,
986986
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
987987
dma_async_device_unregister(&fsl_edma->dma_dev);
988-
fsl_disable_clocks(fsl_edma);
988+
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
989989
return ret;
990990
}
991991

@@ -1015,7 +1015,7 @@ static int fsl_edma_remove(struct platform_device *pdev)
10151015
fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
10161016
of_dma_controller_free(np);
10171017
dma_async_device_unregister(&fsl_edma->dma_dev);
1018-
fsl_disable_clocks(fsl_edma);
1018+
fsl_disable_clocks(fsl_edma, DMAMUX_NR);
10191019

10201020
return 0;
10211021
}

0 commit comments

Comments
 (0)