ipath_verbs.c

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

C
1,205
字号
	if (qp_num == IPS_MULTICAST_QPN) {		struct ipath_mcast *mcast;		struct ipath_mcast_qp *p;		mcast = ipath_mcast_find(&hdr->u.l.grh.dgid);		if (mcast == NULL) {			dev->n_pkt_drops++;			goto bail;		}		dev->n_multicast_rcv++;		list_for_each_entry_rcu(p, &mcast->qp_list, list)			ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,				     tlen, p->qp);		/*		 * Notify ipath_multicast_detach() if it is waiting for us		 * to finish.		 */		if (atomic_dec_return(&mcast->refcount) <= 1)			wake_up(&mcast->wait);	} else {		qp = ipath_lookup_qpn(&dev->qp_table, qp_num);		if (qp) {			dev->n_unicast_rcv++;			ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,				     tlen, qp);			/*			 * Notify ipath_destroy_qp() if it is waiting			 * for us to finish.			 */			if (atomic_dec_and_test(&qp->refcount))				wake_up(&qp->wait);		} else			dev->n_pkt_drops++;	}bail:;}/** * ipath_ib_timer - verbs timer * @arg: the device pointer * * This is called from ipath_do_rcv_timer() at interrupt level to check for * QPs which need retransmits and to collect performance numbers. */static void ipath_ib_timer(void *arg){	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;	struct ipath_qp *resend = NULL;	struct list_head *last;	struct ipath_qp *qp;	unsigned long flags;	if (dev == NULL)		return;	spin_lock_irqsave(&dev->pending_lock, flags);	/* Start filling the next pending queue. */	if (++dev->pending_index >= ARRAY_SIZE(dev->pending))		dev->pending_index = 0;	/* Save any requests still in the new queue, they have timed out. */	last = &dev->pending[dev->pending_index];	while (!list_empty(last)) {		qp = list_entry(last->next, struct ipath_qp, timerwait);		list_del_init(&qp->timerwait);		qp->timer_next = resend;		resend = qp;		atomic_inc(&qp->refcount);	}	last = &dev->rnrwait;	if (!list_empty(last)) {		qp = list_entry(last->next, struct ipath_qp, timerwait);		if (--qp->s_rnr_timeout == 0) {			do {				list_del_init(&qp->timerwait);				tasklet_hi_schedule(&qp->s_task);				if (list_empty(last))					break;				qp = list_entry(last->next, struct ipath_qp,						timerwait);			} while (qp->s_rnr_timeout == 0);		}	}	/*	 * We should only be in the started state if pma_sample_start != 0	 */	if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED &&	    --dev->pma_sample_start == 0) {		dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING;		ipath_layer_snapshot_counters(dev->dd, &dev->ipath_sword,					      &dev->ipath_rword,					      &dev->ipath_spkts,					      &dev->ipath_rpkts,					      &dev->ipath_xmit_wait);	}	if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) {		if (dev->pma_sample_interval == 0) {			u64 ta, tb, tc, td, te;			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE;			ipath_layer_snapshot_counters(dev->dd, &ta, &tb,						      &tc, &td, &te);			dev->ipath_sword = ta - dev->ipath_sword;			dev->ipath_rword = tb - dev->ipath_rword;			dev->ipath_spkts = tc - dev->ipath_spkts;			dev->ipath_rpkts = td - dev->ipath_rpkts;			dev->ipath_xmit_wait = te - dev->ipath_xmit_wait;		}		else			dev->pma_sample_interval--;	}	spin_unlock_irqrestore(&dev->pending_lock, flags);	/* XXX What if timer fires again while this is running? */	for (qp = resend; qp != NULL; qp = qp->timer_next) {		struct ib_wc wc;		spin_lock_irqsave(&qp->s_lock, flags);		if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) {			dev->n_timeouts++;			ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);		}		spin_unlock_irqrestore(&qp->s_lock, flags);		/* Notify ipath_destroy_qp() if it is waiting. */		if (atomic_dec_and_test(&qp->refcount))			wake_up(&qp->wait);	}}/** * 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). */static int ipath_ib_piobufavail(void *arg){	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;	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);		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);	u32 vendor, boardrev, majrev, minrev;	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;	ipath_layer_query_device(dev->dd, &vendor, &boardrev,				 &majrev, &minrev);	props->vendor_id = vendor;	props->vendor_part_id = boardrev;	props->hw_ver = boardrev << 16 | majrev << 8 | minrev;	props->sys_image_guid = dev->sys_image_guid;	props->max_mr_size = ~0ull;	props->max_qp = 0xffff;	props->max_qp_wr = 0xffff;	props->max_sge = 255;	props->max_cq = 0xffff;	props->max_cqe = 0xffff;	props->max_mr = 0xffff;	props->max_pd = 0xffff;	props->max_qp_rd_atom = 1;	props->max_qp_init_rd_atom = 1;	/* props->max_res_rd_atom */	props->max_srq = 0xffff;	props->max_srq_wr = 0xffff;	props->max_srq_sge = 255;	/* props->local_ca_ack_delay */	props->atomic_cap = IB_ATOMIC_HCA;	props->max_pkeys = ipath_layer_get_npkeys(dev->dd);	props->max_mcast_grp = 0xffff;	props->max_mcast_qp_attach = 0xffff;	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,};static int ipath_query_port(struct ib_device *ibdev,			    u8 port, struct ib_port_attr *props){	struct ipath_ibdev *dev = to_idev(ibdev);	enum ib_mtu mtu;	u16 lid = ipath_layer_get_lid(dev->dd);	u64 ibcstat;	memset(props, 0, sizeof(*props));	props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE);	props->lmc = dev->mkeyprot_resv_lmc & 7;	props->sm_lid = dev->sm_lid;	props->sm_sl = dev->sm_sl;	ibcstat = ipath_layer_get_lastibcstat(dev->dd);	props->state = ((ibcstat >> 4) & 0x3) + 1;	/* See phys_state_show() */	props->phys_state = ipath_cvt_physportstate[		ipath_layer_get_lastibcstat(dev->dd) & 0xf];	props->port_cap_flags = dev->port_cap_flags;	props->gid_tbl_len = 1;	props->max_msg_sz = 4096;	props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd);	props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) -		dev->n_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;	props->max_mtu = IB_MTU_4096;	switch (ipath_layer_get_ibmtu(dev->dd)) {	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_layer_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 = ipath_layer_get_guid(dev->dd);	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_pd *pd;	struct ib_pd *ret;	pd = kmalloc(sizeof *pd, GFP_KERNEL);	if (!pd) {		ret = ERR_PTR(-ENOMEM);		goto bail;	}	/* 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);	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;	/* A multicast address requires a GRH (see ch. 8.4.1). */	if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&	    ah_attr->dlid != IPS_PERMISSIVE_LID &&	    !(ah_attr->ah_flags & IB_AH_GRH)) {		ret = ERR_PTR(-EINVAL);		goto bail;	}	ah = kmalloc(sizeof *ah, GFP_ATOMIC);	if (!ah) {		ret = ERR_PTR(-ENOMEM);		goto bail;	}	/* ib_create_ah() will initialize ah->ibah. */	ah->attr = *ah_attr;	ret = &ah->ibah;

⌨️ 快捷键说明

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