Commit 8a4f84cb authored by Samuel Holland's avatar Samuel Holland Committed by Lin Yujun
Browse files

clk: sunxi-ng: Unregister clocks/resets when unbinding

stable inclusion
from stable-v5.15.5
commit b5dd513daa70ee8f6d281a20bd28485ee9bb7db2
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9FNFT
CVE: CVE-2021-47205

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b5dd513daa70ee8f6d281a20bd28485ee9bb7db2



---------------------------

Currently, unbinding a CCU driver unmaps the device's MMIO region, while
leaving its clocks/resets and their providers registered. This can cause
a page fault later when some clock operation tries to perform MMIO. Fix
this by separating the CCU initialization from the memory allocation,
and then using a devres callback to unregister the clocks and resets.

This also fixes a memory leak of the `struct ccu_reset`, and uses the
correct owner (the specific platform driver) for the clocks and resets.

Early OF clock providers are never unregistered, and limited error
handling is possible, so they are mostly unchanged. The error reporting
is made more consistent by moving the message inside of_sunxi_ccu_probe.

Signed-off-by: default avatarSamuel Holland <samuel@sholland.org>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20210901050526.45673-2-samuel@sholland.org


Conflicts:
	drivers/clk/sunxi-ng/ccu-sun50i-h6.c
	drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
	drivers/clk/sunxi-ng/ccu-sun50i-h616.c
[bfc78b46284 ("[Backport] clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change")
lead drivers/clk/sunxi-ng/ccu-sun50i-h6.c context conflicts
47e4dc4e ("clk: sunxi-ng: v3s: fix incorrect postdivider on pll-audio")
lead drivers/clk/sunxi-ng/ccu-sun8i-v3s.c context conflicts
88dde5e2 ("clk: sunxi-ng: Add support for the Allwinner H616 CCU")
Introduced drivers/clk/sunxi-ng/ccu-sun50i-h616.c but it is not backport to 5.10]
Signed-off-by: default avatarLin Yujun <linyujun809@huawei.com>
parent 2e754c9d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node,
	val &= ~GENMASK(7, 6);
	writel(val | (2 << 6), reg + SUN4I_AHB_REG);

	sunxi_ccu_probe(node, reg, desc);
	of_sunxi_ccu_probe(node, reg, desc);
}

static void __init sun4i_a10_ccu_setup(struct device_node *node)
+1 −1
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev)
	if (IS_ERR(reg))
		return PTR_ERR(reg);

	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc);
	return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc);
}

static const struct of_device_id sun50i_a100_r_ccu_ids[] = {
+1 −1
Original line number Diff line number Diff line
@@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev)
		writel(val, reg + sun50i_a100_usb2_clk_regs[i]);
	}

	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc);
	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc);
	if (ret)
		return ret;

+1 −1
Original line number Diff line number Diff line
@@ -955,7 +955,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)

	writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);

	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc);
	if (ret)
		return ret;

+1 −1
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
		return;
	}

	sunxi_ccu_probe(node, reg, desc);
	of_sunxi_ccu_probe(node, reg, desc);
}

static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
Loading