watchdog: shwdt: Migrate to per-device locking.
authorPaul Mundt <lethal@linux-sh.org>
Thu, 10 May 2012 06:15:08 +0000 (15:15 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Thu, 10 May 2012 06:15:08 +0000 (15:15 +0900)
Presently we've been using global locking for everything. Push the
locking down to the per-device level in preparation for per-CPU
watchdogs.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
drivers/watchdog/shwdt.c

index 0beabf238d4f41eb289b49fa60b61198611cd35f..0d734a38d29f2e941f72967a0f826b402c068a69 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/spinlock.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/fs.h>
@@ -65,8 +66,6 @@
 static int clock_division_ratio = WTCSR_CKS_4096;
 #define next_ping_period(cks)  (jiffies + msecs_to_jiffies(cks - 4))
 
-static DEFINE_SPINLOCK(shwdt_lock);
-
 #define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;     /* in seconds */
 static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -75,6 +74,7 @@ static unsigned long next_heartbeat;
 struct sh_wdt {
        void __iomem            *base;
        struct device           *dev;
+       spinlock_t              lock;
 
        struct timer_list       timer;
 
@@ -88,7 +88,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev)
        unsigned long flags;
        u8 csr;
 
-       spin_lock_irqsave(&shwdt_lock, flags);
+       spin_lock_irqsave(&wdt->lock, flags);
 
        next_heartbeat = jiffies + (heartbeat * HZ);
        mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
@@ -117,7 +117,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev)
        csr &= ~RSTCSR_RSTS;
        sh_wdt_write_rstcsr(csr);
 #endif
-       spin_unlock_irqrestore(&shwdt_lock, flags);
+       spin_unlock_irqrestore(&wdt->lock, flags);
 
        return 0;
 }
@@ -128,7 +128,7 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev)
        unsigned long flags;
        u8 csr;
 
-       spin_lock_irqsave(&shwdt_lock, flags);
+       spin_lock_irqsave(&wdt->lock, flags);
 
        del_timer(&wdt->timer);
 
@@ -136,33 +136,35 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev)
        csr &= ~WTCSR_TME;
        sh_wdt_write_csr(csr);
 
-       spin_unlock_irqrestore(&shwdt_lock, flags);
+       spin_unlock_irqrestore(&wdt->lock, flags);
 
        return 0;
 }
 
 static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
 {
+       struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
        unsigned long flags;
 
-       spin_lock_irqsave(&shwdt_lock, flags);
+       spin_lock_irqsave(&wdt->lock, flags);
        next_heartbeat = jiffies + (heartbeat * HZ);
-       spin_unlock_irqrestore(&shwdt_lock, flags);
+       spin_unlock_irqrestore(&wdt->lock, flags);
 
        return 0;
 }
 
 static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
 {
+       struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
        unsigned long flags;
 
        if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
                return -EINVAL;
 
-       spin_lock_irqsave(&shwdt_lock, flags);
+       spin_lock_irqsave(&wdt->lock, flags);
        heartbeat = t;
        wdt_dev->timeout = t;
-       spin_unlock_irqrestore(&shwdt_lock, flags);
+       spin_unlock_irqrestore(&wdt->lock, flags);
 
        return 0;
 }
@@ -172,7 +174,7 @@ static void sh_wdt_ping(unsigned long data)
        struct sh_wdt *wdt = (struct sh_wdt *)data;
        unsigned long flags;
 
-       spin_lock_irqsave(&shwdt_lock, flags);
+       spin_lock_irqsave(&wdt->lock, flags);
        if (time_before(jiffies, next_heartbeat)) {
                u8 csr;
 
@@ -186,7 +188,7 @@ static void sh_wdt_ping(unsigned long data)
        } else
                dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
                         "the watchdog\n");
-       spin_unlock_irqrestore(&shwdt_lock, flags);
+       spin_unlock_irqrestore(&wdt->lock, flags);
 }
 
 static const struct watchdog_info sh_wdt_info = {
@@ -238,12 +240,17 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
 
        wdt->dev = &pdev->dev;
 
+       watchdog_set_nowayout(&sh_wdt_dev, nowayout);
+       watchdog_set_drvdata(&sh_wdt_dev, wdt);
+
        wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (unlikely(!wdt->base)) {
                rc = -ENXIO;
                goto out_err;
        }
 
+       spin_lock_init(&wdt->lock);
+
        rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
        if (unlikely(rc)) {
                /* Default timeout if invalid */
@@ -257,9 +264,6 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
                 sh_wdt_dev.timeout, nowayout);
 
-       watchdog_set_nowayout(&sh_wdt_dev, nowayout);
-       watchdog_set_drvdata(&sh_wdt_dev, wdt);
-
        rc = watchdog_register_device(&sh_wdt_dev);
        if (unlikely(rc)) {
                dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);