/** * sh_wdt_ioctl - Query Device * * @inode: inode of device * @file: file handle of device * @cmd: watchdog command * @arg: argument * * Query basic information from the device or ping it, as outlined by the * watchdog API. */ static int sh_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int new_heartbeat; int options, retval = -EINVAL; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info *)arg, &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: sh_wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_heartbeat, (int *)arg)) return -EFAULT; if (sh_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; sh_wdt_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, (int *)arg); case WDIOC_SETOPTIONS: if (get_user(options, (int *)arg)) return -EFAULT; if (options & WDIOS_DISABLECARD) { sh_wdt_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { sh_wdt_start(); retval = 0; } return retval; default: return -ENOIOCTLCMD; } return 0; }
/** * sh_wdt_write - Write to Device * * @file: file handle of device * @buf: buffer to write * @count: length of buffer * @ppos: offset * * Pings the watchdog on write. */ static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; if (count) { if (!nowayout) { size_t i; shwdt_expect_close = 0; for (i = 0; i != count; i++) { char c; if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') shwdt_expect_close = 42; } } sh_wdt_keepalive(); } return count; }
/** * sh_wdt_close - Close the Device * * @inode: inode of device * @file: file handle of device * * Watchdog device is closed and stopped. */ static int sh_wdt_close(struct inode *inode, struct file *file) { if (shwdt_expect_close == 42) { sh_wdt_stop(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); sh_wdt_keepalive(); } clear_bit(0, &shwdt_is_open); shwdt_expect_close = 0; return 0; }
static int sh_wdt_close(struct inode *inode, struct file *file) { struct sh_wdt *wdt = file->private_data; if (wdt->expect_close == 42) { sh_wdt_stop(wdt); } else { dev_crit(wdt->dev, "Unexpected close, not " "stopping watchdog!\n"); sh_wdt_keepalive(wdt); } clear_bit(0, &wdt->enabled); wdt->expect_close = 0; return 0; }
static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct sh_wdt *wdt = file->private_data; if (count) { if (!nowayout) { size_t i; wdt->expect_close = 0; for (i = 0; i != count; i++) { char c; if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') wdt->expect_close = 42; } } sh_wdt_keepalive(wdt); } return count; }