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