Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 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/stdinc.h"
10 : : #include "spdk/string.h"
11 : : #include "spdk/likely.h"
12 : :
13 : : #include "spdk_internal/rdma_provider.h"
14 : : #include "spdk_internal/rdma_utils.h"
15 : : #include "spdk/log.h"
16 : :
17 : : struct spdk_rdma_provider_qp *
18 : 2769 : spdk_rdma_provider_qp_create(struct rdma_cm_id *cm_id,
19 : : struct spdk_rdma_provider_qp_init_attr *qp_attr)
20 : : {
21 : : struct spdk_rdma_provider_qp *spdk_rdma_qp;
22 : : int rc;
23 : 2769 : struct ibv_qp_init_attr attr = {
24 [ # # # # ]: 2769 : .qp_context = qp_attr->qp_context,
25 [ # # # # ]: 2769 : .send_cq = qp_attr->send_cq,
26 [ # # # # ]: 2769 : .recv_cq = qp_attr->recv_cq,
27 [ # # # # ]: 2769 : .srq = qp_attr->srq,
28 [ # # ]: 0 : .cap = qp_attr->cap,
29 : : .qp_type = IBV_QPT_RC
30 : : };
31 : :
32 [ - + # # : 2769 : if (qp_attr->domain_transfer) {
# # ]
33 : 0 : SPDK_ERRLOG("verbs provider doesn't support memory domain transfer functionality");
34 : 0 : return NULL;
35 : : }
36 : :
37 : 2769 : spdk_rdma_qp = calloc(1, sizeof(*spdk_rdma_qp));
38 [ - + ]: 2769 : if (!spdk_rdma_qp) {
39 : 0 : SPDK_ERRLOG("qp memory allocation failed\n");
40 : 0 : return NULL;
41 : : }
42 : :
43 [ + + # # : 2769 : if (qp_attr->stats) {
# # ]
44 [ # # # # : 1747 : spdk_rdma_qp->stats = qp_attr->stats;
# # # # ]
45 [ # # # # ]: 1747 : spdk_rdma_qp->shared_stats = true;
46 : 0 : } else {
47 [ # # # # ]: 1022 : spdk_rdma_qp->stats = calloc(1, sizeof(*spdk_rdma_qp->stats));
48 [ - + # # : 1022 : if (!spdk_rdma_qp->stats) {
# # ]
49 : 0 : SPDK_ERRLOG("qp statistics memory allocation failed\n");
50 : 0 : free(spdk_rdma_qp);
51 : 0 : return NULL;
52 : : }
53 : : }
54 : :
55 [ # # # # ]: 2769 : rc = rdma_create_qp(cm_id, qp_attr->pd, &attr);
56 [ - + ]: 2769 : if (rc) {
57 [ # # # # ]: 0 : SPDK_ERRLOG("Failed to create qp, rc %d, errno %s (%d)\n", rc, spdk_strerror(errno), errno);
58 : 0 : free(spdk_rdma_qp);
59 : 0 : return NULL;
60 : : }
61 [ # # # # : 2769 : spdk_rdma_qp->qp = cm_id->qp;
# # # # ]
62 [ # # # # ]: 2769 : spdk_rdma_qp->cm_id = cm_id;
63 [ # # # # : 2769 : spdk_rdma_qp->domain = spdk_rdma_utils_get_memory_domain(qp_attr->pd);
# # # # ]
64 [ - + # # : 2769 : if (!spdk_rdma_qp->domain) {
# # ]
65 : 0 : spdk_rdma_provider_qp_destroy(spdk_rdma_qp);
66 : 0 : return NULL;
67 : : }
68 : :
69 [ # # ]: 2769 : qp_attr->cap = attr.cap;
70 : :
71 : 2769 : return spdk_rdma_qp;
72 : 0 : }
73 : :
74 : : int
75 : 1479 : spdk_rdma_provider_qp_accept(struct spdk_rdma_provider_qp *spdk_rdma_qp,
76 : : struct rdma_conn_param *conn_param)
77 : : {
78 [ - + # # ]: 1479 : assert(spdk_rdma_qp != NULL);
79 [ - + # # : 1479 : assert(spdk_rdma_qp->cm_id != NULL);
# # # # ]
80 : :
81 [ # # # # ]: 1479 : return rdma_accept(spdk_rdma_qp->cm_id, conn_param);
82 : : }
83 : :
84 : : int
85 : 0 : spdk_rdma_provider_qp_complete_connect(struct spdk_rdma_provider_qp *spdk_rdma_qp)
86 : : {
87 : : /* Nothing to be done for Verbs */
88 : 0 : return 0;
89 : : }
90 : :
91 : : void
92 : 2769 : spdk_rdma_provider_qp_destroy(struct spdk_rdma_provider_qp *spdk_rdma_qp)
93 : : {
94 [ - + # # ]: 2769 : assert(spdk_rdma_qp != NULL);
95 : :
96 [ - + # # : 2769 : if (spdk_rdma_qp->send_wrs.first != NULL) {
# # # # ]
97 : 0 : SPDK_WARNLOG("Destroying qpair with queued Work Requests\n");
98 : 0 : }
99 : :
100 [ + - # # : 2769 : if (spdk_rdma_qp->qp) {
# # ]
101 [ # # # # ]: 2769 : rdma_destroy_qp(spdk_rdma_qp->cm_id);
102 : 0 : }
103 : :
104 [ - + + + : 2769 : if (!spdk_rdma_qp->shared_stats) {
# # # # ]
105 [ # # # # ]: 1022 : free(spdk_rdma_qp->stats);
106 : 0 : }
107 [ + - # # : 2769 : if (spdk_rdma_qp->domain) {
# # ]
108 [ # # # # ]: 2769 : spdk_rdma_utils_put_memory_domain(spdk_rdma_qp->domain);
109 : 0 : }
110 : :
111 : 2769 : free(spdk_rdma_qp);
112 : 2769 : }
113 : :
114 : : int
115 : 2770 : spdk_rdma_provider_qp_disconnect(struct spdk_rdma_provider_qp *spdk_rdma_qp)
116 : : {
117 : 2770 : int rc = 0;
118 : :
119 [ - + # # ]: 2770 : assert(spdk_rdma_qp != NULL);
120 : :
121 [ + - # # : 2770 : if (spdk_rdma_qp->cm_id) {
# # ]
122 [ # # # # ]: 2770 : rc = rdma_disconnect(spdk_rdma_qp->cm_id);
123 [ - + ]: 2770 : if (rc) {
124 [ # # # # : 0 : if (errno == EINVAL && spdk_rdma_qp->qp->context->device->transport_type == IBV_TRANSPORT_IWARP) {
# # # # #
# # # # #
# # # # #
# # # ]
125 : : /* rdma_disconnect may return an error and set errno to EINVAL in case of iWARP.
126 : : * This behaviour is expected since iWARP handles disconnect event other than IB and
127 : : * qpair is already in error state when we call rdma_disconnect */
128 : 0 : return 0;
129 : : }
130 [ # # # # ]: 0 : SPDK_ERRLOG("rdma_disconnect failed, errno %s (%d)\n", spdk_strerror(errno), errno);
131 : 0 : }
132 : 0 : }
133 : :
134 : 2770 : return rc;
135 : 0 : }
136 : :
137 : : bool
138 : 10873900 : spdk_rdma_provider_qp_queue_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp,
139 : : struct ibv_send_wr *first)
140 : : {
141 : : struct ibv_send_wr *last;
142 : :
143 [ - + # # ]: 10873900 : assert(spdk_rdma_qp);
144 [ - + # # ]: 10873900 : assert(first);
145 : :
146 [ # # # # : 10873900 : spdk_rdma_qp->stats->send.num_submitted_wrs++;
# # # # ]
147 : 10873900 : last = first;
148 [ + + # # : 14956633 : while (last->next != NULL) {
# # ]
149 [ # # # # ]: 4082733 : last = last->next;
150 [ # # # # : 4082733 : spdk_rdma_qp->stats->send.num_submitted_wrs++;
# # # # ]
151 : : }
152 : :
153 [ + + # # : 10873900 : if (spdk_rdma_qp->send_wrs.first == NULL) {
# # # # ]
154 [ # # # # : 1560201 : spdk_rdma_qp->send_wrs.first = first;
# # ]
155 [ # # # # : 1560201 : spdk_rdma_qp->send_wrs.last = last;
# # ]
156 : 1560201 : return true;
157 : : } else {
158 [ # # # # : 9313699 : spdk_rdma_qp->send_wrs.last->next = first;
# # # # #
# ]
159 [ # # # # : 9313699 : spdk_rdma_qp->send_wrs.last = last;
# # ]
160 : 9313699 : return false;
161 : : }
162 : 0 : }
163 : :
164 : : int
165 : 76920772 : spdk_rdma_provider_qp_flush_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp,
166 : : struct ibv_send_wr **bad_wr)
167 : : {
168 : : int rc;
169 : :
170 [ - + # # ]: 76920772 : assert(spdk_rdma_qp);
171 [ - + # # ]: 76920772 : assert(bad_wr);
172 : :
173 [ + + # # : 76920772 : if (spdk_unlikely(!spdk_rdma_qp->send_wrs.first)) {
# # # # ]
174 : 75360571 : return 0;
175 : : }
176 : :
177 [ # # # # : 1560201 : rc = ibv_post_send(spdk_rdma_qp->qp, spdk_rdma_qp->send_wrs.first, bad_wr);
# # # # #
# ]
178 : :
179 [ # # # # : 1560201 : spdk_rdma_qp->send_wrs.first = NULL;
# # ]
180 [ # # # # : 1560201 : spdk_rdma_qp->stats->send.doorbell_updates++;
# # # # ]
181 : :
182 : 1560201 : return rc;
183 : 0 : }
184 : :
185 : : bool
186 : 1637 : spdk_rdma_provider_accel_sequence_supported(void)
187 : : {
188 : 1637 : return false;
189 : : }
|