aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2007-10-18 06:07:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:32 -0400
commit612b5a8d3a57d07698ceec0e307a84f38b241fe2 (patch)
treebd7d44b88e00dd8f6fb7ad7afaa9053ac875c317 /drivers/char
parentfcfa4724116589d6a5fac92af410b6f12d41b5bb (diff)
IPMI: new NMI handling
Convert over to the new NMI handling for getting IPMI watchdog timeouts via an NMI. This add config options to know if there is the ability to receive NMIs and if it has an NMI post processing call. Then it modifies the IPMI watchdog to take advantage of this so that it can know if an NMI comes in. It also adds testing that the IPMI NMI watchdog works. Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c146
1 files changed, 105 insertions, 41 deletions
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 19a8683bd25d..e686fc925168 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -50,10 +50,19 @@
50#include <linux/poll.h> 50#include <linux/poll.h>
51#include <linux/string.h> 51#include <linux/string.h>
52#include <linux/ctype.h> 52#include <linux/ctype.h>
53#include <linux/delay.h>
53#include <asm/atomic.h> 54#include <asm/atomic.h>
54 55
55#ifdef CONFIG_X86_LOCAL_APIC 56#ifdef CONFIG_X86
56#include <asm/apic.h> 57/* This is ugly, but I've determined that x86 is the only architecture
58 that can reasonably support the IPMI NMI watchdog timeout at this
59 time. If another architecture adds this capability somehow, it
60 will have to be a somewhat different mechanism and I have no idea
61 how it will work. So in the unlikely event that another
62 architecture supports this, we can figure out a good generic
63 mechanism for it at that time. */
64#include <asm/kdebug.h>
65#define HAVE_DIE_NMI
57#endif 66#endif
58 67
59#define PFX "IPMI Watchdog: " 68#define PFX "IPMI Watchdog: "
@@ -313,6 +322,11 @@ static unsigned char ipmi_version_minor;
313/* If a pretimeout occurs, this is used to allow only one panic to happen. */ 322/* If a pretimeout occurs, this is used to allow only one panic to happen. */
314static atomic_t preop_panic_excl = ATOMIC_INIT(-1); 323static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
315 324
325#ifdef HAVE_DIE_NMI
326static int testing_nmi;
327static int nmi_handler_registered;
328#endif
329
316static int ipmi_heartbeat(void); 330static int ipmi_heartbeat(void);
317 331
318/* We use a mutex to make sure that only one thing can send a set 332/* We use a mutex to make sure that only one thing can send a set
@@ -352,6 +366,9 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
352 int hbnow = 0; 366 int hbnow = 0;
353 367
354 368
369 /* These can be cleared as we are setting the timeout. */
370 pretimeout_since_last_heartbeat = 0;
371
355 data[0] = 0; 372 data[0] = 0;
356 WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); 373 WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
357 374
@@ -426,13 +443,12 @@ static int ipmi_set_timeout(int do_heartbeat)
426 443
427 wait_for_completion(&set_timeout_wait); 444 wait_for_completion(&set_timeout_wait);
428 445
446 mutex_unlock(&set_timeout_lock);
447
429 if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) 448 if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
430 || ((send_heartbeat_now) 449 || ((send_heartbeat_now)
431 && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) 450 && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
432 {
433 rv = ipmi_heartbeat(); 451 rv = ipmi_heartbeat();
434 }
435 mutex_unlock(&set_timeout_lock);
436 452
437out: 453out:
438 return rv; 454 return rv;
@@ -556,9 +572,8 @@ static int ipmi_heartbeat(void)
556 int rv; 572 int rv;
557 struct ipmi_system_interface_addr addr; 573 struct ipmi_system_interface_addr addr;
558 574
559 if (ipmi_ignore_heartbeat) { 575 if (ipmi_ignore_heartbeat)
560 return 0; 576 return 0;
561 }
562 577
563 if (ipmi_start_timer_on_heartbeat) { 578 if (ipmi_start_timer_on_heartbeat) {
564 ipmi_start_timer_on_heartbeat = 0; 579 ipmi_start_timer_on_heartbeat = 0;
@@ -569,7 +584,6 @@ static int ipmi_heartbeat(void)
569 We don't want to set the action, though, we want to 584 We don't want to set the action, though, we want to
570 leave that alone (thus it can't be combined with the 585 leave that alone (thus it can't be combined with the
571 above operation. */ 586 above operation. */
572 pretimeout_since_last_heartbeat = 0;
573 return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); 587 return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
574 } 588 }
575 589
@@ -927,6 +941,45 @@ static void ipmi_register_watchdog(int ipmi_intf)
927 printk(KERN_CRIT PFX "Unable to register misc device\n"); 941 printk(KERN_CRIT PFX "Unable to register misc device\n");
928 } 942 }
929 943
944#ifdef HAVE_DIE_NMI
945 if (nmi_handler_registered) {
946 int old_pretimeout = pretimeout;
947 int old_timeout = timeout;
948 int old_preop_val = preop_val;
949
950 /* Set the pretimeout to go off in a second and give
951 ourselves plenty of time to stop the timer. */
952 ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
953 preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
954 pretimeout = 99;
955 timeout = 100;
956
957 testing_nmi = 1;
958
959 rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
960 if (rv) {
961 printk(KERN_WARNING PFX "Error starting timer to"
962 " test NMI: 0x%x. The NMI pretimeout will"
963 " likely not work\n", rv);
964 rv = 0;
965 goto out_restore;
966 }
967
968 msleep(1500);
969
970 if (testing_nmi != 2) {
971 printk(KERN_WARNING PFX "IPMI NMI didn't seem to"
972 " occur. The NMI pretimeout will"
973 " likely not work\n");
974 }
975 out_restore:
976 testing_nmi = 0;
977 preop_val = old_preop_val;
978 pretimeout = old_pretimeout;
979 timeout = old_timeout;
980 }
981#endif
982
930 out: 983 out:
931 if ((start_now) && (rv == 0)) { 984 if ((start_now) && (rv == 0)) {
932 /* Run from startup, so start the timer now. */ 985 /* Run from startup, so start the timer now. */
@@ -934,6 +987,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
934 ipmi_watchdog_state = action_val; 987 ipmi_watchdog_state = action_val;
935 ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); 988 ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
936 printk(KERN_INFO PFX "Starting now!\n"); 989 printk(KERN_INFO PFX "Starting now!\n");
990 } else {
991 /* Stop the timer now. */
992 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
993 ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
937 } 994 }
938} 995}
939 996
@@ -968,17 +1025,41 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
968 return; 1025 return;
969} 1026}
970 1027
971#ifdef HAVE_NMI_HANDLER 1028#ifdef HAVE_DIE_NMI
972static int 1029static int
973ipmi_nmi(void *dev_id, int cpu, int handled) 1030ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
974{ 1031{
1032 struct die_args *args = data;
1033
1034 if (val != DIE_NMI)
1035 return NOTIFY_OK;
1036
1037 /* Hack, if it's a memory or I/O error, ignore it. */
1038 if (args->err & 0xc0)
1039 return NOTIFY_OK;
1040
1041 /*
1042 * If we get here, it's an NMI that's not a memory or I/O
1043 * error. We can't truly tell if it's from IPMI or not
1044 * without sending a message, and sending a message is almost
1045 * impossible because of locking.
1046 */
1047
1048 if (testing_nmi) {
1049 testing_nmi = 2;
1050 return NOTIFY_STOP;
1051 }
1052
975 /* If we are not expecting a timeout, ignore it. */ 1053 /* If we are not expecting a timeout, ignore it. */
976 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) 1054 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
977 return NOTIFY_DONE; 1055 return NOTIFY_OK;
1056
1057 if (preaction_val != WDOG_PRETIMEOUT_NMI)
1058 return NOTIFY_OK;
978 1059
979 /* If no one else handled the NMI, we assume it was the IPMI 1060 /* If no one else handled the NMI, we assume it was the IPMI
980 watchdog. */ 1061 watchdog. */
981 if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { 1062 if (preop_val == WDOG_PREOP_PANIC) {
982 /* On some machines, the heartbeat will give 1063 /* On some machines, the heartbeat will give
983 an error and not work unless we re-enable 1064 an error and not work unless we re-enable
984 the timer. So do so. */ 1065 the timer. So do so. */
@@ -987,18 +1068,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled)
987 panic(PFX "pre-timeout"); 1068 panic(PFX "pre-timeout");
988 } 1069 }
989 1070
990 return NOTIFY_DONE; 1071 return NOTIFY_STOP;
991} 1072}
992 1073
993static struct nmi_handler ipmi_nmi_handler = 1074static struct notifier_block ipmi_nmi_handler = {
994{ 1075 .notifier_call = ipmi_nmi
995 .link = LIST_HEAD_INIT(ipmi_nmi_handler.link),
996 .dev_name = "ipmi_watchdog",
997 .dev_id = NULL,
998 .handler = ipmi_nmi,
999 .priority = 0, /* Call us last. */
1000}; 1076};
1001int nmi_handler_registered;
1002#endif 1077#endif
1003 1078
1004static int wdog_reboot_handler(struct notifier_block *this, 1079static int wdog_reboot_handler(struct notifier_block *this,
@@ -1115,7 +1190,7 @@ static int preaction_op(const char *inval, char *outval)
1115 preaction_val = WDOG_PRETIMEOUT_NONE; 1190 preaction_val = WDOG_PRETIMEOUT_NONE;
1116 else if (strcmp(inval, "pre_smi") == 0) 1191 else if (strcmp(inval, "pre_smi") == 0)
1117 preaction_val = WDOG_PRETIMEOUT_SMI; 1192 preaction_val = WDOG_PRETIMEOUT_SMI;
1118#ifdef HAVE_NMI_HANDLER 1193#ifdef HAVE_DIE_NMI
1119 else if (strcmp(inval, "pre_nmi") == 0) 1194 else if (strcmp(inval, "pre_nmi") == 0)
1120 preaction_val = WDOG_PRETIMEOUT_NMI; 1195 preaction_val = WDOG_PRETIMEOUT_NMI;
1121#endif 1196#endif
@@ -1149,7 +1224,7 @@ static int preop_op(const char *inval, char *outval)
1149 1224
1150static void check_parms(void) 1225static void check_parms(void)
1151{ 1226{
1152#ifdef HAVE_NMI_HANDLER 1227#ifdef HAVE_DIE_NMI
1153 int do_nmi = 0; 1228 int do_nmi = 0;
1154 int rv; 1229 int rv;
1155 1230
@@ -1162,20 +1237,9 @@ static void check_parms(void)
1162 preop_op("preop_none", NULL); 1237 preop_op("preop_none", NULL);
1163 do_nmi = 0; 1238 do_nmi = 0;
1164 } 1239 }
1165#ifdef CONFIG_X86_LOCAL_APIC
1166 if (nmi_watchdog == NMI_IO_APIC) {
1167 printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
1168 " mode (value is %d), that is incompatible"
1169 " with using NMI in the IPMI watchdog."
1170 " Disabling IPMI nmi pretimeout.\n",
1171 nmi_watchdog);
1172 preaction_val = WDOG_PRETIMEOUT_NONE;
1173 do_nmi = 0;
1174 }
1175#endif
1176 } 1240 }
1177 if (do_nmi && !nmi_handler_registered) { 1241 if (do_nmi && !nmi_handler_registered) {
1178 rv = request_nmi(&ipmi_nmi_handler); 1242 rv = register_die_notifier(&ipmi_nmi_handler);
1179 if (rv) { 1243 if (rv) {
1180 printk(KERN_WARNING PFX 1244 printk(KERN_WARNING PFX
1181 "Can't register nmi handler\n"); 1245 "Can't register nmi handler\n");
@@ -1183,7 +1247,7 @@ static void check_parms(void)
1183 } else 1247 } else
1184 nmi_handler_registered = 1; 1248 nmi_handler_registered = 1;
1185 } else if (!do_nmi && nmi_handler_registered) { 1249 } else if (!do_nmi && nmi_handler_registered) {
1186 release_nmi(&ipmi_nmi_handler); 1250 unregister_die_notifier(&ipmi_nmi_handler);
1187 nmi_handler_registered = 0; 1251 nmi_handler_registered = 0;
1188 } 1252 }
1189#endif 1253#endif
@@ -1219,9 +1283,9 @@ static int __init ipmi_wdog_init(void)
1219 1283
1220 rv = ipmi_smi_watcher_register(&smi_watcher); 1284 rv = ipmi_smi_watcher_register(&smi_watcher);
1221 if (rv) { 1285 if (rv) {
1222#ifdef HAVE_NMI_HANDLER 1286#ifdef HAVE_DIE_NMI
1223 if (preaction_val == WDOG_PRETIMEOUT_NMI) 1287 if (nmi_handler_registered)
1224 release_nmi(&ipmi_nmi_handler); 1288 unregister_die_notifier(&ipmi_nmi_handler);
1225#endif 1289#endif
1226 atomic_notifier_chain_unregister(&panic_notifier_list, 1290 atomic_notifier_chain_unregister(&panic_notifier_list,
1227 &wdog_panic_notifier); 1291 &wdog_panic_notifier);
@@ -1240,9 +1304,9 @@ static void __exit ipmi_wdog_exit(void)
1240 ipmi_smi_watcher_unregister(&smi_watcher); 1304 ipmi_smi_watcher_unregister(&smi_watcher);
1241 ipmi_unregister_watchdog(watchdog_ifnum); 1305 ipmi_unregister_watchdog(watchdog_ifnum);
1242 1306
1243#ifdef HAVE_NMI_HANDLER 1307#ifdef HAVE_DIE_NMI
1244 if (nmi_handler_registered) 1308 if (nmi_handler_registered)
1245 release_nmi(&ipmi_nmi_handler); 1309 unregister_die_notifier(&ipmi_nmi_handler);
1246#endif 1310#endif
1247 1311
1248 atomic_notifier_chain_unregister(&panic_notifier_list, 1312 atomic_notifier_chain_unregister(&panic_notifier_list,