ipath_mad.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,353 行 · 第 1/3 页

C
1,353
字号
	/*	 * Do the port state change now that the other link parameters	 * have been set.	 * Changing the port physical state only makes sense if the link	 * is down or is being set to down.	 */	state = pip->linkspeed_portstate & 0xF;	flags = ipath_layer_get_flags(dev->dd);	lstate = (pip->portphysstate_linkdown >> 4) & 0xF;	if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))		goto err;	/*	 * Only state changes of DOWN, ARM, and ACTIVE are valid	 * and must be in the correct state to take effect (see 7.2.6).	 */	switch (state) {	case IB_PORT_NOP:		if (lstate == 0)			break;		/* FALLTHROUGH */	case IB_PORT_DOWN:		if (lstate == 0)			if (ipath_layer_get_linkdowndefaultstate(dev->dd))				lstate = IPATH_IB_LINKDOWN_SLEEP;			else				lstate = IPATH_IB_LINKDOWN;		else if (lstate == 1)			lstate = IPATH_IB_LINKDOWN_SLEEP;		else if (lstate == 2)			lstate = IPATH_IB_LINKDOWN;		else if (lstate == 3)			lstate = IPATH_IB_LINKDOWN_DISABLE;		else			goto err;		ipath_layer_set_linkstate(dev->dd, lstate);		if (flags & IPATH_LINKACTIVE) {			event.event = IB_EVENT_PORT_ERR;			ib_dispatch_event(&event);		}		break;	case IB_PORT_ARMED:		if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))			break;		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKARM);		if (flags & IPATH_LINKACTIVE) {			event.event = IB_EVENT_PORT_ERR;			ib_dispatch_event(&event);		}		break;	case IB_PORT_ACTIVE:		if (!(flags & IPATH_LINKARMED))			break;		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE);		event.event = IB_EVENT_PORT_ACTIVE;		ib_dispatch_event(&event);		break;	default:		/* XXX We have already partially updated our state! */		goto err;	}	ret = recv_subn_get_portinfo(smp, ibdev, port);	if (clientrereg)		pip->clientrereg_resv_subnetto |= 0x80;	goto done;err:	smp->status |= IB_SMP_INVALID_FIELD;	ret = recv_subn_get_portinfo(smp, ibdev, port);done:	return ret;}static int recv_subn_set_pkeytable(struct ib_smp *smp,				   struct ib_device *ibdev){	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);	__be16 *p = (__be16 *) smp->data;	u16 *q = (u16 *) smp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	unsigned i, n = ipath_layer_get_npkeys(dev->dd);	for (i = 0; i < n; i++)		q[i] = be16_to_cpu(p[i]);	if (startpx != 0 ||	    ipath_layer_set_pkeys(dev->dd, q) != 0)		smp->status |= IB_SMP_INVALID_FIELD;	return recv_subn_get_pkeytable(smp, ibdev);}#define IB_PMA_CLASS_PORT_INFO		__constant_htons(0x0001)#define IB_PMA_PORT_SAMPLES_CONTROL	__constant_htons(0x0010)#define IB_PMA_PORT_SAMPLES_RESULT	__constant_htons(0x0011)#define IB_PMA_PORT_COUNTERS		__constant_htons(0x0012)#define IB_PMA_PORT_COUNTERS_EXT	__constant_htons(0x001D)#define IB_PMA_PORT_SAMPLES_RESULT_EXT	__constant_htons(0x001E)struct ib_perf {	u8 base_version;	u8 mgmt_class;	u8 class_version;	u8 method;	__be16 status;	__be16 unused;	__be64 tid;	__be16 attr_id;	__be16 resv;	__be32 attr_mod;	u8 reserved[40];	u8 data[192];} __attribute__ ((packed));struct ib_pma_classportinfo {	u8 base_version;	u8 class_version;	__be16 cap_mask;	u8 reserved[3];	u8 resp_time_value;	/* only lower 5 bits */	union ib_gid redirect_gid;	__be32 redirect_tc_sl_fl;	/* 8, 4, 20 bits respectively */	__be16 redirect_lid;	__be16 redirect_pkey;	__be32 redirect_qp;	/* only lower 24 bits */	__be32 redirect_qkey;	union ib_gid trap_gid;	__be32 trap_tc_sl_fl;	/* 8, 4, 20 bits respectively */	__be16 trap_lid;	__be16 trap_pkey;	__be32 trap_hl_qp;	/* 8, 24 bits respectively */	__be32 trap_qkey;} __attribute__ ((packed));struct ib_pma_portsamplescontrol {	u8 opcode;	u8 port_select;	u8 tick;	u8 counter_width;	/* only lower 3 bits */	__be32 counter_mask0_9;	/* 2, 10 * 3, bits */	__be16 counter_mask10_14;	/* 1, 5 * 3, bits */	u8 sample_mechanisms;	u8 sample_status;	/* only lower 2 bits */	__be64 option_mask;	__be64 vendor_mask;	__be32 sample_start;	__be32 sample_interval;	__be16 tag;	__be16 counter_select[15];} __attribute__ ((packed));struct ib_pma_portsamplesresult {	__be16 tag;	__be16 sample_status;	/* only lower 2 bits */	__be32 counter[15];} __attribute__ ((packed));struct ib_pma_portsamplesresult_ext {	__be16 tag;	__be16 sample_status;	/* only lower 2 bits */	__be32 extended_width;	/* only upper 2 bits */	__be64 counter[15];} __attribute__ ((packed));struct ib_pma_portcounters {	u8 reserved;	u8 port_select;	__be16 counter_select;	__be16 symbol_error_counter;	u8 link_error_recovery_counter;	u8 link_downed_counter;	__be16 port_rcv_errors;	__be16 port_rcv_remphys_errors;	__be16 port_rcv_switch_relay_errors;	__be16 port_xmit_discards;	u8 port_xmit_constraint_errors;	u8 port_rcv_constraint_errors;	u8 reserved1;	u8 lli_ebor_errors;	/* 4, 4, bits */	__be16 reserved2;	__be16 vl15_dropped;	__be32 port_xmit_data;	__be32 port_rcv_data;	__be32 port_xmit_packets;	__be32 port_rcv_packets;} __attribute__ ((packed));#define IB_PMA_SEL_SYMBOL_ERROR			__constant_htons(0x0001)#define IB_PMA_SEL_LINK_ERROR_RECOVERY		__constant_htons(0x0002)#define IB_PMA_SEL_LINK_DOWNED			__constant_htons(0x0004)#define IB_PMA_SEL_PORT_RCV_ERRORS		__constant_htons(0x0008)#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS	__constant_htons(0x0010)#define IB_PMA_SEL_PORT_XMIT_DISCARDS		__constant_htons(0x0040)#define IB_PMA_SEL_PORT_XMIT_DATA		__constant_htons(0x1000)#define IB_PMA_SEL_PORT_RCV_DATA		__constant_htons(0x2000)#define IB_PMA_SEL_PORT_XMIT_PACKETS		__constant_htons(0x4000)#define IB_PMA_SEL_PORT_RCV_PACKETS		__constant_htons(0x8000)struct ib_pma_portcounters_ext {	u8 reserved;	u8 port_select;	__be16 counter_select;	__be32 reserved1;	__be64 port_xmit_data;	__be64 port_rcv_data;	__be64 port_xmit_packets;	__be64 port_rcv_packets;	__be64 port_unicast_xmit_packets;	__be64 port_unicast_rcv_packets;	__be64 port_multicast_xmit_packets;	__be64 port_multicast_rcv_packets;} __attribute__ ((packed));#define IB_PMA_SELX_PORT_XMIT_DATA		__constant_htons(0x0001)#define IB_PMA_SELX_PORT_RCV_DATA		__constant_htons(0x0002)#define IB_PMA_SELX_PORT_XMIT_PACKETS		__constant_htons(0x0004)#define IB_PMA_SELX_PORT_RCV_PACKETS		__constant_htons(0x0008)#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS	__constant_htons(0x0010)#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS	__constant_htons(0x0020)#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS	__constant_htons(0x0040)#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS	__constant_htons(0x0080)static int recv_pma_get_classportinfo(struct ib_perf *pmp){	struct ib_pma_classportinfo *p =		(struct ib_pma_classportinfo *)pmp->data;	memset(pmp->data, 0, sizeof(pmp->data));	if (pmp->attr_mod != 0)		pmp->status |= IB_SMP_INVALID_FIELD;	/* Indicate AllPortSelect is valid (only one port anyway) */	p->cap_mask = __constant_cpu_to_be16(1 << 8);	p->base_version = 1;	p->class_version = 1;	/*	 * Expected response time is 4.096 usec. * 2^18 == 1.073741824	 * sec.	 */	p->resp_time_value = 18;	return reply((struct ib_smp *) pmp);}/* * The PortSamplesControl.CounterMasks field is an array of 3 bit fields * which specify the N'th counter's capabilities. See ch. 16.1.3.2. * We support 5 counters which only count the mandatory quantities. */#define COUNTER_MASK(q, n) (q << ((9 - n) * 3))#define COUNTER_MASK0_9 \	__constant_cpu_to_be32(COUNTER_MASK(1, 0) | \			       COUNTER_MASK(1, 1) | \			       COUNTER_MASK(1, 2) | \			       COUNTER_MASK(1, 3) | \			       COUNTER_MASK(1, 4))static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,					   struct ib_device *ibdev, u8 port){	struct ib_pma_portsamplescontrol *p =		(struct ib_pma_portsamplescontrol *)pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	unsigned long flags;	u8 port_select = p->port_select;	memset(pmp->data, 0, sizeof(pmp->data));	p->port_select = port_select;	if (pmp->attr_mod != 0 ||	    (port_select != port && port_select != 0xFF))		pmp->status |= IB_SMP_INVALID_FIELD;	/*	 * Ticks are 10x the link transfer period which for 2.5Gbs is 4	 * nsec.  0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec.  Sample	 * intervals are counted in ticks.  Since we use Linux timers, that	 * count in jiffies, we can't sample for less than 1000 ticks if HZ	 * == 1000 (4000 ticks if HZ is 250).	 */	/* XXX This is WRONG. */	p->tick = 250;		/* 1 usec. */	p->counter_width = 4;	/* 32 bit counters */	p->counter_mask0_9 = COUNTER_MASK0_9;	spin_lock_irqsave(&dev->pending_lock, flags);	p->sample_status = dev->pma_sample_status;	p->sample_start = cpu_to_be32(dev->pma_sample_start);	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);	p->tag = cpu_to_be16(dev->pma_tag);	p->counter_select[0] = dev->pma_counter_select[0];	p->counter_select[1] = dev->pma_counter_select[1];	p->counter_select[2] = dev->pma_counter_select[2];	p->counter_select[3] = dev->pma_counter_select[3];	p->counter_select[4] = dev->pma_counter_select[4];	spin_unlock_irqrestore(&dev->pending_lock, flags);	return reply((struct ib_smp *) pmp);}static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,					   struct ib_device *ibdev, u8 port){	struct ib_pma_portsamplescontrol *p =		(struct ib_pma_portsamplescontrol *)pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	unsigned long flags;	u32 start;	int ret;	if (pmp->attr_mod != 0 ||	    (p->port_select != port && p->port_select != 0xFF)) {		pmp->status |= IB_SMP_INVALID_FIELD;		ret = reply((struct ib_smp *) pmp);		goto bail;	}	start = be32_to_cpu(p->sample_start);	if (start != 0) {		spin_lock_irqsave(&dev->pending_lock, flags);		if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {			dev->pma_sample_status =				IB_PMA_SAMPLE_STATUS_STARTED;			dev->pma_sample_start = start;			dev->pma_sample_interval =				be32_to_cpu(p->sample_interval);			dev->pma_tag = be16_to_cpu(p->tag);			if (p->counter_select[0])				dev->pma_counter_select[0] =					p->counter_select[0];			if (p->counter_select[1])				dev->pma_counter_select[1] =					p->counter_select[1];			if (p->counter_select[2])				dev->pma_counter_select[2] =					p->counter_select[2];			if (p->counter_select[3])				dev->pma_counter_select[3] =					p->counter_select[3];			if (p->counter_select[4])				dev->pma_counter_select[4] =					p->counter_select[4];		}		spin_unlock_irqrestore(&dev->pending_lock, flags);	}	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);bail:	return ret;}static u64 get_counter(struct ipath_ibdev *dev, __be16 sel){	u64 ret;	switch (sel) {	case IB_PMA_PORT_XMIT_DATA:		ret = dev->ipath_sword;		break;	case IB_PMA_PORT_RCV_DATA:		ret = dev->ipath_rword;		break;	case IB_PMA_PORT_XMIT_PKTS:		ret = dev->ipath_spkts;		break;	case IB_PMA_PORT_RCV_PKTS:		ret = dev->ipath_rpkts;		break;	case IB_PMA_PORT_XMIT_WAIT:		ret = dev->ipath_xmit_wait;		break;	default:		ret = 0;	}	return ret;}static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,					  struct ib_device *ibdev){	struct ib_pma_portsamplesresult *p =		(struct ib_pma_portsamplesresult *)pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	int i;	memset(pmp->data, 0, sizeof(pmp->data));	p->tag = cpu_to_be16(dev->pma_tag);	p->sample_status = cpu_to_be16(dev->pma_sample_status);	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)		p->counter[i] = cpu_to_be32(			get_counter(dev, dev->pma_counter_select[i]));	return reply((struct ib_smp *) pmp);}static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,					      struct ib_device *ibdev){	struct ib_pma_portsamplesresult_ext *p =		(struct ib_pma_portsamplesresult_ext *)pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	int i;	memset(pmp->data, 0, sizeof(pmp->data));	p->tag = cpu_to_be16(dev->pma_tag);	p->sample_status = cpu_to_be16(dev->pma_sample_status);	/* 64 bits */	p->extended_width = __constant_cpu_to_be32(0x80000000);	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)		p->counter[i] = cpu_to_be64(			get_counter(dev, dev->pma_counter_select[i]));	return reply((struct ib_smp *) pmp);}static int recv_pma_get_portcounters(struct ib_perf *pmp,				     struct ib_device *ibdev, u8 port){	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)		pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	struct ipath_layer_counters cntrs;	u8 port_select = p->port_select;	ipath_layer_get_counters(dev->dd, &cntrs);	/* Adjust counters for any resets done. */	cntrs.symbol_error_counter -= dev->n_symbol_error_counter;	cntrs.link_error_recovery_counter -=		dev->n_link_error_recovery_counter;	cntrs.link_downed_counter -= dev->n_link_downed_counter;	cntrs.port_rcv_errors += dev->rcv_errors;	cntrs.port_rcv_errors -= dev->n_port_rcv_errors;	cntrs.port_rcv_remphys_errors -= dev->n_port_rcv_remphys_errors;	cntrs.port_xmit_discards -= dev->n_port_xmit_discards;	cntrs.port_xmit_data -= dev->n_port_xmit_data;	cntrs.port_rcv_data -= dev->n_port_rcv_data;	cntrs.port_xmit_packets -= dev->n_port_xmit_packets;	cntrs.port_rcv_packets -= dev->n_port_rcv_packets;	memset(pmp->data, 0, sizeof(pmp->data));	p->port_select = port_select;	if (pmp->attr_mod != 0 ||	    (port_select != port && port_select != 0xFF))		pmp->status |= IB_SMP_INVALID_FIELD;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?