Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
5 : : * Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6 : : */
7 : :
8 : : /*
9 : : * NVMe transport abstraction
10 : : */
11 : :
12 : : #include "nvme_internal.h"
13 : : #include "spdk/queue.h"
14 : :
15 : : #define SPDK_MAX_NUM_OF_TRANSPORTS 16
16 : :
17 : : struct spdk_nvme_transport {
18 : : struct spdk_nvme_transport_ops ops;
19 : : TAILQ_ENTRY(spdk_nvme_transport) link;
20 : : };
21 : :
22 : : TAILQ_HEAD(nvme_transport_list, spdk_nvme_transport) g_spdk_nvme_transports =
23 : : TAILQ_HEAD_INITIALIZER(g_spdk_nvme_transports);
24 : :
25 : : static struct spdk_nvme_transport g_transports[SPDK_MAX_NUM_OF_TRANSPORTS] = {};
26 : : static int g_current_transport_index = 0;
27 : :
28 : : struct spdk_nvme_transport_opts g_spdk_nvme_transport_opts = {
29 : : .rdma_srq_size = 0,
30 : : .rdma_max_cq_size = 0,
31 : : .rdma_cm_event_timeout_ms = 1000,
32 : : .rdma_umr_per_io = false,
33 : : };
34 : :
35 : : const struct spdk_nvme_transport *
36 : 2422 : nvme_get_first_transport(void)
37 : : {
38 : 2422 : return TAILQ_FIRST(&g_spdk_nvme_transports);
39 : : }
40 : :
41 : : const struct spdk_nvme_transport *
42 : 1405 : nvme_get_next_transport(const struct spdk_nvme_transport *transport)
43 : : {
44 [ # # # # : 1405 : return TAILQ_NEXT(transport, link);
# # ]
45 : : }
46 : :
47 : : /*
48 : : * Unfortunately, due to NVMe PCIe multiprocess support, we cannot store the
49 : : * transport object in either the controller struct or the admin qpair. This means
50 : : * that a lot of admin related transport calls will have to call nvme_get_transport
51 : : * in order to know which functions to call.
52 : : * In the I/O path, we have the ability to store the transport struct in the I/O
53 : : * qpairs to avoid taking a performance hit.
54 : : */
55 : : const struct spdk_nvme_transport *
56 : 82988162 : nvme_get_transport(const char *transport_name)
57 : : {
58 : : struct spdk_nvme_transport *registered_transport;
59 : :
60 [ + + - + : 109337861 : TAILQ_FOREACH(registered_transport, &g_spdk_nvme_transports, link) {
- + - + ]
61 [ + + + + : 109329651 : if (strcasecmp(transport_name, registered_transport->ops.name) == 0) {
+ + + - +
+ ]
62 : 82979952 : return registered_transport;
63 : : }
64 : 742095 : }
65 : :
66 : 8210 : return NULL;
67 : 1474466 : }
68 : :
69 : : bool
70 : 0 : spdk_nvme_transport_available(enum spdk_nvme_transport_type trtype)
71 : : {
72 : 0 : return nvme_get_transport(spdk_nvme_transport_id_trtype_str(trtype)) == NULL ? false : true;
73 : : }
74 : :
75 : : bool
76 : 126498 : spdk_nvme_transport_available_by_name(const char *transport_name)
77 : : {
78 : 126498 : return nvme_get_transport(transport_name) == NULL ? false : true;
79 : : }
80 : :
81 : : void
82 : 8207 : spdk_nvme_transport_register(const struct spdk_nvme_transport_ops *ops)
83 : : {
84 : : struct spdk_nvme_transport *new_transport;
85 : :
86 [ + + + - ]: 8207 : if (nvme_get_transport(ops->name)) {
87 [ # # ]: 0 : SPDK_ERRLOG("Double registering NVMe transport %s is prohibited.\n", ops->name);
88 [ # # ]: 0 : assert(false);
89 : : }
90 : :
91 [ + + ]: 8207 : if (g_current_transport_index == SPDK_MAX_NUM_OF_TRANSPORTS) {
92 : 0 : SPDK_ERRLOG("Unable to register new NVMe transport.\n");
93 [ # # ]: 0 : assert(false);
94 : : return;
95 : : }
96 [ + - + - : 8207 : new_transport = &g_transports[g_current_transport_index++];
+ - ]
97 : :
98 [ + - ]: 8207 : new_transport->ops = *ops;
99 [ + - + - : 8207 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, new_transport, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
100 : 236 : }
101 : :
102 : 3297 : struct spdk_nvme_ctrlr *nvme_transport_ctrlr_construct(const struct spdk_nvme_transport_id *trid,
103 : : const struct spdk_nvme_ctrlr_opts *opts,
104 : : void *devhandle)
105 : : {
106 [ + - ]: 3297 : const struct spdk_nvme_transport *transport = nvme_get_transport(trid->trstring);
107 : : struct spdk_nvme_ctrlr *ctrlr;
108 : :
109 [ + + ]: 3297 : if (transport == NULL) {
110 [ # # ]: 0 : SPDK_ERRLOG("Transport %s doesn't exist.", trid->trstring);
111 : 0 : return NULL;
112 : : }
113 : :
114 [ + - + - : 3297 : ctrlr = transport->ops.ctrlr_construct(trid, opts, devhandle);
+ - - + +
- ]
115 : :
116 : 3297 : return ctrlr;
117 : 816 : }
118 : :
119 : : int
120 : 126369 : nvme_transport_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
121 : : bool direct_connect)
122 : : {
123 [ + - + - ]: 126369 : const struct spdk_nvme_transport *transport = nvme_get_transport(probe_ctx->trid.trstring);
124 : :
125 [ + + ]: 126369 : if (transport == NULL) {
126 [ # # # # ]: 0 : SPDK_ERRLOG("Transport %s doesn't exist.", probe_ctx->trid.trstring);
127 : 0 : return -ENOENT;
128 : : }
129 : :
130 [ + - + - : 126369 : return transport->ops.ctrlr_scan(probe_ctx, direct_connect);
+ - - + +
- + - ]
131 : 816 : }
132 : :
133 : : int
134 : 66653 : nvme_transport_ctrlr_scan_attached(struct spdk_nvme_probe_ctx *probe_ctx)
135 : : {
136 [ + - + - ]: 66653 : const struct spdk_nvme_transport *transport = nvme_get_transport(probe_ctx->trid.trstring);
137 : :
138 [ + + ]: 66653 : if (transport == NULL) {
139 [ # # # # ]: 0 : SPDK_ERRLOG("Transport %s doesn't exist.", probe_ctx->trid.trstring);
140 : 0 : return -ENOENT;
141 : : }
142 : :
143 [ + - + - : 66653 : if (transport->ops.ctrlr_scan_attached != NULL) {
+ - + - ]
144 [ + - + - : 66653 : return transport->ops.ctrlr_scan_attached(probe_ctx);
+ - - + +
- ]
145 : : }
146 [ # # # # ]: 0 : SPDK_ERRLOG("Transport %s does not support ctrlr_scan_attached callback\n",
147 : : probe_ctx->trid.trstring);
148 : 0 : return -ENOTSUP;
149 : 3 : }
150 : :
151 : : int
152 : 3276 : nvme_transport_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr)
153 : : {
154 [ + - + - ]: 3276 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
155 : :
156 [ + + # # ]: 3276 : assert(transport != NULL);
157 [ + - + - : 3276 : return transport->ops.ctrlr_destruct(ctrlr);
+ - - + +
- ]
158 : : }
159 : :
160 : : int
161 : 3354 : nvme_transport_ctrlr_enable(struct spdk_nvme_ctrlr *ctrlr)
162 : : {
163 [ + - + - ]: 3354 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
164 : :
165 [ + + # # ]: 3354 : assert(transport != NULL);
166 [ + - + - : 3354 : return transport->ops.ctrlr_enable(ctrlr);
+ - - + +
- ]
167 : : }
168 : :
169 : : int
170 : 1 : nvme_transport_ctrlr_enable_interrupts(struct spdk_nvme_ctrlr *ctrlr)
171 : : {
172 [ # # # # ]: 1 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
173 : :
174 [ - + # # ]: 1 : assert(transport != NULL);
175 [ + - # # : 1 : if (transport->ops.ctrlr_enable_interrupts != NULL) {
# # # # ]
176 [ # # # # : 1 : return transport->ops.ctrlr_enable_interrupts(ctrlr);
# # # # #
# ]
177 : : }
178 : :
179 : 0 : return -ENOTSUP;
180 : 0 : }
181 : :
182 : : int
183 : 3202 : nvme_transport_ctrlr_ready(struct spdk_nvme_ctrlr *ctrlr)
184 : : {
185 [ + - + - ]: 3202 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
186 : :
187 [ + + # # ]: 3202 : assert(transport != NULL);
188 [ + + + - : 3202 : if (transport->ops.ctrlr_ready) {
+ - - + ]
189 [ # # # # : 0 : return transport->ops.ctrlr_ready(ctrlr);
# # # # #
# ]
190 : : }
191 : :
192 : 3202 : return 0;
193 : 816 : }
194 : :
195 : : int
196 : 0 : nvme_transport_ctrlr_set_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t value)
197 : : {
198 [ # # # # ]: 0 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
199 : :
200 [ # # # # ]: 0 : assert(transport != NULL);
201 [ # # # # : 0 : return transport->ops.ctrlr_set_reg_4(ctrlr, offset, value);
# # # # #
# ]
202 : : }
203 : :
204 : : int
205 : 0 : nvme_transport_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value)
206 : : {
207 [ # # # # ]: 0 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
208 : :
209 [ # # # # ]: 0 : assert(transport != NULL);
210 [ # # # # : 0 : return transport->ops.ctrlr_set_reg_8(ctrlr, offset, value);
# # # # #
# ]
211 : : }
212 : :
213 : : int
214 : 37729 : nvme_transport_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value)
215 : : {
216 [ + - + - ]: 37729 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
217 : :
218 [ + + # # ]: 37729 : assert(transport != NULL);
219 [ + - + - : 37729 : return transport->ops.ctrlr_get_reg_4(ctrlr, offset, value);
+ - - + +
- ]
220 : : }
221 : :
222 : : int
223 : 762 : nvme_transport_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value)
224 : : {
225 [ + - + - ]: 762 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
226 : :
227 [ + + # # ]: 762 : assert(transport != NULL);
228 [ + - + - : 762 : return transport->ops.ctrlr_get_reg_8(ctrlr, offset, value);
+ - - + +
- ]
229 : : }
230 : :
231 : : static int
232 : 7452966 : nvme_queue_register_operation_completion(struct spdk_nvme_ctrlr *ctrlr, uint64_t value,
233 : : spdk_nvme_reg_cb cb_fn, void *cb_ctx)
234 : : {
235 : : struct nvme_register_completion *ctx;
236 : :
237 : 7452966 : ctx = spdk_zmalloc(sizeof(*ctx), 0, NULL, SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_SHARE);
238 [ + + ]: 7452966 : if (ctx == NULL) {
239 : 0 : return -ENOMEM;
240 : : }
241 : :
242 [ + - + - : 7452966 : ctx->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
+ - + - ]
243 [ + - + - : 7452966 : ctx->cpl.status.sc = SPDK_NVME_SC_SUCCESS;
+ - + - ]
244 [ + - + - ]: 7452966 : ctx->cb_fn = cb_fn;
245 [ + - + - ]: 7452966 : ctx->cb_ctx = cb_ctx;
246 [ + - + - ]: 7452966 : ctx->value = value;
247 [ + - + - ]: 7452966 : ctx->pid = getpid();
248 : :
249 : 7452966 : nvme_ctrlr_lock(ctrlr);
250 [ + - + - : 7452966 : STAILQ_INSERT_TAIL(&ctrlr->register_operations, ctx, stailq);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
251 : 7452966 : nvme_ctrlr_unlock(ctrlr);
252 : :
253 : 7452966 : return 0;
254 : 412316 : }
255 : :
256 : : int
257 : 7098 : nvme_transport_ctrlr_set_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t value,
258 : : spdk_nvme_reg_cb cb_fn, void *cb_arg)
259 : : {
260 [ + - + - ]: 7098 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
261 : : int rc;
262 : :
263 [ + + # # ]: 7098 : assert(transport != NULL);
264 [ + + + - : 7098 : if (transport->ops.ctrlr_set_reg_4_async == NULL) {
+ - + + ]
265 [ + - + - : 2206 : rc = transport->ops.ctrlr_set_reg_4(ctrlr, offset, value);
+ - - + +
- ]
266 [ - + ]: 2206 : if (rc != 0) {
267 : 0 : return rc;
268 : : }
269 : :
270 : 2206 : return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
271 : : }
272 : :
273 [ + - + - : 4892 : return transport->ops.ctrlr_set_reg_4_async(ctrlr, offset, value, cb_fn, cb_arg);
+ - - + +
- ]
274 : 1632 : }
275 : :
276 : : int
277 : 0 : nvme_transport_ctrlr_set_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value,
278 : : spdk_nvme_reg_cb cb_fn, void *cb_arg)
279 : :
280 : : {
281 [ # # # # ]: 0 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
282 : : int rc;
283 : :
284 [ # # # # ]: 0 : assert(transport != NULL);
285 [ # # # # : 0 : if (transport->ops.ctrlr_set_reg_8_async == NULL) {
# # # # ]
286 [ # # # # : 0 : rc = transport->ops.ctrlr_set_reg_8(ctrlr, offset, value);
# # # # #
# ]
287 [ # # ]: 0 : if (rc != 0) {
288 : 0 : return rc;
289 : : }
290 : :
291 : 0 : return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
292 : : }
293 : :
294 [ # # # # : 0 : return transport->ops.ctrlr_set_reg_8_async(ctrlr, offset, value, cb_fn, cb_arg);
# # # # #
# ]
295 : 0 : }
296 : :
297 : : int
298 : 7544389 : nvme_transport_ctrlr_get_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
299 : : spdk_nvme_reg_cb cb_fn, void *cb_arg)
300 : : {
301 [ + - + - ]: 7544389 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
302 : 1547007 : uint32_t value;
303 : : int rc;
304 : :
305 [ + + # # ]: 7544389 : assert(transport != NULL);
306 [ + + + - : 7544389 : if (transport->ops.ctrlr_get_reg_4_async == NULL) {
+ - + + ]
307 [ + - + - : 7449912 : rc = transport->ops.ctrlr_get_reg_4(ctrlr, offset, &value);
+ - - + +
- ]
308 [ - + ]: 7449912 : if (rc != 0) {
309 : 0 : return rc;
310 : : }
311 : :
312 : 7449912 : return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
313 : : }
314 : :
315 [ + - + - : 94477 : return transport->ops.ctrlr_get_reg_4_async(ctrlr, offset, cb_fn, cb_arg);
+ - - + +
- ]
316 : 417131 : }
317 : :
318 : : int
319 : 3354 : nvme_transport_ctrlr_get_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
320 : : spdk_nvme_reg_cb cb_fn, void *cb_arg)
321 : : {
322 [ + - + - ]: 3354 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
323 : 457 : uint64_t value;
324 : : int rc;
325 : :
326 [ + + # # ]: 3354 : assert(transport != NULL);
327 [ + + + - : 3354 : if (transport->ops.ctrlr_get_reg_8_async == NULL) {
+ - + + ]
328 [ + - + - : 848 : rc = transport->ops.ctrlr_get_reg_8(ctrlr, offset, &value);
+ - - + +
- ]
329 [ - + ]: 848 : if (rc != 0) {
330 : 0 : return rc;
331 : : }
332 : :
333 : 848 : return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
334 : : }
335 : :
336 [ + - + - : 2506 : return transport->ops.ctrlr_get_reg_8_async(ctrlr, offset, cb_fn, cb_arg);
+ - - + +
- ]
337 : 816 : }
338 : :
339 : : uint32_t
340 : 3354 : nvme_transport_ctrlr_get_max_xfer_size(struct spdk_nvme_ctrlr *ctrlr)
341 : : {
342 [ + - + - ]: 3354 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
343 : :
344 [ + + # # ]: 3354 : assert(transport != NULL);
345 [ + - + - : 3354 : return transport->ops.ctrlr_get_max_xfer_size(ctrlr);
+ - - + +
- ]
346 : : }
347 : :
348 : : uint16_t
349 : 3211 : nvme_transport_ctrlr_get_max_sges(struct spdk_nvme_ctrlr *ctrlr)
350 : : {
351 [ + - + - ]: 3211 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
352 : :
353 [ + + # # ]: 3211 : assert(transport != NULL);
354 [ + - + - : 3211 : return transport->ops.ctrlr_get_max_sges(ctrlr);
+ - - + +
- ]
355 : : }
356 : :
357 : : int
358 : 0 : nvme_transport_ctrlr_reserve_cmb(struct spdk_nvme_ctrlr *ctrlr)
359 : : {
360 [ # # # # ]: 0 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
361 : :
362 [ # # # # ]: 0 : assert(transport != NULL);
363 [ # # # # : 0 : if (transport->ops.ctrlr_reserve_cmb != NULL) {
# # # # ]
364 [ # # # # : 0 : return transport->ops.ctrlr_reserve_cmb(ctrlr);
# # # # #
# ]
365 : : }
366 : :
367 : 0 : return -ENOTSUP;
368 : 0 : }
369 : :
370 : : void *
371 : 17 : nvme_transport_ctrlr_map_cmb(struct spdk_nvme_ctrlr *ctrlr, size_t *size)
372 : : {
373 [ # # # # ]: 17 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
374 : :
375 [ - + # # ]: 17 : assert(transport != NULL);
376 [ + + # # : 17 : if (transport->ops.ctrlr_map_cmb != NULL) {
# # # # ]
377 [ # # # # : 15 : return transport->ops.ctrlr_map_cmb(ctrlr, size);
# # # # #
# ]
378 : : }
379 : :
380 : 2 : return NULL;
381 : 0 : }
382 : :
383 : : int
384 : 2 : nvme_transport_ctrlr_unmap_cmb(struct spdk_nvme_ctrlr *ctrlr)
385 : : {
386 [ # # # # ]: 2 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
387 : :
388 [ - + # # ]: 2 : assert(transport != NULL);
389 [ + - # # : 2 : if (transport->ops.ctrlr_unmap_cmb != NULL) {
# # # # ]
390 [ # # # # : 2 : return transport->ops.ctrlr_unmap_cmb(ctrlr);
# # # # #
# ]
391 : : }
392 : :
393 : 0 : return 0;
394 : 0 : }
395 : :
396 : : int
397 : 44 : nvme_transport_ctrlr_enable_pmr(struct spdk_nvme_ctrlr *ctrlr)
398 : : {
399 [ # # # # ]: 44 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
400 : :
401 [ - + # # ]: 44 : assert(transport != NULL);
402 [ + - # # : 44 : if (transport->ops.ctrlr_enable_pmr != NULL) {
# # # # ]
403 [ # # # # : 44 : return transport->ops.ctrlr_enable_pmr(ctrlr);
# # # # #
# ]
404 : : }
405 : :
406 : 0 : return -ENOSYS;
407 : 0 : }
408 : :
409 : : int
410 : 44 : nvme_transport_ctrlr_disable_pmr(struct spdk_nvme_ctrlr *ctrlr)
411 : : {
412 [ # # # # ]: 44 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
413 : :
414 [ - + # # ]: 44 : assert(transport != NULL);
415 [ + - # # : 44 : if (transport->ops.ctrlr_disable_pmr != NULL) {
# # # # ]
416 [ # # # # : 44 : return transport->ops.ctrlr_disable_pmr(ctrlr);
# # # # #
# ]
417 : : }
418 : :
419 : 0 : return -ENOSYS;
420 : 0 : }
421 : :
422 : : void *
423 : 44 : nvme_transport_ctrlr_map_pmr(struct spdk_nvme_ctrlr *ctrlr, size_t *size)
424 : : {
425 [ # # # # ]: 44 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
426 : :
427 [ - + # # ]: 44 : assert(transport != NULL);
428 [ + - # # : 44 : if (transport->ops.ctrlr_map_pmr != NULL) {
# # # # ]
429 [ # # # # : 44 : return transport->ops.ctrlr_map_pmr(ctrlr, size);
# # # # #
# ]
430 : : }
431 : :
432 : 0 : return NULL;
433 : 0 : }
434 : :
435 : : int
436 : 44 : nvme_transport_ctrlr_unmap_pmr(struct spdk_nvme_ctrlr *ctrlr)
437 : : {
438 [ # # # # ]: 44 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
439 : :
440 [ - + # # ]: 44 : assert(transport != NULL);
441 [ + - # # : 44 : if (transport->ops.ctrlr_unmap_pmr != NULL) {
# # # # ]
442 [ # # # # : 44 : return transport->ops.ctrlr_unmap_pmr(ctrlr);
# # # # #
# ]
443 : : }
444 : :
445 : 0 : return -ENOSYS;
446 : 0 : }
447 : :
448 : : struct spdk_nvme_qpair *
449 : 5707 : nvme_transport_ctrlr_create_io_qpair(struct spdk_nvme_ctrlr *ctrlr, uint16_t qid,
450 : : const struct spdk_nvme_io_qpair_opts *opts)
451 : : {
452 : : struct spdk_nvme_qpair *qpair;
453 [ + - + - ]: 5707 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
454 : :
455 [ + + # # ]: 5707 : assert(transport != NULL);
456 [ + - + - : 5707 : qpair = transport->ops.ctrlr_create_io_qpair(ctrlr, qid, opts);
+ - - + +
- ]
457 [ + - + + ]: 5707 : if (qpair != NULL && !nvme_qpair_is_admin_queue(qpair)) {
458 [ + - + - ]: 5707 : qpair->transport = transport;
459 : 816 : }
460 : :
461 : 5707 : return qpair;
462 : : }
463 : :
464 : : void
465 : 5707 : nvme_transport_ctrlr_delete_io_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair)
466 : : {
467 [ + - + - ]: 5707 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
468 : : int rc;
469 : :
470 [ + + # # ]: 5707 : assert(transport != NULL);
471 : :
472 : : /* Do not rely on qpair->transport. For multi-process cases, a foreign process may delete
473 : : * the IO qpair, in which case the transport object would be invalid (each process has their
474 : : * own unique transport objects since they contain function pointers). So we look up the
475 : : * transport object in the delete_io_qpair case.
476 : : */
477 [ + - + - : 5707 : rc = transport->ops.ctrlr_delete_io_qpair(ctrlr, qpair);
+ - - + +
- ]
478 [ + + ]: 5707 : if (rc != 0) {
479 [ # # # # ]: 0 : SPDK_ERRLOG("transport %s returned non-zero for ctrlr_delete_io_qpair op\n",
480 : : transport->ops.name);
481 [ # # ]: 0 : assert(false);
482 : : }
483 : 5707 : }
484 : :
485 : : static void
486 : 14116 : nvme_transport_connect_qpair_fail(struct spdk_nvme_qpair *qpair, void *unused)
487 : : {
488 [ # # # # ]: 14116 : struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
489 : :
490 : : /* If the qpair was unable to reconnect, restore the original failure reason */
491 [ # # # # ]: 14116 : qpair->transport_failure_reason = qpair->last_transport_failure_reason;
492 : 14116 : nvme_transport_ctrlr_disconnect_qpair(ctrlr, qpair);
493 : 14116 : }
494 : :
495 : : int
496 : 23295 : nvme_transport_ctrlr_connect_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair)
497 : : {
498 [ + - + - ]: 23295 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
499 : : int rc;
500 : :
501 [ + + # # ]: 23295 : assert(transport != NULL);
502 [ + + + + : 23295 : if (!nvme_qpair_is_admin_queue(qpair) && qpair->transport == NULL) {
+ - + - ]
503 [ # # # # ]: 0 : qpair->transport = transport;
504 : 0 : }
505 : :
506 [ + - + - ]: 23295 : qpair->last_transport_failure_reason = qpair->transport_failure_reason;
507 [ + - ]: 23295 : qpair->transport_failure_reason = SPDK_NVME_QPAIR_FAILURE_NONE;
508 : :
509 : 23295 : nvme_qpair_set_state(qpair, NVME_QPAIR_CONNECTING);
510 [ + - + - : 23295 : rc = transport->ops.ctrlr_connect_qpair(ctrlr, qpair);
+ - - + +
- ]
511 [ + + ]: 23295 : if (rc != 0) {
512 : 13283 : goto err;
513 : : }
514 : :
515 [ + + + - : 10012 : if (qpair->poll_group) {
+ + ]
516 : 2719 : rc = nvme_poll_group_connect_qpair(qpair);
517 [ - + ]: 2719 : if (rc) {
518 : 0 : goto err;
519 : : }
520 : 1 : }
521 : :
522 [ + + + + ]: 10012 : if (!qpair->async) {
523 : : /* Busy wait until the qpair exits the connecting state */
524 [ + + ]: 13714938 : while (nvme_qpair_get_state(qpair) == NVME_QPAIR_CONNECTING) {
525 [ + + + + : 13711068 : if (qpair->poll_group && spdk_nvme_ctrlr_is_fabrics(ctrlr)) {
- + # # ]
526 : 0 : rc = spdk_nvme_poll_group_process_completions(
527 [ # # # # : 0 : qpair->poll_group->group, 0,
# # # # ]
528 : : nvme_transport_connect_qpair_fail);
529 : 0 : } else {
530 : 13711068 : rc = spdk_nvme_qpair_process_completions(qpair, 0);
531 : : }
532 : :
533 [ + + ]: 13711068 : if (rc < 0) {
534 : 833 : goto err;
535 : : }
536 : : }
537 : 824 : }
538 : :
539 : 9179 : return 0;
540 : 14116 : err:
541 : 14116 : nvme_transport_connect_qpair_fail(qpair, NULL);
542 [ + + ]: 14116 : if (nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTING) {
543 [ - + # # : 338 : assert(qpair->async == true);
# # ]
544 : : /* Let the caller to poll the qpair until it is actually disconnected. */
545 : 338 : return 0;
546 : : }
547 : :
548 : 13778 : return rc;
549 : 1632 : }
550 : :
551 : : void
552 : 60123 : nvme_transport_ctrlr_disconnect_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair)
553 : : {
554 [ + - + - ]: 60123 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
555 : :
556 [ + + + + ]: 86162 : if (nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTING ||
557 : 27672 : nvme_qpair_get_state(qpair) == NVME_QPAIR_DISCONNECTED) {
558 : 36789 : return;
559 : : }
560 : :
561 : 23334 : nvme_qpair_set_state(qpair, NVME_QPAIR_DISCONNECTING);
562 [ + + # # ]: 23334 : assert(transport != NULL);
563 : :
564 [ + + + - : 23334 : if (qpair->poll_group && (qpair->active_proc == nvme_ctrlr_get_current_process(ctrlr))) {
+ + + - +
- - + ]
565 : 2719 : nvme_poll_group_disconnect_qpair(qpair);
566 : 1 : }
567 : :
568 [ + - + - : 23334 : transport->ops.ctrlr_disconnect_qpair(ctrlr, qpair);
+ - - + +
- ]
569 : 1633 : }
570 : :
571 : : int
572 : 5 : nvme_transport_qpair_get_fd(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
573 : : struct spdk_event_handler_opts *opts)
574 : : {
575 [ # # # # ]: 5 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
576 : :
577 [ - + # # ]: 5 : assert(transport != NULL);
578 [ + - # # : 5 : if (transport->ops.qpair_get_fd != NULL) {
# # # # ]
579 [ # # # # : 5 : return transport->ops.qpair_get_fd(qpair, opts);
# # # # #
# ]
580 : : }
581 : :
582 : 0 : return -ENOTSUP;
583 : 0 : }
584 : :
585 : : void
586 : 21146 : nvme_transport_ctrlr_disconnect_qpair_done(struct spdk_nvme_qpair *qpair)
587 : : {
588 [ + + + - : 22914 : if (qpair->active_proc == nvme_ctrlr_get_current_process(qpair->ctrlr) ||
+ - + - +
+ + - ]
589 : 1777 : nvme_qpair_is_admin_queue(qpair)) {
590 : 21146 : nvme_qpair_abort_all_queued_reqs(qpair);
591 : 825 : }
592 : 21146 : nvme_qpair_set_state(qpair, NVME_QPAIR_DISCONNECTED);
593 : :
594 : : /* In interrupt mode qpairs that are added to poll group need an event for the
595 : : * disconnected qpairs handling to kick in.
596 : : */
597 [ + + + - : 21146 : if (qpair->poll_group) {
+ + ]
598 [ + - + - : 2600 : nvme_poll_group_write_disconnect_qpair_fd(qpair->poll_group->group);
+ - + - ]
599 : 1 : }
600 : 21146 : }
601 : :
602 : : int
603 : 10734 : nvme_transport_ctrlr_get_memory_domains(const struct spdk_nvme_ctrlr *ctrlr,
604 : : struct spdk_memory_domain **domains, int array_size)
605 : : {
606 [ + - + - ]: 10734 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
607 : :
608 [ + + # # ]: 10734 : assert(transport != NULL);
609 [ + + + - : 10734 : if (transport->ops.ctrlr_get_memory_domains) {
+ - - + ]
610 [ # # # # : 4275 : return transport->ops.ctrlr_get_memory_domains(ctrlr, domains, array_size);
# # # # #
# ]
611 : : }
612 : :
613 : 6459 : return 0;
614 : 4 : }
615 : :
616 : : void
617 : 846 : nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair *qpair)
618 : : {
619 : : const struct spdk_nvme_transport *transport;
620 : :
621 [ + + ]: 846 : if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
622 [ # # # # : 53 : qpair->transport->ops.qpair_abort_reqs(qpair, qpair->abort_dnr);
# # # # #
# # # # #
# # ]
623 : 0 : } else {
624 [ + - + - : 793 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
+ - + - ]
625 [ + + # # ]: 793 : assert(transport != NULL);
626 [ + - + - : 793 : transport->ops.qpair_abort_reqs(qpair, qpair->abort_dnr);
+ - - + +
- + - ]
627 : : }
628 : 846 : }
629 : :
630 : : int
631 : 3354 : nvme_transport_qpair_reset(struct spdk_nvme_qpair *qpair)
632 : : {
633 : : const struct spdk_nvme_transport *transport;
634 : :
635 [ - + ]: 3354 : if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
636 [ # # # # : 0 : return qpair->transport->ops.qpair_reset(qpair);
# # # # #
# # # #
# ]
637 : : }
638 : :
639 [ + - + - : 3354 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
+ - + - ]
640 [ + + # # ]: 3354 : assert(transport != NULL);
641 [ + - + - : 3354 : return transport->ops.qpair_reset(qpair);
+ - - + +
- ]
642 : 816 : }
643 : :
644 : : int
645 : 76934970 : nvme_transport_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *req)
646 : : {
647 : : const struct spdk_nvme_transport *transport;
648 : :
649 [ + + ]: 76934970 : if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
650 [ + - + - : 74915656 : return qpair->transport->ops.qpair_submit_request(qpair, req);
+ - + - +
- - + +
- ]
651 : : }
652 : :
653 [ + - + - : 2019314 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
+ - + - ]
654 [ + + # # ]: 2019314 : assert(transport != NULL);
655 [ + - + - : 2019314 : return transport->ops.qpair_submit_request(qpair, req);
+ - - + +
- ]
656 : 160327 : }
657 : :
658 : : int32_t
659 : 1313379562 : nvme_transport_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
660 : : {
661 : : const struct spdk_nvme_transport *transport;
662 : :
663 [ + + ]: 1313379562 : if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
664 [ + - + - : 1240465218 : return qpair->transport->ops.qpair_process_completions(qpair, max_completions);
+ - + - +
- - + +
- ]
665 : : }
666 : :
667 [ + - + - : 72914344 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
+ - + - ]
668 [ + + # # ]: 72914344 : assert(transport != NULL);
669 [ + - + - : 72914344 : return transport->ops.qpair_process_completions(qpair, max_completions);
+ - - + +
- ]
670 : 1751687 : }
671 : :
672 : : int
673 : 597636 : nvme_transport_qpair_iterate_requests(struct spdk_nvme_qpair *qpair,
674 : : int (*iter_fn)(struct nvme_request *req, void *arg),
675 : : void *arg)
676 : : {
677 : : const struct spdk_nvme_transport *transport;
678 : :
679 [ + - ]: 597636 : if (spdk_likely(!nvme_qpair_is_admin_queue(qpair))) {
680 [ # # # # : 597636 : return qpair->transport->ops.qpair_iterate_requests(qpair, iter_fn, arg);
# # # # #
# # # #
# ]
681 : : }
682 : :
683 [ # # # # : 0 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
# # # # ]
684 [ # # # # ]: 0 : assert(transport != NULL);
685 [ # # # # : 0 : return transport->ops.qpair_iterate_requests(qpair, iter_fn, arg);
# # # # #
# ]
686 : 0 : }
687 : :
688 : : int
689 : 24 : nvme_transport_qpair_authenticate(struct spdk_nvme_qpair *qpair)
690 : : {
691 : : const struct spdk_nvme_transport *transport;
692 : :
693 [ # # # # : 24 : transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
# # # # ]
694 [ - + # # : 24 : if (transport->ops.qpair_authenticate == NULL) {
# # # # ]
695 : 0 : return -ENOTSUP;
696 : : }
697 : :
698 [ # # # # : 24 : return transport->ops.qpair_authenticate(qpair);
# # # # #
# ]
699 : 0 : }
700 : :
701 : : void
702 : 3797 : nvme_transport_admin_qpair_abort_aers(struct spdk_nvme_qpair *qpair)
703 : : {
704 [ + - + - : 3797 : const struct spdk_nvme_transport *transport = nvme_get_transport(qpair->ctrlr->trid.trstring);
+ - + - ]
705 : :
706 [ + + # # ]: 3797 : assert(transport != NULL);
707 [ + - + - : 3797 : transport->ops.admin_qpair_abort_aers(qpair);
+ - - + +
- ]
708 : 3797 : }
709 : :
710 : : struct spdk_nvme_transport_poll_group *
711 : 2422 : nvme_transport_poll_group_create(const struct spdk_nvme_transport *transport)
712 : : {
713 : 2422 : struct spdk_nvme_transport_poll_group *group = NULL;
714 : :
715 [ + - + - : 2422 : group = transport->ops.poll_group_create();
+ - - + +
- ]
716 [ + + ]: 2422 : if (group) {
717 [ + - + - ]: 2422 : group->transport = transport;
718 [ + - + - : 2422 : STAILQ_INIT(&group->connected_qpairs);
+ - + - +
- + - + -
+ - ]
719 [ + - + - : 2422 : STAILQ_INIT(&group->disconnected_qpairs);
+ - + - +
- + - + -
+ - ]
720 [ + - + - ]: 2422 : group->num_connected_qpairs = 0;
721 : 1 : }
722 : :
723 : 2422 : return group;
724 : : }
725 : :
726 : : struct spdk_nvme_transport_poll_group *
727 : 0 : nvme_transport_qpair_get_optimal_poll_group(const struct spdk_nvme_transport *transport,
728 : : struct spdk_nvme_qpair *qpair)
729 : : {
730 [ # # # # : 0 : if (transport->ops.qpair_get_optimal_poll_group) {
# # # # ]
731 [ # # # # : 0 : return transport->ops.qpair_get_optimal_poll_group(qpair);
# # # # #
# ]
732 : : } else {
733 : 0 : return NULL;
734 : : }
735 : 0 : }
736 : :
737 : : int
738 : 2722 : nvme_transport_poll_group_add(struct spdk_nvme_transport_poll_group *tgroup,
739 : : struct spdk_nvme_qpair *qpair)
740 : : {
741 : : int rc;
742 : :
743 [ + - + - : 2722 : rc = tgroup->transport->ops.poll_group_add(tgroup, qpair);
+ - + - +
- - + +
- ]
744 [ + + ]: 2722 : if (rc == 0) {
745 [ + - + - ]: 2722 : qpair->poll_group = tgroup;
746 [ + + # # ]: 2722 : assert(nvme_qpair_get_state(qpair) < NVME_QPAIR_CONNECTED);
747 [ + - + - : 2722 : qpair->poll_group_tailq_head = &tgroup->disconnected_qpairs;
+ - ]
748 [ + - + - : 2722 : STAILQ_INSERT_TAIL(&tgroup->disconnected_qpairs, qpair, poll_group_stailq);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
749 : 1 : }
750 : :
751 : 2722 : return rc;
752 : : }
753 : :
754 : : int
755 : 2728 : nvme_transport_poll_group_remove(struct spdk_nvme_transport_poll_group *tgroup,
756 : : struct spdk_nvme_qpair *qpair)
757 : : {
758 : : int rc __attribute__((unused));
759 : :
760 [ + + + - : 2728 : if (qpair->poll_group_tailq_head == &tgroup->connected_qpairs) {
+ - + - ]
761 : 3 : return -EINVAL;
762 [ + + + - : 2725 : } else if (qpair->poll_group_tailq_head != &tgroup->disconnected_qpairs) {
+ - - + ]
763 : 3 : return -ENOENT;
764 : : }
765 : :
766 [ + - + - : 2722 : rc = tgroup->transport->ops.poll_group_remove(tgroup, qpair);
+ - + - +
- - + +
- ]
767 [ + + # # ]: 2722 : assert(rc == 0);
768 : :
769 [ + + + + : 2741 : STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
+ + + + +
- + - + -
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
770 : :
771 [ + - + - ]: 2722 : qpair->poll_group = NULL;
772 [ + - + - ]: 2722 : qpair->poll_group_tailq_head = NULL;
773 : :
774 : 2722 : return 0;
775 : 1 : }
776 : :
777 : : int64_t
778 : 1490968713 : nvme_transport_poll_group_process_completions(struct spdk_nvme_transport_poll_group *tgroup,
779 : : uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
780 : : {
781 [ + - + - : 1490968713 : return tgroup->transport->ops.poll_group_process_completions(tgroup, completions_per_qpair,
+ - + - +
- - + +
- ]
782 : 77 : disconnected_qpair_cb);
783 : : }
784 : :
785 : : void
786 : 0 : nvme_transport_poll_group_check_disconnected_qpairs(struct spdk_nvme_transport_poll_group *tgroup,
787 : : spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
788 : : {
789 [ # # # # : 0 : return tgroup->transport->ops.poll_group_check_disconnected_qpairs(tgroup,
# # # # #
# # # #
# ]
790 : 0 : disconnected_qpair_cb);
791 : : }
792 : :
793 : : int
794 : 2422 : nvme_transport_poll_group_destroy(struct spdk_nvme_transport_poll_group *tgroup)
795 : : {
796 [ + - + - : 2422 : return tgroup->transport->ops.poll_group_destroy(tgroup);
+ - + - +
- - + +
- ]
797 : : }
798 : :
799 : : int
800 : 2728 : nvme_transport_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
801 : : {
802 : : struct spdk_nvme_transport_poll_group *tgroup;
803 : : int rc __attribute__((unused));
804 : :
805 [ + - + - ]: 2728 : tgroup = qpair->poll_group;
806 : :
807 [ + + + - : 2728 : if (qpair->poll_group_tailq_head == &tgroup->disconnected_qpairs) {
+ - + - ]
808 : 3 : return 0;
809 : : }
810 : :
811 [ + + + - : 2725 : if (qpair->poll_group_tailq_head == &tgroup->connected_qpairs) {
+ - - + ]
812 [ + - + - : 2722 : rc = tgroup->transport->ops.poll_group_disconnect_qpair(qpair);
+ - + - +
- - + +
- ]
813 [ + + # # ]: 2722 : assert(rc == 0);
814 : :
815 [ + - + - : 2722 : qpair->poll_group_tailq_head = &tgroup->disconnected_qpairs;
+ - ]
816 [ + + + + : 2757 : STAILQ_REMOVE(&tgroup->connected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
+ + + + +
- + - + -
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
817 [ + + + - : 2722 : assert(tgroup->num_connected_qpairs > 0);
+ - # # ]
818 [ + - ]: 2722 : tgroup->num_connected_qpairs--;
819 [ + - + - : 2722 : STAILQ_INSERT_TAIL(&tgroup->disconnected_qpairs, qpair, poll_group_stailq);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
820 : :
821 : 2722 : return 0;
822 : : }
823 : :
824 : 3 : return -EINVAL;
825 : 1 : }
826 : :
827 : : int
828 : 3792 : nvme_transport_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
829 : : {
830 : : struct spdk_nvme_transport_poll_group *tgroup;
831 : : int rc;
832 : :
833 [ + - + - ]: 3792 : tgroup = qpair->poll_group;
834 : :
835 [ + + + - : 3792 : if (qpair->poll_group_tailq_head == &tgroup->connected_qpairs) {
+ - + - ]
836 : 1067 : return 0;
837 : : }
838 : :
839 [ + + + - : 2725 : if (qpair->poll_group_tailq_head == &tgroup->disconnected_qpairs) {
+ - - + ]
840 [ + - + - : 2722 : rc = tgroup->transport->ops.poll_group_connect_qpair(qpair);
+ - + - +
- - + +
- ]
841 [ + + ]: 2722 : if (rc == 0) {
842 [ + - + - : 2722 : qpair->poll_group_tailq_head = &tgroup->connected_qpairs;
+ - ]
843 [ + + + - : 2722 : STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
+ + + + +
- + - + -
+ - + - +
- + - + -
+ - - + -
+ - + - +
- + - + #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
844 [ + - + - : 2722 : STAILQ_INSERT_TAIL(&tgroup->connected_qpairs, qpair, poll_group_stailq);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
845 [ + - ]: 2722 : tgroup->num_connected_qpairs++;
846 : 1 : }
847 : :
848 [ + + ]: 2722 : return rc == -EINPROGRESS ? 0 : rc;
849 : : }
850 : :
851 : :
852 : 3 : return -EINVAL;
853 : 1 : }
854 : :
855 : : int
856 : 8 : nvme_transport_poll_group_get_stats(struct spdk_nvme_transport_poll_group *tgroup,
857 : : struct spdk_nvme_transport_poll_group_stat **stats)
858 : : {
859 [ + - # # : 8 : if (tgroup->transport->ops.poll_group_get_stats) {
# # # # #
# # # ]
860 [ # # # # : 8 : return tgroup->transport->ops.poll_group_get_stats(tgroup, stats);
# # # # #
# # # #
# ]
861 : : }
862 : 0 : return -ENOTSUP;
863 : 0 : }
864 : :
865 : : void
866 : 8 : nvme_transport_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgroup,
867 : : struct spdk_nvme_transport_poll_group_stat *stats)
868 : : {
869 [ + - # # : 8 : if (tgroup->transport->ops.poll_group_free_stats) {
# # # # #
# # # ]
870 [ # # # # : 8 : tgroup->transport->ops.poll_group_free_stats(tgroup, stats);
# # # # #
# # # #
# ]
871 : 0 : }
872 : 8 : }
873 : :
874 : : spdk_nvme_transport_type_t
875 : 8 : nvme_transport_get_trtype(const struct spdk_nvme_transport *transport)
876 : : {
877 [ # # # # : 8 : return transport->ops.type;
# # ]
878 : : }
879 : :
880 : : void
881 : 1022 : spdk_nvme_transport_get_opts(struct spdk_nvme_transport_opts *opts, size_t opts_size)
882 : : {
883 [ + + ]: 1022 : if (opts == NULL) {
884 : 0 : SPDK_ERRLOG("opts should not be NULL.\n");
885 : 0 : return;
886 : : }
887 : :
888 [ + + ]: 1022 : if (opts_size == 0) {
889 : 0 : SPDK_ERRLOG("opts_size should not be zero.\n");
890 : 0 : return;
891 : : }
892 : :
893 [ + - + - ]: 1022 : opts->opts_size = opts_size;
894 : :
895 : : #define SET_FIELD(field) \
896 : : if (offsetof(struct spdk_nvme_transport_opts, field) + sizeof(opts->field) <= opts_size) { \
897 : : opts->field = g_spdk_nvme_transport_opts.field; \
898 : : } \
899 : :
900 [ + + + - : 1022 : SET_FIELD(rdma_srq_size);
+ - ]
901 [ + + + - : 1022 : SET_FIELD(rdma_max_cq_size);
+ - + - ]
902 [ + + + - : 1022 : SET_FIELD(rdma_cm_event_timeout_ms);
+ - + - ]
903 [ + + + + : 1022 : SET_FIELD(rdma_umr_per_io);
+ - + - +
- ]
904 : :
905 : : /* Do not remove this statement, you should always update this statement when you adding a new field,
906 : : * and do not forget to add the SET_FIELD statement for your added field. */
907 : : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_transport_opts) == 24, "Incorrect size");
908 : :
909 : : #undef SET_FIELD
910 : 27 : }
911 : :
912 : : int
913 : 1022 : spdk_nvme_transport_set_opts(const struct spdk_nvme_transport_opts *opts, size_t opts_size)
914 : : {
915 [ + + ]: 1022 : if (opts == NULL) {
916 : 0 : SPDK_ERRLOG("opts should not be NULL.\n");
917 : 0 : return -EINVAL;
918 : : }
919 : :
920 [ + + ]: 1022 : if (opts_size == 0) {
921 : 0 : SPDK_ERRLOG("opts_size should not be zero.\n");
922 : 0 : return -EINVAL;
923 : : }
924 : :
925 : : #define SET_FIELD(field) \
926 : : if (offsetof(struct spdk_nvme_transport_opts, field) + sizeof(opts->field) <= opts->opts_size) { \
927 : : g_spdk_nvme_transport_opts.field = opts->field; \
928 : : } \
929 : :
930 [ + - + - : 1022 : SET_FIELD(rdma_srq_size);
- + + - +
- ]
931 [ + - + - : 1022 : SET_FIELD(rdma_max_cq_size);
- + + - +
- + - ]
932 [ + - + - : 1022 : SET_FIELD(rdma_cm_event_timeout_ms);
- + + - +
- + - ]
933 [ + - + + : 1022 : SET_FIELD(rdma_umr_per_io);
- + + - +
- + - +
- ]
934 : :
935 [ + - + - : 1022 : g_spdk_nvme_transport_opts.opts_size = opts->opts_size;
+ - ]
936 : :
937 : : #undef SET_FIELD
938 : :
939 : 1022 : return 0;
940 : 27 : }
941 : :
942 : : volatile struct spdk_nvme_registers *
943 : 10 : spdk_nvme_ctrlr_get_registers(struct spdk_nvme_ctrlr *ctrlr)
944 : : {
945 [ # # # # ]: 10 : const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
946 : :
947 [ - + ]: 10 : if (transport == NULL) {
948 : : /* Transport does not exist. */
949 : 0 : return NULL;
950 : : }
951 : :
952 [ + - # # : 10 : if (transport->ops.ctrlr_get_registers) {
# # # # ]
953 [ # # # # : 10 : return transport->ops.ctrlr_get_registers(ctrlr);
# # # # #
# ]
954 : : }
955 : :
956 : 0 : return NULL;
957 : 0 : }
|