diff options
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_main.c')
| -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; |
