static int set_param_str(const char *val, struct kernel_param *kp) { action_fn fn = (action_fn) kp->arg; int rv = 0; char *dup, *s; dup = kstrdup(val, GFP_KERNEL); if (!dup) return -ENOMEM; s = strstrip(dup); down_read(®ister_sem); rv = fn(s, NULL); if (rv) goto out_unlock; check_parms(); if (watchdog_user) rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); out_unlock: up_read(®ister_sem); kfree(dup); return rv; }
static int set_param_str(const char *val, struct kernel_param *kp) { action_fn fn = (action_fn) kp->arg; int rv = 0; const char *end; char valcp[16]; int len; /* Truncate leading and trailing spaces. */ while (isspace(*val)) val++; end = val + strlen(val) - 1; while ((end >= val) && isspace(*end)) end--; len = end - val + 1; if (len > sizeof(valcp) - 1) return -EINVAL; memcpy(valcp, val, len); valcp[len] = '\0'; down_read(®ister_sem); rv = fn(valcp, NULL); if (rv) goto out_unlock; check_parms(); if (watchdog_user) rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); out_unlock: up_read(®ister_sem); return rv; }
static int set_param_str(const char *val, struct kernel_param *kp) { action_fn fn = (action_fn) kp->arg; int rv = 0; char valcp[16]; char *s; strncpy(valcp, val, 16); valcp[15] = '\0'; s = strstrip(valcp); down_read(®ister_sem); rv = fn(s, NULL); if (rv) goto out_unlock; check_parms(); if (watchdog_user) rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); out_unlock: up_read(®ister_sem); return rv; }
/* Do a delayed shutdown, with the delay in milliseconds. If power_off is false, do a reset. If power_off is true, do a power down. This is primarily for the IMB code's shutdown. */ void ipmi_delayed_shutdown(long delay, int power_off) { ipmi_ignore_heartbeat = 1; if (power_off) ipmi_watchdog_state = WDOG_TIMEOUT_POWER_DOWN; else ipmi_watchdog_state = WDOG_TIMEOUT_RESET; timeout = delay; ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); }
static int set_param_timeout(const char *val, const struct kernel_param *kp) { char *endp; int l; int rv = 0; if (!val) return -EINVAL; l = simple_strtoul(val, &endp, 0); if (endp == val) return -EINVAL; *((int *)kp->arg) = l; if (watchdog_user) rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); return rv; }
static int ipmi_close(struct inode *ino, struct file *filep) { if (iminor(ino) == WATCHDOG_MINOR) { if (expect_close == 42) { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); ipmi_heartbeat(); } clear_bit(0, &ipmi_wdog_open); } expect_close = 0; return 0; }
static void ipmi_register_watchdog(int ipmi_intf) { int rv = -EBUSY; down_write(®ister_sem); if (watchdog_user) goto out; if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf)) goto out; watchdog_ifnum = ipmi_intf; rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user); if (rv < 0) { printk(KERN_CRIT PFX "Unable to register with ipmi\n"); goto out; } ipmi_get_version(watchdog_user, &ipmi_version_major, &ipmi_version_minor); rv = misc_register(&ipmi_wdog_miscdev); if (rv < 0) { ipmi_destroy_user(watchdog_user); watchdog_user = NULL; printk(KERN_CRIT PFX "Unable to register misc device\n"); } out: up_write(®ister_sem); if ((start_now) && (rv == 0)) { /* Run from startup, so start the timer now. */ start_now = 0; /* Disable this function after first startup. */ ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); printk(KERN_INFO PFX "Starting now!\n"); } }
static int ipmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int i; int val; switch(cmd) { case WDIOC_GETSUPPORT: i = copy_to_user(argp, &ident, sizeof(ident)); return i ? -EFAULT : 0; case WDIOC_SETTIMEOUT: i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; timeout = val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); case WDIOC_GETTIMEOUT: i = copy_to_user(argp, &timeout, sizeof(timeout)); if (i) return -EFAULT; return 0; case WDIOC_SET_PRETIMEOUT: i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; pretimeout = val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); case WDIOC_GET_PRETIMEOUT: i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); if (i) return -EFAULT; return 0; case WDIOC_KEEPALIVE: return ipmi_heartbeat(); case WDIOC_SETOPTIONS: i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; if (val & WDIOS_DISABLECARD) { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); ipmi_start_timer_on_heartbeat = 0; } if (val & WDIOS_ENABLECARD) { ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } return 0; case WDIOC_GETSTATUS: val = 0; i = copy_to_user(argp, &val, sizeof(val)); if (i) return -EFAULT; return 0; default: return -ENOIOCTLCMD; } }
static int ipmi_heartbeat(void) { struct kernel_ipmi_msg msg; int rv; struct ipmi_system_interface_addr addr; if (ipmi_ignore_heartbeat) { return 0; } if (ipmi_start_timer_on_heartbeat) { ipmi_start_timer_on_heartbeat = 0; ipmi_watchdog_state = action_val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } else if (pretimeout_since_last_heartbeat) { /* A pretimeout occurred, make sure we set the timeout. We don't want to set the action, though, we want to leave that alone (thus it can't be combined with the above operation. */ pretimeout_since_last_heartbeat = 0; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } down(&heartbeat_lock); atomic_set(&heartbeat_tofree, 2); /* Don't reset the timer if we have the timer turned off, that re-enables the watchdog. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { up(&heartbeat_lock); return 0; } addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; addr.channel = IPMI_BMC_CHANNEL; addr.lun = 0; msg.netfn = 0x06; msg.cmd = IPMI_WDOG_RESET_TIMER; msg.data = NULL; msg.data_len = 0; rv = ipmi_request_supply_msgs(watchdog_user, (struct ipmi_addr *) &addr, 0, &msg, NULL, &heartbeat_smi_msg, &heartbeat_recv_msg, 1); if (rv) { up(&heartbeat_lock); printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } /* Wait for the heartbeat to be sent. */ down(&heartbeat_wait_lock); if (heartbeat_recv_msg.msg.data[0] != 0) { /* Got an error in the heartbeat response. It was already reported in ipmi_wdog_msg_handler, but we should return an error here. */ rv = -EINVAL; } up(&heartbeat_lock); return rv; }
static void ipmi_register_watchdog(int ipmi_intf) { int rv = -EBUSY; if (watchdog_user) goto out; if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf)) goto out; watchdog_ifnum = ipmi_intf; rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user); if (rv < 0) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_CRIT PFX "Unable to register with ipmi\n"); #else ; #endif goto out; } ipmi_get_version(watchdog_user, &ipmi_version_major, &ipmi_version_minor); rv = misc_register(&ipmi_wdog_miscdev); if (rv < 0) { ipmi_destroy_user(watchdog_user); watchdog_user = NULL; #ifdef CONFIG_DEBUG_PRINTK printk(KERN_CRIT PFX "Unable to register misc device\n"); #else ; #endif } #ifdef HAVE_DIE_NMI if (nmi_handler_registered) { int old_pretimeout = pretimeout; int old_timeout = timeout; int old_preop_val = preop_val; /* * Set the pretimeout to go off in a second and give * ourselves plenty of time to stop the timer. */ ipmi_watchdog_state = WDOG_TIMEOUT_RESET; preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */ pretimeout = 99; timeout = 100; testing_nmi = 1; rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); if (rv) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_WARNING PFX "Error starting timer to" " test NMI: 0x%x. The NMI pretimeout will" " likely not work\n", rv); #else ; #endif rv = 0; goto out_restore; } msleep(1500); if (testing_nmi != 2) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_WARNING PFX "IPMI NMI didn't seem to" " occur. The NMI pretimeout will" " likely not work\n"); #else ; #endif } out_restore: testing_nmi = 0; preop_val = old_preop_val; pretimeout = old_pretimeout; timeout = old_timeout; } #endif out: if ((start_now) && (rv == 0)) { /* Run from startup, so start the timer now. */ start_now = 0; /* Disable this function after first startup. */ ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO PFX "Starting now!\n"); #else ; #endif } else { /* Stop the timer now. */ ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } }
static int ipmi_heartbeat(void) { struct kernel_ipmi_msg msg; int rv; struct ipmi_system_interface_addr addr; int timeout_retries = 0; if (ipmi_ignore_heartbeat) return 0; if (ipmi_start_timer_on_heartbeat) { ipmi_start_timer_on_heartbeat = 0; ipmi_watchdog_state = action_val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } else if (pretimeout_since_last_heartbeat) { /* * A pretimeout occurred, make sure we set the timeout. * We don't want to set the action, though, we want to * leave that alone (thus it can't be combined with the * above operation. */ return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } mutex_lock(&heartbeat_lock); restart: atomic_set(&heartbeat_tofree, 2); /* * Don't reset the timer if we have the timer turned off, that * re-enables the watchdog. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { mutex_unlock(&heartbeat_lock); return 0; } addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; addr.channel = IPMI_BMC_CHANNEL; addr.lun = 0; msg.netfn = 0x06; msg.cmd = IPMI_WDOG_RESET_TIMER; msg.data = NULL; msg.data_len = 0; rv = ipmi_request_supply_msgs(watchdog_user, (struct ipmi_addr *) &addr, 0, &msg, NULL, &heartbeat_smi_msg, &heartbeat_recv_msg, 1); if (rv) { mutex_unlock(&heartbeat_lock); printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } /* Wait for the heartbeat to be sent. */ wait_for_completion(&heartbeat_wait); if (heartbeat_recv_msg.msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP) { timeout_retries++; if (timeout_retries > 3) { printk(KERN_ERR PFX ": Unable to restore the IPMI" " watchdog's settings, giving up.\n"); rv = -EIO; goto out_unlock; } /* * The timer was not initialized, that means the BMC was * probably reset and lost the watchdog information. Attempt * to restore the timer's info. Note that we still hold * the heartbeat lock, to keep a heartbeat from happening * in this process, so must say no heartbeat to avoid a * deadlock on this mutex. */ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); if (rv) { printk(KERN_ERR PFX ": Unable to send the command to" " set the watchdog's settings, giving up.\n"); goto out_unlock; } /* We might need a new heartbeat, so do it now */ goto restart; } else if (heartbeat_recv_msg.msg.data[0] != 0) { /* * Got an error in the heartbeat response. It was already * reported in ipmi_wdog_msg_handler, but we should return * an error here. */ rv = -EINVAL; } out_unlock: mutex_unlock(&heartbeat_lock); return rv; }
static void ipmi_register_watchdog(int ipmi_intf) { int rv = -EBUSY; if (watchdog_user) goto out; if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf)) goto out; watchdog_ifnum = ipmi_intf; rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user); if (rv < 0) { printk(KERN_CRIT PFX "Unable to register with ipmi\n"); goto out; } ipmi_get_version(watchdog_user, &ipmi_version_major, &ipmi_version_minor); rv = misc_register(&ipmi_wdog_miscdev); if (rv < 0) { ipmi_destroy_user(watchdog_user); watchdog_user = NULL; printk(KERN_CRIT PFX "Unable to register misc device\n"); } #ifdef HAVE_DIE_NMI if (nmi_handler_registered) { int old_pretimeout = pretimeout; int old_timeout = timeout; int old_preop_val = preop_val; ipmi_watchdog_state = WDOG_TIMEOUT_RESET; preop_val = WDOG_PREOP_NONE; pretimeout = 99; timeout = 100; testing_nmi = 1; rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); if (rv) { printk(KERN_WARNING PFX "Error starting timer to" " test NMI: 0x%x. The NMI pretimeout will" " likely not work\n", rv); rv = 0; goto out_restore; } msleep(1500); if (testing_nmi != 2) { printk(KERN_WARNING PFX "IPMI NMI didn't seem to" " occur. The NMI pretimeout will" " likely not work\n"); } out_restore: testing_nmi = 0; preop_val = old_preop_val; pretimeout = old_pretimeout; timeout = old_timeout; } #endif out: if ((start_now) && (rv == 0)) { start_now = 0; ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); printk(KERN_INFO PFX "Starting now!\n"); } else { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } }
static int ipmi_heartbeat(void) { struct kernel_ipmi_msg msg; int rv; struct ipmi_system_interface_addr addr; if (ipmi_ignore_heartbeat) return 0; if (ipmi_start_timer_on_heartbeat) { ipmi_start_timer_on_heartbeat = 0; ipmi_watchdog_state = action_val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } else if (pretimeout_since_last_heartbeat) { return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } mutex_lock(&heartbeat_lock); atomic_set(&heartbeat_tofree, 2); if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { mutex_unlock(&heartbeat_lock); return 0; } addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; addr.channel = IPMI_BMC_CHANNEL; addr.lun = 0; msg.netfn = 0x06; msg.cmd = IPMI_WDOG_RESET_TIMER; msg.data = NULL; msg.data_len = 0; rv = ipmi_request_supply_msgs(watchdog_user, (struct ipmi_addr *) &addr, 0, &msg, NULL, &heartbeat_smi_msg, &heartbeat_recv_msg, 1); if (rv) { mutex_unlock(&heartbeat_lock); printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } wait_for_completion(&heartbeat_wait); if (heartbeat_recv_msg.msg.data[0] != 0) { rv = -EINVAL; } mutex_unlock(&heartbeat_lock); return rv; }