mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 09:34:17 +00:00
watchdog: fix error in probe() of s3c2410_wdt (reset at booting)
Probe function of s3c2410 watchdog calls request_irq before initializing required value (wdt_count). This incurs resetting watchdog counter value and watchdog-reboot during booting up. This patch addresses such an issue by calling request_irq later. Error handling in probe function and calling oder in remove function are also revised accordingly. Reported-by: Chanwoo Park <cw00.choi@samsung.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
parent
97d2a10d58
commit
78d3e00bb0
@ -312,18 +312,26 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|||||||
dev = &pdev->dev;
|
dev = &pdev->dev;
|
||||||
wdt_dev = &pdev->dev;
|
wdt_dev = &pdev->dev;
|
||||||
|
|
||||||
/* get the memory region for the watchdog timer */
|
|
||||||
|
|
||||||
wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (wdt_mem == NULL) {
|
if (wdt_mem == NULL) {
|
||||||
dev_err(dev, "no memory resource specified\n");
|
dev_err(dev, "no memory resource specified\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||||
|
if (wdt_irq == NULL) {
|
||||||
|
dev_err(dev, "no irq resource specified\n");
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the memory region for the watchdog timer */
|
||||||
|
|
||||||
size = resource_size(wdt_mem);
|
size = resource_size(wdt_mem);
|
||||||
if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
||||||
dev_err(dev, "failed to get memory region\n");
|
dev_err(dev, "failed to get memory region\n");
|
||||||
return -EBUSY;
|
ret = -EBUSY;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
wdt_base = ioremap(wdt_mem->start, size);
|
wdt_base = ioremap(wdt_mem->start, size);
|
||||||
@ -335,29 +343,17 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
DBG("probe: mapped wdt_base=%p\n", wdt_base);
|
DBG("probe: mapped wdt_base=%p\n", wdt_base);
|
||||||
|
|
||||||
wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
||||||
if (wdt_irq == NULL) {
|
|
||||||
dev_err(dev, "no irq resource specified\n");
|
|
||||||
ret = -ENOENT;
|
|
||||||
goto err_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
|
|
||||||
if (ret != 0) {
|
|
||||||
dev_err(dev, "failed to install irq (%d)\n", ret);
|
|
||||||
goto err_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
wdt_clock = clk_get(&pdev->dev, "watchdog");
|
wdt_clock = clk_get(&pdev->dev, "watchdog");
|
||||||
if (IS_ERR(wdt_clock)) {
|
if (IS_ERR(wdt_clock)) {
|
||||||
dev_err(dev, "failed to find watchdog clock source\n");
|
dev_err(dev, "failed to find watchdog clock source\n");
|
||||||
ret = PTR_ERR(wdt_clock);
|
ret = PTR_ERR(wdt_clock);
|
||||||
goto err_irq;
|
goto err_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
clk_enable(wdt_clock);
|
clk_enable(wdt_clock);
|
||||||
|
|
||||||
if (s3c2410wdt_cpufreq_register() < 0) {
|
ret = s3c2410wdt_cpufreq_register();
|
||||||
|
if (ret < 0) {
|
||||||
printk(KERN_ERR PFX "failed to register cpufreq\n");
|
printk(KERN_ERR PFX "failed to register cpufreq\n");
|
||||||
goto err_clk;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
@ -378,12 +374,18 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|||||||
"cannot start\n");
|
"cannot start\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
|
||||||
|
if (ret != 0) {
|
||||||
|
dev_err(dev, "failed to install irq (%d)\n", ret);
|
||||||
|
goto err_cpufreq;
|
||||||
|
}
|
||||||
|
|
||||||
watchdog_set_nowayout(&s3c2410_wdd, nowayout);
|
watchdog_set_nowayout(&s3c2410_wdd, nowayout);
|
||||||
|
|
||||||
ret = watchdog_register_device(&s3c2410_wdd);
|
ret = watchdog_register_device(&s3c2410_wdd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "cannot register watchdog (%d)\n", ret);
|
dev_err(dev, "cannot register watchdog (%d)\n", ret);
|
||||||
goto err_cpufreq;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmr_atboot && started == 0) {
|
if (tmr_atboot && started == 0) {
|
||||||
@ -408,23 +410,26 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_irq:
|
||||||
|
free_irq(wdt_irq->start, pdev);
|
||||||
|
|
||||||
err_cpufreq:
|
err_cpufreq:
|
||||||
s3c2410wdt_cpufreq_deregister();
|
s3c2410wdt_cpufreq_deregister();
|
||||||
|
|
||||||
err_clk:
|
err_clk:
|
||||||
clk_disable(wdt_clock);
|
clk_disable(wdt_clock);
|
||||||
clk_put(wdt_clock);
|
clk_put(wdt_clock);
|
||||||
|
wdt_clock = NULL;
|
||||||
err_irq:
|
|
||||||
free_irq(wdt_irq->start, pdev);
|
|
||||||
|
|
||||||
err_map:
|
err_map:
|
||||||
iounmap(wdt_base);
|
iounmap(wdt_base);
|
||||||
|
|
||||||
err_req:
|
err_req:
|
||||||
release_mem_region(wdt_mem->start, size);
|
release_mem_region(wdt_mem->start, size);
|
||||||
wdt_mem = NULL;
|
|
||||||
|
|
||||||
|
err:
|
||||||
|
wdt_irq = NULL;
|
||||||
|
wdt_mem = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,18 +437,18 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
|
|||||||
{
|
{
|
||||||
watchdog_unregister_device(&s3c2410_wdd);
|
watchdog_unregister_device(&s3c2410_wdd);
|
||||||
|
|
||||||
|
free_irq(wdt_irq->start, dev);
|
||||||
|
|
||||||
s3c2410wdt_cpufreq_deregister();
|
s3c2410wdt_cpufreq_deregister();
|
||||||
|
|
||||||
clk_disable(wdt_clock);
|
clk_disable(wdt_clock);
|
||||||
clk_put(wdt_clock);
|
clk_put(wdt_clock);
|
||||||
wdt_clock = NULL;
|
wdt_clock = NULL;
|
||||||
|
|
||||||
free_irq(wdt_irq->start, dev);
|
|
||||||
wdt_irq = NULL;
|
|
||||||
|
|
||||||
iounmap(wdt_base);
|
iounmap(wdt_base);
|
||||||
|
|
||||||
release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
||||||
|
wdt_irq = NULL;
|
||||||
wdt_mem = NULL;
|
wdt_mem = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user