diff options
author | Nicolin Chen <nicoleotsuka@gmail.com> | 2017-10-12 16:09:59 -0700 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-11-01 15:00:06 +0100 |
commit | 1752c9ee23fb20e5bfdbedf677e91f927f2b8d80 (patch) | |
tree | 5cc03b8cc0bc03f5bedee788468b8a34be2792f5 | |
parent | 54eff2264d3e9fd7e3987de1d7eba1d3581c631e (diff) | |
download | linux-stable-1752c9ee23fb20e5bfdbedf677e91f927f2b8d80.tar.gz linux-stable-1752c9ee23fb20e5bfdbedf677e91f927f2b8d80.tar.bz2 linux-stable-1752c9ee23fb20e5bfdbedf677e91f927f2b8d80.zip |
clk: tegra: dfll: Fix drvdata overwriting issue
Both tegra124-dfll and clk-dfll are using platform_set_drvdata
to set drvdata of the exact same pdev while they use different
pointers for the drvdata. Once the drvdata has been overwritten
by tegra124-dfll, clk-dfll will never get its td pointer as it
expects.
Since tegra124-dfll merely needs its soc pointer in its remove
function, this patch fixes the bug by removing the overwriting
in the tegra124-dfll file and letting the tegra_dfll_unregister
return an soc pointer for it.
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
Acked-By: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/clk/tegra/clk-dfll.c | 10 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-dfll.h | 2 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 12 |
3 files changed, 11 insertions, 13 deletions
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 2c44aeb0b97c..0a7deee74eea 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -1728,10 +1728,10 @@ EXPORT_SYMBOL(tegra_dfll_register); * @pdev: DFLL platform_device * * * Unbind this driver from the DFLL hardware device represented by - * @pdev. The DFLL must be disabled for this to succeed. Returns 0 - * upon success or -EBUSY if the DFLL is still active. + * @pdev. The DFLL must be disabled for this to succeed. Returns a + * soc pointer upon success or -EBUSY if the DFLL is still active. */ -int tegra_dfll_unregister(struct platform_device *pdev) +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev) { struct tegra_dfll *td = platform_get_drvdata(pdev); @@ -1739,7 +1739,7 @@ int tegra_dfll_unregister(struct platform_device *pdev) if (td->mode != DFLL_DISABLED) { dev_err(&pdev->dev, "must disable DFLL before removing driver\n"); - return -EBUSY; + return ERR_PTR(-EBUSY); } debugfs_remove_recursive(td->debugfs_dir); @@ -1753,6 +1753,6 @@ int tegra_dfll_unregister(struct platform_device *pdev) reset_control_assert(td->dvco_rst); - return 0; + return td->soc; } EXPORT_SYMBOL(tegra_dfll_unregister); diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index ed2ad888268f..83352c8078f2 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h @@ -43,7 +43,7 @@ struct tegra_dfll_soc_data { int tegra_dfll_register(struct platform_device *pdev, struct tegra_dfll_soc_data *soc); -int tegra_dfll_unregister(struct platform_device *pdev); +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev); int tegra_dfll_runtime_suspend(struct device *dev); int tegra_dfll_runtime_resume(struct device *dev); diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index ad1c1cc829cb..269d3595758b 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -125,19 +125,17 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) return err; } - platform_set_drvdata(pdev, soc); - return 0; } static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) { - struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev); - int err; + struct tegra_dfll_soc_data *soc; - err = tegra_dfll_unregister(pdev); - if (err < 0) - dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err); + soc = tegra_dfll_unregister(pdev); + if (IS_ERR(soc)) + dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n", + PTR_ERR(soc)); tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); |