aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-02-28 16:32:34 -0500
committerChris Ball <chris@printf.net>2014-03-04 16:28:39 -0500
commitfcdb7c8f5019f77b1f55739a1caf9168d3b455d4 (patch)
tree521af2903ea711ab26d85289d4a4efab48d427d4 /drivers/mmc
parent142dbab951fb9d2281e69f8d7522e6b7e0553ec0 (diff)
mmc: sdhci-spear: fix platform_data usage
sdhci-spear is unsafe should a probe fail or defer, since it overwrites the platform_data with its own driver-private data. It's trivial to fix as SDHCI allows for driver-private data to be appended to its own structure - we just need to arrange the code to allow this. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Chris Ball <chris@printf.net>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-spear.c43
1 files changed, 17 insertions, 26 deletions
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 394714f71b2f..d89267eb14b6 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -105,6 +105,7 @@ static int sdhci_probe(struct platform_device *pdev)
105 struct sdhci_host *host; 105 struct sdhci_host *host;
106 struct resource *iomem; 106 struct resource *iomem;
107 struct spear_sdhci *sdhci; 107 struct spear_sdhci *sdhci;
108 struct device *dev;
108 int ret; 109 int ret;
109 110
110 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 111 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -121,25 +122,28 @@ static int sdhci_probe(struct platform_device *pdev)
121 goto err; 122 goto err;
122 } 123 }
123 124
124 sdhci = devm_kzalloc(&pdev->dev, sizeof(*sdhci), GFP_KERNEL); 125 dev = pdev->dev.parent ? pdev->dev.parent : &pdev->dev;
125 if (!sdhci) { 126 host = sdhci_alloc_host(dev, sizeof(*sdhci));
126 ret = -ENOMEM; 127 if (IS_ERR(host)) {
128 ret = PTR_ERR(host);
127 dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); 129 dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n");
128 goto err; 130 goto err;
129 } 131 }
130 132
133 sdhci = sdhci_priv(host);
134
131 /* clk enable */ 135 /* clk enable */
132 sdhci->clk = devm_clk_get(&pdev->dev, NULL); 136 sdhci->clk = devm_clk_get(&pdev->dev, NULL);
133 if (IS_ERR(sdhci->clk)) { 137 if (IS_ERR(sdhci->clk)) {
134 ret = PTR_ERR(sdhci->clk); 138 ret = PTR_ERR(sdhci->clk);
135 dev_dbg(&pdev->dev, "Error getting clock\n"); 139 dev_dbg(&pdev->dev, "Error getting clock\n");
136 goto err; 140 goto err_host;
137 } 141 }
138 142
139 ret = clk_prepare_enable(sdhci->clk); 143 ret = clk_prepare_enable(sdhci->clk);
140 if (ret) { 144 if (ret) {
141 dev_dbg(&pdev->dev, "Error enabling clock\n"); 145 dev_dbg(&pdev->dev, "Error enabling clock\n");
142 goto err; 146 goto err_host;
143 } 147 }
144 148
145 ret = clk_set_rate(sdhci->clk, 50000000); 149 ret = clk_set_rate(sdhci->clk, 50000000);
@@ -157,19 +161,6 @@ static int sdhci_probe(struct platform_device *pdev)
157 sdhci->data = dev_get_platdata(&pdev->dev); 161 sdhci->data = dev_get_platdata(&pdev->dev);
158 } 162 }
159 163
160 pdev->dev.platform_data = sdhci;
161
162 if (pdev->dev.parent)
163 host = sdhci_alloc_host(pdev->dev.parent, 0);
164 else
165 host = sdhci_alloc_host(&pdev->dev, 0);
166
167 if (IS_ERR(host)) {
168 ret = PTR_ERR(host);
169 dev_dbg(&pdev->dev, "error allocating host\n");
170 goto disable_clk;
171 }
172
173 host->hw_name = "sdhci"; 164 host->hw_name = "sdhci";
174 host->ops = &sdhci_pltfm_ops; 165 host->ops = &sdhci_pltfm_ops;
175 host->irq = platform_get_irq(pdev, 0); 166 host->irq = platform_get_irq(pdev, 0);
@@ -180,13 +171,13 @@ static int sdhci_probe(struct platform_device *pdev)
180 if (!host->ioaddr) { 171 if (!host->ioaddr) {
181 ret = -ENOMEM; 172 ret = -ENOMEM;
182 dev_dbg(&pdev->dev, "failed to remap registers\n"); 173 dev_dbg(&pdev->dev, "failed to remap registers\n");
183 goto free_host; 174 goto disable_clk;
184 } 175 }
185 176
186 ret = sdhci_add_host(host); 177 ret = sdhci_add_host(host);
187 if (ret) { 178 if (ret) {
188 dev_dbg(&pdev->dev, "error adding host\n"); 179 dev_dbg(&pdev->dev, "error adding host\n");
189 goto free_host; 180 goto disable_clk;
190 } 181 }
191 182
192 platform_set_drvdata(pdev, host); 183 platform_set_drvdata(pdev, host);
@@ -257,10 +248,10 @@ static int sdhci_probe(struct platform_device *pdev)
257 248
258set_drvdata: 249set_drvdata:
259 sdhci_remove_host(host, 1); 250 sdhci_remove_host(host, 1);
260free_host:
261 sdhci_free_host(host);
262disable_clk: 251disable_clk:
263 clk_disable_unprepare(sdhci->clk); 252 clk_disable_unprepare(sdhci->clk);
253err_host:
254 sdhci_free_host(host);
264err: 255err:
265 dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); 256 dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret);
266 return ret; 257 return ret;
@@ -269,7 +260,7 @@ err:
269static int sdhci_remove(struct platform_device *pdev) 260static int sdhci_remove(struct platform_device *pdev)
270{ 261{
271 struct sdhci_host *host = platform_get_drvdata(pdev); 262 struct sdhci_host *host = platform_get_drvdata(pdev);
272 struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); 263 struct spear_sdhci *sdhci = sdhci_priv(host);
273 int dead = 0; 264 int dead = 0;
274 u32 scratch; 265 u32 scratch;
275 266
@@ -278,8 +269,8 @@ static int sdhci_remove(struct platform_device *pdev)
278 dead = 1; 269 dead = 1;
279 270
280 sdhci_remove_host(host, dead); 271 sdhci_remove_host(host, dead);
281 sdhci_free_host(host);
282 clk_disable_unprepare(sdhci->clk); 272 clk_disable_unprepare(sdhci->clk);
273 sdhci_free_host(host);
283 274
284 return 0; 275 return 0;
285} 276}
@@ -288,7 +279,7 @@ static int sdhci_remove(struct platform_device *pdev)
288static int sdhci_suspend(struct device *dev) 279static int sdhci_suspend(struct device *dev)
289{ 280{
290 struct sdhci_host *host = dev_get_drvdata(dev); 281 struct sdhci_host *host = dev_get_drvdata(dev);
291 struct spear_sdhci *sdhci = dev_get_platdata(dev); 282 struct spear_sdhci *sdhci = sdhci_priv(host);
292 int ret; 283 int ret;
293 284
294 ret = sdhci_suspend_host(host); 285 ret = sdhci_suspend_host(host);
@@ -301,7 +292,7 @@ static int sdhci_suspend(struct device *dev)
301static int sdhci_resume(struct device *dev) 292static int sdhci_resume(struct device *dev)
302{ 293{
303 struct sdhci_host *host = dev_get_drvdata(dev); 294 struct sdhci_host *host = dev_get_drvdata(dev);
304 struct spear_sdhci *sdhci = dev_get_platdata(dev); 295 struct spear_sdhci *sdhci = sdhci_priv(host);
305 int ret; 296 int ret;
306 297
307 ret = clk_enable(sdhci->clk); 298 ret = clk_enable(sdhci->clk);