diff options
author | Vladimir Zapolskiy <vzapolskiy@gmail.com> | 2010-04-06 17:35:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-07 11:38:05 -0400 |
commit | c783a29efcbc90a90ccfec8956c7ff0854301c34 (patch) | |
tree | a2276c69020c6600112371023d401fa40f83168b /drivers/rtc/rtc-mxc.c | |
parent | 8725d5416213a145ccc9c236dbd26830ba409e00 (diff) |
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/rtc-mxc.c')
-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) | |||
384 | struct rtc_device *rtc; | 384 | struct rtc_device *rtc; |
385 | struct rtc_plat_data *pdata = NULL; | 385 | struct rtc_plat_data *pdata = NULL; |
386 | u32 reg; | 386 | u32 reg; |
387 | int ret, rate; | 387 | unsigned long rate; |
388 | int ret; | ||
388 | 389 | ||
389 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 390 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
390 | if (!res) | 391 | if (!res) |
391 | return -ENODEV; | 392 | return -ENODEV; |
392 | 393 | ||
393 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 394 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
394 | if (!pdata) | 395 | if (!pdata) |
395 | return -ENOMEM; | 396 | return -ENOMEM; |
396 | 397 | ||
397 | pdata->ioaddr = ioremap(res->start, resource_size(res)); | 398 | if (!devm_request_mem_region(&pdev->dev, res->start, |
399 | resource_size(res), pdev->name)) | ||
400 | return -EBUSY; | ||
401 | |||
402 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
403 | resource_size(res)); | ||
398 | 404 | ||
399 | clk = clk_get(&pdev->dev, "ckil"); | 405 | clk = clk_get(&pdev->dev, "ckil"); |
400 | if (IS_ERR(clk)) { | 406 | if (IS_ERR(clk)) { |
401 | iounmap(pdata->ioaddr); | ||
402 | ret = PTR_ERR(clk); | 407 | ret = PTR_ERR(clk); |
403 | goto exit_free_pdata; | 408 | goto exit_free_pdata; |
404 | } | 409 | } |
@@ -413,8 +418,7 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
413 | else if (rate == 38400) | 418 | else if (rate == 38400) |
414 | reg = RTC_INPUT_CLK_38400HZ; | 419 | reg = RTC_INPUT_CLK_38400HZ; |
415 | else { | 420 | else { |
416 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", | 421 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); |
417 | clk_get_rate(clk)); | ||
418 | ret = -EINVAL; | 422 | ret = -EINVAL; |
419 | goto exit_free_pdata; | 423 | goto exit_free_pdata; |
420 | } | 424 | } |
@@ -450,8 +454,8 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
450 | pdata->irq = platform_get_irq(pdev, 0); | 454 | pdata->irq = platform_get_irq(pdev, 0); |
451 | 455 | ||
452 | if (pdata->irq >= 0 && | 456 | if (pdata->irq >= 0 && |
453 | request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, | 457 | devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, |
454 | pdev->name, pdev) < 0) { | 458 | IRQF_SHARED, pdev->name, pdev) < 0) { |
455 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 459 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
456 | pdata->irq = -1; | 460 | pdata->irq = -1; |
457 | } | 461 | } |
@@ -459,10 +463,10 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
459 | return 0; | 463 | return 0; |
460 | 464 | ||
461 | exit_put_clk: | 465 | exit_put_clk: |
466 | clk_disable(pdata->clk); | ||
462 | clk_put(pdata->clk); | 467 | clk_put(pdata->clk); |
463 | 468 | ||
464 | exit_free_pdata: | 469 | exit_free_pdata: |
465 | kfree(pdata); | ||
466 | 470 | ||
467 | return ret; | 471 | return ret; |
468 | } | 472 | } |
@@ -473,12 +477,8 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) | |||
473 | 477 | ||
474 | rtc_device_unregister(pdata->rtc); | 478 | rtc_device_unregister(pdata->rtc); |
475 | 479 | ||
476 | if (pdata->irq >= 0) | ||
477 | free_irq(pdata->irq, pdev); | ||
478 | |||
479 | clk_disable(pdata->clk); | 480 | clk_disable(pdata->clk); |
480 | clk_put(pdata->clk); | 481 | clk_put(pdata->clk); |
481 | kfree(pdata); | ||
482 | platform_set_drvdata(pdev, NULL); | 482 | platform_set_drvdata(pdev, NULL); |
483 | 483 | ||
484 | return 0; | 484 | return 0; |