diff options
author | Russell King - ARM Linux <linux@arm.linux.org.uk> | 2012-10-29 17:43:07 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-11-07 15:02:03 -0500 |
commit | ee3298a2b6832bcfeec040dabf19632b704d826a (patch) | |
tree | 4cc47cfa7510783061db8264c63fa9462f5c8eb8 | |
parent | a0d28ba01ebd048b4ba418142b37f5cf80e6d156 (diff) |
mmc: fix sdhci-dove probe/removal
1. Never ever publish a device in the system before it has been setup
to a usable state.
2. Unregister the device _BEFORE_ taking away any resources it may be
using.
3. Don't check clks against NULL.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r-- | drivers/mmc/host/sdhci-dove.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 90140eb03e36..8fd50a211037 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/err.h> | ||
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
23 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
24 | #include <linux/err.h> | 25 | #include <linux/err.h> |
@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev) | |||
84 | struct sdhci_dove_priv *priv; | 85 | struct sdhci_dove_priv *priv; |
85 | int ret; | 86 | int ret; |
86 | 87 | ||
87 | ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); | ||
88 | if (ret) | ||
89 | goto sdhci_dove_register_fail; | ||
90 | |||
91 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), | 88 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), |
92 | GFP_KERNEL); | 89 | GFP_KERNEL); |
93 | if (!priv) { | 90 | if (!priv) { |
94 | dev_err(&pdev->dev, "unable to allocate private data"); | 91 | dev_err(&pdev->dev, "unable to allocate private data"); |
95 | ret = -ENOMEM; | 92 | return -ENOMEM; |
96 | goto sdhci_dove_allocate_fail; | ||
97 | } | 93 | } |
98 | 94 | ||
95 | priv->clk = clk_get(&pdev->dev, NULL); | ||
96 | if (!IS_ERR(priv->clk)) | ||
97 | clk_prepare_enable(priv->clk); | ||
98 | |||
99 | ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); | ||
100 | if (ret) | ||
101 | goto sdhci_dove_register_fail; | ||
102 | |||
99 | host = platform_get_drvdata(pdev); | 103 | host = platform_get_drvdata(pdev); |
100 | pltfm_host = sdhci_priv(host); | 104 | pltfm_host = sdhci_priv(host); |
101 | pltfm_host->priv = priv; | 105 | pltfm_host->priv = priv; |
102 | 106 | ||
103 | priv->clk = clk_get(&pdev->dev, NULL); | ||
104 | if (!IS_ERR(priv->clk)) | ||
105 | clk_prepare_enable(priv->clk); | ||
106 | return 0; | 107 | return 0; |
107 | 108 | ||
108 | sdhci_dove_allocate_fail: | ||
109 | sdhci_pltfm_unregister(pdev); | ||
110 | sdhci_dove_register_fail: | 109 | sdhci_dove_register_fail: |
110 | if (!IS_ERR(priv->clk)) { | ||
111 | clk_disable_unprepare(priv->clk); | ||
112 | clk_put(priv->clk); | ||
113 | } | ||
111 | return ret; | 114 | return ret; |
112 | } | 115 | } |
113 | 116 | ||
@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) | |||
117 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 120 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
118 | struct sdhci_dove_priv *priv = pltfm_host->priv; | 121 | struct sdhci_dove_priv *priv = pltfm_host->priv; |
119 | 122 | ||
120 | if (priv->clk) { | 123 | sdhci_pltfm_unregister(pdev); |
121 | if (!IS_ERR(priv->clk)) { | 124 | |
122 | clk_disable_unprepare(priv->clk); | 125 | if (!IS_ERR(priv->clk)) { |
123 | clk_put(priv->clk); | 126 | clk_disable_unprepare(priv->clk); |
124 | } | 127 | clk_put(priv->clk); |
125 | devm_kfree(&pdev->dev, priv->clk); | ||
126 | } | 128 | } |
127 | return sdhci_pltfm_unregister(pdev); | 129 | return 0; |
128 | } | 130 | } |
129 | 131 | ||
130 | static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { | 132 | static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { |