Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause 2 : * Copyright (C) 2021 Intel Corporation. All rights reserved. 3 : * Copyright (c) 2020, 2021 Mellanox Technologies LTD. All rights reserved. 4 : * Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 : */ 6 : 7 : #include <rdma/rdma_cma.h> 8 : 9 : #include "spdk/log.h" 10 : #include "spdk/string.h" 11 : #include "spdk/likely.h" 12 : 13 : #include "spdk_internal/rdma_provider.h" 14 : 15 : struct spdk_rdma_provider_srq * 16 0 : spdk_rdma_provider_srq_create(struct spdk_rdma_provider_srq_init_attr *init_attr) 17 : { 18 0 : assert(init_attr); 19 0 : assert(init_attr->pd); 20 : 21 0 : struct spdk_rdma_provider_srq *rdma_srq = calloc(1, sizeof(*rdma_srq)); 22 : 23 0 : if (!rdma_srq) { 24 0 : SPDK_ERRLOG("Can't allocate memory for SRQ handle\n"); 25 0 : return NULL; 26 : } 27 : 28 0 : if (init_attr->stats) { 29 0 : rdma_srq->stats = init_attr->stats; 30 0 : rdma_srq->shared_stats = true; 31 0 : } else { 32 0 : rdma_srq->stats = calloc(1, sizeof(*rdma_srq->stats)); 33 0 : if (!rdma_srq->stats) { 34 0 : SPDK_ERRLOG("SRQ statistics memory allocation failed"); 35 0 : free(rdma_srq); 36 0 : return NULL; 37 : } 38 : } 39 : 40 0 : rdma_srq->srq = ibv_create_srq(init_attr->pd, &init_attr->srq_init_attr); 41 0 : if (!rdma_srq->srq) { 42 0 : if (!init_attr->stats) { 43 0 : free(rdma_srq->stats); 44 0 : } 45 0 : SPDK_ERRLOG("Unable to create SRQ, errno %d (%s)\n", errno, spdk_strerror(errno)); 46 0 : free(rdma_srq); 47 0 : return NULL; 48 : } 49 : 50 0 : return rdma_srq; 51 0 : } 52 : 53 : int 54 0 : spdk_rdma_provider_srq_destroy(struct spdk_rdma_provider_srq *rdma_srq) 55 : { 56 0 : int rc; 57 : 58 0 : if (!rdma_srq) { 59 0 : return 0; 60 : } 61 : 62 0 : assert(rdma_srq->srq); 63 : 64 0 : if (rdma_srq->recv_wrs.first != NULL) { 65 0 : SPDK_WARNLOG("Destroying RDMA SRQ with queued recv WRs\n"); 66 0 : } 67 : 68 0 : rc = ibv_destroy_srq(rdma_srq->srq); 69 0 : if (rc) { 70 0 : SPDK_ERRLOG("SRQ destroy failed with %d\n", rc); 71 0 : } 72 : 73 0 : if (!rdma_srq->shared_stats) { 74 0 : free(rdma_srq->stats); 75 0 : } 76 : 77 0 : free(rdma_srq); 78 : 79 0 : return rc; 80 0 : } 81 : 82 : static inline bool 83 0 : rdma_queue_recv_wrs(struct spdk_rdma_provider_recv_wr_list *recv_wrs, struct ibv_recv_wr *first, 84 : struct spdk_rdma_provider_wr_stats *recv_stats) 85 : { 86 0 : struct ibv_recv_wr *last; 87 : 88 0 : recv_stats->num_submitted_wrs++; 89 0 : last = first; 90 0 : while (last->next != NULL) { 91 0 : last = last->next; 92 0 : recv_stats->num_submitted_wrs++; 93 : } 94 : 95 0 : if (recv_wrs->first == NULL) { 96 0 : recv_wrs->first = first; 97 0 : recv_wrs->last = last; 98 0 : return true; 99 : } else { 100 0 : recv_wrs->last->next = first; 101 0 : recv_wrs->last = last; 102 0 : return false; 103 : } 104 0 : } 105 : 106 : bool 107 0 : spdk_rdma_provider_srq_queue_recv_wrs(struct spdk_rdma_provider_srq *rdma_srq, 108 : struct ibv_recv_wr *first) 109 : { 110 0 : assert(rdma_srq); 111 0 : assert(first); 112 : 113 0 : return rdma_queue_recv_wrs(&rdma_srq->recv_wrs, first, rdma_srq->stats); 114 : } 115 : 116 : int 117 0 : spdk_rdma_provider_srq_flush_recv_wrs(struct spdk_rdma_provider_srq *rdma_srq, 118 : struct ibv_recv_wr **bad_wr) 119 : { 120 0 : int rc; 121 : 122 0 : if (spdk_unlikely(rdma_srq->recv_wrs.first == NULL)) { 123 0 : return 0; 124 : } 125 : 126 0 : rc = ibv_post_srq_recv(rdma_srq->srq, rdma_srq->recv_wrs.first, bad_wr); 127 : 128 0 : rdma_srq->recv_wrs.first = NULL; 129 0 : rdma_srq->stats->doorbell_updates++; 130 : 131 0 : return rc; 132 0 : } 133 : 134 : bool 135 0 : spdk_rdma_provider_qp_queue_recv_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 136 : struct ibv_recv_wr *first) 137 : { 138 0 : assert(spdk_rdma_qp); 139 0 : assert(first); 140 : 141 0 : return rdma_queue_recv_wrs(&spdk_rdma_qp->recv_wrs, first, &spdk_rdma_qp->stats->recv); 142 : } 143 : 144 : int 145 0 : spdk_rdma_provider_qp_flush_recv_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 146 : struct ibv_recv_wr **bad_wr) 147 : { 148 0 : int rc; 149 : 150 0 : if (spdk_unlikely(spdk_rdma_qp->recv_wrs.first == NULL)) { 151 0 : return 0; 152 : } 153 : 154 0 : rc = ibv_post_recv(spdk_rdma_qp->qp, spdk_rdma_qp->recv_wrs.first, bad_wr); 155 : 156 0 : spdk_rdma_qp->recv_wrs.first = NULL; 157 0 : spdk_rdma_qp->stats->recv.doorbell_updates++; 158 : 159 0 : return rc; 160 0 : }