From a477626332800942f463d76aa48db0c47f1dfd18 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Wed, 24 Jun 2026 13:52:37 +0800 Subject: [PATCH] i2c: qup: Propagate clock enable failures The QUP I2C driver treats the core and iface clocks as required resources, but qup_i2c_enable_clocks() ignores clk_prepare_enable() failures. Probe can then continue to register the I2C adapter, and runtime/system resume can return success, even when a required clock transition failed. Make the helper return an error, unwind a partially enabled clock, and propagate failures from probe and resume paths. Signed-off-by: Pengpeng Hou Reviewed-by: Konrad Dybcio Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20260624055237.29977-1-pengpeng@iscas.ac.cn --- drivers/i2c/busses/i2c-qup.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index a0e076fc5f36..ee7915ee2ba2 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1657,10 +1657,21 @@ static const struct i2c_adapter_quirks qup_i2c_quirks_v2 = { .flags = I2C_AQ_NO_ZERO_LEN, }; -static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup) +static int qup_i2c_enable_clocks(struct qup_i2c_dev *qup) { - clk_prepare_enable(qup->clk); - clk_prepare_enable(qup->pclk); + int ret; + + ret = clk_prepare_enable(qup->clk); + if (ret) + return ret; + + ret = clk_prepare_enable(qup->pclk); + if (ret) { + clk_disable_unprepare(qup->clk); + return ret; + } + + return 0; } static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) @@ -1823,7 +1834,9 @@ nodma: ret = PTR_ERR(qup->pclk); goto fail_dma; } - qup_i2c_enable_clocks(qup); + ret = qup_i2c_enable_clocks(qup); + if (ret) + goto fail_dma; src_clk_freq = clk_get_rate(qup->clk); } qup->src_clk_freq = src_clk_freq; @@ -1975,8 +1988,7 @@ static int qup_i2c_pm_resume_runtime(struct device *device) struct qup_i2c_dev *qup = dev_get_drvdata(device); dev_dbg(device, "pm_runtime: resuming...\n"); - qup_i2c_enable_clocks(qup); - return 0; + return qup_i2c_enable_clocks(qup); } static int qup_i2c_suspend(struct device *device) @@ -1988,7 +2000,12 @@ static int qup_i2c_suspend(struct device *device) static int qup_i2c_resume(struct device *device) { - qup_i2c_pm_resume_runtime(device); + int ret; + + ret = qup_i2c_pm_resume_runtime(device); + if (ret) + return ret; + pm_request_autosuspend(device); return 0; }