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