Commit f2ffc44e authored by Corey Minyard's avatar Corey Minyard Committed by Paul Mackerras

[PATCH] IPMI update

 - small cleanups to make the spacing consistent
 - modifications to the watchdog so it starts the first time
   you hit it, not the second.
 - Fix for returning the proper value when starting the
   sequence number timer.
 - Fix a parameter name in the watchdog.
parent 4fa9569b
...@@ -629,20 +629,6 @@ static void request_events(void *send_info) ...@@ -629,20 +629,6 @@ static void request_events(void *send_info)
atomic_set(&kcs_info->req_events, 1); atomic_set(&kcs_info->req_events, 1);
} }
#if 0
static int new_user(void *send_info)
{
if (!try_module_get(THIS_MODULE))
return -EBUSY;
return 0;
}
static void user_left(void *send_info)
{
module_put(THIS_MODULE);
}
#endif
static int initialized = 0; static int initialized = 0;
/* Must be called with interrupts off and with the kcs_lock held. */ /* Must be called with interrupts off and with the kcs_lock held. */
......
...@@ -175,7 +175,7 @@ int ...@@ -175,7 +175,7 @@ int
ipmi_register_all_cmd_rcvr(ipmi_user_t user) ipmi_register_all_cmd_rcvr(ipmi_user_t user)
{ {
unsigned long flags; unsigned long flags;
int rv = -EBUSY; int rv = -EBUSY;
write_lock_irqsave(&(user->intf->users_lock), flags); write_lock_irqsave(&(user->intf->users_lock), flags);
write_lock(&(user->intf->cmd_rcvr_lock)); write_lock(&(user->intf->cmd_rcvr_lock));
...@@ -194,7 +194,7 @@ int ...@@ -194,7 +194,7 @@ int
ipmi_unregister_all_cmd_rcvr(ipmi_user_t user) ipmi_unregister_all_cmd_rcvr(ipmi_user_t user)
{ {
unsigned long flags; unsigned long flags;
int rv = -EINVAL; int rv = -EINVAL;
write_lock_irqsave(&(user->intf->users_lock), flags); write_lock_irqsave(&(user->intf->users_lock), flags);
write_lock(&(user->intf->cmd_rcvr_lock)); write_lock(&(user->intf->cmd_rcvr_lock));
...@@ -431,6 +431,7 @@ static int intf_start_seq_timer(ipmi_smi_t intf, ...@@ -431,6 +431,7 @@ static int intf_start_seq_timer(ipmi_smi_t intf,
{ {
struct seq_table *ent = &(intf->seq_table[seq]); struct seq_table *ent = &(intf->seq_table[seq]);
ent->timeout = ent->orig_timeout; ent->timeout = ent->orig_timeout;
rv = 0;
} }
spin_unlock_irqrestore(&(intf->seq_lock), flags); spin_unlock_irqrestore(&(intf->seq_lock), flags);
...@@ -1023,7 +1024,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, ...@@ -1023,7 +1024,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
int rv; int rv;
ipmi_smi_t new_intf; ipmi_smi_t new_intf;
struct list_head *entry; struct list_head *entry;
unsigned long flags; unsigned long flags;
/* Make sure the driver is actually initialized, this handles /* Make sure the driver is actually initialized, this handles
......
...@@ -215,13 +215,13 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, ...@@ -215,13 +215,13 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg, struct ipmi_recv_msg *recv_msg,
int *send_heartbeat_now) int *send_heartbeat_now)
{ {
struct ipmi_msg msg; struct ipmi_msg msg;
unsigned char data[6]; unsigned char data[6];
int rv; int rv;
struct ipmi_system_interface_addr addr; struct ipmi_system_interface_addr addr;
int hbnow = 0;
*send_heartbeat_now = 0;
data[0] = 0; data[0] = 0;
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
...@@ -233,7 +233,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, ...@@ -233,7 +233,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
/* In ipmi 1.0, setting the timer stops the watchdog, we /* In ipmi 1.0, setting the timer stops the watchdog, we
need to start it back up again. */ need to start it back up again. */
*send_heartbeat_now = 1; hbnow = 1;
} }
data[1] = 0; data[1] = 0;
...@@ -268,10 +268,18 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, ...@@ -268,10 +268,18 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
rv); rv);
} }
if (send_heartbeat_now)
*send_heartbeat_now = hbnow;
return rv; return rv;
} }
static int ipmi_set_timeout(void) /* Parameters to ipmi_set_timeout */
#define IPMI_SET_TIMEOUT_NO_HB 0
#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
#define IPMI_SET_TIMEOUT_FORCE_HB 2
static int ipmi_set_timeout(int do_heartbeat)
{ {
int send_heartbeat_now; int send_heartbeat_now;
int rv; int rv;
...@@ -288,8 +296,12 @@ static int ipmi_set_timeout(void) ...@@ -288,8 +296,12 @@ static int ipmi_set_timeout(void)
if (rv) { if (rv) {
up(&set_timeout_lock); up(&set_timeout_lock);
} else { } else {
if (send_heartbeat_now) if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|| ((send_heartbeat_now)
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
{
rv = ipmi_heartbeat(); rv = ipmi_heartbeat();
}
} }
return rv; return rv;
...@@ -312,7 +324,7 @@ static struct ipmi_recv_msg panic_halt_recv_msg = ...@@ -312,7 +324,7 @@ static struct ipmi_recv_msg panic_halt_recv_msg =
/* Special call, doesn't claim any locks. This is only to be called /* Special call, doesn't claim any locks. This is only to be called
at panic or halt time, in run-to-completion mode, when the caller at panic or halt time, in run-to-completion mode, when the caller
is the only CPU and the only thing that will be going IPMI is the only CPU and the only thing that will be going is these IPMI
calls. */ calls. */
static void panic_halt_ipmi_set_timeout(void) static void panic_halt_ipmi_set_timeout(void)
{ {
...@@ -339,7 +351,7 @@ void ipmi_delayed_shutdown(long delay, int power_off) ...@@ -339,7 +351,7 @@ void ipmi_delayed_shutdown(long delay, int power_off)
else else
ipmi_watchdog_state = WDOG_TIMEOUT_RESET; ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
timeout = delay; timeout = delay;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
} }
/* We use a semaphore to make sure that only one thing can send a /* We use a semaphore to make sure that only one thing can send a
...@@ -390,16 +402,14 @@ static int ipmi_heartbeat(void) ...@@ -390,16 +402,14 @@ static int ipmi_heartbeat(void)
if (ipmi_start_timer_on_heartbeat) { if (ipmi_start_timer_on_heartbeat) {
ipmi_start_timer_on_heartbeat = 0; ipmi_start_timer_on_heartbeat = 0;
ipmi_watchdog_state = action_val; ipmi_watchdog_state = action_val;
return ipmi_set_timeout(); return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
} } else if (pretimeout_since_last_heartbeat) {
if (pretimeout_since_last_heartbeat) {
/* A pretimeout occurred, make sure we set the timeout. /* A pretimeout occurred, make sure we set the timeout.
We don't want to set the action, though, we want to We don't want to set the action, though, we want to
leave that alone (thus it can't be combined with the leave that alone (thus it can't be combined with the
above operation. */ above operation. */
pretimeout_since_last_heartbeat = 0; pretimeout_since_last_heartbeat = 0;
return ipmi_set_timeout(); return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
} }
down(&heartbeat_lock); down(&heartbeat_lock);
...@@ -501,7 +511,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, ...@@ -501,7 +511,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
if (i) if (i)
return -EFAULT; return -EFAULT;
timeout = val; timeout = val;
return ipmi_set_timeout(); return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
i = copy_to_user((void *) arg, i = copy_to_user((void *) arg,
...@@ -516,7 +526,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, ...@@ -516,7 +526,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
if (i) if (i)
return -EFAULT; return -EFAULT;
pretimeout = val; pretimeout = val;
return ipmi_set_timeout(); return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
case WDIOC_GET_PRETIMEOUT: case WDIOC_GET_PRETIMEOUT:
i = copy_to_user((void *) arg, i = copy_to_user((void *) arg,
...@@ -536,14 +546,14 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, ...@@ -536,14 +546,14 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
if (val & WDIOS_DISABLECARD) if (val & WDIOS_DISABLECARD)
{ {
ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
ipmi_start_timer_on_heartbeat = 0; ipmi_start_timer_on_heartbeat = 0;
} }
if (val & WDIOS_ENABLECARD) if (val & WDIOS_ENABLECARD)
{ {
ipmi_watchdog_state = action_val; ipmi_watchdog_state = action_val;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
} }
return 0; return 0;
...@@ -679,7 +689,7 @@ static int ipmi_close(struct inode *ino, struct file *filep) ...@@ -679,7 +689,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
{ {
#ifndef CONFIG_WATCHDOG_NOWAYOUT #ifndef CONFIG_WATCHDOG_NOWAYOUT
ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
#endif #endif
ipmi_wdog_open = 0; ipmi_wdog_open = 0;
} }
...@@ -731,14 +741,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data) ...@@ -731,14 +741,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data)
wake_up_interruptible(&read_q); wake_up_interruptible(&read_q);
kill_fasync(&fasync_q, SIGIO, POLL_IN); kill_fasync(&fasync_q, SIGIO, POLL_IN);
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
pretimeout_since_last_heartbeat = 1;
spin_unlock(&ipmi_read_lock); spin_unlock(&ipmi_read_lock);
} }
} }
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
pretimeout_since_last_heartbeat = 1;
} }
static struct ipmi_user_hndl ipmi_hndlrs = static struct ipmi_user_hndl ipmi_hndlrs =
...@@ -779,7 +789,7 @@ static void ipmi_register_watchdog(int ipmi_intf) ...@@ -779,7 +789,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
/* Run from startup, so start the timer now. */ /* Run from startup, so start the timer now. */
start_now = 0; /* Disable this function after first startup. */ start_now = 0; /* Disable this function after first startup. */
ipmi_watchdog_state = action_val; ipmi_watchdog_state = action_val;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
printk("Starting IPMI Watchdog now!\n"); printk("Starting IPMI Watchdog now!\n");
} }
} }
...@@ -792,6 +802,12 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) ...@@ -792,6 +802,12 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
watchdog. */ watchdog. */
if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
panic("IPMI watchdog pre-timeout"); panic("IPMI watchdog pre-timeout");
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
pretimeout_since_last_heartbeat = 1;
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -1009,7 +1025,7 @@ static void ipmi_unregister_watchdog(void) ...@@ -1009,7 +1025,7 @@ static void ipmi_unregister_watchdog(void)
/* Disable the timer. */ /* Disable the timer. */
ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(); ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
/* Wait to make sure the message makes it out. The lower layer has /* Wait to make sure the message makes it out. The lower layer has
pointers to our buffers, we want to make sure they are done before pointers to our buffers, we want to make sure they are done before
...@@ -1096,7 +1112,7 @@ static int __init ipmi_wdog_setup(char *str) ...@@ -1096,7 +1112,7 @@ static int __init ipmi_wdog_setup(char *str)
else if (strcmp(option, "preop_panic") == 0) { else if (strcmp(option, "preop_panic") == 0) {
preop = "preop_panic"; preop = "preop_panic";
} }
else if (strcmp(option, "preop_none") == 0) { else if (strcmp(option, "preop_give_data") == 0) {
preop = "preop_give_data"; preop = "preop_give_data";
} else { } else {
printk("Unknown IPMI watchdog option: '%s'\n", option); printk("Unknown IPMI watchdog option: '%s'\n", option);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment