]> git.openfabrics.org - ~shefty/libibverbs.git/commitdiff
libibverbs: Add support for XRC QPs
authorSean Hefty <sean.hefty@intel.com>
Mon, 17 Sep 2012 23:00:12 +0000 (16:00 -0700)
committerSean Hefty <sean.hefty@intel.com>
Wed, 26 Sep 2012 19:05:47 +0000 (12:05 -0700)
XRC queue pairs: xrc defines two new types of QPs.  The
initiator, or send-side, xrc qp behaves similar to a send-
only RC qp.  xrc send qp's are managed through the existing
QP functions.  The send_wr structure is extended in a back-
wards compatible way to support posting sends on a send xrc
qp, which require specifying the remote xrc srq.

The target, or receive-side, xrc qp behaves differently
than other implemented qp's.  A recv xrc qp can be created,
modified, and destroyed like other qp's through the existing
calls.  The qp_init_attr structure is extended for xrc qp's.

Because xrc recv qp's are bound to an xrcd, rather than a pd,
it is intended to be used among multiple processes.  Any process
with access to an xrcd may allocate and connect an xrc recv qp.
The actual xrc recv qp is allocated and managed by the kernel.
If the owning process explicit destroys the xrc recv qp, it is
destroyed.  However, if the xrc recv qp is left open when the
user process exits or closes its device, then the lifetime of
the xrc recv qp is bound with the lifetime of the xrcd.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
include/infiniband/driver.h
include/infiniband/kern-abi.h
include/infiniband/verbs.h
src/cmd.c
src/libibverbs.map
src/verbs.c

index dccfd1fa376d64d9bd9deddd6b1296828d61d7ad..f15457c5b293c643f9b3eae93fb98b0e09baa488 100644 (file)
@@ -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);
 
@@ -150,6 +160,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,
index 3d72fa738c964c1cedee6a3f26cfb921b9c03031..b6d5ce9f776f3830c17a17c4bb05ef46636ca31d 100644 (file)
@@ -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;
 };
 
index e67bf21ed00016b4d86907302363be2936889f3a..799822d02c027ba0b489cf6983c3f6fcd1b2ca0c 100644 (file)
@@ -107,7 +107,8 @@ enum ibv_device_cap_flags {
        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_N_NOTIFY_CQ          = 1 << 14,
+       IBV_DEVICE_XRC                  = 1 << 20
 };
 
 enum ibv_atomic_cap {
@@ -440,7 +441,9 @@ struct ibv_srq_init_attr_ex {
 enum ibv_qp_type {
        IBV_QPT_RC = 2,
        IBV_QPT_UC,
-       IBV_QPT_UD
+       IBV_QPT_UD,
+       IBV_QPT_XRC_SEND = 9,
+       IBV_QPT_XRC_RECV
 };
 
 struct ibv_qp_cap {
@@ -461,6 +464,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;
+
+       uint64_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,
@@ -576,6 +599,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;
 };
 
@@ -759,6 +787,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_pd *pd,
                                                 struct ibv_srq_init_attr_ex *srq_init_attr_ex);
@@ -1118,6 +1148,17 @@ 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 = verbs_get_ctx_op(context, create_qp_ex);
+       if (!vctx) {
+               errno = ENOSYS;
+               return NULL;
+       }
+       return vctx->create_qp_ex(context, qp_init_attr_ex);
+}
+
 /**
  * ibv_modify_qp - Modify a queue pair.
  */
index c3c6f537f4c140b336544c098e9fee40ef8bf482..47426abc1f6ea0fc729f0a3449146b74fd0cb52a 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -653,18 +653,109 @@ 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 ibv_context *context;
+       struct verbs_xrcd *vxrcd = NULL;
+
+       IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
+
+       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);
+               context         = vxrcd->xrcd.context;
+               cmd->pd_handle  = vxrcd->handle;
+       } else {
+               context         = pd->context;
+               cmd->pd_handle  = 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       = qp_init_attr_ex->qp_context;
+       qp->qp.pd               = pd;
+       qp->qp.send_cq          = qp_init_attr_ex->send_cq;
+       qp->qp.recv_cq          = qp_init_attr_ex->recv_cq;
+       qp->qp.srq              = qp_init_attr_ex->srq;
+       qp->qp.qp_type          = qp_init_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,
                      struct ibv_create_qp_resp *resp, size_t resp_size)
 {
+       int ret;
+
        IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
 
        cmd->user_handle     = (uintptr_t) qp;
-       cmd->pd_handle       = pd->handle;
+
+       context              = pd->context;
+       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;
@@ -675,21 +766,21 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
        cmd->is_srq          = !!attr->srq;
        cmd->reserved        = 0;
 
-       if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
+       if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
                return errno;
 
        (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
 
        qp->handle                = resp->qp_handle;
        qp->qp_num                = resp->qpn;
-       qp->context               = pd->context;
+       qp->context               = 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;
+               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) {
@@ -708,7 +799,7 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
                        resp_size - sizeof *resp);
        }
 
-       return 0;
+       return ret;
 }
 
 int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
index c8ec645964eccc50e6fb298d6df944d914d9f875..4249793a171798033b86b04bbe557acca04c5194 100644 (file)
@@ -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;
index b5938f2b6a5dc06cc9236bc19dc554fe762d5b63..c11bb0f86ec5f7cdcd2c76786459c5fce3bcab6e 100644 (file)
@@ -398,7 +398,9 @@ default_symver(__ibv_destroy_srq, ibv_destroy_srq);
 struct ibv_qp *__ibv_create_qp(struct ibv_pd *pd,
                               struct ibv_qp_init_attr *qp_init_attr)
 {
-       struct ibv_qp *qp = pd->context->ops.create_qp(pd, qp_init_attr);
+       struct ibv_qp *qp;
+
+       qp = pd->context->ops.create_qp(pd, qp_init_attr);
 
        if (qp) {
                qp->context          = pd->context;