aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/shwdt.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-05-10 02:15:08 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-05-10 02:15:08 -0400
commitf9fb360cb3440fb7d22ad7061de4e99235a97e1c (patch)
tree16c24b4c9b69c4c125e8182be6b01d4cb72519a9 /drivers/watchdog/shwdt.c
parent1950f499df4eacb5d89cf0151f5edda139b800f4 (diff)
watchdog: shwdt: Migrate to per-device locking.
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>
Diffstat (limited to 'drivers/watchdog/shwdt.c')
-rw-r--r--drivers/watchdog/shwdt.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 0beabf238d4f..0d734a38d29f 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -25,6 +25,7 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/spinlock.h>
28#include <linux/miscdevice.h> 29#include <linux/miscdevice.h>
29#include <linux/watchdog.h> 30#include <linux/watchdog.h>
30#include <linux/fs.h> 31#include <linux/fs.h>
@@ -65,8 +66,6 @@
65static int clock_division_ratio = WTCSR_CKS_4096; 66static int clock_division_ratio = WTCSR_CKS_4096;
66#define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) 67#define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4))
67 68
68static DEFINE_SPINLOCK(shwdt_lock);
69
70#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 69#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
71static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 70static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
72static bool nowayout = WATCHDOG_NOWAYOUT; 71static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -75,6 +74,7 @@ static unsigned long next_heartbeat;
75struct sh_wdt { 74struct sh_wdt {
76 void __iomem *base; 75 void __iomem *base;
77 struct device *dev; 76 struct device *dev;
77 spinlock_t lock;
78 78
79 struct timer_list timer; 79 struct timer_list timer;
80 80
@@ -88,7 +88,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev)
88 unsigned long flags; 88 unsigned long flags;
89 u8 csr; 89 u8 csr;
90 90
91 spin_lock_irqsave(&shwdt_lock, flags); 91 spin_lock_irqsave(&wdt->lock, flags);
92 92
93 next_heartbeat = jiffies + (heartbeat * HZ); 93 next_heartbeat = jiffies + (heartbeat * HZ);
94 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); 94 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
@@ -117,7 +117,7 @@ static int sh_wdt_start(struct watchdog_device *wdt_dev)
117 csr &= ~RSTCSR_RSTS; 117 csr &= ~RSTCSR_RSTS;
118 sh_wdt_write_rstcsr(csr); 118 sh_wdt_write_rstcsr(csr);
119#endif 119#endif
120 spin_unlock_irqrestore(&shwdt_lock, flags); 120 spin_unlock_irqrestore(&wdt->lock, flags);
121 121
122 return 0; 122 return 0;
123} 123}
@@ -128,7 +128,7 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev)
128 unsigned long flags; 128 unsigned long flags;
129 u8 csr; 129 u8 csr;
130 130
131 spin_lock_irqsave(&shwdt_lock, flags); 131 spin_lock_irqsave(&wdt->lock, flags);
132 132
133 del_timer(&wdt->timer); 133 del_timer(&wdt->timer);
134 134
@@ -136,33 +136,35 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev)
136 csr &= ~WTCSR_TME; 136 csr &= ~WTCSR_TME;
137 sh_wdt_write_csr(csr); 137 sh_wdt_write_csr(csr);
138 138
139 spin_unlock_irqrestore(&shwdt_lock, flags); 139 spin_unlock_irqrestore(&wdt->lock, flags);
140 140
141 return 0; 141 return 0;
142} 142}
143 143
144static int sh_wdt_keepalive(struct watchdog_device *wdt_dev) 144static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
145{ 145{
146 struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
146 unsigned long flags; 147 unsigned long flags;
147 148
148 spin_lock_irqsave(&shwdt_lock, flags); 149 spin_lock_irqsave(&wdt->lock, flags);
149 next_heartbeat = jiffies + (heartbeat * HZ); 150 next_heartbeat = jiffies + (heartbeat * HZ);
150 spin_unlock_irqrestore(&shwdt_lock, flags); 151 spin_unlock_irqrestore(&wdt->lock, flags);
151 152
152 return 0; 153 return 0;
153} 154}
154 155
155static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t) 156static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
156{ 157{
158 struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
157 unsigned long flags; 159 unsigned long flags;
158 160
159 if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ 161 if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
160 return -EINVAL; 162 return -EINVAL;
161 163
162 spin_lock_irqsave(&shwdt_lock, flags); 164 spin_lock_irqsave(&wdt->lock, flags);
163 heartbeat = t; 165 heartbeat = t;
164 wdt_dev->timeout = t; 166 wdt_dev->timeout = t;
165 spin_unlock_irqrestore(&shwdt_lock, flags); 167 spin_unlock_irqrestore(&wdt->lock, flags);
166 168
167 return 0; 169 return 0;
168} 170}
@@ -172,7 +174,7 @@ static void sh_wdt_ping(unsigned long data)
172 struct sh_wdt *wdt = (struct sh_wdt *)data; 174 struct sh_wdt *wdt = (struct sh_wdt *)data;
173 unsigned long flags; 175 unsigned long flags;
174 176
175 spin_lock_irqsave(&shwdt_lock, flags); 177 spin_lock_irqsave(&wdt->lock, flags);
176 if (time_before(jiffies, next_heartbeat)) { 178 if (time_before(jiffies, next_heartbeat)) {
177 u8 csr; 179 u8 csr;
178 180
@@ -186,7 +188,7 @@ static void sh_wdt_ping(unsigned long data)
186 } else 188 } else
187 dev_warn(wdt->dev, "Heartbeat lost! Will not ping " 189 dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
188 "the watchdog\n"); 190 "the watchdog\n");
189 spin_unlock_irqrestore(&shwdt_lock, flags); 191 spin_unlock_irqrestore(&wdt->lock, flags);
190} 192}
191 193
192static const struct watchdog_info sh_wdt_info = { 194static const struct watchdog_info sh_wdt_info = {
@@ -238,12 +240,17 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
238 240
239 wdt->dev = &pdev->dev; 241 wdt->dev = &pdev->dev;
240 242
243 watchdog_set_nowayout(&sh_wdt_dev, nowayout);
244 watchdog_set_drvdata(&sh_wdt_dev, wdt);
245
241 wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 246 wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
242 if (unlikely(!wdt->base)) { 247 if (unlikely(!wdt->base)) {
243 rc = -ENXIO; 248 rc = -ENXIO;
244 goto out_err; 249 goto out_err;
245 } 250 }
246 251
252 spin_lock_init(&wdt->lock);
253
247 rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); 254 rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
248 if (unlikely(rc)) { 255 if (unlikely(rc)) {
249 /* Default timeout if invalid */ 256 /* Default timeout if invalid */
@@ -257,9 +264,6 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev)
257 dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n", 264 dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
258 sh_wdt_dev.timeout, nowayout); 265 sh_wdt_dev.timeout, nowayout);
259 266
260 watchdog_set_nowayout(&sh_wdt_dev, nowayout);
261 watchdog_set_drvdata(&sh_wdt_dev, wdt);
262
263 rc = watchdog_register_device(&sh_wdt_dev); 267 rc = watchdog_register_device(&sh_wdt_dev);
264 if (unlikely(rc)) { 268 if (unlikely(rc)) {
265 dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); 269 dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);