1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Mellanox Technologies LTD. All rights reserved. 3 * Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 4 */ 5 6 #ifndef SPDK_RDMA_H 7 #define SPDK_RDMA_H 8 9 #include <infiniband/verbs.h> 10 #include <rdma/rdma_cma.h> 11 #include <rdma/rdma_verbs.h> 12 #include "spdk/dma.h" 13 14 /* rxe driver vendor_id has been changed from 0 to 0XFFFFFF in 0184afd15a141d7ce24c32c0d86a1e3ba6bc0eb3 */ 15 #define SPDK_RDMA_RXE_VENDOR_ID_OLD 0 16 #define SPDK_RDMA_RXE_VENDOR_ID_NEW 0XFFFFFF 17 18 struct spdk_rdma_provider_wr_stats { 19 /* Total number of submitted requests */ 20 uint64_t num_submitted_wrs; 21 /* Total number of doorbell updates */ 22 uint64_t doorbell_updates; 23 }; 24 25 struct spdk_rdma_provider_qp_stats { 26 struct spdk_rdma_provider_wr_stats send; 27 struct spdk_rdma_provider_wr_stats recv; 28 }; 29 30 struct spdk_rdma_provider_qp_init_attr { 31 void *qp_context; 32 struct ibv_cq *send_cq; 33 struct ibv_cq *recv_cq; 34 struct ibv_srq *srq; 35 struct ibv_qp_cap cap; 36 struct ibv_pd *pd; 37 struct spdk_rdma_provider_qp_stats *stats; 38 spdk_memory_domain_transfer_data_cb domain_transfer; 39 }; 40 41 struct spdk_rdma_provider_send_wr_list { 42 struct ibv_send_wr *first; 43 struct ibv_send_wr *last; 44 }; 45 46 struct spdk_rdma_provider_recv_wr_list { 47 struct ibv_recv_wr *first; 48 struct ibv_recv_wr *last; 49 }; 50 51 struct spdk_rdma_provider_qp { 52 struct ibv_qp *qp; 53 struct rdma_cm_id *cm_id; 54 struct spdk_memory_domain *domain; 55 struct spdk_rdma_provider_send_wr_list send_wrs; 56 struct spdk_rdma_provider_recv_wr_list recv_wrs; 57 struct spdk_rdma_provider_qp_stats *stats; 58 bool shared_stats; 59 }; 60 61 struct spdk_rdma_provider_srq_init_attr { 62 struct ibv_pd *pd; 63 struct spdk_rdma_provider_wr_stats *stats; 64 struct ibv_srq_init_attr srq_init_attr; 65 }; 66 67 struct spdk_rdma_provider_srq { 68 struct ibv_srq *srq; 69 struct spdk_rdma_provider_recv_wr_list recv_wrs; 70 struct spdk_rdma_provider_wr_stats *stats; 71 bool shared_stats; 72 }; 73 74 /** 75 * Create RDMA SRQ 76 * 77 * \param init_attr Pointer to SRQ init attr 78 * \return pointer to srq on success or NULL on failure. errno is updated in failure case. 79 */ 80 struct spdk_rdma_provider_srq *spdk_rdma_provider_srq_create( 81 struct spdk_rdma_provider_srq_init_attr *init_attr); 82 83 /** 84 * Destroy RDMA SRQ 85 * 86 * \param rdma_srq Pointer to SRQ 87 * \return 0 on success, errno on failure 88 */ 89 int spdk_rdma_provider_srq_destroy(struct spdk_rdma_provider_srq *rdma_srq); 90 91 /** 92 * Append the given recv wr structure to the SRQ's outstanding recv list. 93 * This function accepts either a single Work Request or the first WR in a linked list. 94 * 95 * \param rdma_srq Pointer to SRQ 96 * \param first pointer to the first Work Request 97 * \return true if there were no outstanding WRs before, false otherwise 98 */ 99 bool spdk_rdma_provider_srq_queue_recv_wrs(struct spdk_rdma_provider_srq *rdma_srq, 100 struct ibv_recv_wr *first); 101 102 /** 103 * Submit all queued receive Work Request 104 * 105 * \param rdma_srq Pointer to SRQ 106 * \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value 107 * \return 0 on success, errno on failure 108 */ 109 int spdk_rdma_provider_srq_flush_recv_wrs(struct spdk_rdma_provider_srq *rdma_srq, 110 struct ibv_recv_wr **bad_wr); 111 112 /** 113 * Create RDMA provider specific qpair 114 * 115 * \param cm_id Pointer to RDMA_CM cm_id 116 * \param qp_attr Pointer to qpair init attributes 117 * \return Pointer to a newly created qpair on success or NULL on failure 118 */ 119 struct spdk_rdma_provider_qp *spdk_rdma_provider_qp_create(struct rdma_cm_id *cm_id, 120 struct spdk_rdma_provider_qp_init_attr *qp_attr); 121 122 /** 123 * Accept a connection request. Called by the passive side (NVMEoF target) 124 * 125 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 126 * \param conn_param Optional information needed to establish the connection 127 * \return 0 on success, errno on failure 128 */ 129 int spdk_rdma_provider_qp_accept(struct spdk_rdma_provider_qp *spdk_rdma_qp, 130 struct rdma_conn_param *conn_param); 131 132 /** 133 * Complete the connection process, must be called by the active 134 * side (NVMEoF initiator) upon receipt RDMA_CM_EVENT_CONNECT_RESPONSE 135 * 136 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 137 * \return 0 on success, errno on failure 138 */ 139 int spdk_rdma_provider_qp_complete_connect(struct spdk_rdma_provider_qp *spdk_rdma_qp); 140 141 /** 142 * Destroy RDMA provider specific qpair 143 * 144 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair to be destroyed 145 */ 146 void spdk_rdma_provider_qp_destroy(struct spdk_rdma_provider_qp *spdk_rdma_qp); 147 148 /** 149 * Disconnect a connection and transition associated qpair to error state. 150 * Generates RDMA_CM_EVENT_DISCONNECTED on both connection sides 151 * 152 * \param spdk_rdma_qp Pointer to qpair to be disconnected 153 */ 154 int spdk_rdma_provider_qp_disconnect(struct spdk_rdma_provider_qp *spdk_rdma_qp); 155 156 /** 157 * Append the given send wr structure to the qpair's outstanding sends list. 158 * This function accepts either a single Work Request or the first WR in a linked list. 159 * 160 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 161 * \param first Pointer to the first Work Request 162 * \return true if there were no outstanding WRs before, false otherwise 163 */ 164 bool spdk_rdma_provider_qp_queue_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 165 struct ibv_send_wr *first); 166 167 /** 168 * Submit all queued send Work Request 169 * 170 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 171 * \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value 172 * \return 0 on success, errno on failure 173 */ 174 int spdk_rdma_provider_qp_flush_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 175 struct ibv_send_wr **bad_wr); 176 177 /** 178 * Append the given recv wr structure to the qpair's outstanding recv list. 179 * This function accepts either a single Work Request or the first WR in a linked list. 180 * 181 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 182 * \param first Pointer to the first Work Request 183 * \return true if there were no outstanding WRs before, false otherwise 184 */ 185 bool spdk_rdma_provider_qp_queue_recv_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 186 struct ibv_recv_wr *first); 187 188 /** 189 * Submit all queued recv Work Request 190 * \param spdk_rdma_qp Pointer to SPDK RDMA qpair 191 * \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value 192 * \return 0 on success, errno on failure 193 */ 194 int spdk_rdma_provider_qp_flush_recv_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp, 195 struct ibv_recv_wr **bad_wr); 196 197 bool spdk_rdma_provider_accel_sequence_supported(void); 198 199 #endif /* SPDK_RDMA_H */ 200