@@ -37,6 +37,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
cmd_mw.c
cmd_pd.c
cmd_rwq_ind.c
+ cmd_srq.c
cmd_xrcd.c
compat-1_0.c
device.c
@@ -480,120 +480,6 @@ int ibv_cmd_resize_cq(struct ibv_cq *cq, int cqe,
return 0;
}
-int ibv_cmd_create_srq(struct ibv_pd *pd,
- struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
- struct ibv_create_srq *cmd, size_t cmd_size,
- struct ib_uverbs_create_srq_resp *resp, size_t resp_size)
-{
- int ret;
-
- cmd->user_handle = (uintptr_t) srq;
- cmd->pd_handle = pd->handle;
- cmd->max_wr = attr->attr.max_wr;
- cmd->max_sge = attr->attr.max_sge;
- cmd->srq_limit = attr->attr.srq_limit;
-
- ret = execute_cmd_write(pd->context, IB_USER_VERBS_CMD_CREATE_SRQ, cmd,
- cmd_size, resp, resp_size);
- if (ret)
- return ret;
-
- srq->handle = resp->srq_handle;
- srq->context = pd->context;
-
- if (abi_ver > 5) {
- attr->attr.max_wr = resp->max_wr;
- attr->attr.max_sge = resp->max_sge;
- } else {
- struct ibv_create_srq_resp_v5 *resp_v5 =
- (struct ibv_create_srq_resp_v5 *) resp;
-
- memmove((void *) resp + sizeof *resp,
- (void *) resp_v5 + sizeof *resp_v5,
- resp_size - sizeof *resp);
- }
-
- return 0;
-}
-
-int ibv_cmd_create_srq_ex(struct ibv_context *context,
- struct verbs_srq *srq, int vsrq_sz,
- struct ibv_srq_init_attr_ex *attr_ex,
- struct ibv_create_xsrq *cmd, size_t cmd_size,
- struct ib_uverbs_create_srq_resp *resp, size_t resp_size)
-{
- struct verbs_xrcd *vxrcd = NULL;
- int ret;
-
- if (attr_ex->comp_mask >= IBV_SRQ_INIT_ATTR_RESERVED)
- return EOPNOTSUPP;
-
- if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_PD))
- return EINVAL;
-
- cmd->user_handle = (uintptr_t) srq;
- cmd->pd_handle = attr_ex->pd->handle;
- cmd->max_wr = attr_ex->attr.max_wr;
- cmd->max_sge = attr_ex->attr.max_sge;
- cmd->srq_limit = attr_ex->attr.srq_limit;
-
- cmd->srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
- attr_ex->srq_type : IBV_SRQT_BASIC;
- if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_XRCD) {
- if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ))
- return EINVAL;
-
- vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
- cmd->xrcd_handle = vxrcd->handle;
- cmd->cq_handle = attr_ex->cq->handle;
- } else if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TM) {
- if (cmd->srq_type != IBV_SRQT_TM)
- return EINVAL;
- if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ) ||
- !attr_ex->tm_cap.max_num_tags)
- return EINVAL;
-
- cmd->cq_handle = attr_ex->cq->handle;
- cmd->max_num_tags = attr_ex->tm_cap.max_num_tags;
- } else if (cmd->srq_type != IBV_SRQT_BASIC) {
- return EINVAL;
- }
-
- ret = execute_cmd_write(context, IB_USER_VERBS_CMD_CREATE_XSRQ, cmd,
- cmd_size, resp, resp_size);
- if (ret)
- return ret;
-
- srq->srq.handle = resp->srq_handle;
- srq->srq.context = context;
- srq->srq.srq_context = attr_ex->srq_context;
- srq->srq.pd = attr_ex->pd;
- srq->srq.events_completed = 0;
- pthread_mutex_init(&srq->srq.mutex, NULL);
- pthread_cond_init(&srq->srq.cond, NULL);
-
- /*
- * check that the last field is available.
- * If it is than all the others exist as well
- */
- if (vext_field_avail(struct verbs_srq, srq_num, vsrq_sz)) {
- srq->srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
- attr_ex->srq_type : IBV_SRQT_BASIC;
- if (srq->srq_type == IBV_SRQT_XRC)
- srq->srq_num = resp->srqn;
- if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_XRCD)
- srq->xrcd = vxrcd;
- if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ)
- srq->cq = attr_ex->cq;
- }
-
- attr_ex->attr.max_wr = resp->max_wr;
- attr_ex->attr.max_sge = resp->max_sge;
-
- return 0;
-}
-
-
static int ibv_cmd_modify_srq_v3(struct ibv_srq *srq,
struct ibv_srq_attr *srq_attr,
int srq_attr_mask,
@@ -657,29 +543,6 @@ int ibv_cmd_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
return 0;
}
-int ibv_cmd_destroy_srq(struct ibv_srq *srq)
-{
- struct ibv_destroy_srq req;
- struct ib_uverbs_destroy_srq_resp resp;
- int ret;
-
- req.core_payload = (struct ib_uverbs_destroy_srq){
- .srq_handle = srq->handle,
- };
-
- ret = execute_cmd_write(srq->context, IB_USER_VERBS_CMD_DESTROY_SRQ,
- &req, sizeof(req), &resp, sizeof(resp));
- if (verbs_is_destroy_err(&ret))
- return ret;
-
- pthread_mutex_lock(&srq->mutex);
- while (srq->events_completed != resp.events_reported)
- pthread_cond_wait(&srq->cond, &srq->mutex);
- pthread_mutex_unlock(&srq->mutex);
-
- return 0;
-}
-
static int create_qp_ex_common(struct verbs_qp *qp,
struct ibv_qp_init_attr_ex *qp_attr,
struct verbs_xrcd *vxrcd,
new file mode 100644
@@ -0,0 +1,279 @@
+/*
+ * 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"
+
+static void set_vsrq(struct verbs_srq *vsrq,
+ struct ibv_srq_init_attr_ex *attr_ex,
+ uint32_t srq_num)
+{
+ vsrq->srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
+ attr_ex->srq_type : IBV_SRQT_BASIC;
+ if (vsrq->srq_type == IBV_SRQT_XRC) {
+ vsrq->srq_num = srq_num;
+ vsrq->xrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
+ }
+ if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ)
+ vsrq->cq = attr_ex->cq;
+}
+
+static int ibv_icmd_create_srq(struct ibv_pd *pd, struct verbs_srq *vsrq,
+ struct ibv_srq *srq_in,
+ struct ibv_srq_init_attr_ex *attr_ex,
+ struct ibv_command_buffer *link)
+{
+ DECLARE_FBCMD_BUFFER(cmdb, UVERBS_OBJECT_SRQ, UVERBS_METHOD_SRQ_CREATE, 13, link);
+ struct ib_uverbs_attr *handle;
+ uint32_t max_wr;
+ uint32_t max_sge;
+ uint32_t srq_num;
+ int ret;
+ struct ibv_srq *srq = vsrq ? &vsrq->srq : srq_in;
+ struct verbs_xrcd *vxrcd = NULL;
+ enum ibv_srq_type srq_type;
+
+ srq->context = pd->context;
+ pthread_mutex_init(&srq->mutex, NULL);
+ pthread_cond_init(&srq->cond, NULL);
+
+ srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
+ attr_ex->srq_type : IBV_SRQT_BASIC;
+ switch (srq_type) {
+ case IBV_SRQT_XRC:
+ if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_XRCD) ||
+ !(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE, vxrcd->handle);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE, attr_ex->cq->handle);
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM, &srq_num);
+ break;
+ case IBV_SRQT_TM:
+ if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ) ||
+ !(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TM) ||
+ !(attr_ex->tm_cap.max_num_tags)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE, attr_ex->cq->handle);
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS, attr_ex->tm_cap.max_num_tags);
+ break;
+ default:
+ break;
+ }
+
+ handle = fill_attr_out_obj(cmdb, UVERBS_ATTR_CREATE_SRQ_HANDLE);
+ fill_attr_const_in(cmdb, UVERBS_ATTR_CREATE_SRQ_TYPE, srq_type);
+ fill_attr_in_uint64(cmdb, UVERBS_ATTR_CREATE_SRQ_USER_HANDLE, (uintptr_t)srq);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_CREATE_SRQ_PD_HANDLE, pd->handle);
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_SRQ_MAX_WR, attr_ex->attr.max_wr);
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_SRQ_MAX_SGE, attr_ex->attr.max_sge);
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_CREATE_SRQ_LIMIT, attr_ex->attr.srq_limit);
+ fill_attr_in_fd(cmdb, UVERBS_ATTR_CREATE_SRQ_EVENT_FD, pd->context->async_fd);
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR, &max_wr);
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE, &max_sge);
+
+ switch (execute_ioctl_fallback(srq->context, create_srq, cmdb, &ret)) {
+ case TRY_WRITE: {
+ if (attr_ex->srq_type == IBV_SRQT_BASIC && abi_ver > 5) {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_SRQ);
+
+ *req = (struct ib_uverbs_create_srq){
+ .pd_handle = pd->handle,
+ .user_handle = (uintptr_t)srq,
+ .max_wr = attr_ex->attr.max_wr,
+ .max_sge = attr_ex->attr.max_sge,
+ .srq_limit = attr_ex->attr.srq_limit,
+ };
+
+ ret = execute_write_bufs(
+ srq->context, IB_USER_VERBS_CMD_CREATE_SRQ, req, resp);
+ if (ret)
+ return ret;
+
+ srq->handle = resp->srq_handle;
+ attr_ex->attr.max_wr = resp->max_wr;
+ attr_ex->attr.max_sge = resp->max_sge;
+ } else if (attr_ex->srq_type == IBV_SRQT_BASIC && abi_ver <= 5) {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_SRQ_V5);
+
+ *req = (struct ib_uverbs_create_srq){
+ .pd_handle = pd->handle,
+ .user_handle = (uintptr_t)srq,
+ .max_wr = attr_ex->attr.max_wr,
+ .max_sge = attr_ex->attr.max_sge,
+ .srq_limit = attr_ex->attr.srq_limit,
+ };
+
+ ret = execute_write_bufs(
+ srq->context, IB_USER_VERBS_CMD_CREATE_SRQ_V5, req, resp);
+ if (ret)
+ return ret;
+
+ srq->handle = resp->srq_handle;
+ } else {
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_XSRQ);
+
+ *req = (struct ib_uverbs_create_xsrq){
+ .pd_handle = pd->handle,
+ .user_handle = (uintptr_t)srq,
+ .max_wr = attr_ex->attr.max_wr,
+ .max_sge = attr_ex->attr.max_sge,
+ .srq_limit = attr_ex->attr.srq_limit,
+ .srq_type = attr_ex->srq_type,
+ .cq_handle = attr_ex->cq->handle,
+ };
+
+ if (attr_ex->srq_type == IBV_SRQT_TM)
+ req->max_num_tags = attr_ex->tm_cap.max_num_tags;
+ else
+ req->xrcd_handle = vxrcd->handle;
+
+ ret = execute_write_bufs(
+ srq->context, IB_USER_VERBS_CMD_CREATE_XSRQ, req, resp);
+ if (ret)
+ return ret;
+
+ srq->handle = resp->srq_handle;
+ attr_ex->attr.max_wr = resp->max_wr;
+ attr_ex->attr.max_sge = resp->max_sge;
+ set_vsrq(vsrq, attr_ex, resp->srqn);
+ }
+
+ return 0;
+ }
+
+ case SUCCESS:
+ break;
+
+ default:
+ return ret;
+ }
+
+ srq->handle = read_attr_obj(UVERBS_ATTR_CREATE_SRQ_HANDLE, handle);
+ attr_ex->attr.max_wr = max_wr;
+ attr_ex->attr.max_sge = max_sge;
+ if (vsrq)
+ set_vsrq(vsrq, attr_ex, srq_num);
+
+ return 0;
+}
+
+int ibv_cmd_create_srq(struct ibv_pd *pd, struct ibv_srq *srq,
+ struct ibv_srq_init_attr *attr,
+ struct ibv_create_srq *cmd, size_t cmd_size,
+ struct ib_uverbs_create_srq_resp *resp, size_t resp_size)
+{
+ DECLARE_CMD_BUFFER_COMPAT(cmdb, UVERBS_OBJECT_SRQ,
+ UVERBS_METHOD_SRQ_CREATE, cmd, cmd_size, resp,
+ resp_size);
+
+ struct ibv_srq_init_attr_ex attr_ex = {};
+ int ret;
+
+ memcpy(&attr_ex, attr, sizeof(*attr));
+ ret = ibv_icmd_create_srq(pd, NULL, srq, &attr_ex, cmdb);
+ if (!ret) {
+ attr->attr.max_wr = attr_ex.attr.max_wr;
+ attr->attr.max_sge = attr_ex.attr.max_sge;
+ }
+
+ return ret;
+}
+
+int ibv_cmd_create_srq_ex(struct ibv_context *context,
+ struct verbs_srq *srq,
+ struct ibv_srq_init_attr_ex *attr_ex,
+ struct ibv_create_xsrq *cmd, size_t cmd_size,
+ struct ib_uverbs_create_srq_resp *resp, size_t resp_size)
+{
+ DECLARE_CMD_BUFFER_COMPAT(cmdb, UVERBS_OBJECT_SRQ,
+ UVERBS_METHOD_SRQ_CREATE, cmd, cmd_size, resp,
+ resp_size);
+
+ if (attr_ex->comp_mask >= IBV_SRQ_INIT_ATTR_RESERVED) {
+ errno = EOPNOTSUPP;
+ return errno;
+ }
+
+ if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_PD)) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ return ibv_icmd_create_srq(attr_ex->pd, srq, NULL, attr_ex, cmdb);
+}
+
+int ibv_cmd_destroy_srq(struct ibv_srq *srq)
+{
+ DECLARE_FBCMD_BUFFER(cmdb, UVERBS_OBJECT_SRQ, UVERBS_METHOD_SRQ_DESTROY, 2,
+ NULL);
+ struct ib_uverbs_destroy_srq_resp resp;
+ int ret;
+
+ fill_attr_out_ptr(cmdb, UVERBS_ATTR_DESTROY_SRQ_RESP, &resp);
+ fill_attr_in_obj(cmdb, UVERBS_ATTR_DESTROY_SRQ_HANDLE, srq->handle);
+
+ switch (execute_ioctl_fallback(srq->context, destroy_srq, cmdb, &ret)) {
+ case TRY_WRITE: {
+ struct ibv_destroy_srq req;
+
+ req.core_payload = (struct ib_uverbs_destroy_srq){
+ .srq_handle = srq->handle,
+ };
+
+ ret = execute_cmd_write(srq->context,
+ IB_USER_VERBS_CMD_DESTROY_SRQ, &req,
+ sizeof(req), &resp, sizeof(resp));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (verbs_is_destroy_err(&ret))
+ return ret;
+
+ pthread_mutex_lock(&srq->mutex);
+ while (srq->events_completed != resp.events_reported)
+ pthread_cond_wait(&srq->cond, &srq->mutex);
+ pthread_mutex_unlock(&srq->mutex);
+
+ return 0;
+}
+
@@ -503,7 +503,7 @@ int ibv_cmd_create_srq(struct ibv_pd *pd,
struct ibv_create_srq *cmd, size_t cmd_size,
struct ib_uverbs_create_srq_resp *resp, size_t resp_size);
int ibv_cmd_create_srq_ex(struct ibv_context *context,
- struct verbs_srq *srq, int vsrq_sz,
+ struct verbs_srq *srq,
struct ibv_srq_init_attr_ex *attr_ex,
struct ibv_create_xsrq *cmd, size_t cmd_size,
struct ib_uverbs_create_srq_resp *resp, size_t resp_size);
@@ -308,4 +308,8 @@ struct ibv_create_srq_resp_v5 {
__u32 srq_handle;
};
+#define _STRUCT_ib_uverbs_create_srq_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);
+
#endif /* KERN_ABI_H */
@@ -267,7 +267,6 @@ struct ibv_srq *mlx4_create_xrc_srq(struct ibv_context *context,
cmd.db_addr = (uintptr_t) srq->db;
ret = ibv_cmd_create_srq_ex(context, &srq->verbs_srq,
- sizeof(srq->verbs_srq),
attr_ex,
&cmd.ibv_cmd, sizeof cmd,
&resp.ibv_resp, sizeof resp);
@@ -3160,7 +3160,7 @@ struct ibv_srq *mlx5_create_srq_ex(struct ibv_context *context,
*/
attr->attr.max_wr = msrq->max - 1;
- err = ibv_cmd_create_srq_ex(context, &msrq->vsrq, sizeof(msrq->vsrq),
+ err = ibv_cmd_create_srq_ex(context, &msrq->vsrq,
attr, &cmd.ibv_cmd, sizeof(cmd),
&resp.ibv_resp, sizeof(resp));
Introduce create/destroy SRQ 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 | 137 ----------------------- libibverbs/cmd_srq.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++ libibverbs/driver.h | 2 +- libibverbs/kern-abi.h | 4 + providers/mlx4/srq.c | 1 - providers/mlx5/verbs.c | 2 +- 7 files changed, 286 insertions(+), 140 deletions(-) create mode 100644 libibverbs/cmd_srq.c