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