Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 56384
b: refs/heads/master
c: faa8b6c
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed May 14, 2007
1 parent c9a8c5d commit 659fb80
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 103 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3ec2ab5514dbd6b5c4c3437c6a3cd9e5a90e84ef
refs/heads/master: faa8b6c3c2e1454175609167a25ae525d075f045
5 changes: 0 additions & 5 deletions trunk/arch/i386/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,11 +733,6 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
*/
if (nmi_watchdog_tick(regs, reason))
return;
#endif
if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0)
== NOTIFY_STOP)
return;
#ifdef CONFIG_X86_LOCAL_APIC
if (!do_nmi_callback(regs, smp_processor_id()))
#endif
unknown_nmi_error(reason, regs);
Expand Down
3 changes: 0 additions & 3 deletions trunk/arch/x86_64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,6 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
*/
if (nmi_watchdog_tick(regs,reason))
return;
if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0)
== NOTIFY_STOP)
return;
if (!do_nmi_callback(regs,cpu))
unknown_nmi_error(reason, regs);

Expand Down
134 changes: 42 additions & 92 deletions trunk/drivers/char/ipmi/ipmi_watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,10 @@
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <asm/atomic.h>

#ifdef CONFIG_X86
/* This is ugly, but I've determined that x86 is the only architecture
that can reasonably support the IPMI NMI watchdog timeout at this
time. If another architecture adds this capability somehow, it
will have to be a somewhat different mechanism and I have no idea
how it will work. So in the unlikely event that another
architecture supports this, we can figure out a good generic
mechanism for it at that time. */
#define HAVE_DIE_NMI_POST
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
#endif

#define PFX "IPMI Watchdog: "
Expand Down Expand Up @@ -327,11 +319,6 @@ static unsigned char ipmi_version_minor;
/* If a pretimeout occurs, this is used to allow only one panic to happen. */
static atomic_t preop_panic_excl = ATOMIC_INIT(-1);

#ifdef HAVE_DIE_NMI_POST
static int testing_nmi;
static int nmi_handler_registered;
#endif

static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void);

Expand Down Expand Up @@ -373,10 +360,6 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
int hbnow = 0;


/* These can be cleared as we are setting the timeout. */
ipmi_start_timer_on_heartbeat = 0;
pretimeout_since_last_heartbeat = 0;

data[0] = 0;
WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);

Expand Down Expand Up @@ -451,12 +434,13 @@ static int ipmi_set_timeout(int do_heartbeat)

wait_for_completion(&set_timeout_wait);

mutex_unlock(&set_timeout_lock);

if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|| ((send_heartbeat_now)
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
{
rv = ipmi_heartbeat();
}
mutex_unlock(&set_timeout_lock);

out:
return rv;
Expand Down Expand Up @@ -536,17 +520,20 @@ static int ipmi_heartbeat(void)
int rv;
struct ipmi_system_interface_addr addr;

if (ipmi_ignore_heartbeat)
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);
}

Expand Down Expand Up @@ -934,45 +921,6 @@ static void ipmi_register_watchdog(int ipmi_intf)
printk(KERN_CRIT PFX "Unable to register misc device\n");
}

#ifdef HAVE_DIE_NMI_POST
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) {
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:
up_write(&register_sem);

Expand All @@ -982,10 +930,6 @@ static void ipmi_register_watchdog(int ipmi_intf)
ipmi_watchdog_state = action_val;
ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
printk(KERN_INFO PFX "Starting now!\n");
} else {
/* Stop the timer now. */
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
}
}

Expand Down Expand Up @@ -1022,28 +966,17 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
up_write(&register_sem);
}

#ifdef HAVE_DIE_NMI_POST
#ifdef HAVE_NMI_HANDLER
static int
ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
ipmi_nmi(void *dev_id, int cpu, int handled)
{
if (val != DIE_NMI_POST)
return NOTIFY_OK;

if (testing_nmi) {
testing_nmi = 2;
return NOTIFY_STOP;
}

/* If we are not expecting a timeout, ignore it. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
return NOTIFY_OK;

if (preaction_val != WDOG_PRETIMEOUT_NMI)
return NOTIFY_OK;
return NOTIFY_DONE;

/* If no one else handled the NMI, we assume it was the IPMI
watchdog. */
if (preop_val == WDOG_PREOP_PANIC) {
if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
/* On some machines, the heartbeat will give
an error and not work unless we re-enable
the timer. So do so. */
Expand All @@ -1052,12 +985,18 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
panic(PFX "pre-timeout");
}

return NOTIFY_STOP;
return NOTIFY_DONE;
}

static struct notifier_block ipmi_nmi_handler = {
.notifier_call = ipmi_nmi
static struct nmi_handler ipmi_nmi_handler =
{
.link = LIST_HEAD_INIT(ipmi_nmi_handler.link),
.dev_name = "ipmi_watchdog",
.dev_id = NULL,
.handler = ipmi_nmi,
.priority = 0, /* Call us last. */
};
int nmi_handler_registered;
#endif

static int wdog_reboot_handler(struct notifier_block *this,
Expand Down Expand Up @@ -1174,7 +1113,7 @@ static int preaction_op(const char *inval, char *outval)
preaction_val = WDOG_PRETIMEOUT_NONE;
else if (strcmp(inval, "pre_smi") == 0)
preaction_val = WDOG_PRETIMEOUT_SMI;
#ifdef HAVE_DIE_NMI_POST
#ifdef HAVE_NMI_HANDLER
else if (strcmp(inval, "pre_nmi") == 0)
preaction_val = WDOG_PRETIMEOUT_NMI;
#endif
Expand Down Expand Up @@ -1208,7 +1147,7 @@ static int preop_op(const char *inval, char *outval)

static void check_parms(void)
{
#ifdef HAVE_DIE_NMI_POST
#ifdef HAVE_NMI_HANDLER
int do_nmi = 0;
int rv;

Expand All @@ -1221,17 +1160,28 @@ static void check_parms(void)
preop_op("preop_none", NULL);
do_nmi = 0;
}
#ifdef CONFIG_X86_LOCAL_APIC
if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
" mode (value is %d), that is incompatible"
" with using NMI in the IPMI watchdog."
" Disabling IPMI nmi pretimeout.\n",
nmi_watchdog);
preaction_val = WDOG_PRETIMEOUT_NONE;
do_nmi = 0;
}
#endif
}
if (do_nmi && !nmi_handler_registered) {
rv = register_die_notifier(&ipmi_nmi_handler);
rv = request_nmi(&ipmi_nmi_handler);
if (rv) {
printk(KERN_WARNING PFX
"Can't register nmi handler\n");
return;
} else
nmi_handler_registered = 1;
} else if (!do_nmi && nmi_handler_registered) {
unregister_die_notifier(&ipmi_nmi_handler);
release_nmi(&ipmi_nmi_handler);
nmi_handler_registered = 0;
}
#endif
Expand Down Expand Up @@ -1267,9 +1217,9 @@ static int __init ipmi_wdog_init(void)

rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
#ifdef HAVE_DIE_NMI_POST
if (nmi_handler_registered)
unregister_die_notifier(&ipmi_nmi_handler);
#ifdef HAVE_NMI_HANDLER
if (preaction_val == WDOG_PRETIMEOUT_NMI)
release_nmi(&ipmi_nmi_handler);
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
&wdog_panic_notifier);
Expand All @@ -1288,9 +1238,9 @@ static void __exit ipmi_wdog_exit(void)
ipmi_smi_watcher_unregister(&smi_watcher);
ipmi_unregister_watchdog(watchdog_ifnum);

#ifdef HAVE_DIE_NMI_POST
#ifdef HAVE_NMI_HANDLER
if (nmi_handler_registered)
unregister_die_notifier(&ipmi_nmi_handler);
release_nmi(&ipmi_nmi_handler);
#endif

atomic_notifier_chain_unregister(&panic_notifier_list,
Expand Down
1 change: 0 additions & 1 deletion trunk/include/asm-i386/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ enum die_val {
DIE_GPF,
DIE_CALL,
DIE_NMI_IPI,
DIE_NMI_POST,
DIE_PAGE_FAULT,
};

Expand Down
1 change: 0 additions & 1 deletion trunk/include/asm-x86_64/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ enum die_val {
DIE_GPF,
DIE_CALL,
DIE_NMI_IPI,
DIE_NMI_POST,
DIE_PAGE_FAULT,
};

Expand Down

0 comments on commit 659fb80

Please sign in to comment.