aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/bfin_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/bfin_wdt.c')
-rw-r--r--drivers/watchdog/bfin_wdt.c147
1 files changed, 71 insertions, 76 deletions
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 03b3e3d91e7c..31b42253054e 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -24,8 +24,8 @@
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/uaccess.h>
27#include <asm/blackfin.h> 28#include <asm/blackfin.h>
28#include <asm/uaccess.h>
29 29
30#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) 30#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
31#define stampit() stamp("here i am") 31#define stampit() stamp("here i am")
@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t)
148 int run = bfin_wdt_running(); 148 int run = bfin_wdt_running();
149 bfin_wdt_stop(); 149 bfin_wdt_stop();
150 bfin_write_WDOG_CNT(cnt); 150 bfin_write_WDOG_CNT(cnt);
151 if (run) bfin_wdt_start(); 151 if (run)
152 bfin_wdt_start();
152 } 153 }
153 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); 154 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
154 155
@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
191{ 192{
192 stampit(); 193 stampit();
193 194
194 if (expect_close == 42) { 195 if (expect_close == 42)
195 bfin_wdt_stop(); 196 bfin_wdt_stop();
196 } else { 197 else {
197 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 198 printk(KERN_CRIT PFX
199 "Unexpected close, not stopping watchdog!\n");
198 bfin_wdt_keepalive(); 200 bfin_wdt_keepalive();
199 } 201 }
200
201 expect_close = 0; 202 expect_close = 0;
202 clear_bit(0, &open_check); 203 clear_bit(0, &open_check);
203
204 return 0; 204 return 0;
205} 205}
206 206
@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
214 * Pings the watchdog on write. 214 * Pings the watchdog on write.
215 */ 215 */
216static ssize_t bfin_wdt_write(struct file *file, const char __user *data, 216static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
217 size_t len, loff_t *ppos) 217 size_t len, loff_t *ppos)
218{ 218{
219 stampit(); 219 stampit();
220 220
@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
241 241
242/** 242/**
243 * bfin_wdt_ioctl - Query Device 243 * bfin_wdt_ioctl - Query Device
244 * @inode: inode of device
245 * @file: file handle of device 244 * @file: file handle of device
246 * @cmd: watchdog command 245 * @cmd: watchdog command
247 * @arg: argument 246 * @arg: argument
@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
249 * Query basic information from the device or ping it, as outlined by the 248 * Query basic information from the device or ping it, as outlined by the
250 * watchdog API. 249 * watchdog API.
251 */ 250 */
252static int bfin_wdt_ioctl(struct inode *inode, struct file *file, 251static long bfin_wdt_ioctl(struct file *file,
253 unsigned int cmd, unsigned long arg) 252 unsigned int cmd, unsigned long arg)
254{ 253{
255 void __user *argp = (void __user *)arg; 254 void __user *argp = (void __user *)arg;
256 int __user *p = argp; 255 int __user *p = argp;
@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
258 stampit(); 257 stampit();
259 258
260 switch (cmd) { 259 switch (cmd) {
261 default: 260 case WDIOC_GETSUPPORT:
262 return -ENOTTY; 261 if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
263 262 return -EFAULT;
264 case WDIOC_GETSUPPORT: 263 else
265 if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
266 return -EFAULT;
267 else
268 return 0;
269
270 case WDIOC_GETSTATUS:
271 case WDIOC_GETBOOTSTATUS:
272 return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
273
274 case WDIOC_KEEPALIVE:
275 bfin_wdt_keepalive();
276 return 0; 264 return 0;
277 265 case WDIOC_GETSTATUS:
278 case WDIOC_SETTIMEOUT: { 266 case WDIOC_GETBOOTSTATUS:
279 int new_timeout; 267 return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
280 268 case WDIOC_SETOPTIONS: {
281 if (get_user(new_timeout, p)) 269 unsigned long flags;
282 return -EFAULT; 270 int options, ret = -EINVAL;
283 271
284 if (bfin_wdt_set_timeout(new_timeout)) 272 if (get_user(options, p))
285 return -EINVAL; 273 return -EFAULT;
274
275 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
276 if (options & WDIOS_DISABLECARD) {
277 bfin_wdt_stop();
278 ret = 0;
286 } 279 }
287 /* Fall */ 280 if (options & WDIOS_ENABLECARD) {
288 case WDIOC_GETTIMEOUT: 281 bfin_wdt_start();
289 return put_user(timeout, p); 282 ret = 0;
290
291 case WDIOC_SETOPTIONS: {
292 unsigned long flags;
293 int options, ret = -EINVAL;
294
295 if (get_user(options, p))
296 return -EFAULT;
297
298 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
299
300 if (options & WDIOS_DISABLECARD) {
301 bfin_wdt_stop();
302 ret = 0;
303 }
304
305 if (options & WDIOS_ENABLECARD) {
306 bfin_wdt_start();
307 ret = 0;
308 }
309
310 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
311
312 return ret;
313 } 283 }
284 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
285 return ret;
286 }
287 case WDIOC_KEEPALIVE:
288 bfin_wdt_keepalive();
289 return 0;
290 case WDIOC_SETTIMEOUT: {
291 int new_timeout;
292
293 if (get_user(new_timeout, p))
294 return -EFAULT;
295 if (bfin_wdt_set_timeout(new_timeout))
296 return -EINVAL;
297 }
298 /* Fall */
299 case WDIOC_GETTIMEOUT:
300 return put_user(timeout, p);
301 default:
302 return -ENOTTY;
314 } 303 }
315} 304}
316 305
@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
323 * Handles specific events, such as turning off the watchdog during a 312 * Handles specific events, such as turning off the watchdog during a
324 * shutdown event. 313 * shutdown event.
325 */ 314 */
326static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, 315static int bfin_wdt_notify_sys(struct notifier_block *this,
327 void *unused) 316 unsigned long code, void *unused)
328{ 317{
329 stampit(); 318 stampit();
330 319
@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev)
379#endif 368#endif
380 369
381static const struct file_operations bfin_wdt_fops = { 370static const struct file_operations bfin_wdt_fops = {
382 .owner = THIS_MODULE, 371 .owner = THIS_MODULE,
383 .llseek = no_llseek, 372 .llseek = no_llseek,
384 .write = bfin_wdt_write, 373 .write = bfin_wdt_write,
385 .ioctl = bfin_wdt_ioctl, 374 .unlocked_ioctl = bfin_wdt_ioctl,
386 .open = bfin_wdt_open, 375 .open = bfin_wdt_open,
387 .release = bfin_wdt_release, 376 .release = bfin_wdt_release,
388}; 377};
389 378
390static struct miscdevice bfin_wdt_miscdev = { 379static struct miscdevice bfin_wdt_miscdev = {
@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = {
396static struct watchdog_info bfin_wdt_info = { 385static struct watchdog_info bfin_wdt_info = {
397 .identity = "Blackfin Watchdog", 386 .identity = "Blackfin Watchdog",
398 .options = WDIOF_SETTIMEOUT | 387 .options = WDIOF_SETTIMEOUT |
399 WDIOF_KEEPALIVEPING | 388 WDIOF_KEEPALIVEPING |
400 WDIOF_MAGICCLOSE, 389 WDIOF_MAGICCLOSE,
401}; 390};
402 391
403static struct notifier_block bfin_wdt_notifier = { 392static struct notifier_block bfin_wdt_notifier = {
@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
416 405
417 ret = register_reboot_notifier(&bfin_wdt_notifier); 406 ret = register_reboot_notifier(&bfin_wdt_notifier);
418 if (ret) { 407 if (ret) {
419 pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); 408 pr_devinit(KERN_ERR PFX
409 "cannot register reboot notifier (err=%d)\n", ret);
420 return ret; 410 return ret;
421 } 411 }
422 412
423 ret = misc_register(&bfin_wdt_miscdev); 413 ret = misc_register(&bfin_wdt_miscdev);
424 if (ret) { 414 if (ret) {
425 pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 415 pr_devinit(KERN_ERR PFX
426 WATCHDOG_MINOR, ret); 416 "cannot register miscdev on minor=%d (err=%d)\n",
417 WATCHDOG_MINOR, ret);
427 unregister_reboot_notifier(&bfin_wdt_notifier); 418 unregister_reboot_notifier(&bfin_wdt_notifier);
428 return ret; 419 return ret;
429 } 420 }
@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL");
516MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 507MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
517 508
518module_param(timeout, uint, 0); 509module_param(timeout, uint, 0);
519MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 510MODULE_PARM_DESC(timeout,
511 "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
512 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
520 513
521module_param(nowayout, int, 0); 514module_param(nowayout, int, 0);
522MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 515MODULE_PARM_DESC(nowayout,
516 "Watchdog cannot be stopped once started (default="
517 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");