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/log.h"
15 : :
16 : : struct spdk_rdma_provider_qp *
17 : 3724 : spdk_rdma_provider_qp_create(struct rdma_cm_id *cm_id,
18 : : struct spdk_rdma_provider_qp_init_attr *qp_attr)
19 : : {
20 : : struct spdk_rdma_provider_qp *spdk_rdma_qp;
21 : : int rc;
22 : 3724 : struct ibv_qp_init_attr attr = {
23 [ # # # # ]: 3724 : .qp_context = qp_attr->qp_context,
24 [ # # # # ]: 3724 : .send_cq = qp_attr->send_cq,
25 [ # # # # ]: 3724 : .recv_cq = qp_attr->recv_cq,
26 [ # # # # ]: 3724 : .srq = qp_attr->srq,
27 [ # # ]: 0 : .cap = qp_attr->cap,
28 : : .qp_type = IBV_QPT_RC
29 : : };
30 : :
31 : 3724 : spdk_rdma_qp = calloc(1, sizeof(*spdk_rdma_qp));
32 [ - + ]: 3724 : if (!spdk_rdma_qp) {
33 : 0 : SPDK_ERRLOG("qp memory allocation failed\n");
34 : 0 : return NULL;
35 : : }
36 : :
37 [ + + # # : 3724 : if (qp_attr->stats) {
# # ]
38 [ # # # # : 2706 : spdk_rdma_qp->stats = qp_attr->stats;
# # # # ]
39 [ # # # # ]: 2706 : spdk_rdma_qp->shared_stats = true;
40 : 0 : } else {
41 [ # # # # ]: 1018 : spdk_rdma_qp->stats = calloc(1, sizeof(*spdk_rdma_qp->stats));
42 [ - + # # : 1018 : if (!spdk_rdma_qp->stats) {
# # ]
43 : 0 : SPDK_ERRLOG("qp statistics memory allocation failed\n");
44 : 0 : free(spdk_rdma_qp);
45 : 0 : return NULL;
46 : : }
47 : : }
48 : :
49 [ # # # # ]: 3724 : rc = rdma_create_qp(cm_id, qp_attr->pd, &attr);
50 [ - + ]: 3724 : if (rc) {
51 [ # # # # ]: 0 : SPDK_ERRLOG("Failed to create qp, rc %d, errno %s (%d)\n", rc, spdk_strerror(errno), errno);
52 : 0 : free(spdk_rdma_qp);
53 : 0 : return NULL;
54 : : }
55 : :
56 [ # # ]: 3724 : qp_attr->cap = attr.cap;
57 [ # # # # : 3724 : spdk_rdma_qp->qp = cm_id->qp;
# # # # ]
58 [ # # # # ]: 3724 : spdk_rdma_qp->cm_id = cm_id;
59 : :
60 : 3724 : return spdk_rdma_qp;
61 : 0 : }
62 : :
63 : : int
64 : 2456 : spdk_rdma_provider_qp_accept(struct spdk_rdma_provider_qp *spdk_rdma_qp,
65 : : struct rdma_conn_param *conn_param)
66 : : {
67 [ - + # # ]: 2456 : assert(spdk_rdma_qp != NULL);
68 [ - + # # : 2456 : assert(spdk_rdma_qp->cm_id != NULL);
# # # # ]
69 : :
70 [ # # # # ]: 2456 : return rdma_accept(spdk_rdma_qp->cm_id, conn_param);
71 : : }
72 : :
73 : : int
74 : 0 : spdk_rdma_provider_qp_complete_connect(struct spdk_rdma_provider_qp *spdk_rdma_qp)
75 : : {
76 : : /* Nothing to be done for Verbs */
77 : 0 : return 0;
78 : : }
79 : :
80 : : void
81 : 3724 : spdk_rdma_provider_qp_destroy(struct spdk_rdma_provider_qp *spdk_rdma_qp)
82 : : {
83 [ - + # # ]: 3724 : assert(spdk_rdma_qp != NULL);
84 : :
85 [ - + # # : 3724 : if (spdk_rdma_qp->send_wrs.first != NULL) {
# # # # ]
86 : 0 : SPDK_WARNLOG("Destroying qpair with queued Work Requests\n");
87 : 0 : }
88 : :
89 [ + - # # : 3724 : if (spdk_rdma_qp->qp) {
# # ]
90 [ # # # # ]: 3724 : rdma_destroy_qp(spdk_rdma_qp->cm_id);
91 : 0 : }
92 : :
93 [ - + + + : 3724 : if (!spdk_rdma_qp->shared_stats) {
# # # # ]
94 [ # # # # ]: 1018 : free(spdk_rdma_qp->stats);
95 : 0 : }
96 : :
97 : 3724 : free(spdk_rdma_qp);
98 : 3724 : }
99 : :
100 : : int
101 : 3724 : spdk_rdma_provider_qp_disconnect(struct spdk_rdma_provider_qp *spdk_rdma_qp)
102 : : {
103 : 3724 : int rc = 0;
104 : :
105 [ - + # # ]: 3724 : assert(spdk_rdma_qp != NULL);
106 : :
107 [ + - # # : 3724 : if (spdk_rdma_qp->cm_id) {
# # ]
108 [ # # # # ]: 3724 : rc = rdma_disconnect(spdk_rdma_qp->cm_id);
109 [ - + ]: 3724 : if (rc) {
110 [ # # # # : 0 : if (errno == EINVAL && spdk_rdma_qp->qp->context->device->transport_type == IBV_TRANSPORT_IWARP) {
# # # # #
# # # # #
# # # # #
# # # ]
111 : : /* rdma_disconnect may return an error and set errno to EINVAL in case of iWARP.
112 : : * This behaviour is expected since iWARP handles disconnect event other than IB and
113 : : * qpair is already in error state when we call rdma_disconnect */
114 : 0 : return 0;
115 : : }
116 [ # # # # ]: 0 : SPDK_ERRLOG("rdma_disconnect failed, errno %s (%d)\n", spdk_strerror(errno), errno);
117 : 0 : }
118 : 0 : }
119 : :
120 : 3724 : return rc;
121 : 0 : }
122 : :
123 : : bool
124 : 16249434 : spdk_rdma_provider_qp_queue_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp,
125 : : struct ibv_send_wr *first)
126 : : {
127 : : struct ibv_send_wr *last;
128 : :
129 [ - + # # ]: 16249434 : assert(spdk_rdma_qp);
130 [ - + # # ]: 16249434 : assert(first);
131 : :
132 [ # # # # : 16249434 : spdk_rdma_qp->stats->send.num_submitted_wrs++;
# # # # ]
133 : 16249434 : last = first;
134 [ + + # # : 21245654 : while (last->next != NULL) {
# # ]
135 [ # # # # ]: 4996220 : last = last->next;
136 [ # # # # : 4996220 : spdk_rdma_qp->stats->send.num_submitted_wrs++;
# # # # ]
137 : : }
138 : :
139 [ + + # # : 16249434 : if (spdk_rdma_qp->send_wrs.first == NULL) {
# # # # ]
140 [ # # # # : 3565005 : spdk_rdma_qp->send_wrs.first = first;
# # ]
141 [ # # # # : 3565005 : spdk_rdma_qp->send_wrs.last = last;
# # ]
142 : 3565005 : return true;
143 : : } else {
144 [ # # # # : 12684429 : spdk_rdma_qp->send_wrs.last->next = first;
# # # # #
# ]
145 [ # # # # : 12684429 : spdk_rdma_qp->send_wrs.last = last;
# # ]
146 : 12684429 : return false;
147 : : }
148 : 0 : }
149 : :
150 : : int
151 : 115669767 : spdk_rdma_provider_qp_flush_send_wrs(struct spdk_rdma_provider_qp *spdk_rdma_qp,
152 : : struct ibv_send_wr **bad_wr)
153 : : {
154 : : int rc;
155 : :
156 [ - + # # ]: 115669767 : assert(spdk_rdma_qp);
157 [ - + # # ]: 115669767 : assert(bad_wr);
158 : :
159 [ + + # # : 115669767 : if (spdk_unlikely(!spdk_rdma_qp->send_wrs.first)) {
# # # # ]
160 : 112104762 : return 0;
161 : : }
162 : :
163 [ # # # # : 3565005 : rc = ibv_post_send(spdk_rdma_qp->qp, spdk_rdma_qp->send_wrs.first, bad_wr);
# # # # #
# ]
164 : :
165 [ # # # # : 3565005 : spdk_rdma_qp->send_wrs.first = NULL;
# # ]
166 [ # # # # : 3565005 : spdk_rdma_qp->stats->send.doorbell_updates++;
# # # # ]
167 : :
168 : 3565005 : return rc;
169 : 0 : }
|