watchdog: fix error in probe() of s3c2410_wdt (reset at booting)
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Fri, 13 Jan 2012 05:14:23 +0000 (14:14 +0900)
committerWim Van Sebroeck <wim@iguana.be>
Tue, 28 Feb 2012 16:08:42 +0000 (17:08 +0100)
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>
drivers/watchdog/s3c2410_wdt.c

index 4bc3744e14e4bf54f80a84585d3626d64635ba21..404172f02c9bea73f2be2b523c979693e69679d1 100644 (file)
@@ -312,18 +312,26 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
        dev = &pdev->dev;
        wdt_dev = &pdev->dev;
 
-       /* get the memory region for the watchdog timer */
-
        wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (wdt_mem == NULL) {
                dev_err(dev, "no memory resource specified\n");
                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);
        if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
                dev_err(dev, "failed to get memory region\n");
-               return -EBUSY;
+               ret = -EBUSY;
+               goto err;
        }
 
        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);
 
-       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");
        if (IS_ERR(wdt_clock)) {
                dev_err(dev, "failed to find watchdog clock source\n");
                ret = PTR_ERR(wdt_clock);
-               goto err_irq;
+               goto err_map;
        }
 
        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");
                goto err_clk;
        }
@@ -378,12 +374,18 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
                                                        "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);
 
        ret = watchdog_register_device(&s3c2410_wdd);
        if (ret) {
                dev_err(dev, "cannot register watchdog (%d)\n", ret);
-               goto err_cpufreq;
+               goto err_irq;
        }
 
        if (tmr_atboot && started == 0) {
@@ -408,23 +410,26 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        return 0;
 
+ err_irq:
+       free_irq(wdt_irq->start, pdev);
+
  err_cpufreq:
        s3c2410wdt_cpufreq_deregister();
 
  err_clk:
        clk_disable(wdt_clock);
        clk_put(wdt_clock);
-
- err_irq:
-       free_irq(wdt_irq->start, pdev);
+       wdt_clock = NULL;
 
  err_map:
        iounmap(wdt_base);
 
  err_req:
        release_mem_region(wdt_mem->start, size);
-       wdt_mem = NULL;
 
+ err:
+       wdt_irq = NULL;
+       wdt_mem = NULL;
        return ret;
 }
 
@@ -432,18 +437,18 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
 {
        watchdog_unregister_device(&s3c2410_wdd);
 
+       free_irq(wdt_irq->start, dev);
+
        s3c2410wdt_cpufreq_deregister();
 
        clk_disable(wdt_clock);
        clk_put(wdt_clock);
        wdt_clock = NULL;
 
-       free_irq(wdt_irq->start, dev);
-       wdt_irq = NULL;
-
        iounmap(wdt_base);
 
        release_mem_region(wdt_mem->start, resource_size(wdt_mem));
+       wdt_irq = NULL;
        wdt_mem = NULL;
        return 0;
 }