|
Packit |
6d2c1b |
/*
|
|
Packit |
6d2c1b |
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* This software is available to you under a choice of one of two
|
|
Packit |
6d2c1b |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
6d2c1b |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
6d2c1b |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
6d2c1b |
* BSD license below:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
6d2c1b |
* without modification, are permitted provided that the following
|
|
Packit |
6d2c1b |
* conditions are met:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions of source code must retain the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer in the documentation and/or other materials
|
|
Packit |
6d2c1b |
* provided with the distribution.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
6d2c1b |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
6d2c1b |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
6d2c1b |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
6d2c1b |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
6d2c1b |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
6d2c1b |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
6d2c1b |
* SOFTWARE.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#ifdef HAVE_CONFIG_H
|
|
Packit |
6d2c1b |
#include "config.h"
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
#include "util/valgrind.h"
|
|
Packit |
6d2c1b |
#if defined(DEFINED_DIRECT_VERBS)
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#include "vma/util/valgrind.h"
|
|
Packit |
6d2c1b |
#include "vma/util/utils.h"
|
|
Packit |
6d2c1b |
#include "vma/ib/mlx5/ib_mlx5.h"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int vma_ib_mlx5_get_qp(struct ibv_qp *qp, vma_ib_mlx5_qp_t *mlx5_qp, uint32_t flags)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
int ret = 0;
|
|
Packit |
6d2c1b |
struct mlx5dv_obj obj;
|
|
Packit |
6d2c1b |
struct mlx5dv_qp dqp;
|
|
Packit |
6d2c1b |
enum ibv_qp_attr_mask attr_mask = IBV_QP_CAP;
|
|
Packit |
6d2c1b |
struct ibv_qp_attr tmp_ibv_qp_attr;
|
|
Packit |
6d2c1b |
struct ibv_qp_init_attr tmp_ibv_qp_init_attr;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
memset(&obj, 0, sizeof(obj));
|
|
Packit |
6d2c1b |
memset(&dqp, 0, sizeof(dqp));
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
obj.qp.in = qp;
|
|
Packit |
6d2c1b |
obj.qp.out = &dq;;
|
|
Packit |
6d2c1b |
ret = vma_ib_mlx5dv_init_obj(&obj, MLX5DV_OBJ_QP);
|
|
Packit |
6d2c1b |
if (ret != 0) {
|
|
Packit |
6d2c1b |
goto out;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
VALGRIND_MAKE_MEM_DEFINED(&dqp, sizeof(dqp));
|
|
Packit |
6d2c1b |
mlx5_qp->qp = qp;
|
|
Packit |
6d2c1b |
mlx5_qp->qpn = qp->qp_num;
|
|
Packit |
6d2c1b |
mlx5_qp->flags = flags;
|
|
Packit |
6d2c1b |
mlx5_qp->sq.dbrec = &dqp.dbrec[MLX5_SND_DBR];
|
|
Packit |
6d2c1b |
mlx5_qp->sq.buf = dqp.sq.buf;
|
|
Packit |
6d2c1b |
mlx5_qp->sq.wqe_cnt = dqp.sq.wqe_cnt;
|
|
Packit |
6d2c1b |
mlx5_qp->sq.stride = dqp.sq.stride;
|
|
Packit |
6d2c1b |
mlx5_qp->rq.dbrec = &dqp.dbrec[MLX5_RCV_DBR];
|
|
Packit |
6d2c1b |
mlx5_qp->rq.buf = dqp.rq.buf;
|
|
Packit |
6d2c1b |
mlx5_qp->rq.wqe_cnt = dqp.rq.wqe_cnt;
|
|
Packit |
6d2c1b |
mlx5_qp->rq.stride = dqp.rq.stride;
|
|
Packit |
6d2c1b |
mlx5_qp->rq.wqe_shift = ilog_2(dqp.rq.stride);
|
|
Packit |
6d2c1b |
mlx5_qp->rq.head = 0;
|
|
Packit |
6d2c1b |
mlx5_qp->rq.tail = 0;
|
|
Packit |
6d2c1b |
mlx5_qp->bf.reg = dqp.bf.reg;
|
|
Packit |
6d2c1b |
mlx5_qp->bf.size = dqp.bf.size;
|
|
Packit |
6d2c1b |
mlx5_qp->bf.offset = 0;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
ret = ibv_query_qp(qp, &tmp_ibv_qp_attr, attr_mask, &tmp_ibv_qp_init_attr);
|
|
Packit |
6d2c1b |
if (ret != 0) {
|
|
Packit |
6d2c1b |
goto out;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
VALGRIND_MAKE_MEM_DEFINED(&tmp_ibv_qp_attr, sizeof(tmp_ibv_qp_attr));
|
|
Packit |
6d2c1b |
mlx5_qp->cap.max_send_wr = tmp_ibv_qp_attr.cap.max_send_wr;
|
|
Packit |
6d2c1b |
mlx5_qp->cap.max_recv_wr = tmp_ibv_qp_attr.cap.max_recv_wr;
|
|
Packit |
6d2c1b |
mlx5_qp->cap.max_send_sge = tmp_ibv_qp_attr.cap.max_send_sge;
|
|
Packit |
6d2c1b |
mlx5_qp->cap.max_recv_sge = tmp_ibv_qp_attr.cap.max_recv_sge;
|
|
Packit |
6d2c1b |
mlx5_qp->cap.max_inline_data = tmp_ibv_qp_attr.cap.max_inline_data;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
out:
|
|
Packit |
6d2c1b |
return ret;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int vma_ib_mlx5_get_cq(struct ibv_cq *cq, vma_ib_mlx5_cq_t *mlx5_cq)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
int ret = 0;
|
|
Packit |
6d2c1b |
struct mlx5dv_obj obj;
|
|
Packit |
6d2c1b |
struct mlx5dv_cq dcq;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/* Initialization of cq can be done once to protect
|
|
Packit |
6d2c1b |
* internal data from corruption.
|
|
Packit |
6d2c1b |
* cq field is used to detect one time initialization
|
|
Packit |
6d2c1b |
* For example: this function can be called when QP is moved
|
|
Packit |
6d2c1b |
* from ERROR state to RESET so cq_ci or cq_sn should not be
|
|
Packit |
6d2c1b |
* updated
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
if (mlx5_cq == NULL || mlx5_cq->cq == cq) {
|
|
Packit |
6d2c1b |
return 0;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
memset(&obj, 0, sizeof(obj));
|
|
Packit |
6d2c1b |
memset(&dcq, 0, sizeof(dcq));
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
obj.cq.in = cq;
|
|
Packit |
6d2c1b |
obj.cq.out = &dcq;
|
|
Packit |
6d2c1b |
ret = vma_ib_mlx5dv_init_obj(&obj, MLX5DV_OBJ_CQ);
|
|
Packit |
6d2c1b |
if (ret != 0) {
|
|
Packit |
6d2c1b |
return ret;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
VALGRIND_MAKE_MEM_DEFINED(&dcq, sizeof(dcq));
|
|
Packit |
6d2c1b |
mlx5_cq->cq = cq;
|
|
Packit |
6d2c1b |
mlx5_cq->cq_num = dcq.cqn;
|
|
Packit |
6d2c1b |
mlx5_cq->cq_ci = 0;
|
|
Packit |
6d2c1b |
mlx5_cq->cq_sn = 0;
|
|
Packit |
6d2c1b |
mlx5_cq->cqe_count = dcq.cqe_cnt;
|
|
Packit |
6d2c1b |
mlx5_cq->cqe_size = dcq.cqe_size;
|
|
Packit |
6d2c1b |
mlx5_cq->cqe_size_log = ilog_2(dcq.cqe_size);
|
|
Packit |
6d2c1b |
mlx5_cq->dbrec = dcq.dbrec;
|
|
Packit |
6d2c1b |
mlx5_cq->uar = dcq.cq_uar;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/* Move buffer forward for 128b CQE, so we would get pointer to the 2nd
|
|
Packit |
6d2c1b |
* 64b when polling.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
mlx5_cq->cq_buf = (uint8_t *)dcq.buf + dcq.cqe_size - sizeof(struct mlx5_cqe64);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
return 0;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int vma_ib_mlx5_post_recv(vma_ib_mlx5_qp_t *mlx5_qp,
|
|
Packit |
6d2c1b |
struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
struct mlx5_wqe_data_seg *scat;
|
|
Packit |
6d2c1b |
int err = 0;
|
|
Packit |
6d2c1b |
int nreq;
|
|
Packit |
6d2c1b |
int ind;
|
|
Packit |
6d2c1b |
int i, j;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
ind = mlx5_qp->rq.head & (mlx5_qp->rq.wqe_cnt - 1);
|
|
Packit |
6d2c1b |
*bad_wr = NULL;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
for (nreq = 0; wr; ++nreq, wr = wr->next) {
|
|
Packit |
6d2c1b |
if (unlikely((int)mlx5_qp->rq.head - (int)mlx5_qp->rq.tail + nreq >= (int)mlx5_qp->cap.max_recv_wr)) {
|
|
Packit |
6d2c1b |
errno = ENOMEM;
|
|
Packit |
6d2c1b |
err = -errno;
|
|
Packit |
6d2c1b |
*bad_wr = wr;
|
|
Packit |
6d2c1b |
goto out;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
if (unlikely(wr->num_sge > (int)mlx5_qp->cap.max_recv_sge)) {
|
|
Packit |
6d2c1b |
errno = EINVAL;
|
|
Packit |
6d2c1b |
err = -errno;
|
|
Packit |
6d2c1b |
*bad_wr = wr;
|
|
Packit |
6d2c1b |
goto out;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
scat = (struct mlx5_wqe_data_seg *)((uint8_t *)mlx5_qp->rq.buf + (ind << mlx5_qp->rq.wqe_shift));
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
for (i = 0, j = 0; i < wr->num_sge; ++i) {
|
|
Packit |
6d2c1b |
if (unlikely(!wr->sg_list[i].length)) continue;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
scat[j].byte_count = htonl(wr->sg_list[i].length);
|
|
Packit |
6d2c1b |
scat[j].lkey = htonl(wr->sg_list[i].lkey);
|
|
Packit |
6d2c1b |
scat[j].addr = htonll(wr->sg_list[i].addr);
|
|
Packit |
6d2c1b |
j++;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
if (j < (int)mlx5_qp->cap.max_recv_sge) {
|
|
Packit |
6d2c1b |
scat[j].byte_count = 0;
|
|
Packit |
6d2c1b |
scat[j].lkey = htonl(MLX5_INVALID_LKEY);
|
|
Packit |
6d2c1b |
scat[j].addr = 0;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
ind = (ind + 1) & (mlx5_qp->rq.wqe_cnt - 1);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
out:
|
|
Packit |
6d2c1b |
if (likely(nreq)) {
|
|
Packit |
6d2c1b |
mlx5_qp->rq.head += nreq;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/*
|
|
Packit |
6d2c1b |
* Make sure that descriptors are written before
|
|
Packit |
6d2c1b |
* doorbell record.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
wmb();
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/*
|
|
Packit |
6d2c1b |
* For Raw Packet QP, avoid updating the doorbell record
|
|
Packit |
6d2c1b |
* as long as the QP isn't in RTR state, to avoid receiving
|
|
Packit |
6d2c1b |
* packets in illegal states.
|
|
Packit |
6d2c1b |
* This is only for Raw Packet QPs since they are represented
|
|
Packit |
6d2c1b |
* differently in the hardware.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
if (likely(!((mlx5_qp->qp->qp_type == IBV_QPT_RAW_PACKET ||
|
|
Packit |
6d2c1b |
mlx5_qp->flags & VMA_IB_MLX5_QP_FLAGS_USE_UNDERLAY) &&
|
|
Packit |
6d2c1b |
mlx5_qp->qp->state < IBV_QPS_RTR)))
|
|
Packit |
6d2c1b |
*mlx5_qp->rq.dbrec = htonl(mlx5_qp->rq.head & 0xffff);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
return err;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#endif /* DEFINED_DIRECT_VERBS */
|