[PATCH] drm/sun4i: frontend: fix clock leak on reset failure in runtime resume
Jiawen Liu <[email protected]>
| Newsgroups | dev.linux.lists.linux-sunxi,org.freedesktop.lists.dri-devel,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
sun4i_frontend_runtime_resume() can fail after enabling the bus, mod, and ram clocks if reset_control_reset() returns an error. The function previously returned without disabling those clocks, leaking them and leaving the hardware in an inconsistent state. Check the return value of each clk_prepare_enable() call and unwind the clocks that were successfully enabled on any subsequent failure, including reset failure. Signed-off-by: jiawen <[email protected]> --- diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -647,14 +647,22 @@ clk_set_rate(frontend->mod_clk, 300000000); - clk_prepare_enable(frontend->bus_clk); - clk_prepare_enable(frontend->mod_clk); - clk_prepare_enable(frontend->ram_clk); + ret = clk_prepare_enable(frontend->bus_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(frontend->mod_clk); + if (ret) + goto err_disable_bus_clk; + + ret = clk_prepare_enable(frontend->ram_clk); + if (ret) + goto err_disable_mod_clk; ret = reset_control_reset(frontend->reset); if (ret) { dev_err(dev, "Couldn't reset our device\n"); - return ret; + goto err_disable_ram_clk; } regmap_update_bits(frontend->regs, SUN4I_FRONTEND_EN_REG, @@ -664,6 +672,14 @@ sun4i_frontend_scaler_init(frontend); return 0; + +err_disable_ram_clk: + clk_disable_unprepare(frontend->ram_clk); +err_disable_mod_clk: + clk_disable_unprepare(frontend->mod_clk); +err_disable_bus_clk: + clk_disable_unprepare(frontend->bus_clk); + return ret; } static int sun4i_frontend_runtime_suspend(struct device *dev)