While fixing audss clock access when domain is gated (commit "clk: samsung: Fix clock disable failure because domain being gated") generic code from clk-gate/divider/mux was taken and modified. This generic code leaks memory allocated for internal structures (struct clk_gate/clk_divider/clk_mux). Fix the leak by using resourced managed allocations. The audss clocks are now attached to platform device. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@xxxxxxxxxxx> --- drivers/clk/samsung/clk-exynos-audss.c | 63 ++++++++++++++-------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 9ec7de866ab4..229d54981825 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -142,8 +142,6 @@ static const struct clk_ops audss_clk_gate_ops = { /* * A simplified copy of clk-gate.c:clk_register_gate() to mimic * clk-gate behavior while using customized ops. - * - * TODO: just like clk-gate it leaks memory for struct clk_gate. */ static struct clk *audss_clk_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, u8 bit_idx) @@ -153,7 +151,7 @@ static struct clk *audss_clk_register_gate(struct device *dev, const char *name, struct clk_init_data init; /* allocate the gate */ - gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); + gate = devm_kzalloc(dev, sizeof(struct clk_gate), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); @@ -172,9 +170,6 @@ static struct clk *audss_clk_register_gate(struct device *dev, const char *name, clk = clk_register(dev, &gate->hw); - if (IS_ERR(clk)) - kfree(gate); - return clk; } @@ -238,7 +233,7 @@ static struct clk *audss_clk_register_divider(struct device *dev, struct clk_init_data init; /* allocate the divider */ - div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); + div = devm_kzalloc(dev, sizeof(struct clk_divider), GFP_KERNEL); if (!div) return ERR_PTR(-ENOMEM); @@ -260,9 +255,6 @@ static struct clk *audss_clk_register_divider(struct device *dev, /* register the clock */ clk = clk_register(dev, &div->hw); - if (IS_ERR(clk)) - kfree(div); - return clk; } @@ -319,7 +311,7 @@ static struct clk *audss_clk_register_mux(struct device *dev, const char *name, u32 mask = BIT(width) - 1; /* allocate the mux */ - mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); + mux = devm_kzalloc(dev, sizeof(struct clk_mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); @@ -340,9 +332,6 @@ static struct clk *audss_clk_register_mux(struct device *dev, const char *name, clk = clk_register(dev, &mux->hw); - if (IS_ERR(clk)) - kfree(mux); - return clk; } @@ -398,9 +387,9 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) } - clk_table[EXYNOS_MOUT_AUDSS] = audss_clk_register_mux(NULL, "mout_audss", - mout_audss_p, ARRAY_SIZE(mout_audss_p), - CLK_SET_RATE_NO_REPARENT, 0, 1); + clk_table[EXYNOS_MOUT_AUDSS] = audss_clk_register_mux(&pdev->dev, + "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), + CLK_SET_RATE_NO_REPARENT, 0, 1); cdclk = devm_clk_get(&pdev->dev, "cdclk"); sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); @@ -408,40 +397,40 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) mout_i2s_p[2] = __clk_get_name(sclk_audio); - clk_table[EXYNOS_MOUT_I2S] = audss_clk_register_mux(NULL, "mout_i2s", - mout_i2s_p, ARRAY_SIZE(mout_i2s_p), - CLK_SET_RATE_NO_REPARENT, 2, 2); + clk_table[EXYNOS_MOUT_I2S] = audss_clk_register_mux(&pdev->dev, + "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), + CLK_SET_RATE_NO_REPARENT, 2, 2); - clk_table[EXYNOS_DOUT_SRP] = audss_clk_register_divider(NULL, "dout_srp", - "mout_audss", 0, 0, 4); + clk_table[EXYNOS_DOUT_SRP] = audss_clk_register_divider(&pdev->dev, + "dout_srp", "mout_audss", 0, 0, 4); - clk_table[EXYNOS_DOUT_AUD_BUS] = audss_clk_register_divider(NULL, + clk_table[EXYNOS_DOUT_AUD_BUS] = audss_clk_register_divider(&pdev->dev, "dout_aud_bus", "dout_srp", 0, 4, 4); - clk_table[EXYNOS_DOUT_I2S] = audss_clk_register_divider(NULL, "dout_i2s", - "mout_i2s", 0, 8, 4); + clk_table[EXYNOS_DOUT_I2S] = audss_clk_register_divider(&pdev->dev, + "dout_i2s", "mout_i2s", 0, 8, 4); - clk_table[EXYNOS_SRP_CLK] = audss_clk_register_gate(NULL, "srp_clk", - "dout_srp", CLK_SET_RATE_PARENT, 0); + clk_table[EXYNOS_SRP_CLK] = audss_clk_register_gate(&pdev->dev, + "srp_clk", "dout_srp", CLK_SET_RATE_PARENT, 0); - clk_table[EXYNOS_I2S_BUS] = audss_clk_register_gate(NULL, "i2s_bus", - "dout_aud_bus", CLK_SET_RATE_PARENT, 2); + clk_table[EXYNOS_I2S_BUS] = audss_clk_register_gate(&pdev->dev, + "i2s_bus", "dout_aud_bus", CLK_SET_RATE_PARENT, 2); - clk_table[EXYNOS_SCLK_I2S] = audss_clk_register_gate(NULL, "sclk_i2s", - "dout_i2s", CLK_SET_RATE_PARENT, 3); + clk_table[EXYNOS_SCLK_I2S] = audss_clk_register_gate(&pdev->dev, + "sclk_i2s", "dout_i2s", CLK_SET_RATE_PARENT, 3); - clk_table[EXYNOS_PCM_BUS] = audss_clk_register_gate(NULL, "pcm_bus", - "sclk_pcm", CLK_SET_RATE_PARENT, 4); + clk_table[EXYNOS_PCM_BUS] = audss_clk_register_gate(&pdev->dev, + "pcm_bus", "sclk_pcm", CLK_SET_RATE_PARENT, 4); sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); - clk_table[EXYNOS_SCLK_PCM] = audss_clk_register_gate(NULL, "sclk_pcm", - sclk_pcm_p, CLK_SET_RATE_PARENT, 5); + clk_table[EXYNOS_SCLK_PCM] = audss_clk_register_gate(&pdev->dev, + "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, 5); if (variant == TYPE_EXYNOS5420) { - clk_table[EXYNOS_ADMA] = audss_clk_register_gate(NULL, "adma", - "dout_srp", CLK_SET_RATE_PARENT, 9); + clk_table[EXYNOS_ADMA] = audss_clk_register_gate(&pdev->dev, + "adma", "dout_srp", CLK_SET_RATE_PARENT, 9); } for (i = 0; i < clk_data.clk_num; i++) { -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html