Commit fcdb7c8f authored by Russell King's avatar Russell King Committed by Chris Ball

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 142dbab9
...@@ -105,6 +105,7 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -105,6 +105,7 @@ static int sdhci_probe(struct platform_device *pdev)
struct sdhci_host *host; struct sdhci_host *host;
struct resource *iomem; struct resource *iomem;
struct spear_sdhci *sdhci; struct spear_sdhci *sdhci;
struct device *dev;
int ret; int ret;
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -121,25 +122,28 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -121,25 +122,28 @@ static int sdhci_probe(struct platform_device *pdev)
goto err; goto err;
} }
sdhci = devm_kzalloc(&pdev->dev, sizeof(*sdhci), GFP_KERNEL); dev = pdev->dev.parent ? pdev->dev.parent : &pdev->dev;
if (!sdhci) { host = sdhci_alloc_host(dev, sizeof(*sdhci));
ret = -ENOMEM; if (IS_ERR(host)) {
ret = PTR_ERR(host);
dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n");
goto err; goto err;
} }
sdhci = sdhci_priv(host);
/* clk enable */ /* clk enable */
sdhci->clk = devm_clk_get(&pdev->dev, NULL); sdhci->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(sdhci->clk)) { if (IS_ERR(sdhci->clk)) {
ret = PTR_ERR(sdhci->clk); ret = PTR_ERR(sdhci->clk);
dev_dbg(&pdev->dev, "Error getting clock\n"); dev_dbg(&pdev->dev, "Error getting clock\n");
goto err; goto err_host;
} }
ret = clk_prepare_enable(sdhci->clk); ret = clk_prepare_enable(sdhci->clk);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, "Error enabling clock\n"); dev_dbg(&pdev->dev, "Error enabling clock\n");
goto err; goto err_host;
} }
ret = clk_set_rate(sdhci->clk, 50000000); ret = clk_set_rate(sdhci->clk, 50000000);
...@@ -157,19 +161,6 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -157,19 +161,6 @@ static int sdhci_probe(struct platform_device *pdev)
sdhci->data = dev_get_platdata(&pdev->dev); sdhci->data = dev_get_platdata(&pdev->dev);
} }
pdev->dev.platform_data = sdhci;
if (pdev->dev.parent)
host = sdhci_alloc_host(pdev->dev.parent, 0);
else
host = sdhci_alloc_host(&pdev->dev, 0);
if (IS_ERR(host)) {
ret = PTR_ERR(host);
dev_dbg(&pdev->dev, "error allocating host\n");
goto disable_clk;
}
host->hw_name = "sdhci"; host->hw_name = "sdhci";
host->ops = &sdhci_pltfm_ops; host->ops = &sdhci_pltfm_ops;
host->irq = platform_get_irq(pdev, 0); host->irq = platform_get_irq(pdev, 0);
...@@ -180,13 +171,13 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -180,13 +171,13 @@ static int sdhci_probe(struct platform_device *pdev)
if (!host->ioaddr) { if (!host->ioaddr) {
ret = -ENOMEM; ret = -ENOMEM;
dev_dbg(&pdev->dev, "failed to remap registers\n"); dev_dbg(&pdev->dev, "failed to remap registers\n");
goto free_host; goto disable_clk;
} }
ret = sdhci_add_host(host); ret = sdhci_add_host(host);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, "error adding host\n"); dev_dbg(&pdev->dev, "error adding host\n");
goto free_host; goto disable_clk;
} }
platform_set_drvdata(pdev, host); platform_set_drvdata(pdev, host);
...@@ -257,10 +248,10 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -257,10 +248,10 @@ static int sdhci_probe(struct platform_device *pdev)
set_drvdata: set_drvdata:
sdhci_remove_host(host, 1); sdhci_remove_host(host, 1);
free_host:
sdhci_free_host(host);
disable_clk: disable_clk:
clk_disable_unprepare(sdhci->clk); clk_disable_unprepare(sdhci->clk);
err_host:
sdhci_free_host(host);
err: err:
dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret);
return ret; return ret;
...@@ -269,7 +260,7 @@ static int sdhci_probe(struct platform_device *pdev) ...@@ -269,7 +260,7 @@ static int sdhci_probe(struct platform_device *pdev)
static int sdhci_remove(struct platform_device *pdev) static int sdhci_remove(struct platform_device *pdev)
{ {
struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_host *host = platform_get_drvdata(pdev);
struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); struct spear_sdhci *sdhci = sdhci_priv(host);
int dead = 0; int dead = 0;
u32 scratch; u32 scratch;
...@@ -278,8 +269,8 @@ static int sdhci_remove(struct platform_device *pdev) ...@@ -278,8 +269,8 @@ static int sdhci_remove(struct platform_device *pdev)
dead = 1; dead = 1;
sdhci_remove_host(host, dead); sdhci_remove_host(host, dead);
sdhci_free_host(host);
clk_disable_unprepare(sdhci->clk); clk_disable_unprepare(sdhci->clk);
sdhci_free_host(host);
return 0; return 0;
} }
...@@ -288,7 +279,7 @@ static int sdhci_remove(struct platform_device *pdev) ...@@ -288,7 +279,7 @@ static int sdhci_remove(struct platform_device *pdev)
static int sdhci_suspend(struct device *dev) static int sdhci_suspend(struct device *dev)
{ {
struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_host *host = dev_get_drvdata(dev);
struct spear_sdhci *sdhci = dev_get_platdata(dev); struct spear_sdhci *sdhci = sdhci_priv(host);
int ret; int ret;
ret = sdhci_suspend_host(host); ret = sdhci_suspend_host(host);
...@@ -301,7 +292,7 @@ static int sdhci_suspend(struct device *dev) ...@@ -301,7 +292,7 @@ static int sdhci_suspend(struct device *dev)
static int sdhci_resume(struct device *dev) static int sdhci_resume(struct device *dev)
{ {
struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_host *host = dev_get_drvdata(dev);
struct spear_sdhci *sdhci = dev_get_platdata(dev); struct spear_sdhci *sdhci = sdhci_priv(host);
int ret; int ret;
ret = clk_enable(sdhci->clk); ret = clk_enable(sdhci->clk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment