Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c783a29e authored by Vladimir Zapolskiy's avatar Vladimir Zapolskiy Committed by Linus Torvalds
Browse files

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: default avatarVladimir Zapolskiy <vzapolskiy@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Daniel Mack <daniel@caiaq.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8725d541
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -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;