From 27d8fd9f4c82e0ae1138842fe1e48f3d20016707 Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Thu, 3 Dec 2020 13:47:34 +0300 Subject: [PATCH] rdma: Add functions to work with SRQ Add 4 new functions to create/delete SRQ, queue and flush recv Work Requests. Change-Id: I55401d22724cf1ce24f2cca588f2bd1384cdbcd0 Signed-off-by: Alexey Marchuk Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6289 Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker --- include/spdk_internal/rdma.h | 49 ++++++++++++++++++++ lib/rdma/common.c | 90 +++++++++++++++++++++++++++++++++++- lib/rdma/spdk_rdma.map | 4 ++ 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/include/spdk_internal/rdma.h b/include/spdk_internal/rdma.h index ea3610847..f166b390e 100644 --- a/include/spdk_internal/rdma.h +++ b/include/spdk_internal/rdma.h @@ -55,6 +55,11 @@ struct spdk_rdma_send_wr_list { struct ibv_send_wr *last; }; +struct spdk_rdma_recv_wr_list { + struct ibv_recv_wr *first; + struct ibv_recv_wr *last; +}; + struct spdk_rdma_qp { struct ibv_qp *qp; struct rdma_cm_id *cm_id; @@ -77,6 +82,50 @@ struct spdk_rdma_memory_translation { union spdk_rdma_mr mr_or_key; uint8_t translation_type; }; +struct spdk_rdma_srq_init_attr { + struct ibv_pd *pd; + struct ibv_srq_init_attr srq_init_attr; +}; + +struct spdk_rdma_srq { + struct ibv_srq *srq; + struct spdk_rdma_recv_wr_list recv_wrs; +}; + +/** + * Create RDMA SRQ + * + * \param init_attr Pointer to SRQ init attr + * \return pointer to srq on success or NULL on failure. errno is updated in failure case. + */ +struct spdk_rdma_srq *spdk_rdma_srq_create(struct spdk_rdma_srq_init_attr *init_attr); + +/** + * Destroy RDMA SRQ + * + * \param rdma_srq Pointer to SRQ + * \return 0 on succes, errno on failure + */ +int spdk_rdma_srq_destroy(struct spdk_rdma_srq *rdma_srq); + +/** + * Append the given recv wr structure to the SRQ's outstanding recv list. + * This function accepts either a single Work Request or the first WR in a linked list. + * + * \param rdma_srq Pointer to SRQ + * \param first pointer to the first Work Request + * \return true if there were no outstanding WRs before, false otherwise + */ +bool spdk_rdma_srq_queue_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr *first); + +/** + * Submit all queued receive Work Request + * + * \param rdma_srq Pointer to SRQ + * \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value + * \return 0 on succes, errno on failure + */ +int spdk_rdma_srq_flush_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr **bad_wr); /** * Create RDMA provider specific qpair diff --git a/lib/rdma/common.c b/lib/rdma/common.c index 0bd30183c..ab88a67b9 100644 --- a/lib/rdma/common.c +++ b/lib/rdma/common.c @@ -2,7 +2,7 @@ * BSD LICENSE * * Copyright (c) Intel Corporation. All rights reserved. - * Copyright (c) Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 2020, 2021 Mellanox Technologies LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,8 +31,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "spdk/log.h" #include "spdk/env.h" +#include "spdk/string.h" #include "spdk/likely.h" #include "spdk_internal/rdma.h" @@ -217,3 +220,88 @@ spdk_rdma_get_translation(struct spdk_rdma_mem_map *map, void *address, return 0; } + +struct spdk_rdma_srq * +spdk_rdma_srq_create(struct spdk_rdma_srq_init_attr *init_attr) +{ + assert(init_attr); + assert(init_attr->pd); + + struct spdk_rdma_srq *rdma_srq = calloc(1, sizeof(*rdma_srq)); + + if (!rdma_srq) { + SPDK_ERRLOG("Can't allocate memory for SRQ handle\n"); + return NULL; + } + + rdma_srq->srq = ibv_create_srq(init_attr->pd, &init_attr->srq_init_attr); + if (!rdma_srq->srq) { + SPDK_ERRLOG("Unable to create SRQ, errno %d (%s)\n", errno, spdk_strerror(errno)); + free(rdma_srq); + return NULL; + } + + return rdma_srq; +} + +int +spdk_rdma_srq_destroy(struct spdk_rdma_srq *rdma_srq) +{ + int rc; + + if (!rdma_srq) { + return 0; + } + + assert(rdma_srq->srq); + + if (rdma_srq->recv_wrs.first != NULL) { + SPDK_WARNLOG("Destroying RDMA SRQ with queued recv WRs\n"); + } + + rc = ibv_destroy_srq(rdma_srq->srq); + if (rc) { + SPDK_ERRLOG("SRQ destroy failed with %d\n", rc); + } + + free(rdma_srq); + + return rc; +} + +bool +spdk_rdma_srq_queue_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr *first) +{ + struct ibv_recv_wr *last; + + last = first; + while (last->next != NULL) { + last = last->next; + } + + if (rdma_srq->recv_wrs.first == NULL) { + rdma_srq->recv_wrs.first = first; + rdma_srq->recv_wrs.last = last; + return true; + } else { + rdma_srq->recv_wrs.last->next = first; + rdma_srq->recv_wrs.last = last; + return false; + } +} + +int +spdk_rdma_srq_flush_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr **bad_wr) +{ + int rc; + + if (spdk_unlikely(rdma_srq->recv_wrs.first == NULL)) { + return 0; + } + + rc = ibv_post_srq_recv(rdma_srq->srq, rdma_srq->recv_wrs.first, bad_wr); + + rdma_srq->recv_wrs.first = NULL; + + return rc; +} diff --git a/lib/rdma/spdk_rdma.map b/lib/rdma/spdk_rdma.map index a39c8dbf2..9afe628cf 100644 --- a/lib/rdma/spdk_rdma.map +++ b/lib/rdma/spdk_rdma.map @@ -2,6 +2,10 @@ global: # Public functions + spdk_rdma_srq_create; + spdk_rdma_srq_destroy; + spdk_rdma_srq_queue_recv_wrs; + spdk_rdma_srq_flush_recv_wrs; spdk_rdma_qp_create; spdk_rdma_qp_accept; spdk_rdma_qp_complete_connect;