Commit 5b68790c authored by Ben Dooks's avatar Ben Dooks Committed by Jean Delvare

i2c-s3c2410: Fix bug in releasing driver

When compiled as a module, the i2c-s3c2410 driver does not
free either the IRQ or the i2c adapter it attached to the system.

As part of this fix, move to the usual kernel style
of freeing items as part of the probe error path
making the remove process easier.
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent e00a8cdf
...@@ -745,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) ...@@ -745,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
return 0; return 0;
} }
static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
{
if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
clk_disable(i2c->clk);
clk_put(i2c->clk);
i2c->clk = NULL;
}
if (i2c->regs != NULL) {
iounmap(i2c->regs);
i2c->regs = NULL;
}
if (i2c->ioarea != NULL) {
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
i2c->ioarea = NULL;
}
}
/* s3c24xx_i2c_probe /* s3c24xx_i2c_probe
* *
* called by the bus driver when a suitable device is found * called by the bus driver when a suitable device is found
...@@ -783,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -783,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c->clk)) { if (IS_ERR(i2c->clk)) {
dev_err(&pdev->dev, "cannot get clock\n"); dev_err(&pdev->dev, "cannot get clock\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_noclk;
} }
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
...@@ -796,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -796,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (res == NULL) { if (res == NULL) {
dev_err(&pdev->dev, "cannot find IO resource\n"); dev_err(&pdev->dev, "cannot find IO resource\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_clk;
} }
i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
...@@ -805,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -805,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (i2c->ioarea == NULL) { if (i2c->ioarea == NULL) {
dev_err(&pdev->dev, "cannot request IO\n"); dev_err(&pdev->dev, "cannot request IO\n");
ret = -ENXIO; ret = -ENXIO;
goto out; goto err_clk;
} }
i2c->regs = ioremap(res->start, (res->end-res->start)+1); i2c->regs = ioremap(res->start, (res->end-res->start)+1);
...@@ -813,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -813,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (i2c->regs == NULL) { if (i2c->regs == NULL) {
dev_err(&pdev->dev, "cannot map IO\n"); dev_err(&pdev->dev, "cannot map IO\n");
ret = -ENXIO; ret = -ENXIO;
goto out; goto err_ioarea;
} }
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
...@@ -827,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -827,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
ret = s3c24xx_i2c_init(i2c); ret = s3c24xx_i2c_init(i2c);
if (ret != 0) if (ret != 0)
goto out; goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to /* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending * ensure no current IRQs pending
...@@ -837,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -837,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (res == NULL) { if (res == NULL) {
dev_err(&pdev->dev, "cannot find IRQ\n"); dev_err(&pdev->dev, "cannot find IRQ\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_iomap;
} }
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
...@@ -845,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -845,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ\n"); dev_err(&pdev->dev, "cannot claim IRQ\n");
goto out; goto err_iomap;
} }
i2c->irq = res; i2c->irq = res;
...@@ -855,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -855,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n"); dev_err(&pdev->dev, "failed to add bus to i2c core\n");
goto out; goto err_irq;
} }
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
return 0;
out: err_irq:
if (ret < 0) free_irq(i2c->irq->start, i2c);
s3c24xx_i2c_free(i2c);
err_iomap:
iounmap(i2c->regs);
err_ioarea:
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
err_clk:
clk_disable(i2c->clk);
clk_put(i2c->clk);
err_noclk:
return ret; return ret;
} }
...@@ -878,10 +870,16 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) ...@@ -878,10 +870,16 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
{ {
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
if (i2c != NULL) { i2c_del_adapter(&i2c->adap);
s3c24xx_i2c_free(i2c); free_irq(i2c->irq->start, i2c);
platform_set_drvdata(pdev, NULL);
} clk_disable(i2c->clk);
clk_put(i2c->clk);
iounmap(i2c->regs);
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
return 0; return 0;
} }
......
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