Esempio n. 1
0
int mlx4_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
		   struct ibv_recv_wr **bad_wr)
{
	struct mlx4_qp *qp = to_mqp(ibqp);
	struct mlx4_wqe_data_seg *scat;
	int ret = 0;
	int nreq;
	int ind;
	int i;

	pthread_spin_lock(&qp->rq.lock);

	/* XXX check that state is OK to post receive */

	ind = qp->rq.head & (qp->rq.wqe_cnt - 1);

	for (nreq = 0; wr; ++nreq, wr = wr->next) {
		if (wq_overflow(&qp->rq, nreq, to_mcq(qp->ibv_qp.recv_cq))) {
			ret = -1;
			*bad_wr = wr;
			goto out;
		}

		if (wr->num_sge > qp->rq.max_gs) {
			ret = -1;
			*bad_wr = wr;
			goto out;
		}

		scat = get_recv_wqe(qp, ind);

		for (i = 0; i < wr->num_sge; ++i)
			__set_data_seg(scat + i, wr->sg_list + i);

		if (i < qp->rq.max_gs) {
			scat[i].byte_count = 0;
			scat[i].lkey       = htonl(MLX4_INVALID_LKEY);
			scat[i].addr       = 0;
		}

		qp->rq.wrid[ind] = wr->wr_id;

		ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
	}

out:
	if (nreq) {
		qp->rq.head += nreq;

		/*
		 * Make sure that descriptors are written before
		 * doorbell record.
		 */
		wmb();

		*qp->db = htonl(qp->rq.head & 0xffff);
	}

	pthread_spin_unlock(&qp->rq.lock);

	return ret;
}
static int hns_roce_u_v1_post_recv(struct ibv_qp *ibvqp, struct ibv_recv_wr *wr,
				   struct ibv_recv_wr **bad_wr)
{
	int ret = 0;
	int nreq;
	int ind;
	struct ibv_sge *sg;
	struct hns_roce_rc_rq_wqe *rq_wqe;
	struct hns_roce_qp *qp = to_hr_qp(ibvqp);
	struct hns_roce_context *ctx = to_hr_ctx(ibvqp->context);

	pthread_spin_lock(&qp->rq.lock);

	/* check that state is OK to post receive */
	ind = qp->rq.head & (qp->rq.wqe_cnt - 1);

	for (nreq = 0; wr; ++nreq, wr = wr->next) {
		if (hns_roce_wq_overflow(&qp->rq, nreq,
					 to_hr_cq(qp->ibv_qp.recv_cq))) {
			ret = -1;
			*bad_wr = wr;
			goto out;
		}

		if (wr->num_sge > qp->rq.max_gs) {
			ret = -1;
			*bad_wr = wr;
			goto out;
		}

		rq_wqe = get_recv_wqe(qp, ind);
		if (wr->num_sge > HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM) {
			ret = -1;
			*bad_wr = wr;
			goto out;
		}

		if (wr->num_sge == HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM) {
			roce_set_field(rq_wqe->u32_2,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_M,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_S,
				       HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM);
			sg = wr->sg_list;

			rq_wqe->va0 = htole64(sg->addr);
			rq_wqe->l_key0 = htole32(sg->lkey);
			rq_wqe->length0 = htole32(sg->length);

			sg = wr->sg_list + 1;

			rq_wqe->va1 = htole64(sg->addr);
			rq_wqe->l_key1 = htole32(sg->lkey);
			rq_wqe->length1 = htole32(sg->length);
		} else if (wr->num_sge == HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM - 1) {
			roce_set_field(rq_wqe->u32_2,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_M,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_S,
				       HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM - 1);
			sg = wr->sg_list;

			rq_wqe->va0 = htole64(sg->addr);
			rq_wqe->l_key0 = htole32(sg->lkey);
			rq_wqe->length0 = htole32(sg->length);

		} else if (wr->num_sge == HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM - 2) {
			roce_set_field(rq_wqe->u32_2,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_M,
				       RC_RQ_WQE_NUMBER_OF_DATA_SEG_S,
				       HNS_ROCE_RC_RQ_WQE_MAX_SGE_NUM - 2);
		}

		qp->rq.wrid[ind] = wr->wr_id;

		ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
	}

out:
	if (nreq) {
		qp->rq.head += nreq;

		hns_roce_update_rq_head(ctx, qp->ibv_qp.qp_num,
				    qp->rq.head & ((qp->rq.wqe_cnt << 1) - 1));
	}

	pthread_spin_unlock(&qp->rq.lock);

	return ret;
}