diff options
Diffstat (limited to 'drivers/misc/sgi-xp')
| -rw-r--r-- | drivers/misc/sgi-xp/xp.h | 1 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 5 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 40 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_partition.c | 25 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 88 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpnet.c | 8 | 
6 files changed, 125 insertions, 42 deletions
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index 851b2f25ce0..c862cd4583c 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -25,7 +25,6 @@  #endif  #if defined CONFIG_IA64 -#include <asm/system.h>  #include <asm/sn/arch.h>	/* defines is_shub1() and is_shub2() */  #define is_shub()	ia64_platform_is("sn2")  #endif diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 652593fc486..128d5615c80 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c @@ -828,6 +828,7 @@ enum xp_retval  xpc_allocate_msg_wait(struct xpc_channel *ch)  {  	enum xp_retval ret; +	DEFINE_WAIT(wait);  	if (ch->flags & XPC_C_DISCONNECTING) {  		DBUG_ON(ch->reason == xpInterrupted); @@ -835,7 +836,9 @@ xpc_allocate_msg_wait(struct xpc_channel *ch)  	}  	atomic_inc(&ch->n_on_msg_allocate_wq); -	ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1); +	prepare_to_wait(&ch->msg_allocate_wq, &wait, TASK_INTERRUPTIBLE); +	ret = schedule_timeout(1); +	finish_wait(&ch->msg_allocate_wq, &wait);  	atomic_dec(&ch->n_on_msg_allocate_wq);  	if (ch->flags & XPC_C_DISCONNECTING) { 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; diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index d551f09ccb7..6956f7e7d43 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -439,18 +439,23 @@ xpc_discovery(void)  	 * nodes that can comprise an access protection grouping. The access  	 * protection is in regards to memory, IOI and IPI.  	 */ -	max_regions = 64;  	region_size = xp_region_size; -	switch (region_size) { -	case 128: -		max_regions *= 2; -	case 64: -		max_regions *= 2; -	case 32: -		max_regions *= 2; -		region_size = 16; -		DBUG_ON(!is_shub2()); +	if (is_uv()) +		max_regions = 256; +	else { +		max_regions = 64; + +		switch (region_size) { +		case 128: +			max_regions *= 2; +		case 64: +			max_regions *= 2; +		case 32: +			max_regions *= 2; +			region_size = 16; +			DBUG_ON(!is_shub2()); +		}  	}  	for (region = 0; region < max_regions; region++) { diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 17bbacb1b4b..95c894482fd 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/device.h> +#include <linux/cpu.h> +#include <linux/module.h>  #include <linux/err.h>  #include <linux/slab.h>  #include <asm/uv/uv_hub.h> @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;  					 XPC_NOTIFY_MSG_SIZE_UV)  #define XPC_NOTIFY_IRQ_NAME		"xpc_notify" +static int xpc_mq_node = -1; +  static struct xpc_gru_mq_uv *xpc_activate_mq_uv;  static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)  #if defined CONFIG_X86_64  	mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,  			UV_AFFINITY_CPU); -	if (mq->irq < 0) { -		dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", -			-mq->irq); +	if (mq->irq < 0)  		return mq->irq; -	}  	mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,  	mq->mmr_blade = uv_cpu_to_blade_id(cpu);  	nid = cpu_to_node(cpu); -	page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, -				pg_order); +	page = alloc_pages_exact_node(nid, +				      GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, +				      pg_order);  	if (page == NULL) {  		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "  			"bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -452,9 +454,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,  		if (msg->activate_gru_mq_desc_gpa !=  		    part_uv->activate_gru_mq_desc_gpa) { -			spin_lock_irqsave(&part_uv->flags_lock, irq_flags); +			spin_lock(&part_uv->flags_lock);  			part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; -			spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); +			spin_unlock(&part_uv->flags_lock);  			part_uv->activate_gru_mq_desc_gpa =  			    msg->activate_gru_mq_desc_gpa;  		} @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = {  	.notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,  }; +static int +xpc_init_mq_node(int nid) +{ +	int cpu; + +	get_online_cpus(); + +	for_each_cpu(cpu, cpumask_of_node(nid)) { +		xpc_activate_mq_uv = +			xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, +					     XPC_ACTIVATE_IRQ_NAME, +					     xpc_handle_activate_IRQ_uv); +		if (!IS_ERR(xpc_activate_mq_uv)) +			break; +	} +	if (IS_ERR(xpc_activate_mq_uv)) { +		put_online_cpus(); +		return PTR_ERR(xpc_activate_mq_uv); +	} + +	for_each_cpu(cpu, cpumask_of_node(nid)) { +		xpc_notify_mq_uv = +			xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, +					     XPC_NOTIFY_IRQ_NAME, +					     xpc_handle_notify_IRQ_uv); +		if (!IS_ERR(xpc_notify_mq_uv)) +			break; +	} +	if (IS_ERR(xpc_notify_mq_uv)) { +		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); +		put_online_cpus(); +		return PTR_ERR(xpc_notify_mq_uv); +	} + +	put_online_cpus(); +	return 0; +} +  int  xpc_init_uv(void)  { +	int nid; +	int ret = 0; +  	xpc_arch_ops = xpc_arch_ops_uv;  	if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void)  		return -E2BIG;  	} -	xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, -						  XPC_ACTIVATE_IRQ_NAME, -						  xpc_handle_activate_IRQ_uv); -	if (IS_ERR(xpc_activate_mq_uv)) -		return PTR_ERR(xpc_activate_mq_uv); +	if (xpc_mq_node < 0) +		for_each_online_node(nid) { +			ret = xpc_init_mq_node(nid); -	xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, -						XPC_NOTIFY_IRQ_NAME, -						xpc_handle_notify_IRQ_uv); -	if (IS_ERR(xpc_notify_mq_uv)) { -		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); -		return PTR_ERR(xpc_notify_mq_uv); -	} +			if (!ret) +				break; +		} +	else +		ret = xpc_init_mq_node(xpc_mq_node); -	return 0; +	if (ret < 0) +		dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", +			-ret); + +	return ret;  }  void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void)  	xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);  	xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);  } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index ee5109a3cd9..3fac67a5204 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -495,14 +495,14 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)  		}  	} +	dev->stats.tx_packets++; +	dev->stats.tx_bytes += skb->len; +  	if (atomic_dec_return(&queued_msg->use_count) == 0) {  		dev_kfree_skb(skb);  		kfree(queued_msg);  	} -	dev->stats.tx_packets++; -	dev->stats.tx_bytes += skb->len; -  	return NETDEV_TX_OK;  } @@ -576,7 +576,7 @@ xpnet_init(void)  	 * report an error if the data is not retrievable and the  	 * packet will be dropped.  	 */ -	xpnet_device->features = NETIF_F_NO_CSUM; +	xpnet_device->features = NETIF_F_HW_CSUM;  	result = register_netdev(xpnet_device);  	if (result != 0) {  | 
