+
+ txq->ibv_cq = txq->cq;
+ txq->ibv_qp = txq->qp;
+
+ if (rd->flags & RDMA_DEVICE_F_MLX5DV)
+ {
+ rdma_mlx5_wqe_t *tmpl = (void *) txq->dv_wqe_tmpl;
+ struct mlx5dv_cq dv_cq;
+ struct mlx5dv_qp dv_qp;
+ struct mlx5dv_obj obj = { };
+
+ obj.cq.in = txq->cq;
+ obj.cq.out = &dv_cq;
+ obj.qp.in = txq->qp;
+ obj.qp.out = &dv_qp;
+
+ if (mlx5dv_init_obj (&obj, MLX5DV_OBJ_CQ | MLX5DV_OBJ_QP))
+ return clib_error_return_unix (0, "DV init obj failed");
+
+ if (RDMA_TXQ_BUF_SZ (txq) > dv_qp.sq.wqe_cnt
+ || !is_pow2 (dv_qp.sq.wqe_cnt)
+ || sizeof (rdma_mlx5_wqe_t) != dv_qp.sq.stride
+ || (uword) dv_qp.sq.buf % sizeof (rdma_mlx5_wqe_t))
+ return clib_error_return (0, "Unsupported DV SQ parameters");
+
+ if (RDMA_TXQ_BUF_SZ (txq) > dv_cq.cqe_cnt
+ || !is_pow2 (dv_cq.cqe_cnt)
+ || sizeof (struct mlx5_cqe64) != dv_cq.cqe_size
+ || (uword) dv_cq.buf % sizeof (struct mlx5_cqe64))
+ return clib_error_return (0, "Unsupported DV CQ parameters");
+
+ /* get SQ and doorbell addresses */
+ txq->dv_sq_wqes = dv_qp.sq.buf;
+ txq->dv_sq_dbrec = dv_qp.dbrec;
+ txq->dv_sq_db = dv_qp.bf.reg;
+ txq->dv_sq_log2sz = min_log2 (dv_qp.sq.wqe_cnt);
+
+ /* get CQ and doorbell addresses */
+ txq->dv_cq_cqes = dv_cq.buf;
+ txq->dv_cq_dbrec = dv_cq.dbrec;
+ txq->dv_cq_log2sz = min_log2 (dv_cq.cqe_cnt);
+
+ /* init tx desc template */
+ STATIC_ASSERT_SIZEOF (txq->dv_wqe_tmpl, sizeof (*tmpl));
+ mlx5dv_set_ctrl_seg (&tmpl->ctrl, 0, MLX5_OPCODE_SEND, 0,
+ txq->qp->qp_num, 0, RDMA_MLX5_WQE_DS, 0,
+ RDMA_TXQ_DV_INVALID_ID);
+ /* FIXME: mlx5dv_set_eth_seg(&tmpl->eseg, MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM, 0, 0, 0); */
+ mlx5dv_set_data_seg (&tmpl->dseg, 0, rd->lkey, 0);
+ }
+