diff options
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_main.c')
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 40 | 
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 8d082b46426..82dc5748f87 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 = { @@ -88,7 +92,7 @@ int xpc_disengage_timelimit = XPC_DISENGAGE_DEFAULT_TIMELIMIT;  static int xpc_disengage_min_timelimit;	/* = 0 */  static int xpc_disengage_max_timelimit = 120; -static ctl_table xpc_sys_xpc_hb_dir[] = { +static struct ctl_table xpc_sys_xpc_hb_dir[] = {  	{  	 .procname = "hb_interval",  	 .data = &xpc_hb_interval, @@ -107,7 +111,7 @@ static ctl_table xpc_sys_xpc_hb_dir[] = {  	 .extra2 = &xpc_hb_check_max_interval},  	{}  }; -static ctl_table xpc_sys_xpc_dir[] = { +static struct ctl_table xpc_sys_xpc_dir[] = {  	{  	 .procname = "hb",  	 .mode = 0555, @@ -122,7 +126,7 @@ static ctl_table xpc_sys_xpc_dir[] = {  	 .extra2 = &xpc_disengage_max_timelimit},  	{}  }; -static ctl_table xpc_sys_dir[] = { +static struct ctl_table xpc_sys_dir[] = {  	{  	 .procname = "xpc",  	 .mode = 0555, @@ -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;  | 
