ipath_mad.c

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

C
1,353
字号
	if (cntrs.symbol_error_counter > 0xFFFFUL)		p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF);	else		p->symbol_error_counter =			cpu_to_be16((u16)cntrs.symbol_error_counter);	if (cntrs.link_error_recovery_counter > 0xFFUL)		p->link_error_recovery_counter = 0xFF;	else		p->link_error_recovery_counter =			(u8)cntrs.link_error_recovery_counter;	if (cntrs.link_downed_counter > 0xFFUL)		p->link_downed_counter = 0xFF;	else		p->link_downed_counter = (u8)cntrs.link_downed_counter;	if (cntrs.port_rcv_errors > 0xFFFFUL)		p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF);	else		p->port_rcv_errors =			cpu_to_be16((u16) cntrs.port_rcv_errors);	if (cntrs.port_rcv_remphys_errors > 0xFFFFUL)		p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF);	else		p->port_rcv_remphys_errors =			cpu_to_be16((u16)cntrs.port_rcv_remphys_errors);	if (cntrs.port_xmit_discards > 0xFFFFUL)		p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF);	else		p->port_xmit_discards =			cpu_to_be16((u16)cntrs.port_xmit_discards);	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);	else		p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data);	if (cntrs.port_rcv_data > 0xFFFFFFFFUL)		p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF);	else		p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data);	if (cntrs.port_xmit_packets > 0xFFFFFFFFUL)		p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF);	else		p->port_xmit_packets =			cpu_to_be32((u32)cntrs.port_xmit_packets);	if (cntrs.port_rcv_packets > 0xFFFFFFFFUL)		p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF);	else		p->port_rcv_packets =			cpu_to_be32((u32) cntrs.port_rcv_packets);	return reply((struct ib_smp *) pmp);}static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,					 struct ib_device *ibdev, u8 port){	struct ib_pma_portcounters_ext *p =		(struct ib_pma_portcounters_ext *)pmp->data;	struct ipath_ibdev *dev = to_idev(ibdev);	u64 swords, rwords, spkts, rpkts, xwait;	u8 port_select = p->port_select;	ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,				      &rpkts, &xwait);	/* Adjust counters for any resets done. */	swords -= dev->n_port_xmit_data;	rwords -= dev->n_port_rcv_data;	spkts -= dev->n_port_xmit_packets;	rpkts -= 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;	p->port_xmit_data = cpu_to_be64(swords);	p->port_rcv_data = cpu_to_be64(rwords);	p->port_xmit_packets = cpu_to_be64(spkts);	p->port_rcv_packets = cpu_to_be64(rpkts);	p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit);	p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv);	p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit);	p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv);	return reply((struct ib_smp *) pmp);}static int recv_pma_set_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;	/*	 * Since the HW doesn't support clearing counters, we save the	 * current count and subtract it from future responses.	 */	ipath_layer_get_counters(dev->dd, &cntrs);	if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR)		dev->n_symbol_error_counter = cntrs.symbol_error_counter;	if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY)		dev->n_link_error_recovery_counter =			cntrs.link_error_recovery_counter;	if (p->counter_select & IB_PMA_SEL_LINK_DOWNED)		dev->n_link_downed_counter = cntrs.link_downed_counter;	if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS)		dev->n_port_rcv_errors =			cntrs.port_rcv_errors + dev->rcv_errors;	if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS)		dev->n_port_rcv_remphys_errors =			cntrs.port_rcv_remphys_errors;	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS)		dev->n_port_xmit_discards = cntrs.port_xmit_discards;	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)		dev->n_port_xmit_data = cntrs.port_xmit_data;	if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA)		dev->n_port_rcv_data = cntrs.port_rcv_data;	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS)		dev->n_port_xmit_packets = cntrs.port_xmit_packets;	if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS)		dev->n_port_rcv_packets = cntrs.port_rcv_packets;	return recv_pma_get_portcounters(pmp, ibdev, port);}static int recv_pma_set_portcounters_ext(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);	u64 swords, rwords, spkts, rpkts, xwait;	ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,				      &rpkts, &xwait);	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA)		dev->n_port_xmit_data = swords;	if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA)		dev->n_port_rcv_data = rwords;	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS)		dev->n_port_xmit_packets = spkts;	if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)		dev->n_port_rcv_packets = rpkts;	if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS)		dev->n_unicast_xmit = 0;	if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS)		dev->n_unicast_rcv = 0;	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS)		dev->n_multicast_xmit = 0;	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS)		dev->n_multicast_rcv = 0;	return recv_pma_get_portcounters_ext(pmp, ibdev, port);}static int process_subn(struct ib_device *ibdev, int mad_flags,			u8 port_num, struct ib_mad *in_mad,			struct ib_mad *out_mad){	struct ib_smp *smp = (struct ib_smp *)out_mad;	struct ipath_ibdev *dev = to_idev(ibdev);	int ret;	*out_mad = *in_mad;	if (smp->class_version != 1) {		smp->status |= IB_SMP_UNSUP_VERSION;		ret = reply(smp);		goto bail;	}	/* Is the mkey in the process of expiring? */	if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {		/* Clear timeout and mkey protection field. */		dev->mkey_lease_timeout = 0;		dev->mkeyprot_resv_lmc &= 0x3F;	}	/*	 * M_Key checking depends on	 * Portinfo:M_Key_protect_bits	 */	if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 &&	    dev->mkey != smp->mkey &&	    (smp->method == IB_MGMT_METHOD_SET ||	     (smp->method == IB_MGMT_METHOD_GET &&	      (dev->mkeyprot_resv_lmc >> 7) != 0))) {		if (dev->mkey_violations != 0xFFFF)			++dev->mkey_violations;		if (dev->mkey_lease_timeout ||		    dev->mkey_lease_period == 0) {			ret = IB_MAD_RESULT_SUCCESS |				IB_MAD_RESULT_CONSUMED;			goto bail;		}		dev->mkey_lease_timeout = jiffies +			dev->mkey_lease_period * HZ;		/* Future: Generate a trap notice. */		ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;		goto bail;	} else if (dev->mkey_lease_timeout)		dev->mkey_lease_timeout = 0;	switch (smp->method) {	case IB_MGMT_METHOD_GET:		switch (smp->attr_id) {		case IB_SMP_ATTR_NODE_DESC:			ret = recv_subn_get_nodedescription(smp, ibdev);			goto bail;		case IB_SMP_ATTR_NODE_INFO:			ret = recv_subn_get_nodeinfo(smp, ibdev, port_num);			goto bail;		case IB_SMP_ATTR_GUID_INFO:			ret = recv_subn_get_guidinfo(smp, ibdev);			goto bail;		case IB_SMP_ATTR_PORT_INFO:			ret = recv_subn_get_portinfo(smp, ibdev, port_num);			goto bail;		case IB_SMP_ATTR_PKEY_TABLE:			ret = recv_subn_get_pkeytable(smp, ibdev);			goto bail;		case IB_SMP_ATTR_SM_INFO:			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {				ret = IB_MAD_RESULT_SUCCESS |					IB_MAD_RESULT_CONSUMED;				goto bail;			}			if (dev->port_cap_flags & IB_PORT_SM) {				ret = IB_MAD_RESULT_SUCCESS;				goto bail;			}			/* FALLTHROUGH */		default:			smp->status |= IB_SMP_UNSUP_METH_ATTR;			ret = reply(smp);			goto bail;		}	case IB_MGMT_METHOD_SET:		switch (smp->attr_id) {		case IB_SMP_ATTR_GUID_INFO:			ret = recv_subn_set_guidinfo(smp, ibdev);			goto bail;		case IB_SMP_ATTR_PORT_INFO:			ret = recv_subn_set_portinfo(smp, ibdev, port_num);			goto bail;		case IB_SMP_ATTR_PKEY_TABLE:			ret = recv_subn_set_pkeytable(smp, ibdev);			goto bail;		case IB_SMP_ATTR_SM_INFO:			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {				ret = IB_MAD_RESULT_SUCCESS |					IB_MAD_RESULT_CONSUMED;				goto bail;			}			if (dev->port_cap_flags & IB_PORT_SM) {				ret = IB_MAD_RESULT_SUCCESS;				goto bail;			}			/* FALLTHROUGH */		default:			smp->status |= IB_SMP_UNSUP_METH_ATTR;			ret = reply(smp);			goto bail;		}	case IB_MGMT_METHOD_GET_RESP:		/*		 * The ib_mad module will call us to process responses		 * before checking for other consumers.		 * Just tell the caller to process it normally.		 */		ret = IB_MAD_RESULT_FAILURE;		goto bail;	default:		smp->status |= IB_SMP_UNSUP_METHOD;		ret = reply(smp);	}bail:	return ret;}static int process_perf(struct ib_device *ibdev, u8 port_num,			struct ib_mad *in_mad,			struct ib_mad *out_mad){	struct ib_perf *pmp = (struct ib_perf *)out_mad;	int ret;	*out_mad = *in_mad;	if (pmp->class_version != 1) {		pmp->status |= IB_SMP_UNSUP_VERSION;		ret = reply((struct ib_smp *) pmp);		goto bail;	}	switch (pmp->method) {	case IB_MGMT_METHOD_GET:		switch (pmp->attr_id) {		case IB_PMA_CLASS_PORT_INFO:			ret = recv_pma_get_classportinfo(pmp);			goto bail;		case IB_PMA_PORT_SAMPLES_CONTROL:			ret = recv_pma_get_portsamplescontrol(pmp, ibdev,							      port_num);			goto bail;		case IB_PMA_PORT_SAMPLES_RESULT:			ret = recv_pma_get_portsamplesresult(pmp, ibdev);			goto bail;		case IB_PMA_PORT_SAMPLES_RESULT_EXT:			ret = recv_pma_get_portsamplesresult_ext(pmp,								 ibdev);			goto bail;		case IB_PMA_PORT_COUNTERS:			ret = recv_pma_get_portcounters(pmp, ibdev,							port_num);			goto bail;		case IB_PMA_PORT_COUNTERS_EXT:			ret = recv_pma_get_portcounters_ext(pmp, ibdev,							    port_num);			goto bail;		default:			pmp->status |= IB_SMP_UNSUP_METH_ATTR;			ret = reply((struct ib_smp *) pmp);			goto bail;		}	case IB_MGMT_METHOD_SET:		switch (pmp->attr_id) {		case IB_PMA_PORT_SAMPLES_CONTROL:			ret = recv_pma_set_portsamplescontrol(pmp, ibdev,							      port_num);			goto bail;		case IB_PMA_PORT_COUNTERS:			ret = recv_pma_set_portcounters(pmp, ibdev,							port_num);			goto bail;		case IB_PMA_PORT_COUNTERS_EXT:			ret = recv_pma_set_portcounters_ext(pmp, ibdev,							    port_num);			goto bail;		default:			pmp->status |= IB_SMP_UNSUP_METH_ATTR;			ret = reply((struct ib_smp *) pmp);			goto bail;		}	case IB_MGMT_METHOD_GET_RESP:		/*		 * The ib_mad module will call us to process responses		 * before checking for other consumers.		 * Just tell the caller to process it normally.		 */		ret = IB_MAD_RESULT_FAILURE;		goto bail;	default:		pmp->status |= IB_SMP_UNSUP_METHOD;		ret = reply((struct ib_smp *) pmp);	}bail:	return ret;}/** * ipath_process_mad - process an incoming MAD packet * @ibdev: the infiniband device this packet came in on * @mad_flags: MAD flags * @port_num: the port number this packet came in on * @in_wc: the work completion entry for this packet * @in_grh: the global route header for this packet * @in_mad: the incoming MAD * @out_mad: any outgoing MAD reply * * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not * interested in processing. * * Note that the verbs framework has already done the MAD sanity checks, * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE * MADs. * * This is called by the ib_mad module. */int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,		      struct ib_wc *in_wc, struct ib_grh *in_grh,		      struct ib_mad *in_mad, struct ib_mad *out_mad){	struct ipath_ibdev *dev = to_idev(ibdev);	int ret;	/*	 * Snapshot current HW counters to "clear" them.	 * This should be done when the driver is loaded except that for	 * some reason we get a zillion errors when brining up the link.	 */	if (dev->rcv_errors == 0) {		struct ipath_layer_counters cntrs;		ipath_layer_get_counters(to_idev(ibdev)->dd, &cntrs);		dev->rcv_errors++;		dev->n_symbol_error_counter = cntrs.symbol_error_counter;		dev->n_link_error_recovery_counter =			cntrs.link_error_recovery_counter;		dev->n_link_downed_counter = cntrs.link_downed_counter;		dev->n_port_rcv_errors = cntrs.port_rcv_errors + 1;		dev->n_port_rcv_remphys_errors =			cntrs.port_rcv_remphys_errors;		dev->n_port_xmit_discards = cntrs.port_xmit_discards;		dev->n_port_xmit_data = cntrs.port_xmit_data;		dev->n_port_rcv_data = cntrs.port_rcv_data;		dev->n_port_xmit_packets = cntrs.port_xmit_packets;		dev->n_port_rcv_packets = cntrs.port_rcv_packets;	}	switch (in_mad->mad_hdr.mgmt_class) {	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:	case IB_MGMT_CLASS_SUBN_LID_ROUTED:		ret = process_subn(ibdev, mad_flags, port_num,				   in_mad, out_mad);		goto bail;	case IB_MGMT_CLASS_PERF_MGMT:		ret = process_perf(ibdev, port_num, in_mad, out_mad);		goto bail;	default:		ret = IB_MAD_RESULT_SUCCESS;	}bail:	return ret;}

⌨️ 快捷键说明

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