@@ -36,6 +36,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
cmd_mr.c
cmd_mw.c
cmd_pd.c
+ cmd_qp.c
cmd_rwq_ind.c
cmd_srq.c
cmd_wq.c
@@ -543,90 +543,6 @@ int ibv_cmd_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
return 0;
}
-static int create_qp_ex_common(struct verbs_qp *qp,
- struct ibv_qp_init_attr_ex *qp_attr,
- struct verbs_xrcd *vxrcd,
- struct ib_uverbs_create_qp *cmd)
-{
- cmd->user_handle = (uintptr_t)qp;
-
- if (qp_attr->comp_mask & IBV_QP_INIT_ATTR_XRCD) {
- vxrcd = container_of(qp_attr->xrcd, struct verbs_xrcd, xrcd);
- cmd->pd_handle = vxrcd->handle;
- } else {
- if (!(qp_attr->comp_mask & IBV_QP_INIT_ATTR_PD))
- return EINVAL;
-
- cmd->pd_handle = qp_attr->pd->handle;
- if (qp_attr->comp_mask & IBV_QP_INIT_ATTR_IND_TABLE) {
- if (cmd->max_recv_wr || cmd->max_recv_sge ||
- cmd->recv_cq_handle || qp_attr->srq)
- return EINVAL;
-
- /* send_cq is optinal */
- if (qp_attr->cap.max_send_wr)
- cmd->send_cq_handle = qp_attr->send_cq->handle;
- } else {
- cmd->send_cq_handle = qp_attr->send_cq->handle;
-
- if (qp_attr->qp_type != IBV_QPT_XRC_SEND) {
- cmd->recv_cq_handle = qp_attr->recv_cq->handle;
- cmd->srq_handle = qp_attr->srq ? qp_attr->srq->handle :
- 0;
- }
- }
- }
-
- cmd->max_send_wr = qp_attr->cap.max_send_wr;
- cmd->max_recv_wr = qp_attr->cap.max_recv_wr;
- cmd->max_send_sge = qp_attr->cap.max_send_sge;
- cmd->max_recv_sge = qp_attr->cap.max_recv_sge;
- cmd->max_inline_data = qp_attr->cap.max_inline_data;
- cmd->sq_sig_all = qp_attr->sq_sig_all;
- cmd->qp_type = qp_attr->qp_type;
- cmd->is_srq = !!qp_attr->srq;
- cmd->reserved = 0;
-
- return 0;
-}
-
-static void create_qp_handle_resp_common(struct ibv_context *context,
- struct verbs_qp *qp,
- struct ibv_qp_init_attr_ex *qp_attr,
- struct ib_uverbs_create_qp_resp *resp,
- struct verbs_xrcd *vxrcd,
- int vqp_sz)
-{
- if (abi_ver > 3) {
- qp_attr->cap.max_recv_sge = resp->max_recv_sge;
- qp_attr->cap.max_send_sge = resp->max_send_sge;
- qp_attr->cap.max_recv_wr = resp->max_recv_wr;
- qp_attr->cap.max_send_wr = resp->max_send_wr;
- qp_attr->cap.max_inline_data = resp->max_inline_data;
- }
-
- qp->qp.handle = resp->qp_handle;
- qp->qp.qp_num = resp->qpn;
- qp->qp.context = context;
- qp->qp.qp_context = qp_attr->qp_context;
- qp->qp.pd = qp_attr->pd;
- qp->qp.send_cq = qp_attr->send_cq;
- qp->qp.recv_cq = qp_attr->recv_cq;
- qp->qp.srq = qp_attr->srq;
- qp->qp.qp_type = qp_attr->qp_type;
- qp->qp.state = IBV_QPS_RESET;
- qp->qp.events_completed = 0;
- pthread_mutex_init(&qp->qp.mutex, NULL);
- pthread_cond_init(&qp->qp.cond, NULL);
-
- qp->comp_mask = 0;
- if (vext_field_avail(struct verbs_qp, xrcd, vqp_sz) &&
- (qp_attr->comp_mask & IBV_QP_INIT_ATTR_XRCD)) {
- qp->comp_mask |= VERBS_QP_XRCD;
- qp->xrcd = vxrcd;
- }
-}
-
enum {
CREATE_QP_EX2_SUP_CREATE_FLAGS = IBV_QP_CREATE_BLOCK_SELF_MCAST_LB |
IBV_QP_CREATE_SCATTER_FCS |
@@ -635,163 +551,6 @@ enum {
IBV_QP_CREATE_PCI_WRITE_END_PADDING,
};
-int ibv_cmd_create_qp_ex2(struct ibv_context *context,
- struct verbs_qp *qp, int vqp_sz,
- struct ibv_qp_init_attr_ex *qp_attr,
- struct ibv_create_qp_ex *cmd,
- size_t cmd_size,
- struct ib_uverbs_ex_create_qp_resp *resp,
- size_t resp_size)
-{
- struct verbs_xrcd *vxrcd = NULL;
- int err;
-
- if (!check_comp_mask(qp_attr->comp_mask,
- IBV_QP_INIT_ATTR_PD |
- IBV_QP_INIT_ATTR_XRCD |
- IBV_QP_INIT_ATTR_CREATE_FLAGS |
- IBV_QP_INIT_ATTR_MAX_TSO_HEADER |
- IBV_QP_INIT_ATTR_IND_TABLE |
- IBV_QP_INIT_ATTR_RX_HASH |
- IBV_QP_INIT_ATTR_SEND_OPS_FLAGS))
- return EINVAL;
-
- memset(&cmd->core_payload, 0, sizeof(cmd->core_payload));
-
- err = create_qp_ex_common(qp, qp_attr, vxrcd,
- ibv_create_qp_ex_to_reg(cmd));
- if (err)
- return err;
-
- if (qp_attr->comp_mask & IBV_QP_INIT_ATTR_CREATE_FLAGS) {
- if (qp_attr->create_flags & ~CREATE_QP_EX2_SUP_CREATE_FLAGS)
- return EINVAL;
- cmd->create_flags = qp_attr->create_flags;
-
- if (qp_attr->create_flags & IBV_QP_CREATE_SOURCE_QPN)
- cmd->source_qpn = qp_attr->source_qpn;
- }
-
- if (qp_attr->comp_mask & IBV_QP_INIT_ATTR_IND_TABLE) {
- cmd->rwq_ind_tbl_handle = qp_attr->rwq_ind_tbl->ind_tbl_handle;
- cmd->comp_mask = IB_UVERBS_CREATE_QP_MASK_IND_TABLE;
- }
-
- err = execute_cmd_write_ex(context, IB_USER_VERBS_EX_CMD_CREATE_QP,
- cmd, cmd_size, resp, resp_size);
- if (err)
- return err;
-
- create_qp_handle_resp_common(context, qp, qp_attr, &resp->base, vxrcd,
- vqp_sz);
-
- return 0;
-}
-
-int ibv_cmd_create_qp_ex(struct ibv_context *context,
- struct verbs_qp *qp, int vqp_sz,
- struct ibv_qp_init_attr_ex *attr_ex,
- struct ibv_create_qp *cmd, size_t cmd_size,
- struct ib_uverbs_create_qp_resp *resp, size_t resp_size)
-{
- struct verbs_xrcd *vxrcd = NULL;
- int err;
-
- if (!check_comp_mask(attr_ex->comp_mask,
- IBV_QP_INIT_ATTR_PD |
- IBV_QP_INIT_ATTR_XRCD |
- IBV_QP_INIT_ATTR_SEND_OPS_FLAGS))
- return EOPNOTSUPP;
-
- err = create_qp_ex_common(qp, attr_ex, vxrcd,
- &cmd->core_payload);
- if (err)
- return err;
-
- err = execute_cmd_write(context, IB_USER_VERBS_CMD_CREATE_QP, cmd,
- cmd_size, resp, resp_size);
- if (err)
- return err;
-
- if (abi_ver == 4) {
- struct ibv_create_qp_resp_v4 *resp_v4 =
- (struct ibv_create_qp_resp_v4 *)resp;
-
- memmove((void *)resp + sizeof *resp,
- (void *)resp_v4 + sizeof *resp_v4,
- resp_size - sizeof *resp);
- } else if (abi_ver <= 3) {
- struct ibv_create_qp_resp_v3 *resp_v3 =
- (struct ibv_create_qp_resp_v3 *)resp;
-
- memmove((void *)resp + sizeof *resp,
- (void *)resp_v3 + sizeof *resp_v3,
- resp_size - sizeof *resp);
- }
-
- create_qp_handle_resp_common(context, qp, attr_ex, resp, vxrcd, vqp_sz);
-
- return 0;
-}
-
-int ibv_cmd_create_qp(struct ibv_pd *pd,
- struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
- struct ibv_create_qp *cmd, size_t cmd_size,
- struct ib_uverbs_create_qp_resp *resp, size_t resp_size)
-{
- int ret;
-
- cmd->user_handle = (uintptr_t) qp;
- cmd->pd_handle = pd->handle;
- cmd->send_cq_handle = attr->send_cq->handle;
- cmd->recv_cq_handle = attr->recv_cq->handle;
- cmd->srq_handle = attr->srq ? attr->srq->handle : 0;
- cmd->max_send_wr = attr->cap.max_send_wr;
- cmd->max_recv_wr = attr->cap.max_recv_wr;
- cmd->max_send_sge = attr->cap.max_send_sge;
- cmd->max_recv_sge = attr->cap.max_recv_sge;
- cmd->max_inline_data = attr->cap.max_inline_data;
- cmd->sq_sig_all = attr->sq_sig_all;
- cmd->qp_type = attr->qp_type;
- cmd->is_srq = !!attr->srq;
- cmd->reserved = 0;
-
- ret = execute_cmd_write(pd->context, IB_USER_VERBS_CMD_CREATE_QP, cmd,
- cmd_size, resp, resp_size);
- if (ret)
- return ret;
-
- qp->handle = resp->qp_handle;
- qp->qp_num = resp->qpn;
- qp->context = pd->context;
-
- if (abi_ver > 3) {
- attr->cap.max_recv_sge = resp->max_recv_sge;
- attr->cap.max_send_sge = resp->max_send_sge;
- attr->cap.max_recv_wr = resp->max_recv_wr;
- attr->cap.max_send_wr = resp->max_send_wr;
- attr->cap.max_inline_data = resp->max_inline_data;
- }
-
- if (abi_ver == 4) {
- struct ibv_create_qp_resp_v4 *resp_v4 =
- (struct ibv_create_qp_resp_v4 *) resp;
-
- memmove((void *) resp + sizeof *resp,
- (void *) resp_v4 + sizeof *resp_v4,
- resp_size - sizeof *resp);
- } else if (abi_ver <= 3) {
- struct ibv_create_qp_resp_v3 *resp_v3 =
- (struct ibv_create_qp_resp_v3 *) resp;
-
- memmove((void *) resp + sizeof *resp,
- (void *) resp_v3 + sizeof *resp_v3,
- resp_size - sizeof *resp);
- }
-
- return 0;
-}
-
int ibv_cmd_open_qp(struct ibv_context *context, struct verbs_qp *qp,
int vqp_sz,
struct ibv_qp_open_attr *attr,
@@ -1294,29 +1053,6 @@ int ibv_cmd_create_ah(struct ibv_pd *pd, struct ibv_ah *ah,
return 0;
}
-int ibv_cmd_destroy_qp(struct ibv_qp *qp)
-{
- struct ibv_destroy_qp req;
- struct ib_uverbs_destroy_qp_resp resp;
- int ret;
-
- req.core_payload = (struct ib_uverbs_destroy_qp){
- .qp_handle = qp->handle,
- };
-
- ret = execute_cmd_write(qp->context, IB_USER_VERBS_CMD_DESTROY_QP, &req,
- sizeof(req), &resp, sizeof(resp));
- if (verbs_is_destroy_err(&ret))
- return ret;
-
- pthread_mutex_lock(&qp->mutex);
- while (qp->events_completed != resp.events_reported)
- pthread_cond_wait(&qp->cond, &qp->mutex);
- pthread_mutex_unlock(&qp->mutex);
-
- return 0;
-}
-
int ibv_cmd_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid)
{
struct ibv_attach_mcast req;
new file mode 100644
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2020 Mellanox Technologies, Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <infiniband/cmd_write.h>
+#include "ibverbs.h"
+
+enum {
+ CREATE_QP_EX_SUP_CREATE_FLAGS = IBV_QP_CREATE_BLOCK_SELF_MCAST_LB |
+ IBV_QP_CREATE_SCATTER_FCS |
+ IBV_QP_CREATE_CVLAN_STRIPPING |
+ IBV_QP_CREATE_SOURCE_QPN |
+ IBV_QP_CREATE_PCI_WRITE_END_PADDING
+};
+
+
+static void set_qp(struct verbs_qp *vqp,
+ struct ibv_qp *qp_in,
+ struct ibv_qp_init_attr_ex *attr_ex,
+ struct verbs_xrcd *vxrcd)
+{
+ struct ibv_qp *qp = vqp ? &vqp->qp : qp_in;
+
+ qp->qp_context = attr_ex->qp_context;
+ qp->pd = attr_ex->pd;
+ qp->send_cq = attr_ex->send_cq;
+ qp->recv_cq = attr_ex->recv_cq;
+ qp->srq = attr_ex->srq;
+ qp->qp_type = attr_ex->qp_type;
+ qp->state = IBV_QPS_RESET;
+ qp->events_completed = 0;
+ pthread_mutex_init(&qp->mutex, NULL);
+ pthread_cond_init(&qp->cond, NULL);
+
+ if (vqp) {
+ vqp->comp_mask = 0;
+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) {
+ vqp->comp_mask |= VERBS_QP_XRCD;
+ vqp->xrcd = vxrcd;
+ }
+ }
+}
+
+static int ibv_icmd_create_qp(struct ibv_context *context,
+ struct verbs_qp *vqp,
+ struct ibv_qp *qp_in,
+ struct ibv_qp_init_attr_ex *attr_ex,
+ struct ibv_command_buffer *link)
+{
+ DECLARE_FBCMD_BUFFER(cmdb, UVERBS_OBJECT_QP, UVERBS_METHOD_QP_CREATE, 15, link);
+ struct ib_uverbs_attr *handle;
+ uint32_t qp_num;
+ uint32_t pd_handle;
+ uint32_t send_cq_handle = 0;
+ uint32_t recv_cq_handle = 0;
+ int ret;
+ struct ibv_qp *qp = vqp ? &vqp->qp : qp_in;
+ struct verbs_xrcd *vxrcd = NULL;
+ uint32_t create_flags = 0;
+
+ qp->context = context;
+
+ switch (attr_ex->qp_type) {
+ case IBV_QPT_XRC_RECV:
+ if (!(attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_XRCD_HANDLE, vxrcd->handle);
+ pd_handle = vxrcd->handle;
+ break;
+ case IBV_QPT_RC:
+ case IBV_QPT_UD:
+ case IBV_QPT_UC:
+ case IBV_QPT_RAW_PACKET:
+ case IBV_QPT_XRC_SEND:
+ case IBV_QPT_DRIVER:
+ if (!(attr_ex->comp_mask & IBV_QP_INIT_ATTR_PD)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_PD_HANDLE, attr_ex->pd->handle);
+ pd_handle = attr_ex->pd->handle;
+
+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_IND_TABLE) {
+ if (attr_ex->cap.max_recv_wr || attr_ex->cap.max_recv_sge ||
+ attr_ex->recv_cq || attr_ex->srq) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ fallback_require_ex(cmdb);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_IND_TABLE_HANDLE,
+ attr_ex->rwq_ind_tbl->ind_tbl_handle);
+
+ /* send_cq is optinal */
+ if (attr_ex->cap.max_send_wr) {
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE,
+ attr_ex->send_cq->handle);
+ send_cq_handle = attr_ex->send_cq->handle;
+ }
+ } else {
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE,
+ attr_ex->send_cq->handle);
+ send_cq_handle = attr_ex->send_cq->handle;
+
+ if (attr_ex->qp_type != IBV_QPT_XRC_SEND) {
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE,
+ attr_ex->recv_cq->handle);
+ recv_cq_handle = attr_ex->recv_cq->handle;
+ }
+ }
+
+ /* compatible with kernel code from the 'write' mode */
+ if (attr_ex->qp_type == IBV_QPT_XRC_SEND) {
+ attr_ex->cap.max_recv_wr = 0;
+ attr_ex->cap.max_recv_sge = 0;
+ }
+
+ break;
+ default:
+ errno = EINVAL;
+ return errno;
+ }
+
+ handle = fill_attr_out_obj(cmdb, UVERBS_ATTR_CREATE_QP_HANDLE);
+ fill_attr_const_in(cmdb, UVERBS_ATTR_CREATE_QP_TYPE, attr_ex->qp_type);
+ fill_attr_in_uint64(cmdb, UVERBS_ATTR_CREATE_QP_USER_HANDLE, (uintptr_t)qp);
+
+ static_assert(offsetof(struct ibv_qp_cap, max_send_wr) ==
+ offsetof(struct ib_uverbs_qp_cap, max_send_wr), "Bad layout");
+ static_assert(offsetof(struct ibv_qp_cap, max_recv_wr) ==
+ offsetof(struct ib_uverbs_qp_cap, max_recv_wr), "Bad layout");
+ static_assert(offsetof(struct ibv_qp_cap, max_send_sge) ==
+ offsetof(struct ib_uverbs_qp_cap, max_send_sge), "Bad layout");
+ static_assert(offsetof(struct ibv_qp_cap, max_recv_sge) ==
+ offsetof(struct ib_uverbs_qp_cap, max_recv_sge), "Bad layout");
+ static_assert(offsetof(struct ibv_qp_cap, max_inline_data) ==
+ offsetof(struct ib_uverbs_qp_cap, max_inline_data), "Bad layout");
+
+ fill_attr_in_ptr(cmdb, UVERBS_ATTR_CREATE_QP_CAP, &attr_ex->cap);
+ fill_attr_in_fd(cmdb, UVERBS_ATTR_CREATE_QP_EVENT_FD, context->async_fd);
+
+ if (attr_ex->sq_sig_all)
+ create_flags |= IB_UVERBS_QP_CREATE_SQ_SIG_ALL;
+
+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_CREATE_FLAGS) {
+ if (attr_ex->create_flags & ~CREATE_QP_EX_SUP_CREATE_FLAGS) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ fallback_require_ex(cmdb);
+ create_flags |= attr_ex->create_flags;
+
+ if (attr_ex->create_flags & IBV_QP_CREATE_SOURCE_QPN) {
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_QP_SOURCE_QPN,
+ attr_ex->source_qpn);
+ /* source QPN is a self attribute once moving to ioctl,
+ * no extra bit is supported.
+ */
+ create_flags &= ~IBV_QP_CREATE_SOURCE_QPN;
+ }
+ }
+
+ if (create_flags)
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_QP_FLAGS,
+ create_flags);
+
+ if (attr_ex->srq)
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_QP_SRQ_HANDLE, attr_ex->srq->handle);
+
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_CREATE_QP_RESP_CAP, &attr_ex->cap);
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_CREATE_QP_RESP_QP_NUM, &qp_num);
+
+ switch (execute_ioctl_fallback(context, create_qp, cmdb, &ret)) {
+ case TRY_WRITE: {
+ if (abi_ver > 4) {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_QP);
+
+ *req = (struct ib_uverbs_create_qp){
+ .pd_handle = pd_handle,
+ .user_handle = (uintptr_t)qp,
+ .max_send_wr = attr_ex->cap.max_send_wr,
+ .max_recv_wr = attr_ex->cap.max_recv_wr,
+ .max_send_sge = attr_ex->cap.max_send_sge,
+ .max_recv_sge = attr_ex->cap.max_recv_sge,
+ .max_inline_data = attr_ex->cap.max_inline_data,
+ .sq_sig_all = attr_ex->sq_sig_all,
+ .qp_type = attr_ex->qp_type,
+ .srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0,
+ .is_srq = !!attr_ex->srq,
+ .recv_cq_handle = recv_cq_handle,
+ .send_cq_handle = send_cq_handle,
+ };
+
+ ret = execute_write_bufs(
+ context, IB_USER_VERBS_CMD_CREATE_QP, req, resp);
+ if (ret)
+ return ret;
+
+ qp->handle = resp->qp_handle;
+ qp->qp_num = resp->qpn;
+
+ attr_ex->cap.max_recv_sge = resp->max_recv_sge;
+ attr_ex->cap.max_send_sge = resp->max_send_sge;
+ attr_ex->cap.max_recv_wr = resp->max_recv_wr;
+ attr_ex->cap.max_send_wr = resp->max_send_wr;
+ attr_ex->cap.max_inline_data = resp->max_inline_data;
+
+ } else if (abi_ver == 4) {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_QP_V4);
+
+ *req = (struct ib_uverbs_create_qp){
+ .pd_handle = pd_handle,
+ .user_handle = (uintptr_t)qp,
+ .max_send_wr = attr_ex->cap.max_send_wr,
+ .max_recv_wr = attr_ex->cap.max_recv_wr,
+ .max_send_sge = attr_ex->cap.max_send_sge,
+ .max_recv_sge = attr_ex->cap.max_recv_sge,
+ .max_inline_data = attr_ex->cap.max_inline_data,
+ .sq_sig_all = attr_ex->sq_sig_all,
+ .qp_type = attr_ex->qp_type,
+ .srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0,
+ .is_srq = !!attr_ex->srq,
+ .recv_cq_handle = recv_cq_handle,
+ .send_cq_handle = send_cq_handle,
+ };
+
+ ret = execute_write_bufs(
+ context, IB_USER_VERBS_CMD_CREATE_QP_V4, req, resp);
+ if (ret)
+ return ret;
+
+ qp->handle = resp->qp_handle;
+ qp->qp_num = resp->qpn;
+
+ attr_ex->cap.max_recv_sge = resp->max_recv_sge;
+ attr_ex->cap.max_send_sge = resp->max_send_sge;
+ attr_ex->cap.max_recv_wr = resp->max_recv_wr;
+ attr_ex->cap.max_send_wr = resp->max_send_wr;
+ attr_ex->cap.max_inline_data = resp->max_inline_data;
+ } else {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_QP_V3);
+
+ *req = (struct ib_uverbs_create_qp){
+ .pd_handle = pd_handle,
+ .user_handle = (uintptr_t)qp,
+ .max_send_wr = attr_ex->cap.max_send_wr,
+ .max_recv_wr = attr_ex->cap.max_recv_wr,
+ .max_send_sge = attr_ex->cap.max_send_sge,
+ .max_recv_sge = attr_ex->cap.max_recv_sge,
+ .max_inline_data = attr_ex->cap.max_inline_data,
+ .sq_sig_all = attr_ex->sq_sig_all,
+ .qp_type = attr_ex->qp_type,
+ .srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0,
+ .is_srq = !!attr_ex->srq,
+ .recv_cq_handle = recv_cq_handle,
+ .send_cq_handle = send_cq_handle,
+ };
+
+ ret = execute_write_bufs(
+ context, IB_USER_VERBS_CMD_CREATE_QP_V3, req, resp);
+ if (ret)
+ return ret;
+
+ qp->handle = resp->qp_handle;
+ qp->qp_num = resp->qpn;
+ }
+
+ set_qp(vqp, qp, attr_ex, vxrcd);
+ return 0;
+ }
+
+ case TRY_WRITE_EX: {
+ DECLARE_LEGACY_UHW_BUFS_EX(link,
+ IB_USER_VERBS_EX_CMD_CREATE_QP);
+
+ *req = (struct ib_uverbs_ex_create_qp){
+ .pd_handle = pd_handle,
+ .user_handle = (uintptr_t)qp,
+ .max_send_wr = attr_ex->cap.max_send_wr,
+ .max_recv_wr = attr_ex->cap.max_recv_wr,
+ .max_send_sge = attr_ex->cap.max_send_sge,
+ .max_recv_sge = attr_ex->cap.max_recv_sge,
+ .max_inline_data = attr_ex->cap.max_inline_data,
+ .sq_sig_all = attr_ex->sq_sig_all,
+ .qp_type = attr_ex->qp_type,
+ .srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0,
+ .is_srq = !!attr_ex->srq,
+ .recv_cq_handle = recv_cq_handle,
+ .send_cq_handle = send_cq_handle,
+ };
+
+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_CREATE_FLAGS) {
+ req->create_flags = attr_ex->create_flags;
+
+ if (attr_ex->create_flags & IBV_QP_CREATE_SOURCE_QPN)
+ req->source_qpn = attr_ex->source_qpn;
+ }
+
+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_IND_TABLE) {
+ req->rwq_ind_tbl_handle = attr_ex->rwq_ind_tbl->ind_tbl_handle;
+ req->comp_mask = IB_UVERBS_CREATE_QP_MASK_IND_TABLE;
+ }
+
+ ret = execute_write_bufs_ex(
+ context, IB_USER_VERBS_EX_CMD_CREATE_QP, req, resp);
+ if (ret)
+ return ret;
+
+ qp->handle = resp->base.qp_handle;
+ qp->qp_num = resp->base.qpn;
+
+ attr_ex->cap.max_recv_sge = resp->base.max_recv_sge;
+ attr_ex->cap.max_send_sge = resp->base.max_send_sge;
+ attr_ex->cap.max_recv_wr = resp->base.max_recv_wr;
+ attr_ex->cap.max_send_wr = resp->base.max_send_wr;
+ attr_ex->cap.max_inline_data = resp->base.max_inline_data;
+ set_qp(vqp, qp, attr_ex, vxrcd);
+ return 0;
+ }
+
+ case SUCCESS:
+ break;
+
+ default:
+ return ret;
+ }
+
+ qp->handle = read_attr_obj(UVERBS_ATTR_CREATE_QP_HANDLE, handle);
+ qp->qp_num = qp_num;
+ set_qp(vqp, qp, attr_ex, vxrcd);
+
+ return 0;
+}
+
+int ibv_cmd_create_qp(struct ibv_pd *pd,
+ struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
+ struct ibv_create_qp *cmd, size_t cmd_size,
+ struct ib_uverbs_create_qp_resp *resp, size_t resp_size)
+{
+ DECLARE_CMD_BUFFER_COMPAT(cmdb, UVERBS_OBJECT_QP,
+ UVERBS_METHOD_QP_CREATE, cmd, cmd_size, resp,
+ resp_size);
+
+ struct ibv_qp_init_attr_ex attr_ex = {};
+ int ret;
+
+ memcpy(&attr_ex, attr, sizeof(*attr));
+ attr_ex.comp_mask |= IBV_QP_INIT_ATTR_PD;
+ attr_ex.pd = pd;
+ ret = ibv_icmd_create_qp(pd->context, NULL, qp, &attr_ex, cmdb);
+ if (!ret)
+ memcpy(&attr->cap, &attr_ex.cap, sizeof(attr_ex.cap));
+
+ return ret;
+}
+
+int ibv_cmd_create_qp_ex(struct ibv_context *context,
+ struct verbs_qp *qp,
+ struct ibv_qp_init_attr_ex *attr_ex,
+ struct ibv_create_qp *cmd, size_t cmd_size,
+ struct ib_uverbs_create_qp_resp *resp, size_t resp_size)
+{
+ DECLARE_CMD_BUFFER_COMPAT(cmdb, UVERBS_OBJECT_QP,
+ UVERBS_METHOD_QP_CREATE, cmd, cmd_size, resp,
+ resp_size);
+
+ if (!check_comp_mask(attr_ex->comp_mask,
+ IBV_QP_INIT_ATTR_PD |
+ IBV_QP_INIT_ATTR_XRCD |
+ IBV_QP_INIT_ATTR_SEND_OPS_FLAGS)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ return ibv_icmd_create_qp(context, qp, NULL, attr_ex, cmdb);
+}
+
+int ibv_cmd_create_qp_ex2(struct ibv_context *context,
+ struct verbs_qp *qp,
+ struct ibv_qp_init_attr_ex *attr_ex,
+ struct ibv_create_qp_ex *cmd,
+ size_t cmd_size,
+ struct ib_uverbs_ex_create_qp_resp *resp,
+ size_t resp_size)
+{
+ DECLARE_CMD_BUFFER_COMPAT(cmdb, UVERBS_OBJECT_QP,
+ UVERBS_METHOD_QP_CREATE, cmd, cmd_size, resp,
+ resp_size);
+
+ if (!check_comp_mask(attr_ex->comp_mask,
+ IBV_QP_INIT_ATTR_PD |
+ IBV_QP_INIT_ATTR_XRCD |
+ IBV_QP_INIT_ATTR_CREATE_FLAGS |
+ IBV_QP_INIT_ATTR_MAX_TSO_HEADER |
+ IBV_QP_INIT_ATTR_IND_TABLE |
+ IBV_QP_INIT_ATTR_RX_HASH |
+ IBV_QP_INIT_ATTR_SEND_OPS_FLAGS)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ return ibv_icmd_create_qp(context, qp, NULL, attr_ex, cmdb);
+}
+
+int ibv_cmd_destroy_qp(struct ibv_qp *qp)
+{
+ DECLARE_FBCMD_BUFFER(cmdb, UVERBS_OBJECT_QP, UVERBS_METHOD_QP_DESTROY, 2,
+ NULL);
+ struct ib_uverbs_destroy_qp_resp resp;
+ int ret;
+
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_DESTROY_QP_RESP, &resp);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_DESTROY_QP_HANDLE, qp->handle);
+
+ switch (execute_ioctl_fallback(qp->context, destroy_qp, cmdb, &ret)) {
+ case TRY_WRITE: {
+ struct ibv_destroy_qp req;
+
+ req.core_payload = (struct ib_uverbs_destroy_qp){
+ .qp_handle = qp->handle,
+ };
+
+ ret = execute_cmd_write(qp->context,
+ IB_USER_VERBS_CMD_DESTROY_QP, &req,
+ sizeof(req), &resp, sizeof(resp));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (verbs_is_destroy_err(&ret))
+ return ret;
+
+ pthread_mutex_lock(&qp->mutex);
+ while (qp->events_completed != resp.events_reported)
+ pthread_cond_wait(&qp->cond, &qp->mutex);
+ pthread_mutex_unlock(&qp->mutex);
+
+ return 0;
+}
@@ -521,12 +521,12 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
struct ibv_create_qp *cmd, size_t cmd_size,
struct ib_uverbs_create_qp_resp *resp, size_t resp_size);
int ibv_cmd_create_qp_ex(struct ibv_context *context,
- struct verbs_qp *qp, int vqp_sz,
+ struct verbs_qp *qp,
struct ibv_qp_init_attr_ex *attr_ex,
struct ibv_create_qp *cmd, size_t cmd_size,
struct ib_uverbs_create_qp_resp *resp, size_t resp_size);
int ibv_cmd_create_qp_ex2(struct ibv_context *context,
- struct verbs_qp *qp, int vqp_sz,
+ struct verbs_qp *qp,
struct ibv_qp_init_attr_ex *qp_attr,
struct ibv_create_qp_ex *cmd,
size_t cmd_size,
@@ -312,4 +312,11 @@ struct ibv_create_srq_resp_v5 {
enum { IB_USER_VERBS_CMD_CREATE_SRQ_V5 = IB_USER_VERBS_CMD_CREATE_SRQ };
DECLARE_CMDX(IB_USER_VERBS_CMD_CREATE_SRQ_V5, ibv_create_srq_v5, ib_uverbs_create_srq, ibv_create_srq_resp_v5);
+#define _STRUCT_ib_uverbs_create_qp_v4
+enum { IB_USER_VERBS_CMD_CREATE_QP_V4 = IB_USER_VERBS_CMD_CREATE_QP };
+DECLARE_CMDX(IB_USER_VERBS_CMD_CREATE_QP_V4, ibv_create_qp_v4, ib_uverbs_create_qp, ibv_create_qp_resp_v4);
+
+#define _STRUCT_ib_uverbs_create_qp_v3
+enum { IB_USER_VERBS_CMD_CREATE_QP_V3 = IB_USER_VERBS_CMD_CREATE_QP };
+DECLARE_CMDX(IB_USER_VERBS_CMD_CREATE_QP_V3, ibv_create_qp_v3, ib_uverbs_create_qp, ibv_create_qp_resp_v3);
#endif /* KERN_ABI_H */
@@ -600,20 +600,6 @@ LATEST_SYMVER_FUNC(ibv_create_qp, 1_1, "IBVERBS_1.1",
{
struct ibv_qp *qp = get_ops(pd->context)->create_qp(pd, qp_init_attr);
- if (qp) {
- qp->context = pd->context;
- qp->qp_context = qp_init_attr->qp_context;
- qp->pd = pd;
- qp->send_cq = qp_init_attr->send_cq;
- qp->recv_cq = qp_init_attr->recv_cq;
- qp->srq = qp_init_attr->srq;
- qp->qp_type = qp_init_attr->qp_type;
- qp->state = IBV_QPS_RESET;
- qp->events_completed = 0;
- pthread_mutex_init(&qp->mutex, NULL);
- pthread_cond_init(&qp->cond, NULL);
- }
-
return qp;
}
@@ -826,7 +826,7 @@ static struct ibv_qp *create_qp(struct ibv_context *ibvctx,
if (attr->qp_type == IBV_QPT_DRIVER)
req.driver_qp_type = efa_attr->driver_qp_type;
- err = ibv_cmd_create_qp_ex(ibvctx, &qp->verbs_qp, sizeof(qp->verbs_qp),
+ err = ibv_cmd_create_qp_ex(ibvctx, &qp->verbs_qp,
attr, &req.ibv_cmd, sizeof(req),
&resp.ibv_resp, sizeof(resp));
if (err)
@@ -790,7 +790,7 @@ static int mlx4_cmd_create_qp_ex_rss(struct ibv_context *context,
sizeof(cmd_ex.rx_hash_key));
ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp,
- sizeof(qp->verbs_qp), attr, &cmd_ex.ibv_cmd,
+ attr, &cmd_ex.ibv_cmd,
sizeof(cmd_ex), &resp.ibv_resp,
sizeof(resp));
return ret;
@@ -849,7 +849,7 @@ static int mlx4_cmd_create_qp_ex(struct ibv_context *context,
cmd_ex.drv_payload = cmd->drv_payload;
ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp,
- sizeof(qp->verbs_qp), attr, &cmd_ex.ibv_cmd,
+ attr, &cmd_ex.ibv_cmd,
sizeof(cmd_ex), &resp.ibv_resp,
sizeof(resp));
return ret;
@@ -981,7 +981,7 @@ static struct ibv_qp *create_qp_ex(struct ibv_context *context,
ret = mlx4_cmd_create_qp_ex(context, attr, &cmd, qp);
else
ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp,
- sizeof(qp->verbs_qp), attr,
+ attr,
&cmd.ibv_cmd, sizeof(cmd), &resp,
sizeof(resp));
if (ret)
@@ -1866,7 +1866,7 @@ static int mlx5_cmd_create_rss_qp(struct ibv_context *context,
attr->rx_hash_conf.rx_hash_key_len);
ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp,
- sizeof(qp->verbs_qp), attr,
+ attr,
&cmd_ex_rss.ibv_cmd, sizeof(cmd_ex_rss),
&resp.ibv_resp, sizeof(resp));
if (ret)
@@ -1899,7 +1899,7 @@ static int mlx5_cmd_create_qp_ex(struct ibv_context *context,
cmd_ex.drv_payload = cmd->drv_payload;
ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp,
- sizeof(qp->verbs_qp), attr, &cmd_ex.ibv_cmd,
+ attr, &cmd_ex.ibv_cmd,
sizeof(cmd_ex), &resp->ibv_resp,
sizeof(*resp));
@@ -1990,7 +1990,7 @@ static int create_dct(struct ibv_context *context,
}
cmd.uidx = usr_idx;
- ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, sizeof(qp->verbs_qp),
+ ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp,
attr, &cmd.ibv_cmd, sizeof(cmd),
&resp.ibv_resp, sizeof(resp));
if (ret) {
@@ -2290,7 +2290,7 @@ static struct ibv_qp *create_qp(struct ibv_context *context,
if (attr->comp_mask & MLX5_CREATE_QP_EX2_COMP_MASK)
ret = mlx5_cmd_create_qp_ex(context, attr, &cmd, qp, &resp_ex);
else
- ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, sizeof(qp->verbs_qp),
+ ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp,
attr, &cmd.ibv_cmd, sizeof(cmd),
&resp.ibv_resp, sizeof(resp));
if (ret) {
Introduce create/destroy QP commands over the ioctl interface to let it be extended to get an asynchronous event FD. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> --- libibverbs/CMakeLists.txt | 1 + libibverbs/cmd.c | 264 ------------------------- libibverbs/cmd_qp.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++ libibverbs/driver.h | 4 +- libibverbs/kern-abi.h | 7 + libibverbs/verbs.c | 14 -- providers/efa/verbs.c | 2 +- providers/mlx4/verbs.c | 6 +- providers/mlx5/verbs.c | 8 +- 9 files changed, 494 insertions(+), 288 deletions(-) create mode 100644 libibverbs/cmd_qp.c