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; }