diff options
author | Vladimir Zapolskiy <vzapolskiy@gmail.com> | 2010-04-06 23:35:07 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-07 17:38:05 +0200 |
commit | c783a29efcbc90a90ccfec8956c7ff0854301c34 (patch) | |
tree | a2276c69020c6600112371023d401fa40f83168b /drivers/rtc | |
parent | memcg: fix race in file_mapped accounting (diff) | |
download | linux-c783a29efcbc90a90ccfec8956c7ff0854301c34.tar.xz linux-c783a29efcbc90a90ccfec8956c7ff0854301c34.zip |
rtc-mxc: multiple fixes in rtc-mxc probe method
On exit paths in mxc_rtc_probe() method some resources are not freed
correctly.
This patch fixes:
* unrequested memory region containing imx RTC registers
* iounmap() isn't called on exit_free_pdata branch
* clock get rate is called for freed clock source
* clock isn't disabled on exit_put_clk branch
To simplify the fix managed device resources are used.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Vladimir Zapolskiy <vzapolskiy@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-mxc.c | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index c77f6f72f950..d71fe61db1d6 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -384,21 +384,26 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) struct rtc_device *rtc; struct rtc_plat_data *pdata = NULL; u32 reg; - int ret, rate; + unsigned long rate; + int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - pdata->ioaddr = ioremap(res->start, resource_size(res)); + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), pdev->name)) + return -EBUSY; + + pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); clk = clk_get(&pdev->dev, "ckil"); if (IS_ERR(clk)) { - iounmap(pdata->ioaddr); ret = PTR_ERR(clk); goto exit_free_pdata; } @@ -413,8 +418,7 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) else if (rate == 38400) reg = RTC_INPUT_CLK_38400HZ; else { - dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", - clk_get_rate(clk)); + dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); ret = -EINVAL; goto exit_free_pdata; } @@ -450,8 +454,8 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) pdata->irq = platform_get_irq(pdev, 0); if (pdata->irq >= 0 && - request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, - pdev->name, pdev) < 0) { + devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, + IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = -1; } @@ -459,10 +463,10 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) return 0; exit_put_clk: + clk_disable(pdata->clk); clk_put(pdata->clk); exit_free_pdata: - kfree(pdata); return ret; } @@ -473,12 +477,8 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) rtc_device_unregister(pdata->rtc); - if (pdata->irq >= 0) - free_irq(pdata->irq, pdev); - clk_disable(pdata->clk); clk_put(pdata->clk); - kfree(pdata); platform_set_drvdata(pdev, NULL); return 0; |