[PATCH 4.9 04/56] dmaengine: fsl-edma: disable clks on all error paths

2018-03-02 Thread Greg Kroah-Hartman
4.9-stable review patch.  If anyone has any objections, please let me know.

--

From: Andreas Platschek 


[ Upstream commit 2610acf46b9ed528ec2cacd717bc9d354e452b73 ]

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 
Signed-off-by: Vinod Koul 
Signed-off-by: Sasha Levin 
Signed-off-by: Greg Kroah-Hartman 
---
 drivers/dma/fsl-edma.c |   28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -863,11 +863,11 @@ static void fsl_edma_irq_exit(
}
 }
 
-static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma)
+static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
 {
int i;
 
-   for (i = 0; i < DMAMUX_NR; i++)
+   for (i = 0; i < nr_clocks; i++)
clk_disable_unprepare(fsl_edma->muxclk[i]);
 }
 
@@ -904,25 +904,25 @@ static int fsl_edma_probe(struct platfor
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
fsl_edma->muxbase[i] = devm_ioremap_resource(>dev, res);
-   if (IS_ERR(fsl_edma->muxbase[i]))
+   if (IS_ERR(fsl_edma->muxbase[i])) {
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
return PTR_ERR(fsl_edma->muxbase[i]);
+   }
 
sprintf(clkname, "dmamux%d", i);
fsl_edma->muxclk[i] = devm_clk_get(>dev, clkname);
if (IS_ERR(fsl_edma->muxclk[i])) {
dev_err(>dev, "Missing DMAMUX block clock.\n");
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
return PTR_ERR(fsl_edma->muxclk[i]);
}
 
ret = clk_prepare_enable(fsl_edma->muxclk[i]);
-   if (ret) {
-   /* disable only clks which were enabled on error */
-   for (; i >= 0; i--)
-   clk_disable_unprepare(fsl_edma->muxclk[i]);
-
-   dev_err(>dev, "DMAMUX clk block failed.\n");
-   return ret;
-   }
+   if (ret)
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
 
}
 
@@ -976,7 +976,7 @@ static int fsl_edma_probe(struct platfor
if (ret) {
dev_err(>dev,
"Can't register Freescale eDMA engine. (%d)\n", ret);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
return ret;
}
 
@@ -985,7 +985,7 @@ static int fsl_edma_probe(struct platfor
dev_err(>dev,
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
dma_async_device_unregister(_edma->dma_dev);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
return ret;
}
 
@@ -1015,7 +1015,7 @@ static int fsl_edma_remove(struct platfo
fsl_edma_cleanup_vchan(_edma->dma_dev);
of_dma_controller_free(np);
dma_async_device_unregister(_edma->dma_dev);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
 
return 0;
 }




[PATCH 4.9 04/56] dmaengine: fsl-edma: disable clks on all error paths

2018-03-02 Thread Greg Kroah-Hartman
4.9-stable review patch.  If anyone has any objections, please let me know.

--

From: Andreas Platschek 


[ Upstream commit 2610acf46b9ed528ec2cacd717bc9d354e452b73 ]

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 
Signed-off-by: Vinod Koul 
Signed-off-by: Sasha Levin 
Signed-off-by: Greg Kroah-Hartman 
---
 drivers/dma/fsl-edma.c |   28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -863,11 +863,11 @@ static void fsl_edma_irq_exit(
}
 }
 
-static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma)
+static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
 {
int i;
 
-   for (i = 0; i < DMAMUX_NR; i++)
+   for (i = 0; i < nr_clocks; i++)
clk_disable_unprepare(fsl_edma->muxclk[i]);
 }
 
@@ -904,25 +904,25 @@ static int fsl_edma_probe(struct platfor
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
fsl_edma->muxbase[i] = devm_ioremap_resource(>dev, res);
-   if (IS_ERR(fsl_edma->muxbase[i]))
+   if (IS_ERR(fsl_edma->muxbase[i])) {
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
return PTR_ERR(fsl_edma->muxbase[i]);
+   }
 
sprintf(clkname, "dmamux%d", i);
fsl_edma->muxclk[i] = devm_clk_get(>dev, clkname);
if (IS_ERR(fsl_edma->muxclk[i])) {
dev_err(>dev, "Missing DMAMUX block clock.\n");
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
return PTR_ERR(fsl_edma->muxclk[i]);
}
 
ret = clk_prepare_enable(fsl_edma->muxclk[i]);
-   if (ret) {
-   /* disable only clks which were enabled on error */
-   for (; i >= 0; i--)
-   clk_disable_unprepare(fsl_edma->muxclk[i]);
-
-   dev_err(>dev, "DMAMUX clk block failed.\n");
-   return ret;
-   }
+   if (ret)
+   /* on error: disable all previously enabled clks */
+   fsl_disable_clocks(fsl_edma, i);
 
}
 
@@ -976,7 +976,7 @@ static int fsl_edma_probe(struct platfor
if (ret) {
dev_err(>dev,
"Can't register Freescale eDMA engine. (%d)\n", ret);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
return ret;
}
 
@@ -985,7 +985,7 @@ static int fsl_edma_probe(struct platfor
dev_err(>dev,
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
dma_async_device_unregister(_edma->dma_dev);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
return ret;
}
 
@@ -1015,7 +1015,7 @@ static int fsl_edma_remove(struct platfo
fsl_edma_cleanup_vchan(_edma->dma_dev);
of_dma_controller_free(np);
dma_async_device_unregister(_edma->dma_dev);
-   fsl_disable_clocks(fsl_edma);
+   fsl_disable_clocks(fsl_edma, DMAMUX_NR);
 
return 0;
 }