diff --git a/debian/ibverbs-providers.symbols b/debian/ibverbs-providers.symbols index 3697696ab..59de5ce77 100644 --- a/debian/ibverbs-providers.symbols +++ b/debian/ibverbs-providers.symbols @@ -220,3 +220,19 @@ libionic.so.1 ibverbs-providers #MINVER# ionic_dv_pd_set_udma_mask@IONIC_1.0 59 ionic_dv_pd_set_sqcmb@IONIC_1.0 59 ionic_dv_pd_set_rqcmb@IONIC_1.0 59 + IONIC_1.1@IONIC_1.1 65 + ionic_dv_is_ionic_ctx@IONIC_1.1 65 + ionic_dv_is_ionic_pd@IONIC_1.1 65 + ionic_dv_is_ionic_cq@IONIC_1.1 65 + ionic_dv_is_ionic_qp@IONIC_1.1 65 + ionic_dv_cq_get_udma_mask@IONIC_1.1 65 + ionic_dv_qp_get_udma_idx@IONIC_1.1 65 + ionic_dv_pd_set_expdb_mask@IONIC_1.1 65 + ionic_dv_qp_set_gda@IONIC_1.1 65 + ionic_dv_qp_get_send_dbell_data@IONIC_1.1 65 + ionic_dv_qp_get_recv_dbell_data@IONIC_1.1 65 + ionic_dv_get_ctx@IONIC_1.1 65 + ionic_dv_get_cq@IONIC_1.1 65 + ionic_dv_get_qp@IONIC_1.1 65 + ionic_dv_create_cq_ex@IONIC_1.1 65 + diff --git a/debian/libibverbs-dev.install b/debian/libibverbs-dev.install index 141ad7975..1f3e9a04b 100644 --- a/debian/libibverbs-dev.install +++ b/debian/libibverbs-dev.install @@ -3,6 +3,7 @@ usr/include/infiniband/efadv.h usr/include/infiniband/hnsdv.h usr/include/infiniband/ib_user_ioctl_verbs.h usr/include/infiniband/ionic_dv.h +usr/include/infiniband/ionic_fw_types.h usr/include/infiniband/manadv.h usr/include/infiniband/mlx4dv.h usr/include/infiniband/mlx5_api.h diff --git a/providers/ionic/CMakeLists.txt b/providers/ionic/CMakeLists.txt index a28083fdc..ff03656a9 100644 --- a/providers/ionic/CMakeLists.txt +++ b/providers/ionic/CMakeLists.txt @@ -1,5 +1,5 @@ rdma_shared_provider(ionic libionic.map - 1 1.0.${PACKAGE_VERSION} + 1 1.1.${PACKAGE_VERSION} ionic.c ionic_verbs.c ionic_memory.c @@ -9,6 +9,7 @@ rdma_shared_provider(ionic libionic.map publish_headers(infiniband ionic_dv.h + ionic_fw_types.h ) rdma_pkg_config("ionic" "libibverbs" "${CMAKE_THREAD_LIBS_INIT}") diff --git a/providers/ionic/ionic.h b/providers/ionic/ionic.h index 8a9319728..c22e9316a 100644 --- a/providers/ionic/ionic.h +++ b/providers/ionic/ionic.h @@ -19,6 +19,7 @@ #include "ionic-abi.h" +#include "ionic_dv.h" #include "ionic_memory.h" #include "ionic_queue.h" #include "ionic_table.h" @@ -47,14 +48,18 @@ #define IONIC_PD_TAG_RQ (IONIC_PD_TAG | 3) enum { + IONIC_CQ_SUPPORTED_COMP_MASK = + IBV_CQ_INIT_ATTR_MASK_FLAGS | + IBV_CQ_INIT_ATTR_MASK_PD, + IONIC_CQ_SUPPORTED_WC_FLAGS = - IBV_WC_EX_WITH_BYTE_LEN | - IBV_WC_EX_WITH_IMM | - IBV_WC_EX_WITH_QP_NUM | - IBV_WC_EX_WITH_SRC_QP | - IBV_WC_EX_WITH_SLID | - IBV_WC_EX_WITH_SL | - IBV_WC_EX_WITH_DLID_PATH_BITS + IBV_WC_STANDARD_FLAGS, + + IONIC_CQ_SUPPORTED_EXT_COMP_MASK = + IONIC_CQ_INIT_ATTR_MASK_FLAGS, + + IONIC_CQ_SUPPORTED_EXT_FLAGS = + IONIC_CQ_INIT_ATTR_CCQE, }; enum { @@ -121,6 +126,7 @@ struct ionic_pd { struct ionic_td *td; uint8_t udma_mask; + uint8_t expdb_mask; uint8_t sq_cmb; uint8_t rq_cmb; @@ -193,6 +199,7 @@ struct ionic_rq { uint16_t cmb_prod; uint8_t cmb; bool flush; + bool gda; }; struct ionic_sq { @@ -213,6 +220,7 @@ struct ionic_sq { bool flush; bool flush_rcvd; bool color; + bool gda; }; struct ionic_qp { @@ -354,5 +362,8 @@ static inline void ionic_dbg_xdump(struct ionic_ctx *ctx, const char *str, /* ionic_verbs.h */ void ionic_verbs_set_ops(struct ionic_ctx *ctx); +struct ibv_cq_ex *ionic_create_cq_ex_common(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex, + struct ionic_cq_init_attr_ex *ionic_ex); #endif /* IONIC_H */ diff --git a/providers/ionic/ionic_dv.c b/providers/ionic/ionic_dv.c index 738fcc3e2..4fae1fb78 100644 --- a/providers/ionic/ionic_dv.c +++ b/providers/ionic/ionic_dv.c @@ -6,6 +6,26 @@ #include "ionic.h" #include "ionic_dv.h" +bool ionic_dv_is_ionic_ctx(struct ibv_context *ibctx) +{ + return is_ionic_ctx(ibctx); +} + +bool ionic_dv_is_ionic_pd(struct ibv_pd *ibpd) +{ + return is_ionic_pd(ibpd); +} + +bool ionic_dv_is_ionic_cq(struct ibv_cq *ibcq) +{ + return is_ionic_cq(ibcq); +} + +bool ionic_dv_is_ionic_qp(struct ibv_qp *ibqp) +{ + return is_ionic_qp(ibqp); +} + uint8_t ionic_dv_ctx_get_udma_count(struct ibv_context *ibctx) { if (!is_ionic_ctx(ibctx)) @@ -30,6 +50,22 @@ uint8_t ionic_dv_pd_get_udma_mask(struct ibv_pd *ibpd) return to_ionic_pd(ibpd)->udma_mask; } +uint8_t ionic_dv_cq_get_udma_mask(struct ibv_cq *ibcq) +{ + if (!is_ionic_cq(ibcq)) + return 0; + + return to_ionic_vcq(ibcq)->udma_mask; +} + +uint8_t ionic_dv_qp_get_udma_idx(struct ibv_qp *ibqp) +{ + if (!is_ionic_qp(ibqp)) + return 0; + + return to_ionic_qp(ibqp)->udma_idx; +} + int ionic_dv_pd_set_udma_mask(struct ibv_pd *ibpd, uint8_t udma_mask) { if (!is_ionic_pd(ibpd)) @@ -43,6 +79,19 @@ int ionic_dv_pd_set_udma_mask(struct ibv_pd *ibpd, uint8_t udma_mask) return 0; } +int ionic_dv_pd_set_expdb_mask(struct ibv_pd *ibpd, uint8_t mask) +{ + struct ionic_pd *pd; + + if (!is_ionic_pd(ibpd)) + return EPERM; + + pd = to_ionic_pd(ibpd); + pd->expdb_mask = mask & ((IONIC_EXPDB_512 << 1) - 1); + + return 0; +} + static uint8_t ionic_dv_cmb_val(bool enable, bool expdb, bool require) { uint8_t cmb = 0; @@ -105,3 +154,124 @@ int ionic_dv_pd_set_rqcmb(struct ibv_pd *ibpd, bool enable, bool expdb, bool req return 0; } + +int ionic_dv_qp_set_gda(struct ibv_qp *ibqp, bool enable_send, bool enable_recv) +{ + struct ionic_qp *qp; + + if (!is_ionic_qp(ibqp)) + return EPERM; + + qp = to_ionic_qp(ibqp); + + if (enable_send && qp->sq.cmb & IONIC_CMB_EXPDB) + return EINVAL; + + if (enable_recv && qp->rq.cmb & IONIC_CMB_EXPDB) + return EINVAL; + + qp->sq.gda = enable_send; + qp->rq.gda = enable_recv; + + return 0; +} + +int ionic_dv_qp_get_send_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata) +{ + struct ionic_qp *qp; + + if (!is_ionic_qp(ibqp)) + return EPERM; + + qp = to_ionic_qp(ibqp); + + *dbdata = ionic_queue_dbell_val(&qp->sq.queue); + + return 0; +} + +int ionic_dv_qp_get_recv_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata) +{ + struct ionic_qp *qp; + + if (!is_ionic_qp(ibqp)) + return EPERM; + + qp = to_ionic_qp(ibqp); + + *dbdata = ionic_queue_dbell_val(&qp->rq.queue); + + return 0; +} + +int ionic_dv_get_ctx(struct ionic_dv_ctx *dvctx, struct ibv_context *ibctx) +{ + struct ionic_ctx *ctx; + + if (!is_ionic_ctx(ibctx)) + return EPERM; + + ctx = to_ionic_ctx(ibctx); + + dvctx->db_page = ctx->dbpage_page; + dvctx->db_ptr = ctx->dbpage; + dvctx->sq_qtype = ctx->sq_qtype; + dvctx->rq_qtype = ctx->rq_qtype; + dvctx->cq_qtype = ctx->cq_qtype; + + return 0; +} + +static void ionic_dv_get_queue(struct ionic_dv_queue *dvq, struct ionic_queue *q) +{ + dvq->ptr = q->ptr; + dvq->size = q->size; + dvq->db_val = q->dbell; + dvq->mask = (uint16_t)q->mask; + dvq->depth_log2 = q->depth_log2; + dvq->stride_log2 = q->stride_log2; +} + +int ionic_dv_get_cq(struct ionic_dv_cq *dvcq, struct ibv_cq *ibcq, uint8_t udma_idx) +{ + struct ionic_vcq *vcq; + + if (!is_ionic_cq(ibcq)) + return EPERM; + + vcq = to_ionic_vcq(ibcq); + + if (!(vcq->udma_mask & BIT(udma_idx))) + return EINVAL; + + ionic_dv_get_queue(&dvcq->q, &vcq->cq[udma_idx].q); + + return 0; +} + +int ionic_dv_get_qp(struct ionic_dv_qp *dvqp, struct ibv_qp *ibqp) +{ + struct ionic_qp *qp; + + if (!is_ionic_qp(ibqp)) + return EPERM; + + qp = to_ionic_qp(ibqp); + + ionic_dv_get_queue(&dvqp->rq, &qp->rq.queue); + ionic_dv_get_queue(&dvqp->sq, &qp->sq.queue); + + return 0; +} + +struct ibv_cq_ex *ionic_dv_create_cq_ex(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex, + struct ionic_cq_init_attr_ex *ionic_ex) +{ + if (!is_ionic_ctx(ibctx)) { + errno = EPERM; + return NULL; + } + + return ionic_create_cq_ex_common(ibctx, ex, ionic_ex); +} diff --git a/providers/ionic/ionic_dv.h b/providers/ionic/ionic_dv.h index a11f5a212..a1dc1db79 100644 --- a/providers/ionic/ionic_dv.h +++ b/providers/ionic/ionic_dv.h @@ -12,6 +12,25 @@ #ifdef __cplusplus extern "C" { #endif +/** + * ionic_dv_is_ionic_ctx - Test if context belongs to ionic provider. + */ +bool ionic_dv_is_ionic_ctx(struct ibv_context *ibctx); + +/** + * ionic_dv_is_ionic_pd - Test if pd belongs to ionic provider. + */ +bool ionic_dv_is_ionic_pd(struct ibv_pd *ibpd); + +/** + * ionic_dv_is_ionic_cq - Test if cq belongs to ionic provider. + */ +bool ionic_dv_is_ionic_cq(struct ibv_cq *ibcq); + +/** + * ionic_dv_is_ionic_qp - Test if qp belongs to ionic provider. + */ +bool ionic_dv_is_ionic_qp(struct ibv_qp *ibqp); /** * ionic_dv_ctx_get_udma_count - Get number of udma pipelines. @@ -44,6 +63,26 @@ uint8_t ionic_dv_pd_get_udma_mask(struct ibv_pd *ibpd); */ int ionic_dv_pd_set_udma_mask(struct ibv_pd *ibpd, uint8_t udma_mask); +/** + * ionic_dv_cq_get_udma_mask - Get mask of udma pipeline ids of completion queue. + */ +uint8_t ionic_dv_cq_get_udma_mask(struct ibv_cq *ibcq); + +/** + * ionic_dv_qp_get_udma_idx - Get udma pipeline id of queue pair. + */ +uint8_t ionic_dv_qp_get_udma_idx(struct ibv_qp *ibqp); + +/** + * ionic_dv_pd_set_expdb_mask - Specify expdb mask. + * + * Queues associated with this pd will attempt to have expdb on for WQE sizes + * other than default (and supported by the NIC). + * + * @mask - IONIC_EXPDB_* bitmap + */ +int ionic_dv_pd_set_expdb_mask(struct ibv_pd *ibpd, uint8_t mask); + /** * ionic_dv_pd_set_sqcmb - Specify send queue preference for controller memory bar. * @@ -68,6 +107,139 @@ int ionic_dv_pd_set_sqcmb(struct ibv_pd *ibpd, bool enable, bool expdb, bool req */ int ionic_dv_pd_set_rqcmb(struct ibv_pd *ibpd, bool enable, bool expdb, bool require); +/** + * ionic_dv_qp_set_gda - Enable or disable GPU-Direct Async (GDA) mode. + * + * In GDA mode, when the application calls ibv_post_send() or ibv_post_recv(), the + * provider writes WQEs in the descriptor ring without ringing the doorbell. + * + * To ring the doorbell, after posting the work the application should query to get the + * doorbell data, and later write that data to the memory mapped doorbell register. + * + * See also: ionic_dv_get_ctx() + * See also: ionic_dv_qp_get_send_dbell_data() + * See also: ionic_dv_qp_get_recv_dbell_data() + * + * @ibqp - Set GDA mode for this queue pair. + * @enable_send - Enable GDA mode for the send queue. + * @enable_recv - Enable GDA mode for the recv queue. + */ +int ionic_dv_qp_set_gda(struct ibv_qp *ibqp, bool enable_send, bool enable_recv); + +/** + * ionic_dv_qp_get_send_dbell_data - Get send queue doorbell data. + * + * In GDA mode, when the application calls ibv_post_send() the provider writes WQEs in + * the descriptor ring without ringing the doorbell. The application should query the + * doorbell data immediately after posting the work. The application requests the + * GPU to fill the source buffers of the data transfer with the result of computation. + * The application requests the GPU to write the doorbell data to the memory mapped + * doorbell register immediately when the computation is complete, triggering the data + * transfer. + * + * It is important that the GPU ring the doorbell in sequential order. If work requests + * are posted in batches A, B, and C, with respective doorbell data, the data path must + * not write B or C before A, and must not write C before B. It is ok to skip writing a + * doorbell, like writing only C, which will trigger the data transfer for all of the + * work up to that point in the sequence. + * + * @ibqp - Get send doorbell data for this queue pair. + * @dbdata - Output parameter for doorbell data. + */ +int ionic_dv_qp_get_send_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata); + +/** + * ionic_dv_qp_get_recv_dbell_data - Get recv queue doorbell data. + * + * In GDA mode, when the application calls ibv_post_recv() the provider writes WQEs in + * the descriptor ring without ringing the doorbell. After polling recv completions, the + * application can immediately re-post the receive buffers without ringing the doorbell. + * The application should query the doorbell data immediately after posting the buffers. + * The application requests the GPU consume the data from the receive buffers. The + * application requests the GPU to write the doorbell data to the memory mapped doorbell + * register immediately after the received data is consumed, making the buffers available + * for the next data transfer. + * + * It is important that the GPU ring the doorbell in sequential order. If work requests + * are posted in batches A, B, and C, with respective doorbell data, the data path must + * not write B or C before A, and must not write C before B. It is ok to skip writing a + * doorbell, like writing only C, which will make buffers available up to that point in + * the sequence. + * + * @ibqp - Get recv doorbell data for this queue pair. + * @dbdata - Output parameter for doorbell data. + */ +int ionic_dv_qp_get_recv_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata); + +/** struct ionic_dv_ctx - Context information for gpu-initiated rdma. */ +struct ionic_dv_ctx { + void *db_page; + uint64_t *db_ptr; + uint8_t sq_qtype; + uint8_t rq_qtype; + uint8_t cq_qtype; +}; + +/** struct ionic_dv_queue - Queue information for gpu-initiated rdma. */ +struct ionic_dv_queue { + void *ptr; + size_t size; + uint64_t db_val; + uint16_t mask; + uint8_t depth_log2; + uint8_t stride_log2; +}; + +/** struct ionic_dv_cq - CQ information for gpu-initiated rdma. */ +struct ionic_dv_cq { + struct ionic_dv_queue q; +}; + +/** struct ionic_dv_qp - QP information for gpu-initiated rdma. */ +struct ionic_dv_qp { + struct ionic_dv_queue rq; + struct ionic_dv_queue sq; +}; + +/** + * ionic_dv_get_ctx - Extract context information for gpu-initiated rdma. + */ +int ionic_dv_get_ctx(struct ionic_dv_ctx *dvctx, struct ibv_context *ibctx); + +/** + * ionic_dv_get_cq - Extract cq information for gpu-initiated rdma. + */ +int ionic_dv_get_cq(struct ionic_dv_cq *dvcq, struct ibv_cq *ibcq, uint8_t udma_idx); + +/** + * ionic_dv_get_qp - Extract qp information for gpu-initiated rdma. + */ +int ionic_dv_get_qp(struct ionic_dv_qp *dvqp, struct ibv_qp *ibqp); + +enum ionic_cq_init_attr_mask { + IONIC_CQ_INIT_ATTR_MASK_FLAGS = 1 << 0, +}; + +enum ionic_cq_init_attr_flags { + IONIC_CQ_INIT_ATTR_CCQE = 1 << 0, +}; + +struct ionic_cq_init_attr_ex { + uint32_t comp_mask; + uint32_t flags; +}; + +/** + * ionic_dv_create_cq_ex - Create an IBV CQ with vendor-specific attributes. + * + * @ibctx - Context CQ will be attached to. + * @ex - IBV attributes to create the CQ with. + * @ionic_ex - Vendor-specific attributes to create the CQ with. + */ +struct ibv_cq_ex *ionic_dv_create_cq_ex(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex, + struct ionic_cq_init_attr_ex *ionic_ex); + #ifdef __cplusplus } #endif diff --git a/providers/ionic/ionic_fw_types.h b/providers/ionic/ionic_fw_types.h index 1546ff808..c1070534f 100644 --- a/providers/ionic/ionic_fw_types.h +++ b/providers/ionic/ionic_fw_types.h @@ -6,6 +6,12 @@ #ifndef IONIC_FW_TYPES_H #define IONIC_FW_TYPES_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + #define IONIC_EXP_DBELL_SZ 8 /* common to all versions */ @@ -258,4 +264,8 @@ enum ionic_v2_op { IONIC_V2_OP_BIND_MW = 0x8, }; +#ifdef __cplusplus +} +#endif + #endif /* IONIC_FW_TYPES_H */ diff --git a/providers/ionic/ionic_verbs.c b/providers/ionic/ionic_verbs.c index 5108a6fbc..87ba180c2 100644 --- a/providers/ionic/ionic_verbs.c +++ b/providers/ionic/ionic_verbs.c @@ -264,6 +264,7 @@ static struct ibv_pd *ionic_alloc_parent_domain(struct ibv_context *context, pd->root_ibpd = root_ibpd; pd->udma_mask = init_pd->udma_mask; + pd->expdb_mask = init_pd->expdb_mask; pd->sq_cmb = init_pd->sq_cmb; pd->rq_cmb = init_pd->rq_cmb; @@ -310,6 +311,7 @@ static struct ibv_pd *ionic_alloc_pd(struct ibv_context *ibctx) goto err_cmd; pd->udma_mask = ionic_ctx_udma_mask(ctx); + pd->expdb_mask = ctx->expdb_mask & IONIC_EXPDB_64; pd->sq_cmb = IONIC_CMB_ENABLE; if (ctx->sq_expdb) @@ -592,26 +594,57 @@ static uint8_t ionic_wc_read_dlid_path_bits(struct ibv_cq_ex *ibcq_ex) return vcq->cur_wc.dlid_path_bits; } -static struct ibv_cq_ex *ionic_create_cq_ex(struct ibv_context *ibctx, - struct ibv_cq_init_attr_ex *ex) +struct ibv_cq_ex *ionic_create_cq_ex_common(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex, + struct ionic_cq_init_attr_ex *ionic_ex) { struct ionic_ctx *ctx = to_ionic_ctx(ibctx); struct ionic_pd *pd = NULL; struct ionic_vcq *vcq; struct uionic_cq req = {}; struct uionic_cq_resp resp = {}; + uint32_t ncqe; int cq_i, rc; - if (ex->wc_flags & ~IONIC_CQ_SUPPORTED_WC_FLAGS) { + if (ionic_ex) { + if (!check_comp_mask(ionic_ex->comp_mask, + IONIC_CQ_SUPPORTED_EXT_COMP_MASK)) { + rc = ENOTSUP; + goto err; + } + + if (ionic_ex->comp_mask & IONIC_CQ_INIT_ATTR_MASK_FLAGS) { + if (!check_comp_mask(ionic_ex->flags, + IONIC_CQ_SUPPORTED_EXT_FLAGS)) { + rc = ENOTSUP; + goto err; + } + } + } + + if (!check_comp_mask(ex->comp_mask, IONIC_CQ_SUPPORTED_COMP_MASK)) { rc = ENOTSUP; goto err; } - if (ex->cqe < 1 || ex->cqe + IONIC_CQ_GRACE > 0xffff) { - rc = EINVAL; + if (!check_comp_mask(ex->wc_flags, IONIC_CQ_SUPPORTED_WC_FLAGS)) { + rc = ENOTSUP; goto err; } + if (ionic_ex && + (ionic_ex->comp_mask & IONIC_CQ_INIT_ATTR_MASK_FLAGS) && + (ionic_ex->flags & IONIC_CQ_INIT_ATTR_CCQE)) { + ncqe = 0; + } else { + ncqe = ex->cqe; + + if (!ncqe || ncqe + IONIC_CQ_GRACE > 0xffff) { + rc = EINVAL; + goto err; + } + } + vcq = calloc(1, sizeof(*vcq)); if (!vcq) { rc = ENOMEM; @@ -697,6 +730,12 @@ static struct ibv_cq_ex *ionic_create_cq_ex(struct ibv_context *ibctx, return NULL; } +static struct ibv_cq_ex *ionic_create_cq_ex(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex) +{ + return ionic_create_cq_ex_common(ibctx, ex, NULL); +} + static struct ibv_cq *ionic_create_cq(struct ibv_context *ibctx, int ncqe, struct ibv_comp_channel *channel, int vec) @@ -1512,13 +1551,17 @@ static int ionic_req_notify_cq(struct ibv_cq *ibcq, int solicited_only) } static bool ionic_expdb_wqe_size_supported(struct ionic_ctx *ctx, + struct ionic_pd *pd, uint32_t wqe_size) { + int mask; + + mask = pd->expdb_mask & ctx->expdb_mask; switch (wqe_size) { - case 64: return ctx->expdb_mask & IONIC_EXPDB_64; - case 128: return ctx->expdb_mask & IONIC_EXPDB_128; - case 256: return ctx->expdb_mask & IONIC_EXPDB_256; - case 512: return ctx->expdb_mask & IONIC_EXPDB_512; + case 64: return mask & IONIC_EXPDB_64; + case 128: return mask & IONIC_EXPDB_128; + case 256: return mask & IONIC_EXPDB_256; + case 512: return mask & IONIC_EXPDB_512; } return false; @@ -1588,7 +1631,7 @@ static int ionic_qp_sq_init(struct ionic_ctx *ctx, struct ionic_qp *qp, struct i wqe_size = ionic_v1_send_wqe_min_size(max_sge, max_data, qp->sq.spec, true); - if (!ionic_expdb_wqe_size_supported(ctx, wqe_size)) + if (!ionic_expdb_wqe_size_supported(ctx, pd, wqe_size)) qp->sq.cmb &= ~IONIC_CMB_EXPDB; } @@ -1662,7 +1705,7 @@ static int ionic_qp_rq_init(struct ionic_ctx *ctx, struct ionic_qp *qp, struct i if (qp->rq.cmb & IONIC_CMB_EXPDB) { wqe_size = ionic_v1_recv_wqe_min_size(max_sge, qp->rq.spec, true); - if (!ionic_expdb_wqe_size_supported(ctx, wqe_size)) + if (!ionic_expdb_wqe_size_supported(ctx, pd, wqe_size)) qp->rq.cmb &= ~IONIC_CMB_EXPDB; } @@ -1765,7 +1808,7 @@ static int ionic_wr_complete(struct ibv_qp_ex *ibqp_ex) if (qp->sq.cmb_ptr) { ionic_post_send_cmb(ctx, qp); - } else { + } else if (!qp->sq.gda) { udma_to_device_barrier(); verbs_debug(&ctx->vctx, "dbell qp %u sq val %" PRIx64, qp->qpid, ionic_queue_dbell_val(&qp->sq.queue)); @@ -3031,7 +3074,7 @@ static int ionic_post_send_common(struct ionic_ctx *ctx, if (qp->sq.cmb_ptr) { ionic_post_send_cmb(ctx, qp); - } else { + } else if (!qp->sq.gda) { udma_to_device_barrier(); verbs_debug(&ctx->vctx, "dbell qp %u sq val %" PRIx64, qp->qpid, ionic_queue_dbell_val(&qp->sq.queue)); @@ -3168,7 +3211,7 @@ static int ionic_post_recv_common(struct ionic_ctx *ctx, if (qp->rq.cmb_ptr) { ionic_post_recv_cmb(ctx, qp); - } else { + } else if (!qp->rq.gda) { udma_to_device_barrier(); verbs_debug(&ctx->vctx, "dbell qp %u rq val %" PRIx64, qp->qpid, diff --git a/providers/ionic/libionic.map b/providers/ionic/libionic.map index 3efca32b9..690d443ca 100644 --- a/providers/ionic/libionic.map +++ b/providers/ionic/libionic.map @@ -10,3 +10,21 @@ IONIC_1.0 { ionic_dv_pd_set_rqcmb; local: *; }; + +IONIC_1.1 { + global: + ionic_dv_is_ionic_ctx; + ionic_dv_is_ionic_pd; + ionic_dv_is_ionic_cq; + ionic_dv_is_ionic_qp; + ionic_dv_cq_get_udma_mask; + ionic_dv_qp_get_udma_idx; + ionic_dv_pd_set_expdb_mask; + ionic_dv_qp_set_gda; + ionic_dv_qp_get_send_dbell_data; + ionic_dv_qp_get_recv_dbell_data; + ionic_dv_get_ctx; + ionic_dv_get_cq; + ionic_dv_get_qp; + ionic_dv_create_cq_ex; +} IONIC_1.0; diff --git a/providers/ionic/man/CMakeLists.txt b/providers/ionic/man/CMakeLists.txt index 2827560fd..894a83423 100644 --- a/providers/ionic/man/CMakeLists.txt +++ b/providers/ionic/man/CMakeLists.txt @@ -1,9 +1,23 @@ rdma_man_pages( ionicdv.7.md + ionic_dv_is_ionic_ctx.3.md + ionic_dv_is_ionic_pd.3.md + ionic_dv_is_ionic_cq.3.md + ionic_dv_is_ionic_qp.3.md ionic_dv_ctx_get_udma_count.3.md ionic_dv_ctx_get_udma_mask.3.md ionic_dv_pd_get_udma_mask.3.md ionic_dv_pd_set_udma_mask.3.md + ionic_dv_cq_get_udma_mask.3.md + ionic_dv_qp_get_udma_idx.3.md + ionic_dv_pd_set_expdb_mask.3.md ionic_dv_pd_set_sqcmb.3.md ionic_dv_pd_set_rqcmb.3.md + ionic_dv_qp_set_gda.3.md + ionic_dv_qp_get_send_dbell_data.3.md + ionic_dv_qp_get_recv_dbell_data.3.md + ionic_dv_get_ctx.3.md + ionic_dv_get_cq.3.md + ionic_dv_get_qp.3.md + ionic_dv_create_cq_ex.3.md ) diff --git a/providers/ionic/man/ionic_dv_cq_get_udma_mask.3.md b/providers/ionic/man/ionic_dv_cq_get_udma_mask.3.md new file mode 100644 index 000000000..0e6ccd357 --- /dev/null +++ b/providers/ionic/man/ionic_dv_cq_get_udma_mask.3.md @@ -0,0 +1,52 @@ +--- +layout: page +title: IONIC_DV_CQ_GET_UDMA_MASK +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_cq_get_udma_mask - Get UDMA pipeline mask of a completion queue + +# SYNOPSIS + +```c +#include + +uint8_t ionic_dv_cq_get_udma_mask(struct ibv_cq *ibcq); +``` + +# DESCRIPTION + +**ionic_dv_cq_get_udma_mask()** returns the bitmask of UDMA pipelines +assigned to the completion queue *ibcq*. Each set bit represents a UDMA +pipeline that the completion queue spans. + +A completion queue inherits its UDMA mask from the protection domain at +creation time via **ionic_dv_pd_set_udma_mask**(3). + +# ARGUMENTS + +*ibcq* +: The completion queue to query. Must be an ionic completion queue. + +# RETURN VALUE + +Returns the UDMA pipeline bitmask of the completion queue. Returns 0 if +*ibcq* is not an ionic completion queue. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_ctx_get_udma_count**(3), +**ionic_dv_ctx_get_udma_mask**(3), +**ionic_dv_pd_get_udma_mask**(3), +**ionic_dv_pd_set_udma_mask**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_create_cq_ex.3.md b/providers/ionic/man/ionic_dv_create_cq_ex.3.md new file mode 100644 index 000000000..3099ae397 --- /dev/null +++ b/providers/ionic/man/ionic_dv_create_cq_ex.3.md @@ -0,0 +1,83 @@ +--- +layout: page +title: IONIC_DV_CREATE_CQ_EX +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_create_cq_ex - Create a completion queue with vendor-specific attributes + +# SYNOPSIS + +```c +#include + +struct ibv_cq_ex *ionic_dv_create_cq_ex(struct ibv_context *ibctx, + struct ibv_cq_init_attr_ex *ex, + struct ionic_cq_init_attr_ex *ionic_ex); +``` + +# DESCRIPTION + +**ionic_dv_create_cq_ex()** creates a completion queue with both standard +IBV attributes and ionic vendor-specific attributes. + +The *ionic_ex* parameter may be NULL, in which case the function behaves +identically to **ibv_create_cq_ex**. When provided, *ionic_ex* allows +specifying additional ionic-specific options: + +## ionic_cq_init_attr_ex + +*comp_mask* +: Bitmask of **enum ionic_cq_init_attr_mask** values indicating + which fields are valid. + +*flags* +: Bitmask of **enum ionic_cq_init_attr_flags** values. Only valid + when *comp_mask* includes **IONIC_CQ_INIT_ATTR_MASK_FLAGS**. + +## Flags + +**IONIC_CQ_INIT_ATTR_CCQE** +: Enable compact CQE mode. When set, the CQ may be created with + zero entries and CQEs are encoded in a compact format. + +# ARGUMENTS + +*ibctx* +: The device context to create the CQ on. Must be an ionic device + context. + +*ex* +: Standard IBV CQ creation attributes. + +*ionic_ex* +: Ionic vendor-specific CQ creation attributes. May be NULL. + +# RETURN VALUE + +Returns a pointer to the created **ibv_cq_ex** on success, or NULL on +failure with errno set: + +*EPERM* +: *ibctx* is not an ionic device context. + +*ENOTSUP* +: Unsupported flags or comp_mask bits were specified. + +*EINVAL* +: Invalid CQ size or parameters. + +# SEE ALSO + +**ionicdv**(7), +**ibv_create_cq_ex**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_get_cq.3.md b/providers/ionic/man/ionic_dv_get_cq.3.md new file mode 100644 index 000000000..2cfb43ce5 --- /dev/null +++ b/providers/ionic/man/ionic_dv_get_cq.3.md @@ -0,0 +1,67 @@ +--- +layout: page +title: IONIC_DV_GET_CQ +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_get_cq - Extract completion queue information for GPU-initiated RDMA + +# SYNOPSIS + +```c +#include + +int ionic_dv_get_cq(struct ionic_dv_cq *dvcq, struct ibv_cq *ibcq, + uint8_t udma_idx); +``` + +# DESCRIPTION + +**ionic_dv_get_cq()** extracts completion queue descriptor information +for the UDMA pipeline *udma_idx* into the *dvcq* structure. The returned +**ionic_dv_queue** contains the queue buffer pointer, size, doorbell +value, mask, and log2 depth and stride. + +A completion queue may span multiple UDMA pipelines. The *udma_idx* +selects which pipeline's CQ descriptor to extract. Use +**ionic_dv_cq_get_udma_mask**(3) to determine valid pipeline indices. + +# ARGUMENTS + +*dvcq* +: Output structure to receive the CQ queue descriptor. + +*ibcq* +: The completion queue to query. Must be an ionic completion queue. + +*udma_idx* +: The UDMA pipeline index to extract. Must be a pipeline that the + CQ spans (i.e., the corresponding bit must be set in the CQ's + UDMA mask). + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibcq* is not an ionic completion queue. + +*EINVAL* +: *udma_idx* is not a valid pipeline for this CQ. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_get_ctx**(3), +**ionic_dv_get_qp**(3), +**ionic_dv_cq_get_udma_mask**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_get_ctx.3.md b/providers/ionic/man/ionic_dv_get_ctx.3.md new file mode 100644 index 000000000..d8e8431d6 --- /dev/null +++ b/providers/ionic/man/ionic_dv_get_ctx.3.md @@ -0,0 +1,63 @@ +--- +layout: page +title: IONIC_DV_GET_CTX +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_get_ctx - Extract context information for GPU-initiated RDMA + +# SYNOPSIS + +```c +#include + +int ionic_dv_get_ctx(struct ionic_dv_ctx *dvctx, struct ibv_context *ibctx); +``` + +# DESCRIPTION + +**ionic_dv_get_ctx()** extracts device context information needed for +GPU-initiated RDMA operations into the *dvctx* structure. + +The returned information includes: + +- **db_page** / **db_ptr**: The memory mapped doorbell page and pointer + that the GPU uses to ring doorbells. +- **sq_qtype**, **rq_qtype**, **cq_qtype**: Queue type identifiers used + in doorbell encoding. + +This function is used together with **ionic_dv_get_cq**(3) and +**ionic_dv_get_qp**(3) to obtain all information needed for a GPU to +directly operate on ionic queues. + +# ARGUMENTS + +*dvctx* +: Output structure to receive the context information. + +*ibctx* +: The device context to query. Must be an ionic device context. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibctx* is not an ionic device context. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_qp_set_gda**(3), +**ionic_dv_get_cq**(3), +**ionic_dv_get_qp**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_get_qp.3.md b/providers/ionic/man/ionic_dv_get_qp.3.md new file mode 100644 index 000000000..f17e34f1d --- /dev/null +++ b/providers/ionic/man/ionic_dv_get_qp.3.md @@ -0,0 +1,58 @@ +--- +layout: page +title: IONIC_DV_GET_QP +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_get_qp - Extract queue pair information for GPU-initiated RDMA + +# SYNOPSIS + +```c +#include + +int ionic_dv_get_qp(struct ionic_dv_qp *dvqp, struct ibv_qp *ibqp); +``` + +# DESCRIPTION + +**ionic_dv_get_qp()** extracts send and receive queue descriptor +information into the *dvqp* structure. Each **ionic_dv_queue** in the +returned structure contains the queue buffer pointer, size, doorbell +value, mask, and log2 depth and stride. + +This function is used together with **ionic_dv_get_ctx**(3) and +**ionic_dv_get_cq**(3) to obtain all information needed for a GPU to +directly operate on ionic queues in GDA mode. + +# ARGUMENTS + +*dvqp* +: Output structure to receive the send and receive queue descriptors. + +*ibqp* +: The queue pair to query. Must be an ionic queue pair. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibqp* is not an ionic queue pair. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_get_ctx**(3), +**ionic_dv_get_cq**(3), +**ionic_dv_qp_set_gda**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_is_ionic_cq.3.md b/providers/ionic/man/ionic_dv_is_ionic_cq.3.md new file mode 100644 index 000000000..1bfeb7d55 --- /dev/null +++ b/providers/ionic/man/ionic_dv_is_ionic_cq.3.md @@ -0,0 +1,48 @@ +--- +layout: page +title: IONIC_DV_IS_IONIC_CQ +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_is_ionic_cq - Test if a completion queue belongs to the ionic provider + +# SYNOPSIS + +```c +#include + +bool ionic_dv_is_ionic_cq(struct ibv_cq *ibcq); +``` + +# DESCRIPTION + +**ionic_dv_is_ionic_cq()** tests whether the completion queue *ibcq* +belongs to the ionic provider. This can be used by applications that +support multiple RDMA providers to determine whether ionic-specific +direct verbs may be called on the completion queue. + +# ARGUMENTS + +*ibcq* +: The completion queue to test. + +# RETURN VALUE + +Returns true if *ibcq* is an ionic completion queue, false otherwise. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_is_ionic_ctx**(3), +**ionic_dv_is_ionic_pd**(3), +**ionic_dv_is_ionic_qp**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_is_ionic_ctx.3.md b/providers/ionic/man/ionic_dv_is_ionic_ctx.3.md new file mode 100644 index 000000000..3585c097d --- /dev/null +++ b/providers/ionic/man/ionic_dv_is_ionic_ctx.3.md @@ -0,0 +1,48 @@ +--- +layout: page +title: IONIC_DV_IS_IONIC_CTX +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_is_ionic_ctx - Test if a device context belongs to the ionic provider + +# SYNOPSIS + +```c +#include + +bool ionic_dv_is_ionic_ctx(struct ibv_context *ibctx); +``` + +# DESCRIPTION + +**ionic_dv_is_ionic_ctx()** tests whether the device context *ibctx* +belongs to the ionic provider. This can be used by applications that +support multiple RDMA providers to determine whether ionic-specific +direct verbs may be called on the context. + +# ARGUMENTS + +*ibctx* +: The device context to test. + +# RETURN VALUE + +Returns true if *ibctx* is an ionic device context, false otherwise. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_is_ionic_pd**(3), +**ionic_dv_is_ionic_cq**(3), +**ionic_dv_is_ionic_qp**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_is_ionic_pd.3.md b/providers/ionic/man/ionic_dv_is_ionic_pd.3.md new file mode 100644 index 000000000..a7568509f --- /dev/null +++ b/providers/ionic/man/ionic_dv_is_ionic_pd.3.md @@ -0,0 +1,48 @@ +--- +layout: page +title: IONIC_DV_IS_IONIC_PD +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_is_ionic_pd - Test if a protection domain belongs to the ionic provider + +# SYNOPSIS + +```c +#include + +bool ionic_dv_is_ionic_pd(struct ibv_pd *ibpd); +``` + +# DESCRIPTION + +**ionic_dv_is_ionic_pd()** tests whether the protection domain *ibpd* +belongs to the ionic provider. This can be used by applications that +support multiple RDMA providers to determine whether ionic-specific +direct verbs may be called on the protection domain. + +# ARGUMENTS + +*ibpd* +: The protection domain to test. + +# RETURN VALUE + +Returns true if *ibpd* is an ionic protection domain, false otherwise. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_is_ionic_ctx**(3), +**ionic_dv_is_ionic_cq**(3), +**ionic_dv_is_ionic_qp**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_is_ionic_qp.3.md b/providers/ionic/man/ionic_dv_is_ionic_qp.3.md new file mode 100644 index 000000000..cd1678314 --- /dev/null +++ b/providers/ionic/man/ionic_dv_is_ionic_qp.3.md @@ -0,0 +1,48 @@ +--- +layout: page +title: IONIC_DV_IS_IONIC_QP +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_is_ionic_qp - Test if a queue pair belongs to the ionic provider + +# SYNOPSIS + +```c +#include + +bool ionic_dv_is_ionic_qp(struct ibv_qp *ibqp); +``` + +# DESCRIPTION + +**ionic_dv_is_ionic_qp()** tests whether the queue pair *ibqp* +belongs to the ionic provider. This can be used by applications that +support multiple RDMA providers to determine whether ionic-specific +direct verbs may be called on the queue pair. + +# ARGUMENTS + +*ibqp* +: The queue pair to test. + +# RETURN VALUE + +Returns true if *ibqp* is an ionic queue pair, false otherwise. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_is_ionic_ctx**(3), +**ionic_dv_is_ionic_pd**(3), +**ionic_dv_is_ionic_cq**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_pd_set_expdb_mask.3.md b/providers/ionic/man/ionic_dv_pd_set_expdb_mask.3.md new file mode 100644 index 000000000..76eb9f16d --- /dev/null +++ b/providers/ionic/man/ionic_dv_pd_set_expdb_mask.3.md @@ -0,0 +1,62 @@ +--- +layout: page +title: IONIC_DV_PD_SET_EXPDB_MASK +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_pd_set_expdb_mask - Set express doorbell WQE size mask on a protection domain + +# SYNOPSIS + +```c +#include + +int ionic_dv_pd_set_expdb_mask(struct ibv_pd *ibpd, uint8_t mask); +``` + +# DESCRIPTION + +**ionic_dv_pd_set_expdb_mask()** sets the express doorbell WQE size mask +on the protection domain *ibpd*. Queues created under this protection +domain will attempt to use express doorbell for WQE sizes enabled by +*mask*, subject to device support. + +By default, only 64-byte WQE express doorbell is enabled. Use this +function to enable express doorbell for additional WQE sizes. + +The *mask* is a bitwise OR of **IONIC_EXPDB_64**, **IONIC_EXPDB_128**, +**IONIC_EXPDB_256**, and **IONIC_EXPDB_512** constants defined in the +kernel ABI header. Bits not supported by the device are silently ignored. + +# ARGUMENTS + +*ibpd* +: The protection domain to configure. Must be an ionic protection + domain. + +*mask* +: Bitmask of IONIC_EXPDB_* flags indicating desired express doorbell + WQE sizes. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibpd* is not an ionic protection domain. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_pd_set_sqcmb**(3), +**ionic_dv_pd_set_rqcmb**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_qp_get_recv_dbell_data.3.md b/providers/ionic/man/ionic_dv_qp_get_recv_dbell_data.3.md new file mode 100644 index 000000000..dba125085 --- /dev/null +++ b/providers/ionic/man/ionic_dv_qp_get_recv_dbell_data.3.md @@ -0,0 +1,64 @@ +--- +layout: page +title: IONIC_DV_QP_GET_RECV_DBELL_DATA +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_qp_get_recv_dbell_data - Get receive queue doorbell data for GDA mode + +# SYNOPSIS + +```c +#include + +int ionic_dv_qp_get_recv_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata); +``` + +# DESCRIPTION + +**ionic_dv_qp_get_recv_dbell_data()** retrieves the current doorbell data +for the receive queue of *ibqp*. This is used in GPU-Direct Async (GDA) +mode. + +In GDA mode, **ibv_post_recv()** writes WQEs into the descriptor ring +without ringing the doorbell. After polling completions and re-posting +receive buffers, the application queries the doorbell data. The GPU +writes this data to the memory mapped doorbell register after consuming +the received data, making the buffers available for the next transfer. + +Doorbells must be rung in sequential order. If buffers are posted in +batches A, B, and C, the GPU must not write B before A, or C before B. +Skipping intermediate doorbells is allowed (e.g., writing only C makes +all preceding buffers available). + +# ARGUMENTS + +*ibqp* +: The queue pair to query. Must be an ionic queue pair. + +*dbdata* +: Output parameter to receive the 64-bit doorbell data value. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibqp* is not an ionic queue pair. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_qp_set_gda**(3), +**ionic_dv_qp_get_send_dbell_data**(3), +**ionic_dv_get_ctx**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_qp_get_send_dbell_data.3.md b/providers/ionic/man/ionic_dv_qp_get_send_dbell_data.3.md new file mode 100644 index 000000000..767baf520 --- /dev/null +++ b/providers/ionic/man/ionic_dv_qp_get_send_dbell_data.3.md @@ -0,0 +1,62 @@ +--- +layout: page +title: IONIC_DV_QP_GET_SEND_DBELL_DATA +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_qp_get_send_dbell_data - Get send queue doorbell data for GDA mode + +# SYNOPSIS + +```c +#include + +int ionic_dv_qp_get_send_dbell_data(struct ibv_qp *ibqp, uint64_t *dbdata); +``` + +# DESCRIPTION + +**ionic_dv_qp_get_send_dbell_data()** retrieves the current doorbell data +for the send queue of *ibqp*. This is used in GPU-Direct Async (GDA) mode. + +In GDA mode, **ibv_post_send()** writes WQEs into the descriptor ring +without ringing the doorbell. The application should query the doorbell +data immediately after posting. The GPU writes this data to the memory +mapped doorbell register to trigger the data transfer. + +Doorbells must be rung in sequential order. If work is posted in batches +A, B, and C, the GPU must not write B before A, or C before B. Skipping +intermediate doorbells is allowed (e.g., writing only C triggers all +preceding work). + +# ARGUMENTS + +*ibqp* +: The queue pair to query. Must be an ionic queue pair. + +*dbdata* +: Output parameter to receive the 64-bit doorbell data value. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibqp* is not an ionic queue pair. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_qp_set_gda**(3), +**ionic_dv_qp_get_recv_dbell_data**(3), +**ionic_dv_get_ctx**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_qp_get_udma_idx.3.md b/providers/ionic/man/ionic_dv_qp_get_udma_idx.3.md new file mode 100644 index 000000000..df77db799 --- /dev/null +++ b/providers/ionic/man/ionic_dv_qp_get_udma_idx.3.md @@ -0,0 +1,53 @@ +--- +layout: page +title: IONIC_DV_QP_GET_UDMA_IDX +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_qp_get_udma_idx - Get UDMA pipeline index of a queue pair + +# SYNOPSIS + +```c +#include + +uint8_t ionic_dv_qp_get_udma_idx(struct ibv_qp *ibqp); +``` + +# DESCRIPTION + +**ionic_dv_qp_get_udma_idx()** returns the UDMA pipeline index assigned +to the queue pair *ibqp*. The pipeline index identifies which UDMA data +path the queue pair uses for its operations. + +A queue pair is assigned to a UDMA pipeline at creation time based on +the UDMA mask of its protection domain. Use +**ionic_dv_pd_set_udma_mask**(3) to control pipeline assignment. + +# ARGUMENTS + +*ibqp* +: The queue pair to query. Must be an ionic queue pair. + +# RETURN VALUE + +Returns the UDMA pipeline index of the queue pair. Returns 0 if *ibqp* +is not an ionic queue pair. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_ctx_get_udma_count**(3), +**ionic_dv_ctx_get_udma_mask**(3), +**ionic_dv_cq_get_udma_mask**(3), +**ionic_dv_pd_set_udma_mask**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionic_dv_qp_set_gda.3.md b/providers/ionic/man/ionic_dv_qp_set_gda.3.md new file mode 100644 index 000000000..43dcf4d98 --- /dev/null +++ b/providers/ionic/man/ionic_dv_qp_set_gda.3.md @@ -0,0 +1,69 @@ +--- +layout: page +title: IONIC_DV_QP_SET_GDA +section: 3 +tagline: Verbs +date: 2025-06-23 +header: "Ionic Programmer's Manual" +footer: ionic +--- + +# NAME + +ionic_dv_qp_set_gda - Enable or disable GPU-Direct Async mode on a queue pair + +# SYNOPSIS + +```c +#include + +int ionic_dv_qp_set_gda(struct ibv_qp *ibqp, bool enable_send, + bool enable_recv); +``` + +# DESCRIPTION + +**ionic_dv_qp_set_gda()** enables or disables GPU-Direct Async (GDA) mode +on the queue pair *ibqp*. + +In GDA mode, **ibv_post_send()** and **ibv_post_recv()** write WQEs into +the descriptor ring without ringing the doorbell. The application obtains +the doorbell data via **ionic_dv_qp_get_send_dbell_data**(3) or +**ionic_dv_qp_get_recv_dbell_data**(3), then arranges for the GPU to write +that data to the memory mapped doorbell register to initiate the transfer. + +GDA mode is incompatible with express doorbell (EXPDB) on the same queue. +If EXPDB is active on the send or receive queue, the corresponding GDA +enable will fail. + +# ARGUMENTS + +*ibqp* +: The queue pair to configure. Must be an ionic queue pair. + +*enable_send* +: Enable GDA mode for the send queue. + +*enable_recv* +: Enable GDA mode for the receive queue. + +# RETURN VALUE + +Returns 0 on success, or a positive errno value on failure: + +*EPERM* +: *ibqp* is not an ionic queue pair. + +*EINVAL* +: GDA was requested on a queue that has express doorbell enabled. + +# SEE ALSO + +**ionicdv**(7), +**ionic_dv_qp_get_send_dbell_data**(3), +**ionic_dv_qp_get_recv_dbell_data**(3), +**ionic_dv_get_ctx**(3) + +# AUTHORS + +Advanced Micro Devices, Inc. diff --git a/providers/ionic/man/ionicdv.7.md b/providers/ionic/man/ionicdv.7.md index faf80063b..2e858feab 100644 --- a/providers/ionic/man/ionicdv.7.md +++ b/providers/ionic/man/ionicdv.7.md @@ -29,13 +29,31 @@ to bypass the libibverbs API. The direct include of ionic_dv.h together with linkage to the ionic library will allow usage of this new interface. +## Provider Detection + +Applications that may run on different RDMA providers can use +**ionic_dv_is_ionic_ctx**(3), **ionic_dv_is_ionic_pd**(3), +**ionic_dv_is_ionic_cq**(3), and **ionic_dv_is_ionic_qp**(3) +to test whether a given verbs object belongs to the ionic provider +before calling ionic-specific direct verbs. + ## UDMA Pipelines Ionic devices expose multiple UDMA pipelines. Queues can be assigned to specific pipelines by setting a UDMA mask on the protection domain before creating queues. Use **ionic_dv_ctx_get_udma_count**(3) and **ionic_dv_ctx_get_udma_mask**(3) to query the available pipelines, and -**ionic_dv_pd_set_udma_mask**(3) to restrict queue placement. +**ionic_dv_pd_set_udma_mask**(3) to restrict queue placement. After +creating queues, use **ionic_dv_cq_get_udma_mask**(3) to query the UDMA +mask assigned to a completion queue, and **ionic_dv_qp_get_udma_idx**(3) +to query the UDMA pipeline index assigned to a queue pair. + +## Express Doorbell + +Express doorbell optimizations can reduce doorbell overhead for certain +WQE sizes. By default, only 64-byte WQE express doorbell is enabled. +Use **ionic_dv_pd_set_expdb_mask**(3) to enable express doorbell for +additional WQE sizes on a protection domain. ## Controller Memory Bar (CMB) @@ -45,14 +63,48 @@ may also be enabled. Use **ionic_dv_pd_set_sqcmb**(3) and **ionic_dv_pd_set_rqcmb**(3) to configure CMB preferences on a protection domain before creating queues. +## GPU-Direct Async (GDA) + +GPU-Direct Async mode allows GPU-initiated RDMA operations. When GDA is +enabled on a queue pair, posting work requests writes WQEs without ringing +the doorbell. The GPU can then ring the doorbell directly by writing +doorbell data to the memory mapped doorbell register. + +Use **ionic_dv_qp_set_gda**(3) to enable GDA mode on a queue pair. +After posting work, use **ionic_dv_qp_get_send_dbell_data**(3) and +**ionic_dv_qp_get_recv_dbell_data**(3) to obtain the doorbell data. +Use **ionic_dv_get_ctx**(3), **ionic_dv_get_cq**(3), and +**ionic_dv_get_qp**(3) to extract queue information for direct GPU +access. + +## Extended CQ Creation + +Use **ionic_dv_create_cq_ex**(3) to create a completion queue with +vendor-specific attributes. This extends the standard **ibv_create_cq_ex** +interface with ionic-specific options such as compact CQE (CCQE) mode. + # SEE ALSO +**ionic_dv_is_ionic_ctx**(3), +**ionic_dv_is_ionic_pd**(3), +**ionic_dv_is_ionic_cq**(3), +**ionic_dv_is_ionic_qp**(3), **ionic_dv_ctx_get_udma_count**(3), **ionic_dv_ctx_get_udma_mask**(3), **ionic_dv_pd_get_udma_mask**(3), **ionic_dv_pd_set_udma_mask**(3), +**ionic_dv_cq_get_udma_mask**(3), +**ionic_dv_qp_get_udma_idx**(3), +**ionic_dv_pd_set_expdb_mask**(3), **ionic_dv_pd_set_sqcmb**(3), **ionic_dv_pd_set_rqcmb**(3), +**ionic_dv_qp_set_gda**(3), +**ionic_dv_qp_get_send_dbell_data**(3), +**ionic_dv_qp_get_recv_dbell_data**(3), +**ionic_dv_get_ctx**(3), +**ionic_dv_get_cq**(3), +**ionic_dv_get_qp**(3), +**ionic_dv_create_cq_ex**(3), **verbs**(7) # AUTHORS