Commit 1950f499df4eacb5d89cf0151f5edda139b800f4

Authored by Paul Mundt
1 parent 4096812636

watchdog: shwdt: Conversion to watchdog core.

Fairly straightforward conversion to utilize watchdog core support.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

Showing 2 changed files with 45 additions and 154 deletions Side-by-side Diff

drivers/watchdog/Kconfig
... ... @@ -1138,6 +1138,7 @@
1138 1138 config SH_WDT
1139 1139 tristate "SuperH Watchdog"
1140 1140 depends on SUPERH && (CPU_SH3 || CPU_SH4)
  1141 + select WATCHDOG_CORE
1141 1142 help
1142 1143 This driver adds watchdog support for the integrated watchdog in the
1143 1144 SuperH processors. If you have one of these processors and wish
drivers/watchdog/shwdt.c
... ... @@ -27,12 +27,10 @@
27 27 #include <linux/types.h>
28 28 #include <linux/miscdevice.h>
29 29 #include <linux/watchdog.h>
30   -#include <linux/ioport.h>
31 30 #include <linux/fs.h>
32 31 #include <linux/mm.h>
33 32 #include <linux/slab.h>
34 33 #include <linux/io.h>
35   -#include <linux/uaccess.h>
36 34 #include <asm/watchdog.h>
37 35  
38 36 #define DRV_NAME "sh-wdt"
... ... @@ -67,8 +65,6 @@
67 65 static int clock_division_ratio = WTCSR_CKS_4096;
68 66 #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4))
69 67  
70   -static const struct watchdog_info sh_wdt_info;
71   -static struct platform_device *sh_wdt_dev;
72 68 static DEFINE_SPINLOCK(shwdt_lock);
73 69  
74 70 #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
75 71  
... ... @@ -86,8 +82,9 @@
86 82 char expect_close;
87 83 };
88 84  
89   -static void sh_wdt_start(struct sh_wdt *wdt)
  85 +static int sh_wdt_start(struct watchdog_device *wdt_dev)
90 86 {
  87 + struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
91 88 unsigned long flags;
92 89 u8 csr;
93 90  
94 91  
95 92  
... ... @@ -121,10 +118,13 @@
121 118 sh_wdt_write_rstcsr(csr);
122 119 #endif
123 120 spin_unlock_irqrestore(&shwdt_lock, flags);
  121 +
  122 + return 0;
124 123 }
125 124  
126   -static void sh_wdt_stop(struct sh_wdt *wdt)
  125 +static int sh_wdt_stop(struct watchdog_device *wdt_dev)
127 126 {
  127 + struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
128 128 unsigned long flags;
129 129 u8 csr;
130 130  
131 131  
132 132  
133 133  
... ... @@ -137,18 +137,22 @@
137 137 sh_wdt_write_csr(csr);
138 138  
139 139 spin_unlock_irqrestore(&shwdt_lock, flags);
  140 +
  141 + return 0;
140 142 }
141 143  
142   -static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
  144 +static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
143 145 {
144 146 unsigned long flags;
145 147  
146 148 spin_lock_irqsave(&shwdt_lock, flags);
147 149 next_heartbeat = jiffies + (heartbeat * HZ);
148 150 spin_unlock_irqrestore(&shwdt_lock, flags);
  151 +
  152 + return 0;
149 153 }
150 154  
151   -static int sh_wdt_set_heartbeat(int t)
  155 +static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
152 156 {
153 157 unsigned long flags;
154 158  
155 159  
... ... @@ -157,7 +161,9 @@
157 161  
158 162 spin_lock_irqsave(&shwdt_lock, flags);
159 163 heartbeat = t;
  164 + wdt_dev->timeout = t;
160 165 spin_unlock_irqrestore(&shwdt_lock, flags);
  166 +
161 167 return 0;
162 168 }
163 169  
... ... @@ -183,123 +189,6 @@
183 189 spin_unlock_irqrestore(&shwdt_lock, flags);
184 190 }
185 191  
186   -static int sh_wdt_open(struct inode *inode, struct file *file)
187   -{
188   - struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
189   -
190   - if (test_and_set_bit(0, &wdt->enabled))
191   - return -EBUSY;
192   - if (nowayout)
193   - __module_get(THIS_MODULE);
194   -
195   - file->private_data = wdt;
196   -
197   - sh_wdt_start(wdt);
198   -
199   - return nonseekable_open(inode, file);
200   -}
201   -
202   -static int sh_wdt_close(struct inode *inode, struct file *file)
203   -{
204   - struct sh_wdt *wdt = file->private_data;
205   -
206   - if (wdt->expect_close == 42) {
207   - sh_wdt_stop(wdt);
208   - } else {
209   - dev_crit(wdt->dev, "Unexpected close, not "
210   - "stopping watchdog!\n");
211   - sh_wdt_keepalive(wdt);
212   - }
213   -
214   - clear_bit(0, &wdt->enabled);
215   - wdt->expect_close = 0;
216   -
217   - return 0;
218   -}
219   -
220   -static ssize_t sh_wdt_write(struct file *file, const char *buf,
221   - size_t count, loff_t *ppos)
222   -{
223   - struct sh_wdt *wdt = file->private_data;
224   -
225   - if (count) {
226   - if (!nowayout) {
227   - size_t i;
228   -
229   - wdt->expect_close = 0;
230   -
231   - for (i = 0; i != count; i++) {
232   - char c;
233   - if (get_user(c, buf + i))
234   - return -EFAULT;
235   - if (c == 'V')
236   - wdt->expect_close = 42;
237   - }
238   - }
239   - sh_wdt_keepalive(wdt);
240   - }
241   -
242   - return count;
243   -}
244   -
245   -static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
246   - unsigned long arg)
247   -{
248   - struct sh_wdt *wdt = file->private_data;
249   - int new_heartbeat;
250   - int options, retval = -EINVAL;
251   -
252   - switch (cmd) {
253   - case WDIOC_GETSUPPORT:
254   - return copy_to_user((struct watchdog_info *)arg,
255   - &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0;
256   - case WDIOC_GETSTATUS:
257   - case WDIOC_GETBOOTSTATUS:
258   - return put_user(0, (int *)arg);
259   - case WDIOC_SETOPTIONS:
260   - if (get_user(options, (int *)arg))
261   - return -EFAULT;
262   -
263   - if (options & WDIOS_DISABLECARD) {
264   - sh_wdt_stop(wdt);
265   - retval = 0;
266   - }
267   -
268   - if (options & WDIOS_ENABLECARD) {
269   - sh_wdt_start(wdt);
270   - retval = 0;
271   - }
272   -
273   - return retval;
274   - case WDIOC_KEEPALIVE:
275   - sh_wdt_keepalive(wdt);
276   - return 0;
277   - case WDIOC_SETTIMEOUT:
278   - if (get_user(new_heartbeat, (int *)arg))
279   - return -EFAULT;
280   -
281   - if (sh_wdt_set_heartbeat(new_heartbeat))
282   - return -EINVAL;
283   -
284   - sh_wdt_keepalive(wdt);
285   - /* Fall */
286   - case WDIOC_GETTIMEOUT:
287   - return put_user(heartbeat, (int *)arg);
288   - default:
289   - return -ENOTTY;
290   - }
291   - return 0;
292   -}
293   -
294   -static const struct file_operations sh_wdt_fops = {
295   - .owner = THIS_MODULE,
296   - .llseek = no_llseek,
297   - .write = sh_wdt_write,
298   - .unlocked_ioctl = sh_wdt_ioctl,
299   - .open = sh_wdt_open,
300   - .release = sh_wdt_close,
301   -};
302   -
303 192 static const struct watchdog_info sh_wdt_info = {
304 193 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
305 194 WDIOF_MAGICCLOSE,
306 195  
... ... @@ -307,12 +196,19 @@
307 196 .identity = "SH WDT",
308 197 };
309 198  
310   -static struct miscdevice sh_wdt_miscdev = {
311   - .minor = WATCHDOG_MINOR,
312   - .name = "watchdog",
313   - .fops = &sh_wdt_fops,
  199 +static const struct watchdog_ops sh_wdt_ops = {
  200 + .owner = THIS_MODULE,
  201 + .start = sh_wdt_start,
  202 + .stop = sh_wdt_stop,
  203 + .ping = sh_wdt_keepalive,
  204 + .set_timeout = sh_wdt_set_heartbeat,
314 205 };
315 206  
  207 +static struct watchdog_device sh_wdt_dev = {
  208 + .info = &sh_wdt_info,
  209 + .ops = &sh_wdt_ops,
  210 +};
  211 +
316 212 static int __devinit sh_wdt_probe(struct platform_device *pdev)
317 213 {
318 214 struct sh_wdt *wdt;
319 215  
320 216  
... ... @@ -348,13 +244,25 @@
348 244 goto out_err;
349 245 }
350 246  
351   - sh_wdt_miscdev.parent = wdt->dev;
  247 + rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
  248 + if (unlikely(rc)) {
  249 + /* Default timeout if invalid */
  250 + sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT);
352 251  
353   - rc = misc_register(&sh_wdt_miscdev);
  252 + dev_warn(&pdev->dev,
  253 + "heartbeat value must be 1<=x<=3600, using %d\n",
  254 + sh_wdt_dev.timeout);
  255 + }
  256 +
  257 + dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
  258 + sh_wdt_dev.timeout, nowayout);
  259 +
  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);
354 264 if (unlikely(rc)) {
355   - dev_err(&pdev->dev,
356   - "Can't register miscdev on minor=%d (err=%d)\n",
357   - sh_wdt_miscdev.minor, rc);
  265 + dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);
358 266 goto out_unmap;
359 267 }
360 268  
... ... @@ -364,7 +272,6 @@
364 272 wdt->timer.expires = next_ping_period(clock_division_ratio);
365 273  
366 274 platform_set_drvdata(pdev, wdt);
367   - sh_wdt_dev = pdev;
368 275  
369 276 dev_info(&pdev->dev, "initialized.\n");
370 277  
371 278  
... ... @@ -387,10 +294,8 @@
387 294  
388 295 platform_set_drvdata(pdev, NULL);
389 296  
390   - misc_deregister(&sh_wdt_miscdev);
  297 + watchdog_unregister_device(&sh_wdt_dev);
391 298  
392   - sh_wdt_dev = NULL;
393   -
394 299 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
395 300 devm_iounmap(&pdev->dev, wdt->base);
396 301 devm_kfree(&pdev->dev, wdt);
... ... @@ -400,9 +305,7 @@
400 305  
401 306 static void sh_wdt_shutdown(struct platform_device *pdev)
402 307 {
403   - struct sh_wdt *wdt = platform_get_drvdata(pdev);
404   -
405   - sh_wdt_stop(wdt);
  308 + sh_wdt_stop(&sh_wdt_dev);
406 309 }
407 310  
408 311 static struct platform_driver sh_wdt_driver = {
... ... @@ -418,8 +321,6 @@
418 321  
419 322 static int __init sh_wdt_init(void)
420 323 {
421   - int rc;
422   -
423 324 if (unlikely(clock_division_ratio < 0x5 ||
424 325 clock_division_ratio > 0x7)) {
425 326 clock_division_ratio = WTCSR_CKS_4096;
... ... @@ -427,17 +328,6 @@
427 328 pr_info("divisor must be 0x5<=x<=0x7, using %d\n",
428 329 clock_division_ratio);
429 330 }
430   -
431   - rc = sh_wdt_set_heartbeat(heartbeat);
432   - if (unlikely(rc)) {
433   - heartbeat = WATCHDOG_HEARTBEAT;
434   -
435   - pr_info("heartbeat value must be 1<=x<=3600, using %d\n",
436   - heartbeat);
437   - }
438   -
439   - pr_info("configured with heartbeat=%d sec (nowayout=%d)\n",
440   - heartbeat, nowayout);
441 331  
442 332 return platform_driver_register(&sh_wdt_driver);
443 333 }