/** * Copyright (C) Mellanox Technologies Ltd. 2001-2018. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #if HAVE_INFINIBAND_MLX5_HW_H #include "ib_mlx5_hw.h" #include #include #include #include #include #include /* Since this file intended to emulate DV using legacy mlx5_hw.h definitions * we include DV declarations. */ #define UCT_IB_MLX5_H_ #include static void UCS_F_MAYBE_UNUSED uct_ib_mlx5_obj_error(const char *obj_name) { ucs_error("Failed to get mlx5 %s information. Please make sure the installed " "libmlx5 version matches the one UCX was compiled with (%s)", obj_name, UCT_IB_LIBMLX5_VER); } #if !HAVE_DECL_MLX5DV_INIT_OBJ ucs_status_t uct_ib_mlx5_get_qp_info(struct ibv_qp *qp, uct_ib_mlx5dv_qp_t *qp_info) { #if HAVE_DECL_IBV_MLX5_EXP_GET_QP_INFO struct ibv_mlx5_qp_info ibv_qp_info; int ret; ret = ibv_mlx5_exp_get_qp_info(qp, &ibv_qp_info); if (ret != 0) { uct_ib_mlx5_obj_error("qp"); return UCS_ERR_NO_DEVICE; } qp_info->dv.dbrec = ibv_qp_info.dbrec; qp_info->dv.sq.buf = ibv_qp_info.sq.buf; qp_info->dv.sq.wqe_cnt = ibv_qp_info.sq.wqe_cnt; qp_info->dv.sq.stride = ibv_qp_info.sq.stride; qp_info->dv.rq.buf = ibv_qp_info.rq.buf; qp_info->dv.rq.wqe_cnt = ibv_qp_info.rq.wqe_cnt; qp_info->dv.rq.stride = ibv_qp_info.rq.stride; qp_info->dv.bf.reg = ibv_qp_info.bf.reg; qp_info->dv.bf.size = ibv_qp_info.bf.size; #else struct mlx5_qp *mqp = ucs_container_of(qp, struct mlx5_qp, verbs_qp.qp); if ((mqp->sq.cur_post != 0) || (mqp->rq.head != 0)) { ucs_warn("cur_post=%d head=%d need_lock=%d", mqp->sq.cur_post, mqp->rq.head, mqp->bf->need_lock); return UCS_ERR_NO_DEVICE; } qp_info->dv.qpn = qp->qp_num; qp_info->dv.dbrec = mqp->db; qp_info->dv.sq.buf = mqp->buf.buf + mqp->sq.offset; qp_info->dv.sq.wqe_cnt = mqp->sq.wqe_cnt; qp_info->dv.sq.stride = 1 << mqp->sq.wqe_shift; qp_info->dv.rq.buf = mqp->buf.buf + mqp->rq.offset; qp_info->dv.rq.wqe_cnt = mqp->rq.wqe_cnt; qp_info->dv.rq.stride = 1 << mqp->rq.wqe_shift; qp_info->dv.bf.reg = mqp->bf->reg; if (mqp->bf->uuarn > 0) { qp_info->dv.bf.size = mqp->bf->buf_size; } else { qp_info->dv.bf.size = 0; /* No BF */ } #endif return UCS_OK; } ucs_status_t uct_ib_mlx5_get_srq_info(struct ibv_srq *srq, uct_ib_mlx5dv_srq_t *srq_info) { #if HAVE_DECL_IBV_MLX5_EXP_GET_SRQ_INFO struct ibv_mlx5_srq_info ibv_srq_info; int ret; ret = ibv_mlx5_exp_get_srq_info(srq, &ibv_srq_info); if (ret != 0) { uct_ib_mlx5_obj_error("srq"); return UCS_ERR_NO_DEVICE; } srq_info->dv.buf = ibv_srq_info.buf; srq_info->dv.dbrec = ibv_srq_info.dbrec; srq_info->dv.stride = ibv_srq_info.stride; srq_info->dv.head = ibv_srq_info.head; srq_info->dv.tail = ibv_srq_info.tail; #else struct mlx5_srq *msrq; if (srq->handle == LEGACY_XRC_SRQ_HANDLE) { srq = (struct ibv_srq *)(((struct ibv_srq_legacy *)srq)->ibv_srq); } msrq = ucs_container_of(srq, struct mlx5_srq, vsrq.srq); if (msrq->counter != 0) { ucs_error("SRQ counter is not 0 (%d)", msrq->counter); return UCS_ERR_NO_DEVICE; } srq_info->dv.buf = msrq->buf.buf; srq_info->dv.dbrec = msrq->db; srq_info->dv.stride = 1 << msrq->wqe_shift; srq_info->dv.head = msrq->head; srq_info->dv.tail = msrq->tail; #endif return UCS_OK; } static ucs_status_t uct_ib_mlx5_get_cq(struct ibv_cq *cq, uct_ib_mlx5dv_cq_t *mlx5_cq) { #if HAVE_DECL_IBV_MLX5_EXP_GET_CQ_INFO struct ibv_mlx5_cq_info ibv_cq_info; int ret; ret = ibv_mlx5_exp_get_cq_info(cq, &ibv_cq_info); if (ret != 0) { uct_ib_mlx5_obj_error("cq"); return UCS_ERR_NO_DEVICE; } mlx5_cq->dv.buf = ibv_cq_info.buf; mlx5_cq->dv.cqe_cnt = ibv_cq_info.cqe_cnt; mlx5_cq->dv.cqn = ibv_cq_info.cqn; mlx5_cq->dv.cqe_size = ibv_cq_info.cqe_size; #else struct mlx5_cq *mcq = ucs_container_of(cq, struct mlx5_cq, ibv_cq); int ret; if (mcq->cons_index != 0) { ucs_error("CQ consumer index is not 0 (%d)", mcq->cons_index); return UCS_ERR_NO_DEVICE; } mlx5_cq->dv.buf = mcq->active_buf->buf; mlx5_cq->dv.cqe_cnt = mcq->ibv_cq.cqe + 1; mlx5_cq->dv.cqn = mcq->cqn; mlx5_cq->dv.cqe_size = mcq->cqe_sz; #endif return UCS_OK; } ucs_status_t uct_ib_mlx5dv_init_obj(uct_ib_mlx5dv_t *obj, uint64_t obj_type) { ucs_status_t ret = UCS_OK; if (obj_type & MLX5DV_OBJ_QP) { ret = uct_ib_mlx5_get_qp_info(obj->dv.qp.in, ucs_container_of(obj->dv.qp.out, uct_ib_mlx5dv_qp_t, dv)); } if (!ret && (obj_type & MLX5DV_OBJ_CQ)) { ret = uct_ib_mlx5_get_cq(obj->dv.cq.in, ucs_container_of(obj->dv.cq.out, uct_ib_mlx5dv_cq_t, dv)); } if (!ret && (obj_type & MLX5DV_OBJ_SRQ)) { ret = uct_ib_mlx5_get_srq_info(obj->dv.srq.in, ucs_container_of(obj->dv.srq.out, uct_ib_mlx5dv_srq_t, dv)); } #if HAVE_IBV_EXP_DM if (!ret && (obj_type & MLX5DV_OBJ_DM)) { ret = uct_ib_mlx5_get_dm_info(obj->dv_dm.in, obj->dv_dm.out); } #endif return ret; } #endif void uct_ib_mlx5_update_cq_ci(struct ibv_cq *cq, unsigned cq_ci) { #if HAVE_DECL_IBV_MLX5_EXP_UPDATE_CQ_CI ibv_mlx5_exp_update_cq_ci(cq, cq_ci); #else struct mlx5_cq *mcq = ucs_container_of(cq, struct mlx5_cq, ibv_cq); mcq->cons_index = cq_ci; #endif } unsigned uct_ib_mlx5_get_cq_ci(struct ibv_cq *cq) { struct mlx5_cq *mcq = ucs_container_of(cq, struct mlx5_cq, ibv_cq); return mcq->cons_index; } #if !HAVE_DECL_MLX5DV_OBJ_AH void uct_ib_mlx5_get_av(struct ibv_ah *ah, struct mlx5_wqe_av *av) { memcpy(av, &ucs_container_of(ah, struct mlx5_ah, ibv_ah)->av, sizeof(*av)); } #endif struct ibv_qp *uct_dv_get_cmd_qp(struct ibv_srq *srq) { #if HAVE_STRUCT_MLX5_SRQ_CMD_QP struct mlx5_srq *msrq; if (srq->handle == LEGACY_XRC_SRQ_HANDLE) { srq = (struct ibv_srq *)(((struct ibv_srq_legacy *)srq)->ibv_srq); } msrq = ucs_container_of(srq, struct mlx5_srq, vsrq.srq); if (msrq->counter != 0) { ucs_error("SRQ counter is not 0 (%d)", msrq->counter); return NULL; } return &msrq->cmd_qp->verbs_qp.qp; #else return NULL; #endif } struct mlx5_uar_data { enum { __DUMMY } map_type; void *regs; }; void *uct_dv_get_info_uar0(void *uar) { #if HAVE_DECL_MLX5DV_INIT_OBJ struct mlx5_uar_data *muar = uar; return muar[0].regs; #else return NULL; #endif } #endif