aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 8d082b46426b..d971817182f7 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -53,6 +53,10 @@
53#include <linux/kthread.h> 53#include <linux/kthread.h>
54#include "xpc.h" 54#include "xpc.h"
55 55
56#ifdef CONFIG_X86_64
57#include <asm/traps.h>
58#endif
59
56/* define two XPC debug device structures to be used with dev_dbg() et al */ 60/* define two XPC debug device structures to be used with dev_dbg() et al */
57 61
58struct device_driver xpc_dbg_name = { 62struct device_driver xpc_dbg_name = {
@@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
1079 return NOTIFY_DONE; 1083 return NOTIFY_DONE;
1080} 1084}
1081 1085
1086/* Used to only allow one cpu to complete disconnect */
1087static unsigned int xpc_die_disconnecting;
1088
1082/* 1089/*
1083 * Notify other partitions to deactivate from us by first disengaging from all 1090 * Notify other partitions to deactivate from us by first disengaging from all
1084 * references to our memory. 1091 * references to our memory.
@@ -1092,6 +1099,9 @@ xpc_die_deactivate(void)
1092 long keep_waiting; 1099 long keep_waiting;
1093 long wait_to_print; 1100 long wait_to_print;
1094 1101
1102 if (cmpxchg(&xpc_die_disconnecting, 0, 1))
1103 return;
1104
1095 /* keep xpc_hb_checker thread from doing anything (just in case) */ 1105 /* keep xpc_hb_checker thread from doing anything (just in case) */
1096 xpc_exiting = 1; 1106 xpc_exiting = 1;
1097 1107
@@ -1159,7 +1169,7 @@ xpc_die_deactivate(void)
1159 * about the lack of a heartbeat. 1169 * about the lack of a heartbeat.
1160 */ 1170 */
1161static int 1171static int
1162xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 1172xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
1163{ 1173{
1164#ifdef CONFIG_IA64 /* !!! temporary kludge */ 1174#ifdef CONFIG_IA64 /* !!! temporary kludge */
1165 switch (event) { 1175 switch (event) {
@@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
1191 break; 1201 break;
1192 } 1202 }
1193#else 1203#else
1194 xpc_die_deactivate(); 1204 struct die_args *die_args = _die_args;
1205
1206 switch (event) {
1207 case DIE_TRAP:
1208 if (die_args->trapnr == X86_TRAP_DF)
1209 xpc_die_deactivate();
1210
1211 if (((die_args->trapnr == X86_TRAP_MF) ||
1212 (die_args->trapnr == X86_TRAP_XF)) &&
1213 !user_mode_vm(die_args->regs))
1214 xpc_die_deactivate();
1215
1216 break;
1217 case DIE_INT3:
1218 case DIE_DEBUG:
1219 break;
1220 case DIE_OOPS:
1221 case DIE_GPF:
1222 default:
1223 xpc_die_deactivate();
1224 }
1195#endif 1225#endif
1196 1226
1197 return NOTIFY_DONE; 1227 return NOTIFY_DONE;