diff options
author | Roland Dreier <rolandd@cisco.com> | 2005-09-26 21:07:33 +0000 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-11-09 11:35:57 -0800 |
commit | 773fdb91eb7b02f41d6b6d860d8464bc00d44e8a (patch) | |
tree | a02cd79dedd4dc13efee6affece1e741f27f3825 | |
parent | b5f6de0c3c313311bd5d095faba3117641533ca4 (diff) | |
download | libibverbs-773fdb91eb7b02f41d6b6d860d8464bc00d44e8a.tar.gz |
Update libibverbs and libmthca to handle uverbs ABI version 3
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | debian/changelog | 2 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | debian/copyright | 2 | ||||
-rw-r--r-- | debian/ibverbs-utils.install (renamed from debian/ibverbs-examples.install) | 0 | ||||
-rw-r--r-- | examples/rc_pingpong.c | 36 | ||||
-rw-r--r-- | examples/srq_pingpong.c | 40 | ||||
-rw-r--r-- | examples/uc_pingpong.c | 36 | ||||
-rw-r--r-- | examples/ud_pingpong.c | 38 | ||||
-rw-r--r-- | include/infiniband/driver.h | 9 | ||||
-rw-r--r-- | include/infiniband/kern-abi.h | 164 | ||||
-rw-r--r-- | include/infiniband/verbs.h | 52 | ||||
-rw-r--r-- | src/cmd.c | 123 | ||||
-rw-r--r-- | src/device.c | 31 | ||||
-rw-r--r-- | src/ibverbs.h | 33 | ||||
-rw-r--r-- | src/libibverbs.map | 2 | ||||
-rw-r--r-- | src/verbs.c | 111 |
19 files changed, 485 insertions, 219 deletions
@@ -1,3 +1,20 @@ +2005-09-25 Roland Dreier <roland@cisco.com> + + * examples/rc_pingpong.c, examples/srq_pingpong.c, + examples/uc_pingpong.c, examples/ud_pingpong.c: Update to match + new completion channel and CQ creation API. + + * include/infiniband/driver.h, include/infiniband/verbs.h, + src/device.c, src/ibverbs.h, src/verbs.c, src/cmd.c: Add notion of + "completion channel" that allows consumers to dynamically create + and destroy file descriptors for retrieving completion events. + Completion channels are handled natively with kernel ABI version 3 + and simulated with backwards compatibility implementations for ABI + versions 1 and 2. + + * include/infiniband/kern-abi.h: Update to match kernel ABI + version 3. + 2005-09-07 Roland Dreier <roland@cisco.com> * src/device.c (ibv_get_device_guid): Use htonll() instead of diff --git a/Makefile.am b/Makefile.am index c93dc33..c9b21ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,7 +47,7 @@ man_MANS = man/ibv_asyncwatch.1 man/ibv_devices.1 man/ibv_devinfo.1 \ man/ibv_srq_pingpong.1 DEBIAN = debian/changelog debian/compat debian/control debian/copyright \ - debian/ibverbs-examples.install debian/libibverbs1.install \ + debian/ibverbs-utils.install debian/libibverbs1.install \ debian/libibverbs-dev.install debian/rules EXTRA_DIST = include/infiniband/driver.h include/infiniband/kern-abi.h \ diff --git a/configure.in b/configure.in index 8cdf99c..920b640 100644 --- a/configure.in +++ b/configure.in @@ -1,11 +1,11 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) -AC_INIT(libibverbs, 1.0-rc2, openib-general@openib.org) +AC_INIT(libibverbs, 1.0-rc3, openib-general@openib.org) AC_CONFIG_SRCDIR([src/ibverbs.h]) AC_CONFIG_AUX_DIR(config) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libibverbs, 1.0-rc2) +AM_INIT_AUTOMAKE(libibverbs, 1.0-rc3) AM_PROG_LIBTOOL diff --git a/debian/changelog b/debian/changelog index 9bd0c15..fd4b352 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -libibverbs (1.0-rc2-1) unstable; urgency=low +libibverbs (1.0-rc3) unstable; urgency=low * Initial Release. (Closes: #325752) diff --git a/debian/control b/debian/control index 09e73b7..f0a9c2f 100644 --- a/debian/control +++ b/debian/control @@ -34,7 +34,7 @@ Description: Development files for the libibverbs library It contains the header files and static libraries (optionally) needed for compiling. -Package: libibverbs-dbg +Package: libibverbs1-dbg Section: libdevel Priority: extra Architecture: any diff --git a/debian/copyright b/debian/copyright index 016b027..357cd87 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,7 +4,7 @@ Mon, 25 Apr 2005 10:21:08 -0700. Source: It was downloaded from the OpenIB subversion repository at -<https://openib.org/svn/gen2/trunk/src/userspace/libibverbs> +<https://openib.org/downloads.html> Authors: The complete list of upstream authors is in the file diff --git a/debian/ibverbs-examples.install b/debian/ibverbs-utils.install index 98d1583..98d1583 100644 --- a/debian/ibverbs-examples.install +++ b/debian/ibverbs-utils.install diff --git a/examples/rc_pingpong.c b/examples/rc_pingpong.c index 65ab080..8767514 100644 --- a/examples/rc_pingpong.c +++ b/examples/rc_pingpong.c @@ -61,14 +61,15 @@ enum { static int page_size; struct pingpong_context { - struct ibv_context *context; - struct ibv_pd *pd; - struct ibv_mr *mr; - struct ibv_cq *cq; - struct ibv_qp *qp; - void *buf; - int size; - int rx_depth; + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + struct ibv_cq *cq; + struct ibv_qp *qp; + void *buf; + int size; + int rx_depth; }; struct pingpong_dest { @@ -290,7 +291,8 @@ out: } static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, - int rx_depth, int port) + int rx_depth, int port, + int use_event) { struct pingpong_context *ctx; @@ -316,6 +318,15 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + return NULL; + } + } else + ctx->channel = NULL; + ctx->pd = ibv_alloc_pd(ctx->context); if (!ctx->pd) { fprintf(stderr, "Couldn't allocate PD\n"); @@ -328,7 +339,8 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } - ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL); + ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, + ctx->channel, 0); if (!ctx->cq) { fprintf(stderr, "Couldn't create CQ\n"); return NULL; @@ -546,7 +558,7 @@ int main(int argc, char *argv[]) } } - ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port); + ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); if (!ctx) return 1; @@ -605,7 +617,7 @@ int main(int argc, char *argv[]) struct ibv_cq *ev_cq; void *ev_ctx; - if (ibv_get_cq_event(ctx->context, 0, &ev_cq, &ev_ctx)) { + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } diff --git a/examples/srq_pingpong.c b/examples/srq_pingpong.c index deb1699..aa4ef1f 100644 --- a/examples/srq_pingpong.c +++ b/examples/srq_pingpong.c @@ -63,16 +63,17 @@ enum { static int page_size; struct pingpong_context { - struct ibv_context *context; - struct ibv_pd *pd; - struct ibv_mr *mr; - struct ibv_cq *cq; - struct ibv_srq *srq; - struct ibv_qp *qp[MAX_QP]; - void *buf; - int size; - int num_qp; - int rx_depth; + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + struct ibv_cq *cq; + struct ibv_srq *srq; + struct ibv_qp *qp[MAX_QP]; + void *buf; + int size; + int num_qp; + int rx_depth; }; struct pingpong_dest { @@ -324,7 +325,8 @@ out: } static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, - int num_qp, int rx_depth, int port) + int num_qp, int rx_depth, int port, + int use_event) { struct pingpong_context *ctx; int i; @@ -352,6 +354,15 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + return NULL; + } + } else + ctx->channel = NULL; + ctx->pd = ibv_alloc_pd(ctx->context); if (!ctx->pd) { fprintf(stderr, "Couldn't allocate PD\n"); @@ -364,7 +375,8 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } - ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL); + ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, + ctx->channel, 0); if (!ctx->cq) { fprintf(stderr, "Couldn't create CQ\n"); return NULL; @@ -615,7 +627,7 @@ int main(int argc, char *argv[]) } } - ctx = pp_init_ctx(ib_dev, size, num_qp, rx_depth, ib_port); + ctx = pp_init_ctx(ib_dev, size, num_qp, rx_depth, ib_port, use_event); if (!ctx) return 1; @@ -678,7 +690,7 @@ int main(int argc, char *argv[]) struct ibv_cq *ev_cq; void *ev_ctx; - if (ibv_get_cq_event(ctx->context, 0, &ev_cq, &ev_ctx)) { + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } diff --git a/examples/uc_pingpong.c b/examples/uc_pingpong.c index 6d3e80a..aa68579 100644 --- a/examples/uc_pingpong.c +++ b/examples/uc_pingpong.c @@ -61,14 +61,15 @@ enum { static int page_size; struct pingpong_context { - struct ibv_context *context; - struct ibv_pd *pd; - struct ibv_mr *mr; - struct ibv_cq *cq; - struct ibv_qp *qp; - void *buf; - int size; - int rx_depth; + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + struct ibv_cq *cq; + struct ibv_qp *qp; + void *buf; + int size; + int rx_depth; }; struct pingpong_dest { @@ -282,7 +283,8 @@ out: } static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, - int rx_depth, int port) + int rx_depth, int port, + int use_event) { struct pingpong_context *ctx; @@ -308,6 +310,15 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + return NULL; + } + } else + ctx->channel = NULL; + ctx->pd = ibv_alloc_pd(ctx->context); if (!ctx->pd) { fprintf(stderr, "Couldn't allocate PD\n"); @@ -320,7 +331,8 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } - ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL); + ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, + ctx->channel, 0); if (!ctx->cq) { fprintf(stderr, "Couldn't create CQ\n"); return NULL; @@ -538,7 +550,7 @@ int main(int argc, char *argv[]) } } - ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port); + ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); if (!ctx) return 1; @@ -597,7 +609,7 @@ int main(int argc, char *argv[]) struct ibv_cq *ev_cq; void *ev_ctx; - if (ibv_get_cq_event(ctx->context, 0, &ev_cq, &ev_ctx)) { + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } diff --git a/examples/ud_pingpong.c b/examples/ud_pingpong.c index 23fe25d..c2d0c4c 100644 --- a/examples/ud_pingpong.c +++ b/examples/ud_pingpong.c @@ -61,15 +61,16 @@ enum { static int page_size; struct pingpong_context { - struct ibv_context *context; - struct ibv_pd *pd; - struct ibv_mr *mr; - struct ibv_cq *cq; - struct ibv_qp *qp; - struct ibv_ah *ah; - void *buf; - int size; - int rx_depth; + struct ibv_context *context; + struct ibv_comp_channel *channel; + struct ibv_pd *pd; + struct ibv_mr *mr; + struct ibv_cq *cq; + struct ibv_qp *qp; + struct ibv_ah *ah; + void *buf; + int size; + int rx_depth; }; struct pingpong_dest { @@ -279,7 +280,8 @@ out: } static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, - int rx_depth, int port) + int rx_depth, int port, + int use_event) { struct pingpong_context *ctx; @@ -305,6 +307,15 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } + if (use_event) { + ctx->channel = ibv_create_comp_channel(ctx->context); + if (!ctx->channel) { + fprintf(stderr, "Couldn't create completion channel\n"); + return NULL; + } + } else + ctx->channel = NULL; + ctx->pd = ibv_alloc_pd(ctx->context); if (!ctx->pd) { fprintf(stderr, "Couldn't allocate PD\n"); @@ -317,7 +328,8 @@ static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size, return NULL; } - ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL); + ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL, + ctx->channel, 0); if (!ctx->cq) { fprintf(stderr, "Couldn't create CQ\n"); return NULL; @@ -542,7 +554,7 @@ int main(int argc, char *argv[]) } } - ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port); + ctx = pp_init_ctx(ib_dev, size, rx_depth, ib_port, use_event); if (!ctx) return 1; @@ -601,7 +613,7 @@ int main(int argc, char *argv[]) struct ibv_cq *ev_cq; void *ev_ctx; - if (ibv_get_cq_event(ctx->context, 0, &ev_cq, &ev_ctx)) { + if (ibv_get_cq_event(ctx->channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h index b5d41bb..3fe6d09 100644 --- a/include/infiniband/driver.h +++ b/include/infiniband/driver.h @@ -64,9 +64,9 @@ typedef struct ibv_device *(*ibv_driver_init_func)(struct sysfs_class_device *); -extern int ibv_cmd_get_context(int num_comp, struct ibv_context *context, - struct ibv_get_context *cmd, size_t cmd_size, - struct ibv_get_context_resp *resp, size_t resp_size); +extern int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd, + size_t cmd_size, struct ibv_get_context_resp *resp, + size_t resp_size); extern int ibv_cmd_query_device(struct ibv_context *context, struct ibv_device_attr *device_attr, struct ibv_query_device *cmd, size_t cmd_size); @@ -87,7 +87,8 @@ extern int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length, size_t cmd_size); extern int ibv_cmd_dereg_mr(struct ibv_mr *mr); extern int ibv_cmd_create_cq(struct ibv_context *context, int cqe, - struct ibv_cq *cq, + struct ibv_comp_channel *channel, + int comp_vector, struct ibv_cq *cq, struct ibv_create_cq *cmd, size_t cmd_size, struct ibv_create_cq_resp *resp, size_t resp_size); extern int ibv_cmd_destroy_cq(struct ibv_cq *cq); diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h index 59a153d..e02f94f 100644 --- a/include/infiniband/kern-abi.h +++ b/include/infiniband/kern-abi.h @@ -47,15 +47,12 @@ * The minimum and maximum kernel ABI that we can handle. */ #define IB_USER_VERBS_MIN_ABI_VERSION 1 -#define IB_USER_VERBS_MAX_ABI_VERSION 2 +#define IB_USER_VERBS_MAX_ABI_VERSION 3 enum { - IB_USER_VERBS_CMD_QUERY_PARAMS, IB_USER_VERBS_CMD_GET_CONTEXT, IB_USER_VERBS_CMD_QUERY_DEVICE, IB_USER_VERBS_CMD_QUERY_PORT, - IB_USER_VERBS_CMD_QUERY_GID, - IB_USER_VERBS_CMD_QUERY_PKEY, IB_USER_VERBS_CMD_ALLOC_PD, IB_USER_VERBS_CMD_DEALLOC_PD, IB_USER_VERBS_CMD_CREATE_AH, @@ -70,6 +67,7 @@ enum { IB_USER_VERBS_CMD_ALLOC_MW, IB_USER_VERBS_CMD_BIND_MW, IB_USER_VERBS_CMD_DEALLOC_MW, + IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL, IB_USER_VERBS_CMD_CREATE_CQ, IB_USER_VERBS_CMD_RESIZE_CQ, IB_USER_VERBS_CMD_DESTROY_CQ, @@ -133,13 +131,12 @@ struct ibv_get_context { __u16 in_words; __u16 out_words; __u64 response; - __u64 cq_fd_tab; __u64 driver_data[0]; }; struct ibv_get_context_resp { __u32 async_fd; - __u32 reserved; + __u32 num_comp_vectors; }; struct ibv_query_device { @@ -227,37 +224,6 @@ struct ibv_query_port_resp { __u8 reserved[3]; }; -struct ibv_query_gid { - __u32 command; - __u16 in_words; - __u16 out_words; - __u64 response; - __u8 port_num; - __u8 index; - __u8 reserved[6]; - __u64 driver_data[0]; -}; - -struct ibv_query_gid_resp { - __u8 gid[16]; -}; - -struct ibv_query_pkey { - __u32 command; - __u16 in_words; - __u16 out_words; - __u64 response; - __u8 port_num; - __u8 index; - __u8 reserved[6]; - __u64 driver_data[0]; -}; - -struct ibv_query_pkey_resp { - __u16 pkey; - __u16 reserved; -}; - struct ibv_alloc_pd { __u32 command; __u16 in_words; @@ -303,6 +269,17 @@ struct ibv_dereg_mr { __u32 mr_handle; }; +struct ibv_create_comp_channel { + __u32 command; + __u16 in_words; + __u16 out_words; + __u64 response; +}; + +struct ibv_create_comp_channel_resp { + __u32 fd; +}; + struct ibv_create_cq { __u32 command; __u16 in_words; @@ -310,7 +287,9 @@ struct ibv_create_cq { __u64 response; __u64 user_handle; __u32 cqe; - __u32 event_handler; + __u32 comp_vector; + __s32 comp_channel; + __u32 reserved; __u64 driver_data[0]; }; @@ -319,13 +298,6 @@ struct ibv_create_cq_resp { __u32 cqe; }; -struct ibv_destroy_cq_v1 { - __u32 command; - __u16 in_words; - __u16 out_words; - __u32 cq_handle; -}; - struct ibv_destroy_cq { __u32 command; __u16 in_words; @@ -415,13 +387,6 @@ struct ibv_modify_qp { __u64 driver_data[0]; }; -struct ibv_destroy_qp_v1 { - __u32 command; - __u16 in_words; - __u16 out_words; - __u32 qp_handle; -}; - struct ibv_destroy_qp { __u32 command; __u16 in_words; @@ -487,6 +452,84 @@ struct ibv_modify_srq { __u64 driver_data[0]; }; +struct ibv_destroy_srq { + __u32 command; + __u16 in_words; + __u16 out_words; + __u64 response; + __u32 srq_handle; + __u32 reserved; +}; + +struct ibv_destroy_srq_resp { + __u32 events_reported; +}; + +/* + * Compatibility with older ABI versions + */ + +enum { + IB_USER_VERBS_CMD_QUERY_PARAMS_V2, + IB_USER_VERBS_CMD_GET_CONTEXT_V2, + IB_USER_VERBS_CMD_QUERY_DEVICE_V2, + IB_USER_VERBS_CMD_QUERY_PORT_V2, + IB_USER_VERBS_CMD_QUERY_GID_V2, + IB_USER_VERBS_CMD_QUERY_PKEY_V2, + IB_USER_VERBS_CMD_ALLOC_PD_V2, + IB_USER_VERBS_CMD_DEALLOC_PD_V2, + IB_USER_VERBS_CMD_CREATE_AH_V2, + IB_USER_VERBS_CMD_MODIFY_AH_V2, + IB_USER_VERBS_CMD_QUERY_AH_V2, + IB_USER_VERBS_CMD_DESTROY_AH_V2, + IB_USER_VERBS_CMD_REG_MR_V2, + IB_USER_VERBS_CMD_REG_SMR_V2, + IB_USER_VERBS_CMD_REREG_MR_V2, + IB_USER_VERBS_CMD_QUERY_MR_V2, + IB_USER_VERBS_CMD_DEREG_MR_V2, + IB_USER_VERBS_CMD_ALLOC_MW_V2, + IB_USER_VERBS_CMD_BIND_MW_V2, + IB_USER_VERBS_CMD_DEALLOC_MW_V2, + IB_USER_VERBS_CMD_CREATE_CQ_V2, + IB_USER_VERBS_CMD_RESIZE_CQ_V2, + IB_USER_VERBS_CMD_DESTROY_CQ_V2, + IB_USER_VERBS_CMD_POLL_CQ_V2, + IB_USER_VERBS_CMD_PEEK_CQ_V2, + IB_USER_VERBS_CMD_REQ_NOTIFY_CQ_V2, + IB_USER_VERBS_CMD_CREATE_QP_V2, + IB_USER_VERBS_CMD_QUERY_QP_V2, + IB_USER_VERBS_CMD_MODIFY_QP_V2, + IB_USER_VERBS_CMD_DESTROY_QP_V2, + IB_USER_VERBS_CMD_POST_SEND_V2, + IB_USER_VERBS_CMD_POST_RECV_V2, + IB_USER_VERBS_CMD_ATTACH_MCAST_V2, + IB_USER_VERBS_CMD_DETACH_MCAST_V2, + IB_USER_VERBS_CMD_CREATE_SRQ_V2, + IB_USER_VERBS_CMD_MODIFY_SRQ_V2, + IB_USER_VERBS_CMD_QUERY_SRQ_V2, + IB_USER_VERBS_CMD_DESTROY_SRQ_V2, + IB_USER_VERBS_CMD_POST_SRQ_RECV_V2, + /* + * Set commands that didn't exist to -1 so our compile-time + * trick opcodes in IBV_INIT_CMD() doesn't break. + */ + IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1, +}; + +struct ibv_destroy_cq_v1 { + __u32 command; + __u16 in_words; + __u16 out_words; + __u32 cq_handle; +}; + +struct ibv_destroy_qp_v1 { + __u32 command; + __u16 in_words; + __u16 out_words; + __u32 qp_handle; +}; + struct ibv_destroy_srq_v1 { __u32 command; __u16 in_words; @@ -494,17 +537,24 @@ struct ibv_destroy_srq_v1 { __u32 srq_handle; }; -struct ibv_destroy_srq { +struct ibv_get_context_v2 { __u32 command; __u16 in_words; __u16 out_words; __u64 response; - __u32 srq_handle; - __u32 reserved; + __u64 cq_fd_tab; + __u64 driver_data[0]; }; -struct ibv_destroy_srq_resp { - __u32 events_reported; +struct ibv_create_cq_v2 { + __u32 command; + __u16 in_words; + __u16 out_words; + __u64 response; + __u64 user_handle; + __u32 cqe; + __u32 event_handler; + __u64 driver_data[0]; }; #endif /* KERN_ABI_H */ diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h index 07f0054..d58e586 100644 --- a/include/infiniband/verbs.h +++ b/include/infiniband/verbs.h @@ -494,6 +494,10 @@ struct ibv_qp { uint32_t events_completed; }; +struct ibv_comp_channel { + int fd; +}; + struct ibv_cq { struct ibv_context *context; void *cq_context; @@ -515,8 +519,7 @@ struct ibv_device; struct ibv_context; struct ibv_device_ops { - struct ibv_context * (*alloc_context)(struct ibv_device *device, - int num_comp, int cmd_fd); + struct ibv_context * (*alloc_context)(struct ibv_device *device, int cmd_fd); void (*free_context)(struct ibv_context *context); }; @@ -532,18 +535,16 @@ struct ibv_context_ops { struct ibv_device_attr *device_attr); int (*query_port)(struct ibv_context *context, uint8_t port_num, struct ibv_port_attr *port_attr); - int (*query_gid)(struct ibv_context *context, uint8_t port_num, - int index, union ibv_gid *gid); - int (*query_pkey)(struct ibv_context *context, uint8_t port_num, - int index, uint16_t *pkey); struct ibv_pd * (*alloc_pd)(struct ibv_context *context); int (*dealloc_pd)(struct ibv_pd *pd); struct ibv_mr * (*reg_mr)(struct ibv_pd *pd, void *addr, size_t length, enum ibv_access_flags access); int (*dereg_mr)(struct ibv_mr *mr); - struct ibv_cq * (*create_cq)(struct ibv_context *context, int cqe); + struct ibv_cq * (*create_cq)(struct ibv_context *context, int cqe, + struct ibv_comp_channel *channel, + int comp_vector); int (*poll_cq)(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc); - int (*req_notify_cq)(struct ibv_cq *cq, int solicited); + int (*req_notify_cq)(struct ibv_cq *cq, int solicited_only); void (*cq_event)(struct ibv_cq *cq); int (*destroy_cq)(struct ibv_cq *cq); struct ibv_srq * (*create_srq)(struct ibv_pd *pd, @@ -576,8 +577,8 @@ struct ibv_context { struct ibv_context_ops ops; int cmd_fd; int async_fd; - int num_comp; - int cq_fd[1]; + int num_comp_vectors; + void *abi_compat; }; /** @@ -672,10 +673,29 @@ extern struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr, extern int ibv_dereg_mr(struct ibv_mr *mr); /** + * ibv_create_comp_channel - Create a completion event channel + */ +extern struct ibv_comp_channel *ibv_create_comp_channel(struct ibv_context *context); + +/** + * ibv_destroy_comp_channel - Destroy a completion event channel + */ +extern int ibv_destroy_comp_channel(struct ibv_comp_channel *channel); + +/** * ibv_create_cq - Create a completion queue + * @context - Context CQ will be attached to + * @cqe - Minimum number of entries required for CQ + * @cq_context - Consumer-supplied context returned for completion events + * @channel - Completion channel where completion events will be queued. + * May be NULL if completion events will not be used. + * @comp_vector - Completion vector used to signal completion events. + * Must be >= 0 and < context->num_comp_vectors. */ extern struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, - void *cq_context); + void *cq_context, + struct ibv_comp_channel *channel, + int comp_vector); /** * ibv_destroy_cq - Destroy a completion queue @@ -684,16 +704,14 @@ extern int ibv_destroy_cq(struct ibv_cq *cq); /** * ibv_get_cq_event - Read next CQ event - * @context: Context to get CQ event for - * @comp_num: Index of completion event to check. Must be >= 0 and - * <= context->num_comp. + * @channel: Channel to get next event from. * @cq: Used to return pointer to CQ. * @cq_context: Used to return consumer-supplied CQ context. * * All completion events returned by ibv_get_cq_event() must * eventually be acknowledged with ibv_ack_cq_events(). */ -extern int ibv_get_cq_event(struct ibv_context *context, int comp_num, +extern int ibv_get_cq_event(struct ibv_comp_channel *channel, struct ibv_cq **cq, void **cq_context); /** @@ -731,9 +749,9 @@ static inline int ibv_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc /** * ibv_req_notify_cq - Request completion notification on a CQ. */ -static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited) +static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only) { - return cq->context->ops.req_notify_cq(cq, solicited); + return cq->context->ops.req_notify_cq(cq, solicited_only); } /** @@ -43,24 +43,54 @@ #include "ibverbs.h" -int ibv_cmd_get_context(int num_comp, struct ibv_context *context, - struct ibv_get_context *cmd, size_t cmd_size, - struct ibv_get_context_resp *resp, size_t resp_size) +static int ibv_cmd_get_context_v2(struct ibv_context *context, + struct ibv_get_context *new_cmd, + size_t new_cmd_size, + struct ibv_get_context_resp *resp, + size_t resp_size) { - uint32_t *cq_fd_tab; - int i; + struct ibv_abi_compat_v2 *t; + struct ibv_get_context_v2 *cmd; + size_t cmd_size; + uint32_t cq_fd; + + t = malloc(sizeof *t); + if (!t) + return ENOMEM; + pthread_mutex_init(&t->in_use, NULL); + + cmd_size = sizeof cmd + new_cmd_size - sizeof *new_cmd; + cmd = alloca(cmd_size); + memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd); - cq_fd_tab = alloca(num_comp * sizeof (uint32_t)); IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size); + cmd->cq_fd_tab = (uintptr_t) &cq_fd; - cmd->cq_fd_tab = (uintptr_t) cq_fd_tab; + if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) + return errno; + + context->async_fd = resp->async_fd; + context->num_comp_vectors = 1; + t->channel.fd = cq_fd; + context->abi_compat = t; + + return 0; +} + +int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd, + size_t cmd_size, struct ibv_get_context_resp *resp, + size_t resp_size) +{ + if (abi_ver <= 2) + return ibv_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size); + + IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size); if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) return errno; - context->async_fd = resp->async_fd; - for (i = 0; i < num_comp; ++i) - context->cq_fd[i] = cq_fd_tab[i]; + context->async_fd = resp->async_fd; + context->num_comp_vectors = resp->num_comp_vectors; return 0; } @@ -155,42 +185,6 @@ int ibv_cmd_query_port(struct ibv_context *context, uint8_t port_num, return 0; } -int ibv_cmd_query_gid(struct ibv_context *context, uint8_t port_num, - int index, union ibv_gid *gid) -{ - struct ibv_query_gid cmd; - struct ibv_query_gid_resp resp; - - IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_GID, &resp, sizeof resp); - cmd.port_num = port_num; - cmd.index = index; - - if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) - return errno; - - memcpy(gid->raw, resp.gid, 16); - - return 0; -} - -int ibv_cmd_query_pkey(struct ibv_context *context, uint8_t port_num, - int index, uint16_t *pkey) -{ - struct ibv_query_pkey cmd; - struct ibv_query_pkey_resp resp; - - IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_PKEY, &resp, sizeof resp); - cmd.port_num = port_num; - cmd.index = index; - - if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) - return errno; - - *pkey = resp.pkey; - - return 0; -} - int ibv_cmd_alloc_pd(struct ibv_context *context, struct ibv_pd *pd, struct ibv_alloc_pd *cmd, size_t cmd_size, struct ibv_alloc_pd_resp *resp, size_t resp_size) @@ -256,15 +250,48 @@ int ibv_cmd_dereg_mr(struct ibv_mr *mr) return 0; } +static int ibv_cmd_create_cq_v2(struct ibv_context *context, int cqe, + struct ibv_cq *cq, + struct ibv_create_cq *new_cmd, size_t new_cmd_size, + struct ibv_create_cq_resp *resp, size_t resp_size) +{ + struct ibv_create_cq_v2 *cmd; + size_t cmd_size; + + cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd; + cmd = alloca(cmd_size); + memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd); + + IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size); + cmd->user_handle = (uintptr_t) cq; + cmd->cqe = cqe; + cmd->event_handler = 0; + + if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) + return errno; + + cq->handle = resp->cq_handle; + cq->cqe = resp->cqe; + + return 0; +} + int ibv_cmd_create_cq(struct ibv_context *context, int cqe, - struct ibv_cq *cq, + struct ibv_comp_channel *channel, + int comp_vector, struct ibv_cq *cq, struct ibv_create_cq *cmd, size_t cmd_size, struct ibv_create_cq_resp *resp, size_t resp_size) { + if (abi_ver <= 2) + return ibv_cmd_create_cq_v2(context, cqe, cq, + cmd, cmd_size, resp, resp_size); + IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size); cmd->user_handle = (uintptr_t) cq; cmd->cqe = cqe; - cmd->event_handler = 0; + cmd->comp_vector = comp_vector; + cmd->comp_channel = channel ? channel->fd : -1; + cmd->reserved = 0; if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) return errno; diff --git a/src/device.c b/src/device.c index 82afcdd..47e771e 100644 --- a/src/device.c +++ b/src/device.c @@ -88,8 +88,6 @@ struct ibv_context *ibv_open_device(struct ibv_device *device) char *devpath; int cmd_fd; struct ibv_context *context; - struct ibv_query_params cmd; - struct ibv_query_params_resp resp; asprintf(&devpath, "/dev/infiniband/%s", device->dev->name); @@ -101,17 +99,12 @@ struct ibv_context *ibv_open_device(struct ibv_device *device) if (cmd_fd < 0) return NULL; - IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_PARAMS, &resp, sizeof resp); - if (write(cmd_fd, &cmd, sizeof cmd) != sizeof cmd) - goto err; - - context = device->ops.alloc_context(device, resp.num_cq_events, cmd_fd); + context = device->ops.alloc_context(device, cmd_fd); if (!context) goto err; - context->device = device; - context->cmd_fd = cmd_fd; - context->num_comp = resp.num_cq_events; + context->device = device; + context->cmd_fd = cmd_fd; return context; @@ -123,14 +116,22 @@ err: int ibv_close_device(struct ibv_context *context) { - int i; + int async_fd = context->async_fd; + int cmd_fd = context->cmd_fd; + int cq_fd = -1; + + if (abi_ver <= 2) { + struct ibv_abi_compat_v2 *t = context->abi_compat; + cq_fd = t->channel.fd; + free(context->abi_compat); + } context->device->ops.free_context(context); - close(context->async_fd); - for (i = 0; i < context->num_comp; ++i) - close(context->cq_fd[i]); - close(context->cmd_fd); + close(async_fd); + close(cmd_fd); + if (abi_ver <= 2) + close(cq_fd); return 0; } diff --git a/src/ibverbs.h b/src/ibverbs.h index 0953686..96a88b3 100644 --- a/src/ibverbs.h +++ b/src/ibverbs.h @@ -50,6 +50,11 @@ struct ibv_driver { ibv_driver_init_func init_func; }; +struct ibv_abi_compat_v2 { + struct ibv_comp_channel channel; + pthread_mutex_t in_use; +}; + extern HIDDEN int abi_ver; extern struct dlist *ibverbs_init(void); @@ -58,19 +63,25 @@ extern int ibv_init_mem_map(void); extern int ibv_lock_range(void *base, size_t size); extern int ibv_unlock_range(void *base, size_t size); -#define IBV_INIT_CMD(cmd, size, opcode) \ - do { \ - (cmd)->command = IB_USER_VERBS_CMD_##opcode; \ - (cmd)->in_words = (size) / 4; \ - (cmd)->out_words = 0; \ +#define IBV_INIT_CMD(cmd, size, opcode) \ + do { \ + if (abi_ver > 2) \ + (cmd)->command = IB_USER_VERBS_CMD_##opcode; \ + else \ + (cmd)->command = IB_USER_VERBS_CMD_##opcode##_V2; \ + (cmd)->in_words = (size) / 4; \ + (cmd)->out_words = 0; \ } while (0) -#define IBV_INIT_CMD_RESP(cmd, size, opcode, out, outsize) \ - do { \ - (cmd)->command = IB_USER_VERBS_CMD_##opcode; \ - (cmd)->in_words = (size) / 4; \ - (cmd)->out_words = (outsize) / 4; \ - (cmd)->response = (uintptr_t) (out); \ +#define IBV_INIT_CMD_RESP(cmd, size, opcode, out, outsize) \ + do { \ + if (abi_ver > 2) \ + (cmd)->command = IB_USER_VERBS_CMD_##opcode; \ + else \ + (cmd)->command = IB_USER_VERBS_CMD_##opcode##_V2; \ + (cmd)->in_words = (size) / 4; \ + (cmd)->out_words = (outsize) / 4; \ + (cmd)->response = (uintptr_t) (out); \ } while (0) #endif /* IB_VERBS_H */ diff --git a/src/libibverbs.map b/src/libibverbs.map index 5300a40..072287e 100644 --- a/src/libibverbs.map +++ b/src/libibverbs.map @@ -15,6 +15,8 @@ IBVERBS_1.0 { ibv_dealloc_pd; ibv_reg_mr; ibv_dereg_mr; + ibv_create_comp_channel; + ibv_destroy_comp_channel; ibv_create_cq; ibv_destroy_cq; ibv_get_cq_event; diff --git a/src/verbs.c b/src/verbs.c index 28fddcc..d3eb42e 100644 --- a/src/verbs.c +++ b/src/verbs.c @@ -37,6 +37,7 @@ #endif /* HAVE_CONFIG_H */ #include <stdio.h> +#include <netinet/in.h> #include <unistd.h> #include <errno.h> @@ -57,13 +58,45 @@ int ibv_query_port(struct ibv_context *context, uint8_t port_num, int ibv_query_gid(struct ibv_context *context, uint8_t port_num, int index, union ibv_gid *gid) { - return context->ops.query_gid(context, port_num, index, gid); + char *attr_name; + char attr[sizeof "0000:0000:0000:0000:0000:0000:0000:0000\0"]; + uint16_t val; + int i; + + asprintf(&attr_name, "%s/ports/%d/gids/%d", + context->device->ibdev->path, port_num, index); + + if (sysfs_read_attribute_value(attr_name, attr, sizeof attr)) + return -1; + + for (i = 0; i < 8; ++i) { + if (sscanf(attr + i * 5, "%hx", &val) != 1) + return -1; + gid->raw[i * 2 ] = val >> 8; + gid->raw[i * 2 + 1] = val & 0xff; + } + + return 0; } int ibv_query_pkey(struct ibv_context *context, uint8_t port_num, int index, uint16_t *pkey) { - return context->ops.query_pkey(context, port_num, index, pkey); + char *attr_name; + char attr[sizeof "0x0000\0"]; + uint16_t val; + + asprintf(&attr_name, "%s/ports/%d/pkeys/%d", + context->device->ibdev->path, port_num, index); + + if (sysfs_read_attribute_value(attr_name, attr, sizeof attr)) + return -1; + + if (sscanf(attr, "%hx", &val) != 1) + return -1; + + *pkey = htons(val); + return 0; } struct ibv_pd *ibv_alloc_pd(struct ibv_context *context) @@ -101,10 +134,71 @@ int ibv_dereg_mr(struct ibv_mr *mr) return mr->context->ops.dereg_mr(mr); } -struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, - void *cq_context) +static struct ibv_comp_channel *ibv_create_comp_channel_v2(struct ibv_context *context) +{ + struct ibv_abi_compat_v2 *t = context->abi_compat; + static int warned; + + if (!pthread_mutex_trylock(&t->in_use)) + return &t->channel; + + if (!warned) { + fprintf(stderr, PFX "Warning: kernel's ABI version %d limits capacity.\n" + " Only one completion channel can be created per context.\n", + abi_ver); + ++warned; + } + + return NULL; +} + +struct ibv_comp_channel *ibv_create_comp_channel(struct ibv_context *context) { - struct ibv_cq *cq = context->ops.create_cq(context, cqe); + struct ibv_comp_channel *channel; + struct ibv_create_comp_channel cmd; + struct ibv_create_comp_channel_resp resp; + + if (abi_ver <= 2) + return ibv_create_comp_channel_v2(context); + + channel = malloc(sizeof *channel); + if (!channel) + return NULL; + + IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_COMP_CHANNEL, &resp, sizeof resp); + if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) { + free(channel); + return NULL; + } + + channel->fd = resp.fd; + + return channel; +} + +static int ibv_destroy_comp_channel_v2(struct ibv_comp_channel *channel) +{ + struct ibv_abi_compat_v2 *t = (struct ibv_abi_compat_v2 *) channel; + pthread_mutex_unlock(&t->in_use); + return 0; +} + +int ibv_destroy_comp_channel(struct ibv_comp_channel *channel) +{ + if (abi_ver <= 2) + return ibv_destroy_comp_channel_v2(channel); + + close(channel->fd); + free(channel); + + return 0; +} + +struct ibv_cq *ibv_create_cq(struct ibv_context *context, int cqe, void *cq_context, + struct ibv_comp_channel *channel, int comp_vector) +{ + struct ibv_cq *cq = context->ops.create_cq(context, cqe, channel, + comp_vector); if (cq) { cq->context = context; @@ -124,15 +218,12 @@ int ibv_destroy_cq(struct ibv_cq *cq) } -int ibv_get_cq_event(struct ibv_context *context, int comp_num, +int ibv_get_cq_event(struct ibv_comp_channel *channel, struct ibv_cq **cq, void **cq_context) { struct ibv_comp_event ev; - if (comp_num < 0 || comp_num >= context->num_comp) - return -1; - - if (read(context->cq_fd[comp_num], &ev, sizeof ev) != sizeof ev) + if (read(channel->fd, &ev, sizeof ev) != sizeof ev) return -1; *cq = (struct ibv_cq *) (uintptr_t) ev.cq_handle; |