ipath_verbs.c

来自「linux 内核源代码」· C语言 代码 · 共 1,887 行 · 第 1/4 页

C
1,887
字号
 * @hdr: the packet header * @hdrwords: the number of words in the header * @ss: the SGE to send * @len: the length of the packet in bytes */int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,		     u32 hdrwords, struct ipath_sge_state *ss, u32 len){	struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;	u32 plen;	int ret;	u32 dwords = (len + 3) >> 2;	/* +1 is for the qword padding of pbc */	plen = hdrwords + dwords + 1;	/* Drop non-VL15 packets if we are not in the active state */	if (!(dd->ipath_flags & IPATH_LINKACTIVE) &&	    qp->ibqp.qp_type != IB_QPT_SMI) {		if (qp->s_wqe)			ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS);		ret = 0;	} else		ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,					   ss, len, plen, dwords);	return ret;}int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords,			    u64 *rwords, u64 *spkts, u64 *rpkts,			    u64 *xmit_wait){	int ret;	if (!(dd->ipath_flags & IPATH_INITTED)) {		/* no hardware, freeze, etc. */		ret = -EINVAL;		goto bail;	}	*swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);	*rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);	*spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);	*rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);	*xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt);	ret = 0;bail:	return ret;}/** * ipath_get_counters - get various chip counters * @dd: the infinipath device * @cntrs: counters are placed here * * Return the counters needed by recv_pma_get_portcounters(). */int ipath_get_counters(struct ipath_devdata *dd,		       struct ipath_verbs_counters *cntrs){	struct ipath_cregs const *crp = dd->ipath_cregs;	int ret;	if (!(dd->ipath_flags & IPATH_INITTED)) {		/* no hardware, freeze, etc. */		ret = -EINVAL;		goto bail;	}	cntrs->symbol_error_counter =		ipath_snap_cntr(dd, crp->cr_ibsymbolerrcnt);	cntrs->link_error_recovery_counter =		ipath_snap_cntr(dd, crp->cr_iblinkerrrecovcnt);	/*	 * The link downed counter counts when the other side downs the	 * connection.  We add in the number of times we downed the link	 * due to local link integrity errors to compensate.	 */	cntrs->link_downed_counter =		ipath_snap_cntr(dd, crp->cr_iblinkdowncnt);	cntrs->port_rcv_errors =		ipath_snap_cntr(dd, crp->cr_rxdroppktcnt) +		ipath_snap_cntr(dd, crp->cr_rcvovflcnt) +		ipath_snap_cntr(dd, crp->cr_portovflcnt) +		ipath_snap_cntr(dd, crp->cr_err_rlencnt) +		ipath_snap_cntr(dd, crp->cr_invalidrlencnt) +		ipath_snap_cntr(dd, crp->cr_errlinkcnt) +		ipath_snap_cntr(dd, crp->cr_erricrccnt) +		ipath_snap_cntr(dd, crp->cr_errvcrccnt) +		ipath_snap_cntr(dd, crp->cr_errlpcrccnt) +		ipath_snap_cntr(dd, crp->cr_badformatcnt) +		dd->ipath_rxfc_unsupvl_errs;	cntrs->port_rcv_remphys_errors =		ipath_snap_cntr(dd, crp->cr_rcvebpcnt);	cntrs->port_xmit_discards = ipath_snap_cntr(dd, crp->cr_unsupvlcnt);	cntrs->port_xmit_data = ipath_snap_cntr(dd, crp->cr_wordsendcnt);	cntrs->port_rcv_data = ipath_snap_cntr(dd, crp->cr_wordrcvcnt);	cntrs->port_xmit_packets = ipath_snap_cntr(dd, crp->cr_pktsendcnt);	cntrs->port_rcv_packets = ipath_snap_cntr(dd, crp->cr_pktrcvcnt);	cntrs->local_link_integrity_errors =		(dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?		dd->ipath_lli_errs : dd->ipath_lli_errors;	cntrs->excessive_buffer_overrun_errors = dd->ipath_overrun_thresh_errs;	ret = 0;bail:	return ret;}/** * ipath_ib_piobufavail - callback when a PIO buffer is available * @arg: the device pointer * * This is called from ipath_intr() at interrupt level when a PIO buffer is * available after ipath_verbs_send() returned an error that no buffers were * available.  Return 1 if we consumed all the PIO buffers and we still have * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and * return zero). */int ipath_ib_piobufavail(struct ipath_ibdev *dev){	struct ipath_qp *qp;	unsigned long flags;	if (dev == NULL)		goto bail;	spin_lock_irqsave(&dev->pending_lock, flags);	while (!list_empty(&dev->piowait)) {		qp = list_entry(dev->piowait.next, struct ipath_qp,				piowait);		list_del_init(&qp->piowait);		clear_bit(IPATH_S_BUSY, &qp->s_busy);		tasklet_hi_schedule(&qp->s_task);	}	spin_unlock_irqrestore(&dev->pending_lock, flags);bail:	return 0;}static int ipath_query_device(struct ib_device *ibdev,			      struct ib_device_attr *props){	struct ipath_ibdev *dev = to_idev(ibdev);	memset(props, 0, sizeof(*props));	props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |		IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |		IB_DEVICE_SYS_IMAGE_GUID;	props->page_size_cap = PAGE_SIZE;	props->vendor_id = dev->dd->ipath_vendorid;	props->vendor_part_id = dev->dd->ipath_deviceid;	props->hw_ver = dev->dd->ipath_pcirev;	props->sys_image_guid = dev->sys_image_guid;	props->max_mr_size = ~0ull;	props->max_qp = ib_ipath_max_qps;	props->max_qp_wr = ib_ipath_max_qp_wrs;	props->max_sge = ib_ipath_max_sges;	props->max_cq = ib_ipath_max_cqs;	props->max_ah = ib_ipath_max_ahs;	props->max_cqe = ib_ipath_max_cqes;	props->max_mr = dev->lk_table.max;	props->max_fmr = dev->lk_table.max;	props->max_map_per_fmr = 32767;	props->max_pd = ib_ipath_max_pds;	props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC;	props->max_qp_init_rd_atom = 255;	/* props->max_res_rd_atom */	props->max_srq = ib_ipath_max_srqs;	props->max_srq_wr = ib_ipath_max_srq_wrs;	props->max_srq_sge = ib_ipath_max_srq_sges;	/* props->local_ca_ack_delay */	props->atomic_cap = IB_ATOMIC_GLOB;	props->max_pkeys = ipath_get_npkeys(dev->dd);	props->max_mcast_grp = ib_ipath_max_mcast_grps;	props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached;	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *		props->max_mcast_grp;	return 0;}const u8 ipath_cvt_physportstate[16] = {	[INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,	[INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,};u32 ipath_get_cr_errpkey(struct ipath_devdata *dd){	return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);}static int ipath_query_port(struct ib_device *ibdev,			    u8 port, struct ib_port_attr *props){	struct ipath_ibdev *dev = to_idev(ibdev);	struct ipath_devdata *dd = dev->dd;	enum ib_mtu mtu;	u16 lid = dd->ipath_lid;	u64 ibcstat;	memset(props, 0, sizeof(*props));	props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE);	props->lmc = dd->ipath_lmc;	props->sm_lid = dev->sm_lid;	props->sm_sl = dev->sm_sl;	ibcstat = dd->ipath_lastibcstat;	props->state = ((ibcstat >> 4) & 0x3) + 1;	/* See phys_state_show() */	props->phys_state = ipath_cvt_physportstate[		dd->ipath_lastibcstat & 0xf];	props->port_cap_flags = dev->port_cap_flags;	props->gid_tbl_len = 1;	props->max_msg_sz = 0x80000000;	props->pkey_tbl_len = ipath_get_npkeys(dd);	props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) -		dev->z_pkey_violations;	props->qkey_viol_cntr = dev->qkey_violations;	props->active_width = IB_WIDTH_4X;	/* See rate_show() */	props->active_speed = 1;	/* Regular 10Mbs speed. */	props->max_vl_num = 1;		/* VLCap = VL0 */	props->init_type_reply = 0;	/*	 * Note: the chip supports a maximum MTU of 4096, but the driver	 * hasn't implemented this feature yet, so set the maximum value	 * to 2048.	 */	props->max_mtu = IB_MTU_2048;	switch (dd->ipath_ibmtu) {	case 4096:		mtu = IB_MTU_4096;		break;	case 2048:		mtu = IB_MTU_2048;		break;	case 1024:		mtu = IB_MTU_1024;		break;	case 512:		mtu = IB_MTU_512;		break;	case 256:		mtu = IB_MTU_256;		break;	default:		mtu = IB_MTU_2048;	}	props->active_mtu = mtu;	props->subnet_timeout = dev->subnet_timeout;	return 0;}static int ipath_modify_device(struct ib_device *device,			       int device_modify_mask,			       struct ib_device_modify *device_modify){	int ret;	if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID |				   IB_DEVICE_MODIFY_NODE_DESC)) {		ret = -EOPNOTSUPP;		goto bail;	}	if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC)		memcpy(device->node_desc, device_modify->node_desc, 64);	if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID)		to_idev(device)->sys_image_guid =			cpu_to_be64(device_modify->sys_image_guid);	ret = 0;bail:	return ret;}static int ipath_modify_port(struct ib_device *ibdev,			     u8 port, int port_modify_mask,			     struct ib_port_modify *props){	struct ipath_ibdev *dev = to_idev(ibdev);	dev->port_cap_flags |= props->set_port_cap_mask;	dev->port_cap_flags &= ~props->clr_port_cap_mask;	if (port_modify_mask & IB_PORT_SHUTDOWN)		ipath_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);	if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)		dev->qkey_violations = 0;	return 0;}static int ipath_query_gid(struct ib_device *ibdev, u8 port,			   int index, union ib_gid *gid){	struct ipath_ibdev *dev = to_idev(ibdev);	int ret;	if (index >= 1) {		ret = -EINVAL;		goto bail;	}	gid->global.subnet_prefix = dev->gid_prefix;	gid->global.interface_id = dev->dd->ipath_guid;	ret = 0;bail:	return ret;}static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev,				    struct ib_ucontext *context,				    struct ib_udata *udata){	struct ipath_ibdev *dev = to_idev(ibdev);	struct ipath_pd *pd;	struct ib_pd *ret;	/*	 * This is actually totally arbitrary.	Some correctness tests	 * assume there's a maximum number of PDs that can be allocated.	 * We don't actually have this limit, but we fail the test if	 * we allow allocations of more than we report for this value.	 */	pd = kmalloc(sizeof *pd, GFP_KERNEL);	if (!pd) {		ret = ERR_PTR(-ENOMEM);		goto bail;	}	spin_lock(&dev->n_pds_lock);	if (dev->n_pds_allocated == ib_ipath_max_pds) {		spin_unlock(&dev->n_pds_lock);		kfree(pd);		ret = ERR_PTR(-ENOMEM);		goto bail;	}	dev->n_pds_allocated++;	spin_unlock(&dev->n_pds_lock);	/* ib_alloc_pd() will initialize pd->ibpd. */	pd->user = udata != NULL;	ret = &pd->ibpd;bail:	return ret;}static int ipath_dealloc_pd(struct ib_pd *ibpd){	struct ipath_pd *pd = to_ipd(ibpd);	struct ipath_ibdev *dev = to_idev(ibpd->device);	spin_lock(&dev->n_pds_lock);	dev->n_pds_allocated--;	spin_unlock(&dev->n_pds_lock);	kfree(pd);	return 0;}/** * ipath_create_ah - create an address handle * @pd: the protection domain * @ah_attr: the attributes of the AH * * This may be called from interrupt context. */static struct ib_ah *ipath_create_ah(struct ib_pd *pd,				     struct ib_ah_attr *ah_attr){	struct ipath_ah *ah;	struct ib_ah *ret;	struct ipath_ibdev *dev = to_idev(pd->device);	unsigned long flags;	/* A multicast address requires a GRH (see ch. 8.4.1). */	if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE &&	    ah_attr->dlid != IPATH_PERMISSIVE_LID &&	    !(ah_attr->ah_flags & IB_AH_GRH)) {		ret = ERR_PTR(-EINVAL);		goto bail;	}	if (ah_attr->dlid == 0) {		ret = ERR_PTR(-EINVAL);		goto bail;	}	if (ah_attr->port_num < 1 ||	    ah_attr->port_num > pd->device->phys_port_cnt) {		ret = ERR_PTR(-EINVAL);		goto bail;	}	ah = kmalloc(sizeof *ah, GFP_ATOMIC);	if (!ah) {		ret = ERR_PTR(-ENOMEM);		goto bail;	}	spin_lock_irqsave(&dev->n_ahs_lock, flags);	if (dev->n_ahs_allocated == ib_ipath_max_ahs) {		spin_unlock_irqrestore(&dev->n_ahs_lock, flags);		kfree(ah);		ret = ERR_PTR(-ENOMEM);		goto bail;	}	dev->n_ahs_allocated++;	spin_unlock_irqrestore(&dev->n_ahs_lock, flags);	/* ib_create_ah() will initialize ah->ibah. */	ah->attr = *ah_attr;	ret = &ah->ibah;bail:	return ret;}/** * ipath_destroy_ah - destroy an address handle * @ibah: the AH to destroy * * This may be called from interrupt context. */static int ipath_destroy_ah(struct ib_ah *ibah){	struct ipath_ibdev *dev = to_idev(ibah->device);	struct ipath_ah *ah = to_iah(ibah);	unsigned long flags;	spin_lock_irqsave(&dev->n_ahs_lock, flags);	dev->n_ahs_allocated--;	spin_unlock_irqrestore(&dev->n_ahs_lock, flags);	kfree(ah);	return 0;}static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr){	struct ipath_ah *ah = to_iah(ibah);	*ah_attr = ah->attr;

⌨️ 快捷键说明

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