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 8d082b46426..d971817182f 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -53,6 +53,10 @@  #include <linux/kthread.h>  #include "xpc.h" +#ifdef CONFIG_X86_64 +#include <asm/traps.h> +#endif +  /* define two XPC debug device structures to be used with dev_dbg() et al */  struct device_driver xpc_dbg_name = { @@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)  	return NOTIFY_DONE;  } +/* Used to only allow one cpu to complete disconnect */ +static unsigned int xpc_die_disconnecting; +  /*   * Notify other partitions to deactivate from us by first disengaging from all   * references to our memory. @@ -1092,6 +1099,9 @@ xpc_die_deactivate(void)  	long keep_waiting;  	long wait_to_print; +	if (cmpxchg(&xpc_die_disconnecting, 0, 1)) +		return; +  	/* keep xpc_hb_checker thread from doing anything (just in case) */  	xpc_exiting = 1; @@ -1159,7 +1169,7 @@ xpc_die_deactivate(void)   * about the lack of a heartbeat.   */  static int -xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) +xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)  {  #ifdef CONFIG_IA64		/* !!! temporary kludge */  	switch (event) { @@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)  		break;  	}  #else -	xpc_die_deactivate(); +	struct die_args *die_args = _die_args; + +	switch (event) { +	case DIE_TRAP: +		if (die_args->trapnr == X86_TRAP_DF) +			xpc_die_deactivate(); + +		if (((die_args->trapnr == X86_TRAP_MF) || +		     (die_args->trapnr == X86_TRAP_XF)) && +		    !user_mode_vm(die_args->regs)) +			xpc_die_deactivate(); + +		break; +	case DIE_INT3: +	case DIE_DEBUG: +		break; +	case DIE_OOPS: +	case DIE_GPF: +	default: +		xpc_die_deactivate(); +	}  #endif  	return NOTIFY_DONE;  |