⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mthca_qp.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (unlikely(wr->num_sge > qp->rq.max_gs)) {			err = -EINVAL;			*bad_wr = wr;			goto out;		}		for (i = 0; i < wr->num_sge; ++i) {			mthca_set_data_seg(wqe, wr->sg_list + i);			wqe  += sizeof (struct mthca_data_seg);			size += sizeof (struct mthca_data_seg) / 16;		}		qp->wrid[ind] = wr->wr_id;		((struct mthca_next_seg *) prev_wqe)->nda_op =			cpu_to_be32((ind << qp->rq.wqe_shift) | 1);		wmb();		((struct mthca_next_seg *) prev_wqe)->ee_nds =			cpu_to_be32(MTHCA_NEXT_DBD | size);		if (!nreq)			size0 = size;		++ind;		if (unlikely(ind >= qp->rq.max))			ind -= qp->rq.max;		++nreq;		if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {			nreq = 0;			wmb();			mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,				      qp->qpn << 8, dev->kar + MTHCA_RECEIVE_DOORBELL,				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));			qp->rq.next_ind = ind;			qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;		}	}out:	if (likely(nreq)) {		wmb();		mthca_write64((qp->rq.next_ind << qp->rq.wqe_shift) | size0,			      qp->qpn << 8 | nreq, dev->kar + MTHCA_RECEIVE_DOORBELL,			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));	}	qp->rq.next_ind = ind;	qp->rq.head    += nreq;	/*	 * Make sure doorbells don't leak out of RQ spinlock and reach	 * the HCA out of order:	 */	mmiowb();	spin_unlock_irqrestore(&qp->rq.lock, flags);	return err;}int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,			  struct ib_send_wr **bad_wr){	struct mthca_dev *dev = to_mdev(ibqp->device);	struct mthca_qp *qp = to_mqp(ibqp);	u32 dbhi;	void *wqe;	void *prev_wqe;	unsigned long flags;	int err = 0;	int nreq;	int i;	int size;	/*	 * f0 and size0 are only used if nreq != 0, and they will	 * always be initialized the first time through the main loop	 * before nreq is incremented.  So nreq cannot become non-zero	 * without initializing f0 and size0, and they are in fact	 * never used uninitialized.	 */	int uninitialized_var(size0);	u32 uninitialized_var(f0);	int ind;	u8 op0 = 0;	spin_lock_irqsave(&qp->sq.lock, flags);	/* XXX check that state is OK to post send */	ind = qp->sq.head & (qp->sq.max - 1);	for (nreq = 0; wr; ++nreq, wr = wr->next) {		if (unlikely(nreq == MTHCA_ARBEL_MAX_WQES_PER_SEND_DB)) {			nreq = 0;			dbhi = (MTHCA_ARBEL_MAX_WQES_PER_SEND_DB << 24) |				((qp->sq.head & 0xffff) << 8) | f0 | op0;			qp->sq.head += MTHCA_ARBEL_MAX_WQES_PER_SEND_DB;			/*			 * Make sure that descriptors are written before			 * doorbell record.			 */			wmb();			*qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);			/*			 * Make sure doorbell record is written before we			 * write MMIO send doorbell.			 */			wmb();			mthca_write64(dbhi, (qp->qpn << 8) | size0,				      dev->kar + MTHCA_SEND_DOORBELL,				      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));		}		if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {			mthca_err(dev, "SQ %06x full (%u head, %u tail,"					" %d max, %d nreq)\n", qp->qpn,					qp->sq.head, qp->sq.tail,					qp->sq.max, nreq);			err = -ENOMEM;			*bad_wr = wr;			goto out;		}		wqe = get_send_wqe(qp, ind);		prev_wqe = qp->sq.last;		qp->sq.last = wqe;		((struct mthca_next_seg *) wqe)->flags =			((wr->send_flags & IB_SEND_SIGNALED) ?			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |			((wr->send_flags & IB_SEND_SOLICITED) ?			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |			cpu_to_be32(1);		if (wr->opcode == IB_WR_SEND_WITH_IMM ||		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)			((struct mthca_next_seg *) wqe)->imm = wr->imm_data;		wqe += sizeof (struct mthca_next_seg);		size = sizeof (struct mthca_next_seg) / 16;		switch (qp->transport) {		case RC:			switch (wr->opcode) {			case IB_WR_ATOMIC_CMP_AND_SWP:			case IB_WR_ATOMIC_FETCH_AND_ADD:				set_raddr_seg(wqe, wr->wr.atomic.remote_addr,					      wr->wr.atomic.rkey);				wqe += sizeof (struct mthca_raddr_seg);				set_atomic_seg(wqe, wr);				wqe  += sizeof (struct mthca_atomic_seg);				size += (sizeof (struct mthca_raddr_seg) +					 sizeof (struct mthca_atomic_seg)) / 16;				break;			case IB_WR_RDMA_READ:			case IB_WR_RDMA_WRITE:			case IB_WR_RDMA_WRITE_WITH_IMM:				set_raddr_seg(wqe, wr->wr.rdma.remote_addr,					      wr->wr.rdma.rkey);				wqe  += sizeof (struct mthca_raddr_seg);				size += sizeof (struct mthca_raddr_seg) / 16;				break;			default:				/* No extra segments required for sends */				break;			}			break;		case UC:			switch (wr->opcode) {			case IB_WR_RDMA_WRITE:			case IB_WR_RDMA_WRITE_WITH_IMM:				set_raddr_seg(wqe, wr->wr.rdma.remote_addr,					      wr->wr.rdma.rkey);				wqe  += sizeof (struct mthca_raddr_seg);				size += sizeof (struct mthca_raddr_seg) / 16;				break;			default:				/* No extra segments required for sends */				break;			}			break;		case UD:			set_arbel_ud_seg(wqe, wr);			wqe  += sizeof (struct mthca_arbel_ud_seg);			size += sizeof (struct mthca_arbel_ud_seg) / 16;			break;		case MLX:			err = build_mlx_header(dev, to_msqp(qp), ind, wr,					       wqe - sizeof (struct mthca_next_seg),					       wqe);			if (err) {				*bad_wr = wr;				goto out;			}			wqe += sizeof (struct mthca_data_seg);			size += sizeof (struct mthca_data_seg) / 16;			break;		}		if (wr->num_sge > qp->sq.max_gs) {			mthca_err(dev, "too many gathers\n");			err = -EINVAL;			*bad_wr = wr;			goto out;		}		for (i = 0; i < wr->num_sge; ++i) {			mthca_set_data_seg(wqe, wr->sg_list + i);			wqe  += sizeof (struct mthca_data_seg);			size += sizeof (struct mthca_data_seg) / 16;		}		/* Add one more inline data segment for ICRC */		if (qp->transport == MLX) {			((struct mthca_data_seg *) wqe)->byte_count =				cpu_to_be32((1 << 31) | 4);			((u32 *) wqe)[1] = 0;			wqe += sizeof (struct mthca_data_seg);			size += sizeof (struct mthca_data_seg) / 16;		}		qp->wrid[ind + qp->rq.max] = wr->wr_id;		if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {			mthca_err(dev, "opcode invalid\n");			err = -EINVAL;			*bad_wr = wr;			goto out;		}		((struct mthca_next_seg *) prev_wqe)->nda_op =			cpu_to_be32(((ind << qp->sq.wqe_shift) +				     qp->send_wqe_offset) |				    mthca_opcode[wr->opcode]);		wmb();		((struct mthca_next_seg *) prev_wqe)->ee_nds =			cpu_to_be32(MTHCA_NEXT_DBD | size |				    ((wr->send_flags & IB_SEND_FENCE) ?				     MTHCA_NEXT_FENCE : 0));		if (!nreq) {			size0 = size;			op0   = mthca_opcode[wr->opcode];			f0    = wr->send_flags & IB_SEND_FENCE ?				MTHCA_SEND_DOORBELL_FENCE : 0;		}		++ind;		if (unlikely(ind >= qp->sq.max))			ind -= qp->sq.max;	}out:	if (likely(nreq)) {		dbhi = (nreq << 24) | ((qp->sq.head & 0xffff) << 8) | f0 | op0;		qp->sq.head += nreq;		/*		 * Make sure that descriptors are written before		 * doorbell record.		 */		wmb();		*qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);		/*		 * Make sure doorbell record is written before we		 * write MMIO send doorbell.		 */		wmb();		mthca_write64(dbhi, (qp->qpn << 8) | size0, dev->kar + MTHCA_SEND_DOORBELL,			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));	}	/*	 * Make sure doorbells don't leak out of SQ spinlock and reach	 * the HCA out of order:	 */	mmiowb();	spin_unlock_irqrestore(&qp->sq.lock, flags);	return err;}int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,			     struct ib_recv_wr **bad_wr){	struct mthca_dev *dev = to_mdev(ibqp->device);	struct mthca_qp *qp = to_mqp(ibqp);	unsigned long flags;	int err = 0;	int nreq;	int ind;	int i;	void *wqe;	spin_lock_irqsave(&qp->rq.lock, flags);	/* XXX check that state is OK to post receive */	ind = qp->rq.head & (qp->rq.max - 1);	for (nreq = 0; wr; ++nreq, wr = wr->next) {		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {			mthca_err(dev, "RQ %06x full (%u head, %u tail,"					" %d max, %d nreq)\n", qp->qpn,					qp->rq.head, qp->rq.tail,					qp->rq.max, nreq);			err = -ENOMEM;			*bad_wr = wr;			goto out;		}		wqe = get_recv_wqe(qp, ind);		((struct mthca_next_seg *) wqe)->flags = 0;		wqe += sizeof (struct mthca_next_seg);		if (unlikely(wr->num_sge > qp->rq.max_gs)) {			err = -EINVAL;			*bad_wr = wr;			goto out;		}		for (i = 0; i < wr->num_sge; ++i) {			mthca_set_data_seg(wqe, wr->sg_list + i);			wqe += sizeof (struct mthca_data_seg);		}		if (i < qp->rq.max_gs)			mthca_set_data_seg_inval(wqe);		qp->wrid[ind] = wr->wr_id;		++ind;		if (unlikely(ind >= qp->rq.max))			ind -= qp->rq.max;	}out:	if (likely(nreq)) {		qp->rq.head += nreq;		/*		 * Make sure that descriptors are written before		 * doorbell record.		 */		wmb();		*qp->rq.db = cpu_to_be32(qp->rq.head & 0xffff);	}	spin_unlock_irqrestore(&qp->rq.lock, flags);	return err;}void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,			int index, int *dbd, __be32 *new_wqe){	struct mthca_next_seg *next;	/*	 * For SRQs, all receive WQEs generate a CQE, so we're always	 * at the end of the doorbell chain.	 */	if (qp->ibqp.srq && !is_send) {		*new_wqe = 0;		return;	}	if (is_send)		next = get_send_wqe(qp, index);	else		next = get_recv_wqe(qp, index);	*dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));	if (next->ee_nds & cpu_to_be32(0x3f))		*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |			(next->ee_nds & cpu_to_be32(0x3f));	else		*new_wqe = 0;}int mthca_init_qp_table(struct mthca_dev *dev){	int err;	u8 status;	int i;	spin_lock_init(&dev->qp_table.lock);	/*	 * We reserve 2 extra QPs per port for the special QPs.  The	 * special QP for port 1 has to be even, so round up.	 */	dev->qp_table.sqp_start = (dev->limits.reserved_qps + 1) & ~1UL;	err = mthca_alloc_init(&dev->qp_table.alloc,			       dev->limits.num_qps,			       (1 << 24) - 1,			       dev->qp_table.sqp_start +			       MTHCA_MAX_PORTS * 2);	if (err)		return err;	err = mthca_array_init(&dev->qp_table.qp,			       dev->limits.num_qps);	if (err) {		mthca_alloc_cleanup(&dev->qp_table.alloc);		return err;	}	for (i = 0; i < 2; ++i) {		err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,					    dev->qp_table.sqp_start + i * 2,					    &status);		if (err)			goto err_out;		if (status) {			mthca_warn(dev, "CONF_SPECIAL_QP returned "				   "status %02x, aborting.\n",				   status);			err = -EINVAL;			goto err_out;		}	}	return 0; err_out:	for (i = 0; i < 2; ++i)		mthca_CONF_SPECIAL_QP(dev, i, 0, &status);	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);	mthca_alloc_cleanup(&dev->qp_table.alloc);	return err;}void mthca_cleanup_qp_table(struct mthca_dev *dev){	int i;	u8 status;	for (i = 0; i < 2; ++i)		mthca_CONF_SPECIAL_QP(dev, i, 0, &status);	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);	mthca_alloc_cleanup(&dev->qp_table.alloc);}

⌨️ 快捷键说明

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