diff options
-rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 34 |
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 | ||
58 | struct device_driver xpc_dbg_name = { | 62 | struct 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 */ | ||
1087 | static 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 | */ |
1161 | static int | 1171 | static int |
1162 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | 1172 | xpc_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; |