static ssize_t ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (len) { if (!nowayout) { size_t i; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) return -EFAULT; if (c == 'V') set_bit(WDT_OK_TO_CLOSE, &wdt_status); else clear_bit(WDT_OK_TO_CLOSE, &wdt_status); } } wdt_keepalive(); } return len; }
static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { /* See if we got the magic character 'V' and reload the timer */ if(count) { if (!nowayout) { size_t ofs; /* note: just in case someone wrote the magic character * five months ago... */ wdt_expect_close = 0; /* now scan */ for (ofs = 0; ofs != count; ofs++) { char c; if (get_user(c, buf+ofs)) return -EFAULT; if (c == 'V') wdt_expect_close = 42; } } /* someone wrote to us, we should restart timer */ wdt_keepalive(); } return count; }
static long ep93xx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; switch (cmd) { case WDIOC_GETSUPPORT: ret = copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: ret = put_user(0, (int __user *)arg); break; case WDIOC_GETBOOTSTATUS: ret = put_user(boot_status, (int __user *)arg); break; case WDIOC_KEEPALIVE: wdt_keepalive(); ret = 0; break; case WDIOC_GETTIMEOUT: /* actually, it is 0.250 seconds.... */ ret = put_user(1, (int __user *)arg); break; } return ret; }
/* * /dev/watchdog handling */ static ssize_t fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { size_t i; char c; if (count) { if (!nowayout) { clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, &wdt_status); /* is there a magic char ? */ for (i = 0; i != count; i++) { if (get_user(c, buf + i)) return -EFAULT; if (c == SBC7240_MAGIC_CHAR) { set_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, &wdt_status); break; } } } wdt_keepalive(); } return count; }
static ssize_t fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { if (count) { if (!nowayout) { size_t ofs; wdt_expect_close = 0; for (ofs = 0; ofs != count; ofs++) { char c; if (get_user(c, buf + ofs)) return -EFAULT; if (c == 'V') wdt_expect_close = 42; } } wdt_keepalive(); } return count; }
/** * @brief: restart by "reboot" cmd * * @author: caolianming * @date: 2014-01-09 */ static void ak39_restart(char str, const char *cmd) { //ak39_reboot_sys_by_soft(); #if defined CONFIG_AK39_WATCHDOG || defined CONFIG_AK39_WATCHDOG_TOP wdt_enable(); wdt_keepalive(2); #endif }
/** * @brief: ak98_wdt_ioctl * @author: zhouwenyong * @modify: zhongjunchao * @date: 2011-9-26 * * @note: WDIOC_GETSUPPORT,return struct watchdog_info. * WDIOC_KEEPALIVE, set a default timeout (8s). * WDIOC_SETTIMEOUT, set a timeout value what you want (max 8s). * WDIOC_GETTIMEOUT, query the current timeout. * More detail, refer to kernel/Documentation/watchdog/watchdog-api.txt */ static long ak98_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; int ret = -ENOTTY; int time; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info *)argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(def_heartbeat); now_heartbeat = def_heartbeat; return 0; case WDIOC_SETTIMEOUT: if (get_user(time, p)) return -EFAULT; PDEBUG("timeout = %d\n", time); if (time <= 0 || time > 8) return -EINVAL; now_heartbeat = time * 1024 - 1; wdt_keepalive(now_heartbeat); return 0; case WDIOC_GETTIMEOUT: return put_user((now_heartbeat + 1)/1024, p); default: return -ENOTTY; } return ret; }
static int fop_close(struct inode *inode, struct file *file) { if (wdt_expect_close == 42) wdt_turnoff(); else { pr_crit("Unexpected close, not stopping watchdog!\n"); wdt_keepalive(); } clear_bit(0, &wdt_is_open); wdt_expect_close = 0; return 0; }
static int m54xx_wdt_release(struct inode *inode, struct file *file) { if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) wdt_disable(); else { pr_crit("Device closed unexpectedly - timer will not stop\n"); wdt_keepalive(); } clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status); return 0; }
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user((void __user *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int __user *)arg); case WDIOC_SETOPTIONS: { int options; int retval = -EINVAL; if (get_user(options, (int __user *)arg)) return -EFAULT; if (options & WDIOS_DISABLECARD) { wdt_disable(); retval = 0; } if (options & WDIOS_ENABLECARD) { wdt_enable(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, (int __user *)arg)) return -EFAULT; if (wdt_set_timeout(new_timeout)) return -EINVAL; /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, (int __user *)arg); default: return -ENOTTY; } }
static int fop_close(struct inode *inode, struct file *file) { if (test_and_clear_bit(SBC7240_EXPECT_CLOSE_STATUS_BIT, &wdt_status) || !nowayout) { wdt_disable(); } else { printk(KERN_CRIT SBC7240_PREFIX "Unexpected close, not stopping watchdog!\n"); wdt_keepalive(); } clear_bit(SBC7240_OPEN_STATUS_BIT, &wdt_status); return 0; }
static int wdt_release(struct inode *inode, struct file *file) { /* * Shut off the timer. * Lock it in if it's a module and we set nowayout */ if (expect_close == 42) { wdt_stop(); clear_bit(0, &timer_alive); } else { wdt_keepalive(); pr_crit("unexpected close, not stopping watchdog!\n"); } expect_close = 0; return 0; }
static int ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; int time; switch (cmd) { case WDIOC_GETSUPPORT: ret = copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: ret = put_user(0, (int *)arg); break; case WDIOC_GETBOOTSTATUS: ret = put_user(0, (int *)arg); break; case WDIOC_SETTIMEOUT: ret = get_user(time, (int *)arg); if (ret) break; if (time <= 0 || time > 60) { ret = -EINVAL; break; } heartbeat = time; wdt_keepalive(); /* Fall through */ case WDIOC_GETTIMEOUT: ret = put_user(heartbeat, (int *)arg); break; case WDIOC_KEEPALIVE: wdt_enable(); ret = 0; break; } return ret; }
static int wdt_release(struct inode *inode, struct file *file) { /* * Shut off the timer. * Lock it in if it's a module and we set nowayout */ if (expect_close == 42) { wdt_stop(); clear_bit(0, &timer_alive); } else { wdt_keepalive(); // printk(KERN_CRIT PFX ; } expect_close = 0; return 0; }
/* Application main entry point */ void main_task (void *param) { /* Init BSP (also init BSP on ARC core) */ queue = bsp_init (); /* start Quark watchdog */ wdt_start (WDT_MAX_TIMEOUT_MS); /* Init the CFW */ cfw_init (queue); jerry_start (); /* Loop to process message queue */ while (1) { OS_ERR_TYPE err = E_OS_OK; /* Process message with a given timeout */ queue_process_message_wait (queue, 5000, &err); /* Acknowledge the system watchdog to prevent panic and reset */ wdt_keepalive (); } }
/** * @brief: ak98_wdt_write * @author: zhouwenyong * @modify: zhongjunchao * @date: 2011-9-26 * * @note: We support "Magic Close" that driver will not disable the watchdog unless * a specific magic character 'V' has been sent to /dev/watchdog just before * closing the file. */ static ssize_t ak98_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { if (len) { size_t i; atomic_set(&in_write, 1); for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) return -EFAULT; if (c == 'V') { PDEBUG("Detect \"V\" Magic Character\n"); atomic_set(&in_write, 0); } } wdt_keepalive(def_heartbeat); } return len; }
static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int status; int new_options, retval = -EINVAL; int new_timeout; union { struct watchdog_info __user *ident; int __user *i; } uarg; uarg.i = (int __user *)arg; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: wdt_get_status(&status); return put_user(status, uarg.i); case WDIOC_GETBOOTSTATUS: return put_user(0, uarg.i); case WDIOC_SETOPTIONS: if (get_user(new_options, uarg.i)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_stop(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_start(); retval = 0; } return retval; case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, uarg.i)) return -EFAULT; if (wdt_set_timeout(new_timeout)) return -EINVAL; wdt_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timeout, uarg.i); default: return -ENOTTY; } }
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ALiM7101", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; /* arbitrary upper limit */ if (new_timeout < 1 || new_timeout > 3600) return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static int wdt_restart_handle(struct notifier_block *this, unsigned long mode, void *cmd) { /* * Cobalt devices have no way of rebooting themselves other * than getting the watchdog to pull reset, so we restart the * watchdog on reboot with no heartbeat. */ wdt_change(WDT_ENABLE); /* loop until the watchdog fires */ while (true) ; return NOTIFY_DONE; } static struct notifier_block wdt_restart_handler = { .notifier_call = wdt_restart_handle, .priority = 128, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit alim7101_wdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); unregister_restart_handler(&wdt_restart_handler); pci_dev_put(alim7101_pmu); } static int __init alim7101_wdt_init(void) { int rc = -EBUSY; struct pci_dev *ali1543_south; char tmp; pr_info("Steve Hill <*****@*****.**>\n"); alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!alim7101_pmu) { pr_info("ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } /* Set the WDT in the PMU to 1 second */ pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02); ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!ali1543_south) { pr_info("ALi 1543 South-Bridge not present - WDT not set\n"); goto err_out; } pci_read_config_byte(ali1543_south, 0x5e, &tmp); pci_dev_put(ali1543_south); if ((tmp & 0x1e) == 0x00) { if (!use_gpio) { pr_info("Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n"); goto err_out; } nowayout = 1; } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { pr_info("ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); goto err_out; } if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */ timeout = WATCHDOG_TIMEOUT; pr_info("timeout value must be 1 <= x <= 3600, using %d\n", timeout); } rc = register_reboot_notifier(&wdt_notifier); if (rc) { pr_err("cannot register reboot notifier (err=%d)\n", rc); goto err_out; } rc = register_restart_handler(&wdt_restart_handler); if (rc) { pr_err("cannot register restart handler (err=%d)\n", rc); goto err_out_reboot; } rc = misc_register(&wdt_miscdev); if (rc) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_restart; } if (nowayout) __module_get(THIS_MODULE); pr_info("WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_restart: unregister_restart_handler(&wdt_restart_handler); err_out_reboot: unregister_reboot_notifier(&wdt_notifier); err_out: pci_dev_put(alim7101_pmu); return rc; } module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); static const struct pci_device_id alim7101_pci_tbl[] __used = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { } }; MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl); MODULE_AUTHOR("Steve Hill"); MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); MODULE_LICENSE("GPL");
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "W83877F", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (new_timeout < 1 || new_timeout > 3600) return -EINVAL; timeout = new_timeout; wdt_keepalive(); } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit w83877f_wdt_unload(void) { wdt_turnoff(); misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); release_region(WDT_PING, 1); release_region(ENABLE_W83877F_PORT, 2); } static int __init w83877f_wdt_init(void) { int rc = -EBUSY; if (timeout < 1 || timeout > 3600) { timeout = WATCHDOG_TIMEOUT; pr_info("timeout value must be 1 <= x <= 3600, using %d\n", timeout); } if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) { pr_err("I/O address 0x%04x already in use\n", ENABLE_W83877F_PORT); rc = -EIO; goto err_out; } if (!request_region(WDT_PING, 1, "W8387FF WDT")) { pr_err("I/O address 0x%04x already in use\n", WDT_PING); rc = -EIO; goto err_out_region1; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { pr_err("cannot register reboot notifier (err=%d)\n", rc); goto err_out_region2; } rc = misc_register(&wdt_miscdev); if (rc) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_reboot; } pr_info("WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_reboot: unregister_reboot_notifier(&wdt_notifier); err_out_region2: release_region(WDT_PING, 1); err_out_region1: release_region(ENABLE_W83877F_PORT, 2); err_out: return rc; }
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident= { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "SBC60xx", }; switch(cmd) { default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if(new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_SETTIMEOUT: { int new_timeout; if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); } } static struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if(code==SYS_DOWN || code==SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier= { .notifier_call = wdt_notify_sys, }; static void __exit sbc60xxwdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) release_region(wdt_stop,1); release_region(wdt_start,1); } static int __init sbc60xxwdt_init(void) { int rc = -EBUSY; if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", timeout); } if (!request_region(wdt_start, 1, "SBC 60XX WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_start); rc = -EIO; goto err_out; } /* We cannot reserve 0x45 - the kernel already has! */ if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) { if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_stop); rc = -EIO; goto err_out_region1; } } init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 0; rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_region2; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out_miscdev; } printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_miscdev: misc_deregister(&wdt_miscdev); err_out_region2: if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) release_region(wdt_stop,1); err_out_region1: release_region(wdt_start,1); err_out: return rc; }
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ALiM7101", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (new_timeout < 1 || new_timeout > 3600) return -EINVAL; timeout = new_timeout; wdt_keepalive(); } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); if (code == SYS_RESTART) { wdt_change(WDT_ENABLE); printk(KERN_INFO PFX "Watchdog timer is now enabled " "with no heartbeat - should reboot in ~1 second.\n"); } return NOTIFY_DONE; } static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit alim7101_wdt_unload(void) { wdt_turnoff(); misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); pci_dev_put(alim7101_pmu); } static int __init alim7101_wdt_init(void) { int rc = -EBUSY; struct pci_dev *ali1543_south; char tmp; printk(KERN_INFO PFX "Steve Hill <*****@*****.**>.\n"); alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!alim7101_pmu) { printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02); ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!ali1543_south) { printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); goto err_out; } pci_read_config_byte(ali1543_south, 0x5e, &tmp); pci_dev_put(ali1543_south); if ((tmp & 0x1e) == 0x00) { if (!use_gpio) { printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. " "If this is a cobalt board, set the 'use_gpio' " "module parameter.\n"); goto err_out; } nowayout = 1; } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct " "revision number (???1001?) - WDT not set\n"); goto err_out; } if (timeout < 1 || timeout > 3600) { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1 <= x <= 3600, using %d\n", timeout); } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out; } rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_reboot; } if (nowayout) __module_get(THIS_MODULE); printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. " "timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_reboot: unregister_reboot_notifier(&wdt_notifier); err_out: pci_dev_put(alim7101_pmu); return rc; }
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ALiM7101", }; switch(cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if(new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_SETTIMEOUT: { int new_timeout; if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOIOCTLCMD; } } static struct file_operations wdt_fops = { .owner= THIS_MODULE, .llseek= no_llseek, .write= fop_write, .open= fop_open, .release= fop_close, .ioctl= fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor=WATCHDOG_MINOR, .name="watchdog", .fops=&wdt_fops, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code==SYS_DOWN || code==SYS_HALT) wdt_turnoff(); if (code==SYS_RESTART) { /* * Cobalt devices have no way of rebooting themselves other than * getting the watchdog to pull reset, so we restart the watchdog on * reboot with no heartbeat */ wdt_change(WDT_ENABLE); printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); } return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier= { .notifier_call = wdt_notify_sys, }; static void __exit alim7101_wdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); } static int __init alim7101_wdt_init(void) { int rc = -EBUSY; struct pci_dev *ali1543_south; char tmp; printk(KERN_INFO PFX "Steve Hill <*****@*****.**>.\n"); alim7101_pmu = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,NULL); if (!alim7101_pmu) { printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } /* Set the WDT in the PMU to 1 second */ pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02); ali1543_south = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!ali1543_south) { printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); return -EBUSY; } pci_read_config_byte(ali1543_south, 0x5e, &tmp); if ((tmp & 0x1e) != 0x12) { printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); return -EBUSY; } if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", timeout); } init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 1; rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out_miscdev; } printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_miscdev: misc_deregister(&wdt_miscdev); err_out: return rc; }
/*============================================================================ * Hook for the write file operation */ static ssize_t vmiwdt_write(struct file *file_ptr, const char *buffer, size_t nbytes, loff_t * off) { wdt_keepalive(); return 1; }
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "SC520", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (wdt_set_heartbeat(new_timeout)) return -EINVAL; wdt_keepalive(); } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit sc520_wdt_unload(void) { if (!nowayout) wdt_turnoff(); misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); iounmap(wdtmrctl); } static int __init sc520_wdt_init(void) { int rc = -EBUSY; if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); pr_info("timeout value must be 1 <= timeout <= 3600, using %d\n", WATCHDOG_TIMEOUT); } wdtmrctl = ioremap(MMCR_BASE + OFFS_WDTMRCTL, 2); if (!wdtmrctl) { pr_err("Unable to remap memory\n"); rc = -ENOMEM; goto err_out_region2; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { pr_err("cannot register reboot notifier (err=%d)\n", rc); goto err_out_ioremap; } rc = misc_register(&wdt_miscdev); if (rc) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, rc); goto err_out_notifier; } pr_info("WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_notifier: unregister_reboot_notifier(&wdt_notifier); err_out_ioremap: iounmap(wdtmrctl); err_out_region2: return rc; } module_init(sc520_wdt_init); module_exit(sc520_wdt_unload); MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION( "Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
/*============================================================================ * Hook to the ioctl file operation */ int vmiwdt_ioctl(struct inode *inode, struct file *file_ptr, uint32_t cmd, unsigned long arg) { int timeout, status = 0; static struct watchdog_info wdt_info = { .options = WDIOF_SETTIMEOUT, .firmware_version = 0, .identity = MOD_NAME }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user((void *) arg, &wdt_info, sizeof (wdt_info))) return -EFAULT; break; case WDIOC_GETSTATUS: if (copy_to_user((void *) arg, &status, sizeof (int))) return -EFAULT; break; case WDIOC_KEEPALIVE: wdt_keepalive(); break; case WDIOC_SETTIMEOUT: if (copy_from_user(&timeout, (void *) arg, sizeof (int))) return -EFAULT; /* The wdt_set_timeout function expects milliseconds */ timeout *= 1000; wdt_set_timeout(&timeout); timeout /= 1000; if (copy_to_user((void *) arg, &timeout, sizeof (int))) return -EFAULT; break; #ifdef WDIOC_SETTIMEOUT_MS case WDIOC_SETTIMEOUT_MS: #endif if (copy_from_user(&timeout, (void *) arg, sizeof (int))) return -EFAULT; wdt_set_timeout(&timeout); if (copy_to_user((void *) arg, &timeout, sizeof (int))) return -EFAULT; break; case WDIOC_GETTIMEOUT: /* The wdt_set_timeout function returns milliseconds */ timeout = wdt_get_timeout(); timeout /= 1000; if (copy_to_user((void *) arg, &timeout, sizeof (timeout))) return -EFAULT; break; #ifdef WDIOC_GETTIMEOUT_MS case WDIOC_GETTIMEOUT_MS: #endif timeout = wdt_get_timeout(); if (copy_to_user((void *) arg, &timeout, sizeof (timeout))) return -EFAULT; break; default: return -ENOTTY; } return 0; } /*============================================================================ * Hook for the open file operation */ static int vmiwdt_open(struct inode *inode, struct file *file_ptr) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT; #endif if (1 == ++vmiwdt_count) { wdt_enable(); } return 0; }