Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2020 Intel Corporation. All rights reserved.
3 : * Copyright (c) 2019, 2021 Mellanox Technologies LTD. All rights reserved.
4 : */
5 :
6 : /** \file
7 : * NVMe-oF Target transport plugin API
8 : */
9 :
10 : #ifndef SPDK_NVMF_TRANSPORT_H_
11 : #define SPDK_NVMF_TRANSPORT_H_
12 :
13 : #include "spdk/bdev.h"
14 : #include "spdk/thread.h"
15 : #include "spdk/nvme_spec.h"
16 : #include "spdk/nvmf.h"
17 : #include "spdk/nvmf_cmd.h"
18 : #include "spdk/nvmf_spec.h"
19 : #include "spdk/memory.h"
20 :
21 : #define SPDK_NVMF_MAX_SGL_ENTRIES 16
22 :
23 : /* The maximum number of buffers per request */
24 : #define NVMF_REQ_MAX_BUFFERS (SPDK_NVMF_MAX_SGL_ENTRIES * 2 + 1)
25 :
26 : /* Maximum pending AERs that can be migrated */
27 : #define SPDK_NVMF_MIGR_MAX_PENDING_AERS 256
28 :
29 : #define SPDK_NVMF_MAX_ASYNC_EVENTS 4
30 :
31 : /* Some backends require 4K aligned buffers. The iobuf library gives us that
32 : * naturally, but there are buffers allocated other ways that need to use this.
33 : */
34 : #define NVMF_DATA_BUFFER_ALIGNMENT VALUE_4KB
35 : #define NVMF_DATA_BUFFER_MASK (NVMF_DATA_BUFFER_ALIGNMENT - 1LL)
36 :
37 : #define SPDK_NVMF_DEFAULT_ACCEPT_POLL_RATE_US 10000
38 :
39 : union nvmf_h2c_msg {
40 : struct spdk_nvmf_capsule_cmd nvmf_cmd;
41 : struct spdk_nvme_cmd nvme_cmd;
42 : struct spdk_nvmf_fabric_prop_set_cmd prop_set_cmd;
43 : struct spdk_nvmf_fabric_prop_get_cmd prop_get_cmd;
44 : struct spdk_nvmf_fabric_connect_cmd connect_cmd;
45 : };
46 : SPDK_STATIC_ASSERT(sizeof(union nvmf_h2c_msg) == 64, "Incorrect size");
47 :
48 : union nvmf_c2h_msg {
49 : struct spdk_nvme_cpl nvme_cpl;
50 : struct spdk_nvmf_fabric_prop_get_rsp prop_get_rsp;
51 : struct spdk_nvmf_fabric_connect_rsp connect_rsp;
52 : };
53 : SPDK_STATIC_ASSERT(sizeof(union nvmf_c2h_msg) == 16, "Incorrect size");
54 :
55 : struct spdk_nvmf_dif_info {
56 : struct spdk_dif_ctx dif_ctx;
57 : uint32_t elba_length;
58 : uint32_t orig_length;
59 : };
60 :
61 : struct spdk_nvmf_stripped_data {
62 : uint32_t iovcnt;
63 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
64 : };
65 :
66 : enum spdk_nvmf_zcopy_phase {
67 : NVMF_ZCOPY_PHASE_NONE, /* Request is not using ZCOPY */
68 : NVMF_ZCOPY_PHASE_INIT, /* Requesting Buffers */
69 : NVMF_ZCOPY_PHASE_EXECUTE, /* Got buffers processing commands */
70 : NVMF_ZCOPY_PHASE_END_PENDING, /* Releasing buffers */
71 : NVMF_ZCOPY_PHASE_COMPLETE, /* Buffers Released */
72 : NVMF_ZCOPY_PHASE_INIT_FAILED /* Failed to get the buffers */
73 : };
74 :
75 : struct spdk_nvmf_request {
76 : struct spdk_nvmf_qpair *qpair;
77 : uint32_t length;
78 : uint8_t xfer; /* type enum spdk_nvme_data_transfer */
79 : union {
80 : uint8_t raw;
81 : struct {
82 : uint8_t data_from_pool : 1;
83 : uint8_t dif_enabled : 1;
84 : uint8_t first_fused : 1;
85 : uint8_t rsvd : 5;
86 : };
87 : };
88 : uint8_t zcopy_phase; /* type enum spdk_nvmf_zcopy_phase */
89 : uint8_t iovcnt;
90 : union nvmf_h2c_msg *cmd;
91 : union nvmf_c2h_msg *rsp;
92 : STAILQ_ENTRY(spdk_nvmf_request) buf_link;
93 : TAILQ_ENTRY(spdk_nvmf_request) link;
94 :
95 : /* Memory domain which describes payload in this request. If the bdev doesn't support memory
96 : * domains, bdev layer will do the necessary push or pull operation. */
97 : struct spdk_memory_domain *memory_domain;
98 : /* Context to be passed to memory domain operations. */
99 : void *memory_domain_ctx;
100 : struct spdk_accel_sequence *accel_sequence;
101 :
102 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
103 :
104 : struct spdk_nvmf_stripped_data *stripped_data;
105 :
106 : struct spdk_nvmf_dif_info dif;
107 :
108 : struct spdk_bdev_io_wait_entry bdev_io_wait;
109 : spdk_nvmf_nvme_passthru_cmd_cb cmd_cb_fn;
110 : struct spdk_nvmf_request *first_fused_req;
111 : struct spdk_nvmf_request *req_to_abort;
112 : struct spdk_poller *poller;
113 : struct spdk_bdev_io *zcopy_bdev_io; /* Contains the bdev_io when using ZCOPY */
114 :
115 : /* Timeout tracked for connect and abort flows. */
116 : uint64_t timeout_tsc;
117 : };
118 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_request) == 776, "Incorrect size");
119 :
120 : enum spdk_nvmf_qpair_state {
121 : SPDK_NVMF_QPAIR_UNINITIALIZED = 0,
122 : SPDK_NVMF_QPAIR_ACTIVE,
123 : SPDK_NVMF_QPAIR_DEACTIVATING,
124 : SPDK_NVMF_QPAIR_ERROR,
125 : };
126 :
127 : typedef void (*spdk_nvmf_state_change_done)(void *cb_arg, int status);
128 :
129 : struct spdk_nvmf_qpair {
130 : uint8_t state; /* ref spdk_nvmf_qpair_state */
131 : uint8_t rsvd;
132 : uint16_t qid;
133 : uint16_t sq_head;
134 : uint16_t sq_head_max;
135 :
136 : struct spdk_nvmf_transport *transport;
137 : struct spdk_nvmf_ctrlr *ctrlr;
138 : struct spdk_nvmf_poll_group *group;
139 :
140 : union {
141 : struct spdk_nvmf_request *first_fused_req;
142 : struct spdk_nvmf_request *connect_req;
143 : };
144 :
145 : TAILQ_HEAD(, spdk_nvmf_request) outstanding;
146 : TAILQ_ENTRY(spdk_nvmf_qpair) link;
147 :
148 : spdk_nvmf_state_change_done state_cb;
149 : void *state_cb_arg;
150 :
151 : bool connect_received;
152 : bool disconnect_started;
153 : };
154 :
155 : struct spdk_nvmf_transport_poll_group {
156 : struct spdk_nvmf_transport *transport;
157 : /* Requests that are waiting to obtain a data buffer */
158 : STAILQ_HEAD(, spdk_nvmf_request) pending_buf_queue;
159 : struct spdk_iobuf_channel *buf_cache;
160 : struct spdk_nvmf_poll_group *group;
161 : TAILQ_ENTRY(spdk_nvmf_transport_poll_group) link;
162 : };
163 :
164 : struct spdk_nvmf_poll_group {
165 : struct spdk_thread *thread;
166 : struct spdk_poller *poller;
167 :
168 : TAILQ_HEAD(, spdk_nvmf_transport_poll_group) tgroups;
169 :
170 : /* Array of poll groups indexed by subsystem id (sid) */
171 : struct spdk_nvmf_subsystem_poll_group *sgroups;
172 : uint32_t num_sgroups;
173 :
174 : /* Protected by mutex. Counts qpairs that have connected at a
175 : * transport level, but are not associated with a subsystem
176 : * or controller yet (because the CONNECT capsule hasn't
177 : * been received). */
178 : uint32_t current_unassociated_qpairs;
179 :
180 : /* All of the queue pairs that belong to this poll group */
181 : TAILQ_HEAD(, spdk_nvmf_qpair) qpairs;
182 :
183 : /* Statistics */
184 : struct spdk_nvmf_poll_group_stat stat;
185 :
186 : spdk_nvmf_poll_group_destroy_done_fn destroy_cb_fn;
187 : void *destroy_cb_arg;
188 :
189 : struct spdk_nvmf_tgt *tgt;
190 :
191 : TAILQ_ENTRY(spdk_nvmf_poll_group) link;
192 :
193 : pthread_mutex_t mutex;
194 : };
195 :
196 : struct spdk_nvmf_listener {
197 : struct spdk_nvme_transport_id trid;
198 : uint32_t ref;
199 :
200 : TAILQ_ENTRY(spdk_nvmf_listener) link;
201 : };
202 :
203 : /**
204 : * A subset of struct spdk_nvme_ctrlr_data that are emulated by a fabrics device.
205 : */
206 : struct spdk_nvmf_ctrlr_data {
207 : uint8_t aerl;
208 : uint16_t kas;
209 : /** pci vendor id */
210 : uint16_t vid;
211 : /** pci subsystem vendor id */
212 : uint16_t ssvid;
213 : /** ieee oui identifier */
214 : uint8_t ieee[3];
215 : struct spdk_nvme_cdata_oacs oacs;
216 : struct spdk_nvme_cdata_oncs oncs;
217 : struct spdk_nvme_cdata_fuses fuses;
218 : struct spdk_nvme_cdata_sgls sgls;
219 : struct spdk_nvme_cdata_nvmf_specific nvmf_specific;
220 : };
221 :
222 : #define MAX_MEMPOOL_NAME_LENGTH 40
223 :
224 : struct spdk_nvmf_transport {
225 : struct spdk_nvmf_tgt *tgt;
226 : const struct spdk_nvmf_transport_ops *ops;
227 : struct spdk_nvmf_transport_opts opts;
228 :
229 : char iobuf_name[MAX_MEMPOOL_NAME_LENGTH];
230 :
231 : TAILQ_HEAD(, spdk_nvmf_listener) listeners;
232 : TAILQ_ENTRY(spdk_nvmf_transport) link;
233 :
234 : pthread_mutex_t mutex;
235 : };
236 :
237 : typedef void (*spdk_nvmf_transport_qpair_fini_cb)(void *cb_arg);
238 :
239 : struct spdk_nvmf_transport_ops {
240 : /**
241 : * Transport name
242 : */
243 : char name[SPDK_NVMF_TRSTRING_MAX_LEN];
244 :
245 : /**
246 : * Transport type
247 : */
248 : enum spdk_nvme_transport_type type;
249 :
250 : /**
251 : * Initialize transport options to default value
252 : */
253 : void (*opts_init)(struct spdk_nvmf_transport_opts *opts);
254 :
255 : /**
256 : * Create a transport for the given transport opts. Either synchronous
257 : * or asynchronous version shall be implemented.
258 : */
259 : struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_transport_opts *opts);
260 : int (*create_async)(struct spdk_nvmf_transport_opts *opts, spdk_nvmf_transport_create_done_cb cb_fn,
261 : void *cb_arg);
262 :
263 : /**
264 : * Dump transport-specific opts into JSON
265 : */
266 : void (*dump_opts)(struct spdk_nvmf_transport *transport,
267 : struct spdk_json_write_ctx *w);
268 :
269 : /**
270 : * Destroy the transport
271 : */
272 : int (*destroy)(struct spdk_nvmf_transport *transport,
273 : spdk_nvmf_transport_destroy_done_cb cb_fn, void *cb_arg);
274 :
275 : /**
276 : * Instruct the transport to accept new connections at the address
277 : * provided. This may be called multiple times.
278 : */
279 : int (*listen)(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid,
280 : struct spdk_nvmf_listen_opts *opts);
281 :
282 : /**
283 : * Dump transport-specific listen opts into JSON
284 : */
285 : void (*listen_dump_opts)(struct spdk_nvmf_transport *transport,
286 : const struct spdk_nvme_transport_id *trid, struct spdk_json_write_ctx *w);
287 :
288 : /**
289 : * Stop accepting new connections at the given address.
290 : */
291 : void (*stop_listen)(struct spdk_nvmf_transport *transport,
292 : const struct spdk_nvme_transport_id *trid);
293 :
294 : /**
295 : * It is a notification that a listener is being associated with the subsystem.
296 : * Most transports will not need to take any action here, as the enforcement
297 : * of the association is done in the generic code.
298 : *
299 : * Returns a negated errno code to block the association. 0 to allow.
300 : */
301 : int (*listen_associate)(struct spdk_nvmf_transport *transport,
302 : const struct spdk_nvmf_subsystem *subsystem,
303 : const struct spdk_nvme_transport_id *trid);
304 :
305 : /**
306 : * It is a notification that a namespace is being added to the subsystem.
307 : * Most transports will not need to take any action here.
308 : *
309 : * Returns a negated errno code to block the attachment. 0 to allow.
310 : */
311 : int (*subsystem_add_ns)(struct spdk_nvmf_transport *transport,
312 : const struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *ns);
313 :
314 : /**
315 : * It is a notification that a namespace has been removed from the subsystem.
316 : * Most transports will not need to take any action here.
317 : */
318 : void (*subsystem_remove_ns)(struct spdk_nvmf_transport *transport,
319 : const struct spdk_nvmf_subsystem *subsystem, uint32_t nsid);
320 :
321 : /**
322 : * Initialize subset of identify controller data.
323 : */
324 : void (*cdata_init)(struct spdk_nvmf_transport *transport, struct spdk_nvmf_subsystem *subsystem,
325 : struct spdk_nvmf_ctrlr_data *cdata);
326 :
327 : /**
328 : * Fill out a discovery log entry for a specific listen address.
329 : */
330 : void (*listener_discover)(struct spdk_nvmf_transport *transport,
331 : struct spdk_nvme_transport_id *trid,
332 : struct spdk_nvmf_discovery_log_page_entry *entry);
333 :
334 : /**
335 : * Create a new poll group
336 : */
337 : struct spdk_nvmf_transport_poll_group *(*poll_group_create)(struct spdk_nvmf_transport *transport,
338 : struct spdk_nvmf_poll_group *group);
339 :
340 : /**
341 : * Get the polling group of the queue pair optimal for the specific transport
342 : */
343 : struct spdk_nvmf_transport_poll_group *(*get_optimal_poll_group)(struct spdk_nvmf_qpair *qpair);
344 :
345 : /**
346 : * Destroy a poll group
347 : */
348 : void (*poll_group_destroy)(struct spdk_nvmf_transport_poll_group *group);
349 :
350 : /**
351 : * Add a qpair to a poll group
352 : */
353 : int (*poll_group_add)(struct spdk_nvmf_transport_poll_group *group,
354 : struct spdk_nvmf_qpair *qpair);
355 :
356 : /**
357 : * Remove a qpair from a poll group
358 : */
359 : int (*poll_group_remove)(struct spdk_nvmf_transport_poll_group *group,
360 : struct spdk_nvmf_qpair *qpair);
361 :
362 : /**
363 : * Poll the group to process I/O
364 : */
365 : int (*poll_group_poll)(struct spdk_nvmf_transport_poll_group *group);
366 :
367 : /*
368 : * Free the request without sending a response
369 : * to the originator. Release memory tied to this request.
370 : */
371 : int (*req_free)(struct spdk_nvmf_request *req);
372 :
373 : /*
374 : * Signal request completion, which sends a response
375 : * to the originator.
376 : */
377 : int (*req_complete)(struct spdk_nvmf_request *req);
378 :
379 : /*
380 : * Deinitialize a connection.
381 : */
382 : void (*qpair_fini)(struct spdk_nvmf_qpair *qpair,
383 : spdk_nvmf_transport_qpair_fini_cb cb_fn,
384 : void *cb_args);
385 :
386 : /*
387 : * Get the peer transport ID for the queue pair.
388 : */
389 : int (*qpair_get_peer_trid)(struct spdk_nvmf_qpair *qpair,
390 : struct spdk_nvme_transport_id *trid);
391 :
392 : /*
393 : * Get the local transport ID for the queue pair.
394 : */
395 : int (*qpair_get_local_trid)(struct spdk_nvmf_qpair *qpair,
396 : struct spdk_nvme_transport_id *trid);
397 :
398 : /*
399 : * Get the listener transport ID that accepted this qpair originally.
400 : */
401 : int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
402 : struct spdk_nvme_transport_id *trid);
403 :
404 : /*
405 : * Abort the request which the abort request specifies.
406 : * This function can complete synchronously or asynchronously, but
407 : * is expected to call spdk_nvmf_request_complete() in the end
408 : * for both cases.
409 : */
410 : void (*qpair_abort_request)(struct spdk_nvmf_qpair *qpair,
411 : struct spdk_nvmf_request *req);
412 :
413 : /*
414 : * Dump transport poll group statistics into JSON.
415 : */
416 : void (*poll_group_dump_stat)(struct spdk_nvmf_transport_poll_group *group,
417 : struct spdk_json_write_ctx *w);
418 :
419 : /*
420 : * A notification that a subsystem has been configured to allow access
421 : * from the given host.
422 : * This callback is optional and not all transports need to implement it.
423 : */
424 : int (*subsystem_add_host)(struct spdk_nvmf_transport *transport,
425 : const struct spdk_nvmf_subsystem *subsystem,
426 : const char *hostnqn,
427 : const struct spdk_json_val *transport_specific);
428 :
429 : /*
430 : * A notification that a subsystem is no longer configured to allow access
431 : * from the given host.
432 : * This callback is optional and not all transports need to implement it.
433 : */
434 : void (*subsystem_remove_host)(struct spdk_nvmf_transport *transport,
435 : const struct spdk_nvmf_subsystem *subsystem,
436 : const char *hostnqn);
437 :
438 : /*
439 : * A callback used to dump subsystem's host data for a specific transport.
440 : * This callback is optional and not all transports need to implement it.
441 : */
442 : void (*subsystem_dump_host)(struct spdk_nvmf_transport *transport,
443 : const struct spdk_nvmf_subsystem *subsystem,
444 : const char *hostnqn, struct spdk_json_write_ctx *w);
445 : };
446 :
447 : /**
448 : * Register the operations for a given transport type.
449 : *
450 : * This function should be invoked by referencing the macro
451 : * SPDK_NVMF_TRANSPORT_REGISTER macro in the transport's .c file.
452 : *
453 : * \param ops The operations associated with an NVMe-oF transport.
454 : */
455 : void spdk_nvmf_transport_register(const struct spdk_nvmf_transport_ops *ops);
456 :
457 : int spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
458 :
459 : /**
460 : * Function to be called for each newly discovered qpair.
461 : *
462 : * \param tgt The nvmf target
463 : * \param qpair The newly discovered qpair.
464 : */
465 : void spdk_nvmf_tgt_new_qpair(struct spdk_nvmf_tgt *tgt, struct spdk_nvmf_qpair *qpair);
466 :
467 : /**
468 : * A subset of struct spdk_nvme_registers that are emulated by a fabrics device.
469 : */
470 : struct spdk_nvmf_registers {
471 : union spdk_nvme_cap_register cap;
472 : union spdk_nvme_vs_register vs;
473 : union spdk_nvme_cc_register cc;
474 : union spdk_nvme_csts_register csts;
475 : union spdk_nvme_aqa_register aqa;
476 : uint64_t asq;
477 : uint64_t acq;
478 : };
479 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_registers) == 40, "Incorrect size");
480 :
481 : const struct spdk_nvmf_registers *spdk_nvmf_ctrlr_get_regs(struct spdk_nvmf_ctrlr *ctrlr);
482 :
483 : void spdk_nvmf_request_free_buffers(struct spdk_nvmf_request *req,
484 : struct spdk_nvmf_transport_poll_group *group,
485 : struct spdk_nvmf_transport *transport);
486 : int spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req,
487 : struct spdk_nvmf_transport_poll_group *group,
488 : struct spdk_nvmf_transport *transport,
489 : uint32_t length);
490 :
491 : bool spdk_nvmf_request_get_dif_ctx(struct spdk_nvmf_request *req, struct spdk_dif_ctx *dif_ctx);
492 :
493 : void spdk_nvmf_request_exec(struct spdk_nvmf_request *req);
494 : void spdk_nvmf_request_exec_fabrics(struct spdk_nvmf_request *req);
495 : int spdk_nvmf_request_free(struct spdk_nvmf_request *req);
496 : int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);
497 : void spdk_nvmf_request_zcopy_start(struct spdk_nvmf_request *req);
498 : void spdk_nvmf_request_zcopy_end(struct spdk_nvmf_request *req, bool commit);
499 :
500 : static inline bool
501 8 : spdk_nvmf_request_using_zcopy(const struct spdk_nvmf_request *req)
502 : {
503 8 : return req->zcopy_phase != NVMF_ZCOPY_PHASE_NONE;
504 : }
505 :
506 : /**
507 : * Remove the given qpair from the poll group.
508 : *
509 : * \param qpair The qpair to remove.
510 : */
511 : void spdk_nvmf_poll_group_remove(struct spdk_nvmf_qpair *qpair);
512 :
513 : /**
514 : * Get the NVMe-oF subsystem associated with this controller.
515 : *
516 : * \param ctrlr The NVMe-oF controller
517 : *
518 : * \return The NVMe-oF subsystem
519 : */
520 : struct spdk_nvmf_subsystem *
521 : spdk_nvmf_ctrlr_get_subsystem(struct spdk_nvmf_ctrlr *ctrlr);
522 :
523 : /**
524 : * Get the NVMe-oF controller ID.
525 : *
526 : * \param ctrlr The NVMe-oF controller
527 : *
528 : * \return The NVMe-oF controller ID
529 : */
530 : uint16_t spdk_nvmf_ctrlr_get_id(struct spdk_nvmf_ctrlr *ctrlr);
531 :
532 : struct spdk_nvmf_ctrlr_feat {
533 : union spdk_nvme_feat_arbitration arbitration;
534 : union spdk_nvme_feat_power_management power_management;
535 : union spdk_nvme_feat_error_recovery error_recovery;
536 : union spdk_nvme_feat_volatile_write_cache volatile_write_cache;
537 : union spdk_nvme_feat_number_of_queues number_of_queues;
538 : union spdk_nvme_feat_interrupt_coalescing interrupt_coalescing;
539 : union spdk_nvme_feat_interrupt_vector_configuration interrupt_vector_configuration;
540 : union spdk_nvme_feat_write_atomicity write_atomicity;
541 : union spdk_nvme_feat_async_event_configuration async_event_configuration;
542 : union spdk_nvme_feat_keep_alive_timer keep_alive_timer;
543 : };
544 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_feat) == 40, "Incorrect size");
545 :
546 : /*
547 : * Migration data structure used to save & restore a NVMe-oF controller.
548 : *
549 : * The data structure is experimental.
550 : *
551 : */
552 : struct spdk_nvmf_ctrlr_migr_data {
553 : /* `data_size` is valid size of `spdk_nvmf_ctrlr_migr_data` without counting `unused`.
554 : * We use this field to migrate `spdk_nvmf_ctrlr_migr_data` from source VM and restore
555 : * it in destination VM.
556 : */
557 : uint32_t data_size;
558 : /* `regs_size` is valid size of `spdk_nvmf_registers`. */
559 : uint32_t regs_size;
560 : /* `feat_size` is valid size of `spdk_nvmf_ctrlr_feat`. */
561 : uint32_t feat_size;
562 : uint32_t reserved;
563 :
564 : struct spdk_nvmf_registers regs;
565 : uint8_t regs_reserved[216];
566 :
567 : struct spdk_nvmf_ctrlr_feat feat;
568 : uint8_t feat_reserved[216];
569 :
570 : uint16_t cntlid;
571 : uint8_t acre;
572 : uint8_t num_aer_cids;
573 : uint32_t num_async_events;
574 :
575 : union spdk_nvme_async_event_completion async_events[SPDK_NVMF_MIGR_MAX_PENDING_AERS];
576 : uint16_t aer_cids[SPDK_NVMF_MAX_ASYNC_EVENTS];
577 : uint64_t notice_aen_mask;
578 :
579 : uint8_t unused[2516];
580 : };
581 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
582 : regs) - offsetof(struct spdk_nvmf_ctrlr_migr_data, data_size) == 16, "Incorrect header size");
583 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
584 : feat) - offsetof(struct spdk_nvmf_ctrlr_migr_data, regs) == 256, "Incorrect regs size");
585 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
586 : cntlid) - offsetof(struct spdk_nvmf_ctrlr_migr_data, feat) == 256, "Incorrect feat size");
587 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_migr_data) == 4096, "Incorrect size");
588 :
589 : /**
590 : * Save the NVMe-oF controller state and configuration.
591 : *
592 : * The API is experimental.
593 : *
594 : * It is allowed to save the data only when the nvmf subystem is in paused
595 : * state i.e. there are no outstanding cmds in nvmf layer (other than aer),
596 : * pending async event completions are getting blocked.
597 : *
598 : * To preserve thread safety this function must be executed on the same thread
599 : * the NVMe-OF controller was created.
600 : *
601 : * \param ctrlr The NVMe-oF controller
602 : * \param data The NVMe-oF controller state and configuration to be saved
603 : *
604 : * \return 0 on success or a negated errno on failure.
605 : */
606 : int spdk_nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
607 : struct spdk_nvmf_ctrlr_migr_data *data);
608 :
609 : /**
610 : * Restore the NVMe-oF controller state and configuration.
611 : *
612 : * The API is experimental.
613 : *
614 : * It is allowed to restore the data only when the nvmf subystem is in paused
615 : * state.
616 : *
617 : * To preserve thread safety this function must be executed on the same thread
618 : * the NVMe-OF controller was created.
619 : *
620 : * AERs shall be restored using spdk_nvmf_request_exec after this function is executed.
621 : *
622 : * \param ctrlr The NVMe-oF controller
623 : * \param data The NVMe-oF controller state and configuration to be restored
624 : *
625 : * \return 0 on success or a negated errno on failure.
626 : */
627 : int spdk_nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
628 : const struct spdk_nvmf_ctrlr_migr_data *data);
629 :
630 : static inline enum spdk_nvme_data_transfer
631 10 : spdk_nvmf_req_get_xfer(struct spdk_nvmf_request *req) {
632 : enum spdk_nvme_data_transfer xfer;
633 10 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
634 10 : struct spdk_nvme_sgl_descriptor *sgl = &cmd->dptr.sgl1;
635 :
636 : /* Figure out data transfer direction */
637 10 : if (cmd->opc == SPDK_NVME_OPC_FABRIC)
638 : {
639 2 : xfer = spdk_nvme_opc_get_data_transfer(req->cmd->nvmf_cmd.fctype);
640 : } else
641 : {
642 8 : xfer = spdk_nvme_opc_get_data_transfer(cmd->opc);
643 : }
644 :
645 10 : if (xfer == SPDK_NVME_DATA_NONE)
646 : {
647 0 : return xfer;
648 : }
649 :
650 : /* Even for commands that may transfer data, they could have specified 0 length.
651 : * We want those to show up with xfer SPDK_NVME_DATA_NONE.
652 : */
653 10 : switch (sgl->generic.type)
654 : {
655 4 : case SPDK_NVME_SGL_TYPE_DATA_BLOCK:
656 : case SPDK_NVME_SGL_TYPE_BIT_BUCKET:
657 : case SPDK_NVME_SGL_TYPE_SEGMENT:
658 : case SPDK_NVME_SGL_TYPE_LAST_SEGMENT:
659 : case SPDK_NVME_SGL_TYPE_TRANSPORT_DATA_BLOCK:
660 4 : if (sgl->unkeyed.length == 0) {
661 0 : xfer = SPDK_NVME_DATA_NONE;
662 : }
663 4 : break;
664 6 : case SPDK_NVME_SGL_TYPE_KEYED_DATA_BLOCK:
665 6 : if (sgl->keyed.length == 0) {
666 0 : xfer = SPDK_NVME_DATA_NONE;
667 : }
668 6 : break;
669 : }
670 :
671 10 : return xfer;
672 : }
673 :
674 : /**
675 : * Complete Asynchronous Event as Error.
676 : *
677 : * \param ctrlr Controller whose AER is going to be completed.
678 : * \param info Asynchronous Event Error Information to be reported.
679 : *
680 : * \return int. 0 if it completed successfully, or negative errno if it failed.
681 : */
682 : int spdk_nvmf_ctrlr_async_event_error_event(struct spdk_nvmf_ctrlr *ctrlr,
683 : enum spdk_nvme_async_event_info_error info);
684 :
685 : /**
686 : * Abort outstanding Asynchronous Event Requests (AERs).
687 : *
688 : * Completes AERs with ABORTED_BY_REQUEST status code.
689 : *
690 : * \param ctrlr Controller whose AERs are going to be aborted.
691 : */
692 : void spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr);
693 :
694 : /*
695 : * Macro used to register new transports.
696 : */
697 : #define SPDK_NVMF_TRANSPORT_REGISTER(name, transport_ops) \
698 : static void __attribute__((constructor)) _spdk_nvmf_transport_register_##name(void) \
699 : { \
700 : spdk_nvmf_transport_register(transport_ops); \
701 : }
702 :
703 : #endif
|