Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Vladimir Zapolskiy and committed by
Linus Torvalds
c783a29e 8725d541

+13 -13
+13 -13
drivers/rtc/rtc-mxc.c
··· 384 384 struct rtc_device *rtc; 385 385 struct rtc_plat_data *pdata = NULL; 386 386 u32 reg; 387 - int ret, rate; 387 + unsigned long rate; 388 + int ret; 388 389 389 390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 390 391 if (!res) 391 392 return -ENODEV; 392 393 393 - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 394 + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 394 395 if (!pdata) 395 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 405 clk = clk_get(&pdev->dev, "ckil"); 400 406 if (IS_ERR(clk)) { 401 - iounmap(pdata->ioaddr); 402 407 ret = PTR_ERR(clk); 403 408 goto exit_free_pdata; 404 409 } ··· 418 413 else if (rate == 38400) 419 414 reg = RTC_INPUT_CLK_38400HZ; 420 415 else { 421 - dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", 422 - clk_get_rate(clk)); 416 + dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); 423 417 ret = -EINVAL; 424 418 goto exit_free_pdata; 425 419 } ··· 454 450 pdata->irq = platform_get_irq(pdev, 0); 455 451 456 452 if (pdata->irq >= 0 && 457 - request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, 458 - pdev->name, pdev) < 0) { 453 + devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, 454 + IRQF_SHARED, pdev->name, pdev) < 0) { 459 455 dev_warn(&pdev->dev, "interrupt not available.\n"); 460 456 pdata->irq = -1; 461 457 } ··· 463 459 return 0; 464 460 465 461 exit_put_clk: 462 + clk_disable(pdata->clk); 466 463 clk_put(pdata->clk); 467 464 468 465 exit_free_pdata: 469 - kfree(pdata); 470 466 471 467 return ret; 472 468 } ··· 477 473 478 474 rtc_device_unregister(pdata->rtc); 479 475 480 - if (pdata->irq >= 0) 481 - free_irq(pdata->irq, pdev); 482 - 483 476 clk_disable(pdata->clk); 484 477 clk_put(pdata->clk); 485 - kfree(pdata); 486 478 platform_set_drvdata(pdev, NULL); 487 479 488 480 return 0;