Message ID | 20240422113629.1629891-1-alexander.stein@ew.tq-group.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3,1/1] i2c: lpi2c: Avoid calling clk_get_rate during transfer | expand |
Hello Alexander, On Mon, Apr 22, 2024 at 01:36:29PM +0200, Alexander Stein wrote: > The dependency from v2 has already been merged in commit b0cde62e4c548 > ("clk: Add a devm variant of clk_rate_exclusive_get()"). Note that you might also need 7f1dd39aedfccf60772328c5b88d56dbd39954c3 which is part of v6.9-rc5. Best regards Uwe
Hi Uwe, On Mon, Apr 22, 2024 at 05:42:20PM +0200, Uwe Kleine-König wrote: > On Mon, Apr 22, 2024 at 01:36:29PM +0200, Alexander Stein wrote: > > The dependency from v2 has already been merged in commit b0cde62e4c548 > > ("clk: Add a devm variant of clk_rate_exclusive_get()"). > > Note that you might also need 7f1dd39aedfccf60772328c5b88d56dbd39954c3 > which is part of v6.9-rc5. it's fine... I have rebased all my branches on top of v6.9-rc5. Thanks! Andi
Hi On Mon, 22 Apr 2024 13:36:29 +0200, Alexander Stein wrote: > Instead of repeatedly calling clk_get_rate for each transfer, lock > the clock rate and cache the value. > A deadlock has been observed while adding tlv320aic32x4 audio codec to > the system. When this clock provider adds its clock, the clk mutex is > locked already, it needs to access i2c, which in return needs the mutex > for clk_get_rate as well. > > [...] Applied to i2c/i2c-host on git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git Thank you, Andi Patches applied =============== [1/1] i2c: lpi2c: Avoid calling clk_get_rate during transfer commit: 7ec84d4d55504710a828047d079cb22f12d4133f
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 6d72e4e126dde..36e8f6196a87b 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -99,6 +99,7 @@ struct lpi2c_imx_struct { __u8 *rx_buf; __u8 *tx_buf; struct completion complete; + unsigned long rate_per; unsigned int msglen; unsigned int delivered; unsigned int block_data; @@ -212,9 +213,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) lpi2c_imx_set_mode(lpi2c_imx); - clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk); - if (!clk_rate) - return -EINVAL; + clk_rate = lpi2c_imx->rate_per; if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST) filt = 0; @@ -611,6 +610,20 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (ret) return ret; + /* + * Lock the parent clock rate to avoid getting parent clock upon + * each transfer + */ + ret = devm_clk_rate_exclusive_get(&pdev->dev, lpi2c_imx->clks[0].clk); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "can't lock I2C peripheral clock rate\n"); + + lpi2c_imx->rate_per = clk_get_rate(lpi2c_imx->clks[0].clk); + if (!lpi2c_imx->rate_per) + return dev_err_probe(&pdev->dev, -EINVAL, + "can't get I2C peripheral clock rate\n"); + pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_get_noresume(&pdev->dev);