From: Sean Hefty Date: Fri, 28 Sep 2012 17:44:45 +0000 (-0700) Subject: refresh X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=ba04a45c29adcecd5543959a2c864b6ee347cc15;p=~shefty%2Flibibverbs.git refresh --- diff --git a/meta b/meta index 415e2f5..15ed961 100644 --- a/meta +++ b/meta @@ -1,12 +1,11 @@ Version: 1 -Previous: 9c927a492c4b681fa8f6f01004d811187ae7c1b2 -Head: b301fa827367508d386a607cfad5b9863372f456 +Previous: 15fbbd6a1651ac1cd8fdf42d86c640c350d8d2bf +Head: 092bcc697d9bb0d4fe8cc322d57b9248800d2e71 Applied: verbs-ext: b1cc207d04e9df91c000aadd20d3612f3cb58552 xrcd: f2b48b365d126d1c4bc61b3b3ea1ab9b7f2544f4 srq_ex: 91fdc5b4aaf078280ff31bd0cf35760a6ae5dd10 - xrc_qp: a98e29562c1d727dd492cfa66b628369460969f6 - refresh-temp: b301fa827367508d386a607cfad5b9863372f456 + xrc_qp: 092bcc697d9bb0d4fe8cc322d57b9248800d2e71 Unapplied: open_qp: 02ed1a5b57528c104aefa6608f45bdf2d718ded3 open_qp_man: 3ba2056186d67520b8302137c5906a0083891d7f diff --git a/patches/refresh-temp b/patches/refresh-temp deleted file mode 100644 index 045d7eb..0000000 --- a/patches/refresh-temp +++ /dev/null @@ -1,317 +0,0 @@ -Bottom: f12a9640338b48e3a608e0b2ec69517ecd34327e -Top: 61b6c90445f6c7731dcbedec80b9701b071ba0f8 -Author: Sean Hefty -Date: 2012-09-28 10:44:45 -0700 - -Refresh of xrc_qp - ---- - -diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h -index 05ff730..d43ae07 100644 ---- a/include/infiniband/driver.h -+++ b/include/infiniband/driver.h -@@ -81,6 +81,16 @@ struct verbs_srq { - uint32_t srq_num; - }; - -+enum verbs_qp_mask { -+ VERBS_QP_XRCD = 1 << 0, -+ VERBS_QP_RESERVED = 1 << 1 -+}; -+ -+struct verbs_qp { -+ struct ibv_qp qp; -+ uint32_t comp_mask; -+ struct verbs_xrcd *xrcd; -+}; - typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path, - int abi_version); - typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path, -@@ -152,6 +162,10 @@ 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 ibv_create_qp_resp *resp, size_t resp_size); -+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 ibv_create_qp_resp *resp, size_t resp_size); - int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *qp_attr, - int attr_mask, - struct ibv_qp_init_attr *qp_init_attr, -diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h -index 3d72fa7..b6d5ce9 100644 ---- a/include/infiniband/kern-abi.h -+++ b/include/infiniband/kern-abi.h -@@ -617,6 +617,11 @@ struct ibv_kern_send_wr { - __u32 remote_qkey; - __u32 reserved; - } ud; -+ struct { -+ __u64 reserved[3]; -+ __u32 reserved2; -+ __u32 remote_srqn; -+ } xrc; - } wr; - }; - -diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h -index 6465aae..1356757 100644 ---- a/include/infiniband/verbs.h -+++ b/include/infiniband/verbs.h -@@ -91,21 +91,22 @@ enum ibv_transport_type { - }; - - enum ibv_device_cap_flags { -- IBV_DEVICE_RESIZE_MAX_WR = 1, -- IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1, -- IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2, -- IBV_DEVICE_RAW_MULTI = 1 << 3, -- IBV_DEVICE_AUTO_PATH_MIG = 1 << 4, -- IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5, -- IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6, -- IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7, -- IBV_DEVICE_SHUTDOWN_PORT = 1 << 8, -- IBV_DEVICE_INIT_TYPE = 1 << 9, -- IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10, -- IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11, -- IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, -- IBV_DEVICE_SRQ_RESIZE = 1 << 13, -- IBV_DEVICE_N_NOTIFY_CQ = 1 << 14 -+ IBV_DEVICE_RESIZE_MAX_WR = 1, -+ IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1, -+ IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2, -+ IBV_DEVICE_RAW_MULTI = 1 << 3, -+ IBV_DEVICE_AUTO_PATH_MIG = 1 << 4, -+ IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5, -+ IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6, -+ IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7, -+ IBV_DEVICE_SHUTDOWN_PORT = 1 << 8, -+ IBV_DEVICE_INIT_TYPE = 1 << 9, -+ IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10, -+ IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11, -+ IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, -+ IBV_DEVICE_SRQ_RESIZE = 1 << 13, -+ IBV_DEVICE_N_NOTIFY_CQ = 1 << 14, -+ IBV_DEVICE_XRC = 1 << 20 - }; - - enum ibv_atomic_cap { -@@ -445,7 +446,11 @@ struct ibv_srq_init_attr_ex { - }; - - enum ibv_qp_type { -- IBV_QPT_RC = 2, IBV_QPT_UC, IBV_QPT_UD -+ IBV_QPT_RC = 2, -+ IBV_QPT_UC, -+ IBV_QPT_UD, -+ IBV_QPT_XRC_SEND = 9, -+ IBV_QPT_XRC_RECV - }; - - struct ibv_qp_cap { -@@ -466,6 +471,26 @@ struct ibv_qp_init_attr { - int sq_sig_all; - }; - -+enum ibv_qp_init_attr_mask { -+ IBV_QP_INIT_ATTR_PD = 1 << 0, -+ IBV_QP_INIT_ATTR_XRCD = 1 << 1, -+ IBV_QP_INIT_ATTR_RESERVED = 1 << 2 -+}; -+ -+struct ibv_qp_init_attr_ex { -+ void *qp_context; -+ struct ibv_cq *send_cq; -+ struct ibv_cq *recv_cq; -+ struct ibv_srq *srq; -+ struct ibv_qp_cap cap; -+ enum ibv_qp_type qp_type; -+ int sq_sig_all; -+ -+ uint32_t comp_mask; -+ struct ibv_pd *pd; -+ struct ibv_xrcd *xrcd; -+}; -+ - enum ibv_qp_attr_mask { - IBV_QP_STATE = 1 << 0, - IBV_QP_CUR_STATE = 1 << 1, -@@ -579,6 +604,11 @@ struct ibv_send_wr { - uint32_t remote_qpn; - uint32_t remote_qkey; - } ud; -+ struct { -+ uint64_t reserved[3]; -+ uint32_t reserved2; -+ uint32_t remote_srqn; -+ } xrc; - } wr; - }; - -@@ -755,7 +785,8 @@ struct ibv_context { - enum verbs_context_mask { - VERBS_CONTEXT_XRCD = 1 << 0, - VERBS_CONTEXT_SRQ = 1 << 1, -- VERBS_CONTEXT_RESERVED = 1 << 2 -+ VERBS_CONTEXT_QP = 1 << 2, -+ VERBS_CONTEXT_RESERVED = 1 << 3 - }; - - struct verbs_context { -@@ -763,6 +794,8 @@ struct verbs_context { - int (*drv_new_func1) (); new corresponding provider call of func1 - int (*lib_new_func1) (); New library call func1 - */ -+ struct ibv_qp * (*create_qp_ex)(struct ibv_context *context, -+ struct ibv_qp_init_attr_ex *qp_init_attr_ex); - uint32_t (*get_srq_num)(struct ibv_srq *srq); - struct ibv_srq * (*create_srq_ex)(struct ibv_context *context, - struct ibv_srq_init_attr_ex *srq_init_attr_ex); -@@ -1123,6 +1156,23 @@ static inline int ibv_post_srq_recv(struct ibv_srq *srq, - struct ibv_qp *ibv_create_qp(struct ibv_pd *pd, - struct ibv_qp_init_attr *qp_init_attr); - -+static inline struct ibv_qp * -+ibv_create_qp_ex(struct ibv_context *context, struct ibv_qp_init_attr_ex *qp_init_attr_ex) -+{ -+ struct verbs_context *vctx; -+ uint32_t mask = qp_init_attr_ex->comp_mask; -+ -+ if (!(mask & ~(IBV_QP_INIT_ATTR_PD)) && (mask & IBV_QP_INIT_ATTR_PD)) -+ return ibv_create_qp(qp_init_attr_ex->pd, -+ (struct ibv_qp_init_attr *) qp_init_attr_ex); -+ -+ if (!(vctx = verbs_get_ctx_op(context, create_qp_ex))) { -+ errno = ENOSYS; -+ return NULL; -+ } -+ return vctx->create_qp_ex(context, qp_init_attr_ex); -+} -+ - /** - * ibv_modify_qp - Modify a queue pair. - */ -diff --git a/src/cmd.c b/src/cmd.c -index 641ab28..87ac062 100644 ---- a/src/cmd.c -+++ b/src/cmd.c -@@ -666,6 +666,98 @@ int ibv_cmd_destroy_srq(struct ibv_srq *srq) - return 0; - } - -+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 ibv_create_qp_resp *resp, size_t resp_size) -+{ -+ struct verbs_xrcd *vxrcd = NULL; -+ -+ IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size); -+ -+ if (attr_ex->comp_mask >= IBV_QP_INIT_ATTR_RESERVED) -+ return ENOSYS; -+ -+ cmd->user_handle = (uintptr_t) qp; -+ -+ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) { -+ vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd); -+ cmd->pd_handle = vxrcd->handle; -+ } else { -+ if (!(attr_ex->comp_mask & IBV_QP_INIT_ATTR_PD)) -+ return EINVAL; -+ -+ cmd->pd_handle = attr_ex->pd->handle; -+ cmd->send_cq_handle = attr_ex->send_cq->handle; -+ -+ if (attr_ex->qp_type != IBV_QPT_XRC_SEND) { -+ cmd->recv_cq_handle = attr_ex->recv_cq->handle; -+ cmd->srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0; -+ } -+ } -+ -+ cmd->max_send_wr = attr_ex->cap.max_send_wr; -+ cmd->max_recv_wr = attr_ex->cap.max_recv_wr; -+ cmd->max_send_sge = attr_ex->cap.max_send_sge; -+ cmd->max_recv_sge = attr_ex->cap.max_recv_sge; -+ cmd->max_inline_data = attr_ex->cap.max_inline_data; -+ cmd->sq_sig_all = attr_ex->sq_sig_all; -+ cmd->qp_type = attr_ex->qp_type; -+ cmd->is_srq = !!attr_ex->srq; -+ cmd->reserved = 0; -+ -+ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) -+ return errno; -+ -+ (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size); -+ -+ if (abi_ver > 3) { -+ 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; -+ } -+ -+ 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); -+ } -+ -+ qp->qp.handle = resp->qp_handle; -+ qp->qp.qp_num = resp->qpn; -+ qp->qp.context = context; -+ qp->qp.qp_context = attr_ex->qp_context; -+ qp->qp.pd = attr_ex->pd; -+ qp->qp.send_cq = attr_ex->send_cq; -+ qp->qp.recv_cq = attr_ex->recv_cq; -+ qp->qp.srq = attr_ex->srq; -+ qp->qp.qp_type = attr_ex->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 (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) { -+ qp->comp_mask |= VERBS_QP_XRCD; -+ qp->xrcd = 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, -@@ -674,7 +766,7 @@ int ibv_cmd_create_qp(struct ibv_pd *pd, - IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size); - - cmd->user_handle = (uintptr_t) qp; -- cmd->pd_handle = pd->handle; -+ 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; -diff --git a/src/libibverbs.map b/src/libibverbs.map -index c8ec645..4249793 100644 ---- a/src/libibverbs.map -+++ b/src/libibverbs.map -@@ -101,5 +101,6 @@ IBVERBS_1.1 { - ibv_cmd_open_xrcd; - ibv_cmd_close_xrcd; - ibv_cmd_create_srq_ex; -+ ibv_cmd_create_qp_ex; - - } IBVERBS_1.0; diff --git a/patches/xrc_qp b/patches/xrc_qp index b0900b4..4ef0601 100644 --- a/patches/xrc_qp +++ b/patches/xrc_qp @@ -1,5 +1,5 @@ Bottom: f12a9640338b48e3a608e0b2ec69517ecd34327e -Top: f12a9640338b48e3a608e0b2ec69517ecd34327e +Top: 61b6c90445f6c7731dcbedec80b9701b071ba0f8 Author: Sean Hefty Date: 2012-09-17 16:00:12 -0700 @@ -31,4 +31,311 @@ Signed-off-by: Sean Hefty --- - +diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h +index 05ff730..d43ae07 100644 +--- a/include/infiniband/driver.h ++++ b/include/infiniband/driver.h +@@ -81,6 +81,16 @@ struct verbs_srq { + uint32_t srq_num; + }; + ++enum verbs_qp_mask { ++ VERBS_QP_XRCD = 1 << 0, ++ VERBS_QP_RESERVED = 1 << 1 ++}; ++ ++struct verbs_qp { ++ struct ibv_qp qp; ++ uint32_t comp_mask; ++ struct verbs_xrcd *xrcd; ++}; + typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path, + int abi_version); + typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path, +@@ -152,6 +162,10 @@ 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 ibv_create_qp_resp *resp, size_t resp_size); ++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 ibv_create_qp_resp *resp, size_t resp_size); + int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *qp_attr, + int attr_mask, + struct ibv_qp_init_attr *qp_init_attr, +diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h +index 3d72fa7..b6d5ce9 100644 +--- a/include/infiniband/kern-abi.h ++++ b/include/infiniband/kern-abi.h +@@ -617,6 +617,11 @@ struct ibv_kern_send_wr { + __u32 remote_qkey; + __u32 reserved; + } ud; ++ struct { ++ __u64 reserved[3]; ++ __u32 reserved2; ++ __u32 remote_srqn; ++ } xrc; + } wr; + }; + +diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h +index 6465aae..1356757 100644 +--- a/include/infiniband/verbs.h ++++ b/include/infiniband/verbs.h +@@ -91,21 +91,22 @@ enum ibv_transport_type { + }; + + enum ibv_device_cap_flags { +- IBV_DEVICE_RESIZE_MAX_WR = 1, +- IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1, +- IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2, +- IBV_DEVICE_RAW_MULTI = 1 << 3, +- IBV_DEVICE_AUTO_PATH_MIG = 1 << 4, +- IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5, +- IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6, +- IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7, +- IBV_DEVICE_SHUTDOWN_PORT = 1 << 8, +- IBV_DEVICE_INIT_TYPE = 1 << 9, +- IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10, +- IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11, +- IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, +- IBV_DEVICE_SRQ_RESIZE = 1 << 13, +- IBV_DEVICE_N_NOTIFY_CQ = 1 << 14 ++ IBV_DEVICE_RESIZE_MAX_WR = 1, ++ IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1, ++ IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2, ++ IBV_DEVICE_RAW_MULTI = 1 << 3, ++ IBV_DEVICE_AUTO_PATH_MIG = 1 << 4, ++ IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5, ++ IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6, ++ IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7, ++ IBV_DEVICE_SHUTDOWN_PORT = 1 << 8, ++ IBV_DEVICE_INIT_TYPE = 1 << 9, ++ IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10, ++ IBV_DEVICE_SYS_IMAGE_GUID = 1 << 11, ++ IBV_DEVICE_RC_RNR_NAK_GEN = 1 << 12, ++ IBV_DEVICE_SRQ_RESIZE = 1 << 13, ++ IBV_DEVICE_N_NOTIFY_CQ = 1 << 14, ++ IBV_DEVICE_XRC = 1 << 20 + }; + + enum ibv_atomic_cap { +@@ -445,7 +446,11 @@ struct ibv_srq_init_attr_ex { + }; + + enum ibv_qp_type { +- IBV_QPT_RC = 2, IBV_QPT_UC, IBV_QPT_UD ++ IBV_QPT_RC = 2, ++ IBV_QPT_UC, ++ IBV_QPT_UD, ++ IBV_QPT_XRC_SEND = 9, ++ IBV_QPT_XRC_RECV + }; + + struct ibv_qp_cap { +@@ -466,6 +471,26 @@ struct ibv_qp_init_attr { + int sq_sig_all; + }; + ++enum ibv_qp_init_attr_mask { ++ IBV_QP_INIT_ATTR_PD = 1 << 0, ++ IBV_QP_INIT_ATTR_XRCD = 1 << 1, ++ IBV_QP_INIT_ATTR_RESERVED = 1 << 2 ++}; ++ ++struct ibv_qp_init_attr_ex { ++ void *qp_context; ++ struct ibv_cq *send_cq; ++ struct ibv_cq *recv_cq; ++ struct ibv_srq *srq; ++ struct ibv_qp_cap cap; ++ enum ibv_qp_type qp_type; ++ int sq_sig_all; ++ ++ uint32_t comp_mask; ++ struct ibv_pd *pd; ++ struct ibv_xrcd *xrcd; ++}; ++ + enum ibv_qp_attr_mask { + IBV_QP_STATE = 1 << 0, + IBV_QP_CUR_STATE = 1 << 1, +@@ -579,6 +604,11 @@ struct ibv_send_wr { + uint32_t remote_qpn; + uint32_t remote_qkey; + } ud; ++ struct { ++ uint64_t reserved[3]; ++ uint32_t reserved2; ++ uint32_t remote_srqn; ++ } xrc; + } wr; + }; + +@@ -755,7 +785,8 @@ struct ibv_context { + enum verbs_context_mask { + VERBS_CONTEXT_XRCD = 1 << 0, + VERBS_CONTEXT_SRQ = 1 << 1, +- VERBS_CONTEXT_RESERVED = 1 << 2 ++ VERBS_CONTEXT_QP = 1 << 2, ++ VERBS_CONTEXT_RESERVED = 1 << 3 + }; + + struct verbs_context { +@@ -763,6 +794,8 @@ struct verbs_context { + int (*drv_new_func1) (); new corresponding provider call of func1 + int (*lib_new_func1) (); New library call func1 + */ ++ struct ibv_qp * (*create_qp_ex)(struct ibv_context *context, ++ struct ibv_qp_init_attr_ex *qp_init_attr_ex); + uint32_t (*get_srq_num)(struct ibv_srq *srq); + struct ibv_srq * (*create_srq_ex)(struct ibv_context *context, + struct ibv_srq_init_attr_ex *srq_init_attr_ex); +@@ -1123,6 +1156,23 @@ static inline int ibv_post_srq_recv(struct ibv_srq *srq, + struct ibv_qp *ibv_create_qp(struct ibv_pd *pd, + struct ibv_qp_init_attr *qp_init_attr); + ++static inline struct ibv_qp * ++ibv_create_qp_ex(struct ibv_context *context, struct ibv_qp_init_attr_ex *qp_init_attr_ex) ++{ ++ struct verbs_context *vctx; ++ uint32_t mask = qp_init_attr_ex->comp_mask; ++ ++ if (!(mask & ~(IBV_QP_INIT_ATTR_PD)) && (mask & IBV_QP_INIT_ATTR_PD)) ++ return ibv_create_qp(qp_init_attr_ex->pd, ++ (struct ibv_qp_init_attr *) qp_init_attr_ex); ++ ++ if (!(vctx = verbs_get_ctx_op(context, create_qp_ex))) { ++ errno = ENOSYS; ++ return NULL; ++ } ++ return vctx->create_qp_ex(context, qp_init_attr_ex); ++} ++ + /** + * ibv_modify_qp - Modify a queue pair. + */ +diff --git a/src/cmd.c b/src/cmd.c +index 641ab28..87ac062 100644 +--- a/src/cmd.c ++++ b/src/cmd.c +@@ -666,6 +666,98 @@ int ibv_cmd_destroy_srq(struct ibv_srq *srq) + return 0; + } + ++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 ibv_create_qp_resp *resp, size_t resp_size) ++{ ++ struct verbs_xrcd *vxrcd = NULL; ++ ++ IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size); ++ ++ if (attr_ex->comp_mask >= IBV_QP_INIT_ATTR_RESERVED) ++ return ENOSYS; ++ ++ cmd->user_handle = (uintptr_t) qp; ++ ++ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) { ++ vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd); ++ cmd->pd_handle = vxrcd->handle; ++ } else { ++ if (!(attr_ex->comp_mask & IBV_QP_INIT_ATTR_PD)) ++ return EINVAL; ++ ++ cmd->pd_handle = attr_ex->pd->handle; ++ cmd->send_cq_handle = attr_ex->send_cq->handle; ++ ++ if (attr_ex->qp_type != IBV_QPT_XRC_SEND) { ++ cmd->recv_cq_handle = attr_ex->recv_cq->handle; ++ cmd->srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0; ++ } ++ } ++ ++ cmd->max_send_wr = attr_ex->cap.max_send_wr; ++ cmd->max_recv_wr = attr_ex->cap.max_recv_wr; ++ cmd->max_send_sge = attr_ex->cap.max_send_sge; ++ cmd->max_recv_sge = attr_ex->cap.max_recv_sge; ++ cmd->max_inline_data = attr_ex->cap.max_inline_data; ++ cmd->sq_sig_all = attr_ex->sq_sig_all; ++ cmd->qp_type = attr_ex->qp_type; ++ cmd->is_srq = !!attr_ex->srq; ++ cmd->reserved = 0; ++ ++ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) ++ return errno; ++ ++ (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size); ++ ++ if (abi_ver > 3) { ++ 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; ++ } ++ ++ 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); ++ } ++ ++ qp->qp.handle = resp->qp_handle; ++ qp->qp.qp_num = resp->qpn; ++ qp->qp.context = context; ++ qp->qp.qp_context = attr_ex->qp_context; ++ qp->qp.pd = attr_ex->pd; ++ qp->qp.send_cq = attr_ex->send_cq; ++ qp->qp.recv_cq = attr_ex->recv_cq; ++ qp->qp.srq = attr_ex->srq; ++ qp->qp.qp_type = attr_ex->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 (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) { ++ qp->comp_mask |= VERBS_QP_XRCD; ++ qp->xrcd = 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, +@@ -674,7 +766,7 @@ int ibv_cmd_create_qp(struct ibv_pd *pd, + IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size); + + cmd->user_handle = (uintptr_t) qp; +- cmd->pd_handle = pd->handle; ++ 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; +diff --git a/src/libibverbs.map b/src/libibverbs.map +index c8ec645..4249793 100644 +--- a/src/libibverbs.map ++++ b/src/libibverbs.map +@@ -101,5 +101,6 @@ IBVERBS_1.1 { + ibv_cmd_open_xrcd; + ibv_cmd_close_xrcd; + ibv_cmd_create_srq_ex; ++ ibv_cmd_create_qp_ex; + + } IBVERBS_1.0;