mainline inclusion from mainline-v6.9-rc5 commit 2f7b1d8b5505efb0057cd1ab85fca206063ea4c3 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5DP CVE: CVE-2024-27002
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
mt8183-mfgcfg has a mutual dependency with genpd during the probing stage, which leads to a deadlock in the following call stack:
CPU0: genpd_lock --> clk_prepare_lock genpd_power_off_work_fn() genpd_lock() generic_pm_domain::power_off() clk_unprepare() clk_prepare_lock()
CPU1: clk_prepare_lock --> genpd_lock clk_register() __clk_core_init() clk_prepare_lock() clk_pm_runtime_get() genpd_lock()
Do a runtime PM get at the probe function to make sure clk_register() won't acquire the genpd lock. Instead of only modifying mt8183-mfgcfg, do this on all mediatek clock controller probings because we don't believe this would cause any regression.
Verified on MT8183 and MT8192 Chromebooks.
Fixes: acddfc2c261b ("clk: mediatek: Add MT8183 clock support") Signed-off-by: Pin-yen Lin treapking@chromium.org
Link: https://lore.kernel.org/r/20240312115249.3341654-1-treapking@chromium.org Reviewed-by: AngeloGioacchino Del Regno angelogioacchino.delregno@collabora.com Tested-by: AngeloGioacchino Del Regno angelogioacchino.delregno@collabora.com Signed-off-by: Stephen Boyd sboyd@kernel.org Conflicts: drivers/clk/mediatek/clk-mt8183-mfgcfg.c drivers/clk/mediatek/clk-mtk.c [Yongqiang: adapt for origin probe function in mt8183-mfgcfg] Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- drivers/clk/mediatek/clk-mt8183-mfgcfg.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c index 3a33014eee7f..377dae2e51f8 100644 --- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c +++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c @@ -30,14 +30,28 @@ static int clk_mt8183_mfg_probe(struct platform_device *pdev) { struct clk_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; + int ret;
pm_runtime_enable(&pdev->dev);
+ /* + * Do a pm_runtime_get_sync() to workaround a possible + * deadlock between clk_register() and the genpd framework. + */ + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); + return ret; + } + + clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
mtk_clk_register_gates_with_dev(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data, &pdev->dev);
+ pm_runtime_put(&pdev->dev); + return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); }