xref: /spdk/lib/nvmf/nvmf_fc.h (revision 83e8405e4c25408c010ba2b9e02ce45e2347370c)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   Copyright (c) 2018-2019 Broadcom.  All Rights Reserved.
4  *   The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
5  */
6 
7 #ifndef __NVMF_FC_H__
8 #define __NVMF_FC_H__
9 
10 #include "spdk/nvme.h"
11 #include "spdk/nvmf.h"
12 #include "spdk/assert.h"
13 #include "spdk/nvme_spec.h"
14 #include "spdk/nvmf_fc_spec.h"
15 #include "spdk/thread.h"
16 #include "nvmf_internal.h"
17 #include <rte_hash.h>
18 
19 #define SPDK_NVMF_FC_TR_ADDR_LEN 64
20 #define NVMF_FC_INVALID_CONN_ID UINT64_MAX
21 
22 #define SPDK_FC_HW_DUMP_REASON_STR_MAX_SIZE 256
23 #define SPDK_MAX_NUM_OF_FC_PORTS 32
24 #define SPDK_NVMF_PORT_ID_MAX_LEN 32
25 
26 /*
27  * FC HWQP pointer
28  */
29 typedef void *spdk_nvmf_fc_lld_hwqp_t;
30 
31 /*
32  * FC LLD port.
33  */
34 typedef void *spdk_nvmf_fc_lld_fc_port_t;
35 
36 /*
37  * FC HW port states.
38  */
39 enum spdk_fc_port_state {
40 	SPDK_FC_PORT_OFFLINE = 0,
41 	SPDK_FC_PORT_ONLINE = 1,
42 	SPDK_FC_PORT_QUIESCED = 2,
43 };
44 
45 enum spdk_fc_hwqp_state {
46 	SPDK_FC_HWQP_OFFLINE = 0,
47 	SPDK_FC_HWQP_ONLINE = 1,
48 };
49 
50 /*
51  * NVMF FC Object state
52  * Add all the generic states of the object here.
53  * Specific object states can be added separately
54  */
55 enum spdk_nvmf_fc_object_state {
56 	SPDK_NVMF_FC_OBJECT_CREATED = 0,
57 	SPDK_NVMF_FC_OBJECT_TO_BE_DELETED = 1,
58 	SPDK_NVMF_FC_OBJECT_ZOMBIE = 2,      /* Partial Create or Delete  */
59 };
60 
61 /*
62  * FC request state
63  */
64 enum spdk_nvmf_fc_request_state {
65 	SPDK_NVMF_FC_REQ_INIT = 0,
66 	SPDK_NVMF_FC_REQ_READ_BDEV,
67 	SPDK_NVMF_FC_REQ_READ_XFER,
68 	SPDK_NVMF_FC_REQ_READ_RSP,
69 	SPDK_NVMF_FC_REQ_WRITE_BUFFS,
70 	SPDK_NVMF_FC_REQ_WRITE_XFER,
71 	SPDK_NVMF_FC_REQ_WRITE_BDEV,
72 	SPDK_NVMF_FC_REQ_WRITE_RSP,
73 	SPDK_NVMF_FC_REQ_NONE_BDEV,
74 	SPDK_NVMF_FC_REQ_NONE_RSP,
75 	SPDK_NVMF_FC_REQ_SUCCESS,
76 	SPDK_NVMF_FC_REQ_FAILED,
77 	SPDK_NVMF_FC_REQ_ABORTED,
78 	SPDK_NVMF_FC_REQ_BDEV_ABORTED,
79 	SPDK_NVMF_FC_REQ_PENDING,
80 	SPDK_NVMF_FC_REQ_FUSED_WAITING,
81 	SPDK_NVMF_FC_REQ_MAX_STATE,
82 };
83 
84 /*
85  * Generic DMA buffer descriptor
86  */
87 struct spdk_nvmf_fc_buffer_desc {
88 	void *virt;
89 	uint64_t phys;
90 	size_t len;
91 
92 	/* Internal */
93 	uint32_t buf_index;
94 };
95 
96 /*
97  * ABTS handling context
98  */
99 struct spdk_nvmf_fc_abts_ctx {
100 	bool handled;
101 	uint16_t hwqps_responded;
102 	uint16_t rpi;
103 	uint16_t oxid;
104 	uint16_t rxid;
105 	struct spdk_nvmf_fc_nport *nport;
106 	uint16_t nport_hdl;
107 	uint8_t port_hdl;
108 	void *abts_poller_args;
109 	void *sync_poller_args;
110 	int num_hwqps;
111 	bool queue_synced;
112 	uint64_t u_id;
113 	struct spdk_nvmf_fc_hwqp *ls_hwqp;
114 	uint16_t fcp_rq_id;
115 };
116 
117 /*
118  * NVME FC transport errors
119  */
120 struct spdk_nvmf_fc_errors {
121 	uint32_t no_xchg;
122 	uint32_t nport_invalid;
123 	uint32_t unknown_frame;
124 	uint32_t wqe_cmplt_err;
125 	uint32_t wqe_write_err;
126 	uint32_t rq_status_err;
127 	uint32_t rq_buf_len_err;
128 	uint32_t rq_id_err;
129 	uint32_t rq_index_err;
130 	uint32_t invalid_cq_type;
131 	uint32_t invalid_cq_id;
132 	uint32_t fc_req_buf_err;
133 	uint32_t buf_alloc_err;
134 	uint32_t unexpected_err;
135 	uint32_t nvme_cmd_iu_err;
136 	uint32_t nvme_cmd_xfer_err;
137 	uint32_t queue_entry_invalid;
138 	uint32_t invalid_conn_err;
139 	uint32_t fcp_rsp_failure;
140 	uint32_t write_failed;
141 	uint32_t read_failed;
142 	uint32_t rport_invalid;
143 	uint32_t num_aborted;
144 	uint32_t num_abts_sent;
145 };
146 
147 /*
148  *  Send Single Request/Response Sequence.
149  */
150 struct spdk_nvmf_fc_srsr_bufs {
151 	void *rqst;
152 	size_t rqst_len;
153 	void *rsp;
154 	size_t rsp_len;
155 	uint16_t rpi;
156 };
157 
158 struct spdk_nvmf_fc_qpair_remove_ctx {
159 	struct spdk_nvmf_qpair *qpair;
160 	spdk_nvmf_transport_qpair_fini_cb cb_fn;
161 	void *cb_ctx;
162 	struct spdk_thread *qpair_thread;
163 };
164 
165 /*
166  * Struct representing a nport
167  */
168 struct spdk_nvmf_fc_nport {
169 
170 	uint16_t nport_hdl;
171 	uint8_t port_hdl;
172 	uint32_t d_id;
173 	enum spdk_nvmf_fc_object_state nport_state;
174 	struct spdk_nvmf_fc_wwn fc_nodename;
175 	struct spdk_nvmf_fc_wwn fc_portname;
176 
177 	/* list of remote ports (i.e. initiators) connected to nport */
178 	TAILQ_HEAD(, spdk_nvmf_fc_remote_port_info) rem_port_list;
179 	uint32_t rport_count;
180 
181 	void *vendor_data;	/* available for vendor use */
182 
183 	/* list of associations to nport */
184 	TAILQ_HEAD(, spdk_nvmf_fc_association) fc_associations;
185 	uint32_t assoc_count;
186 	struct spdk_nvmf_fc_port *fc_port;
187 	TAILQ_ENTRY(spdk_nvmf_fc_nport) link; /* list of nports on a hw port. */
188 };
189 
190 typedef void (*spdk_nvmf_fc_caller_cb)(void *hwqp, int32_t status, void *args);
191 /*
192  * NVMF FC Connection
193  */
194 struct spdk_nvmf_fc_conn {
195 	struct spdk_nvmf_qpair qpair;
196 	struct spdk_nvme_transport_id trid;
197 
198 	uint32_t s_id;
199 	uint32_t d_id;
200 	uint64_t conn_id;
201 	struct spdk_nvmf_fc_hwqp *hwqp;
202 	uint16_t esrp_ratio;
203 	uint16_t rsp_count;
204 	uint32_t rsn;
205 
206 	/* The maximum number of I/O outstanding on this connection at one time */
207 	uint16_t max_queue_depth;
208 	uint16_t max_rw_depth;
209 	/* The current number of I/O outstanding on this connection. This number
210 	 * includes all I/O from the time the capsule is first received until it is
211 	 * completed.
212 	 */
213 	uint16_t cur_queue_depth;
214 
215 	/* number of read/write requests that are outstanding */
216 	uint16_t cur_fc_rw_depth;
217 
218 	TAILQ_HEAD(, spdk_nvmf_fc_request) fused_waiting_queue;
219 
220 	struct spdk_nvmf_fc_association *fc_assoc;
221 
222 	uint16_t rpi;
223 
224 	/* for association's connection list */
225 	TAILQ_ENTRY(spdk_nvmf_fc_conn) assoc_link;
226 
227 	/* for associations's available connection list */
228 	TAILQ_ENTRY(spdk_nvmf_fc_conn) assoc_avail_link;
229 
230 	/* for hwqp's rport connection list link  */
231 	TAILQ_ENTRY(spdk_nvmf_fc_conn) rport_link;
232 
233 	/* Per connection fc_req pool */
234 	STAILQ_HEAD(, spdk_nvmf_fc_pooled_request) pool_queue;
235 
236 	/* Memory for the fc_req pool objects */
237 	struct spdk_nvmf_fc_pooled_request *pool_memory;
238 
239 	/* Pool size */
240 	uint32_t pool_size;
241 
242 	/* Current free elem in pool */
243 	uint32_t pool_free_elems;
244 
245 	TAILQ_HEAD(, spdk_nvmf_fc_request) in_use_reqs;
246 
247 	enum spdk_nvmf_fc_object_state conn_state;
248 
249 	/* New QP create context. */
250 	struct nvmf_fc_ls_op_ctx *create_opd;
251 
252 	/* Delete conn callback list */
253 	void *ls_del_op_ctx;
254 
255 	bool qpair_fini_done;
256 	spdk_nvmf_fc_caller_cb qpair_fini_done_cb;
257 	void *qpair_fini_done_cb_args;
258 };
259 
260 /*
261  * Structure for maintaining the FC exchanges
262  */
263 struct spdk_nvmf_fc_xchg {
264 	uint32_t xchg_id;   /* The actual xchg identifier */
265 
266 	/* Internal */
267 	TAILQ_ENTRY(spdk_nvmf_fc_xchg) link;
268 	bool active;
269 	bool aborted;
270 	bool send_abts; /* Valid if is_aborted is set. */
271 };
272 
273 /*
274  *  FC poll group structure
275  */
276 struct spdk_nvmf_fc_poll_group {
277 	struct spdk_nvmf_transport_poll_group group;
278 	struct spdk_nvmf_tgt *nvmf_tgt;
279 	uint32_t hwqp_count; /* number of hwqp's assigned to this pg */
280 	TAILQ_HEAD(, spdk_nvmf_fc_hwqp) hwqp_list;
281 
282 	TAILQ_ENTRY(spdk_nvmf_fc_poll_group) link;
283 };
284 
285 /*
286  *  HWQP poller structure passed from main thread
287  */
288 struct spdk_nvmf_fc_hwqp {
289 	enum spdk_fc_hwqp_state state;  /* queue state (for poller) */
290 	bool is_ls_queue;
291 	uint32_t lcore_id;   /* core hwqp is running on (for tracing purposes only) */
292 	struct spdk_thread *thread;  /* thread hwqp is running on */
293 	uint32_t hwqp_id;    /* A unique id (per physical port) for a hwqp */
294 	spdk_nvmf_fc_lld_hwqp_t queues;    /* vendor HW queue set */
295 	struct spdk_nvmf_fc_port *fc_port; /* HW port structure for these queues */
296 	struct spdk_nvmf_fc_poll_group *fgroup;
297 
298 	/* qpair (fc_connection) list */
299 	uint32_t num_conns; /* number of connections to queue */
300 	struct rte_hash *connection_list_hash;
301 	struct rte_hash *rport_list_hash;
302 
303 	TAILQ_HEAD(, spdk_nvmf_fc_request) in_use_reqs;
304 
305 	struct spdk_nvmf_fc_errors counters;
306 
307 	/* Pending LS request waiting for FC resource */
308 	TAILQ_HEAD(, spdk_nvmf_fc_ls_rqst) ls_pending_queue;
309 
310 	/* Sync req list */
311 	TAILQ_HEAD(, spdk_nvmf_fc_poller_api_queue_sync_args) sync_cbs;
312 
313 	TAILQ_ENTRY(spdk_nvmf_fc_hwqp) link;
314 
315 	void *context;			/* Vendor specific context data */
316 };
317 
318 /*
319  * FC HW port.
320  */
321 struct spdk_nvmf_fc_port {
322 	uint8_t port_hdl;
323 	spdk_nvmf_fc_lld_fc_port_t lld_fc_port;
324 	enum spdk_fc_port_state hw_port_status;
325 	uint16_t fcp_rq_id;
326 	struct spdk_nvmf_fc_hwqp ls_queue;
327 
328 	uint32_t num_io_queues;
329 	struct spdk_nvmf_fc_hwqp *io_queues;
330 	/*
331 	 * List of nports on this HW port.
332 	 */
333 	TAILQ_HEAD(, spdk_nvmf_fc_nport)nport_list;
334 	int	num_nports;
335 	TAILQ_ENTRY(spdk_nvmf_fc_port) link;
336 
337 	struct spdk_mempool *io_resource_pool; /* Pools to store bdev_io's for this port */
338 	void *port_ctx;
339 };
340 
341 /*
342  * NVMF FC Request
343  */
344 struct spdk_nvmf_fc_request {
345 	struct spdk_nvmf_request req;
346 	union nvmf_h2c_msg cmd;
347 	struct spdk_nvmf_fc_ersp_iu ersp;
348 	uint32_t poller_lcore; /* for tracing purposes only */
349 	struct spdk_thread *poller_thread;
350 	struct spdk_nvmf_fc_xchg *xchg;
351 	uint16_t oxid;
352 	uint16_t rpi;
353 	struct spdk_nvmf_fc_conn *fc_conn;
354 	struct spdk_nvmf_fc_hwqp *hwqp;
355 	int state;
356 	uint32_t transferred_len;
357 	bool is_aborted;
358 	uint32_t magic;
359 	uint32_t s_id;
360 	uint32_t d_id;
361 	uint32_t csn;
362 	uint32_t app_id;
363 	uint8_t csctl;
364 	TAILQ_ENTRY(spdk_nvmf_fc_request) link;
365 	TAILQ_ENTRY(spdk_nvmf_fc_request) conn_link;
366 	TAILQ_ENTRY(spdk_nvmf_fc_request) fused_link;
367 	TAILQ_HEAD(, spdk_nvmf_fc_caller_ctx) abort_cbs;
368 };
369 
370 SPDK_STATIC_ASSERT(!offsetof(struct spdk_nvmf_fc_request, req),
371 		   "FC request and NVMF request address don't match.");
372 
373 struct spdk_nvmf_fc_pooled_request {
374 	STAILQ_ENTRY(spdk_nvmf_fc_pooled_request) pool_link;
375 };
376 
377 /*
378  * NVMF FC Association
379  */
380 struct spdk_nvmf_fc_association {
381 	uint64_t assoc_id;
382 	uint32_t s_id;
383 	struct spdk_nvmf_fc_nport *tgtport;
384 	struct spdk_nvmf_fc_remote_port_info *rport;
385 	struct spdk_nvmf_subsystem *subsystem;
386 	struct spdk_nvmf_transport *nvmf_transport;
387 	enum spdk_nvmf_fc_object_state assoc_state;
388 
389 	char host_id[FCNVME_ASSOC_HOSTID_LEN];
390 	char host_nqn[SPDK_NVME_NQN_FIELD_SIZE];
391 	char sub_nqn[SPDK_NVME_NQN_FIELD_SIZE];
392 
393 	struct spdk_nvmf_fc_conn *aq_conn; /* connection for admin queue */
394 
395 	uint16_t conn_count;
396 	TAILQ_HEAD(, spdk_nvmf_fc_conn) fc_conns;
397 
398 	void *conns_buf;
399 	TAILQ_HEAD(, spdk_nvmf_fc_conn) avail_fc_conns;
400 
401 	TAILQ_ENTRY(spdk_nvmf_fc_association) link;
402 
403 	/* for port's association free list */
404 	TAILQ_ENTRY(spdk_nvmf_fc_association) port_free_assoc_list_link;
405 
406 	void *ls_del_op_ctx; /* delete assoc. callback list */
407 
408 	/* disconnect cmd buffers (sent to initiator) */
409 	struct spdk_nvmf_fc_srsr_bufs *snd_disconn_bufs;
410 };
411 
412 /*
413  * FC Remote Port
414  */
415 struct spdk_nvmf_fc_remote_port_info {
416 	uint32_t s_id;
417 	uint32_t rpi;
418 	uint32_t assoc_count;
419 	struct spdk_nvmf_fc_wwn fc_nodename;
420 	struct spdk_nvmf_fc_wwn fc_portname;
421 	enum spdk_nvmf_fc_object_state rport_state;
422 	TAILQ_ENTRY(spdk_nvmf_fc_remote_port_info) link;
423 };
424 
425 /*
426  * Poller API error codes
427  */
428 enum spdk_nvmf_fc_poller_api_ret {
429 	SPDK_NVMF_FC_POLLER_API_SUCCESS = 0,
430 	SPDK_NVMF_FC_POLLER_API_ERROR,
431 	SPDK_NVMF_FC_POLLER_API_INVALID_ARG,
432 	SPDK_NVMF_FC_POLLER_API_NO_CONN_ID,
433 	SPDK_NVMF_FC_POLLER_API_DUP_CONN_ID,
434 	SPDK_NVMF_FC_POLLER_API_OXID_NOT_FOUND,
435 };
436 
437 /*
438  * Poller API definitions
439  */
440 enum spdk_nvmf_fc_poller_api {
441 	SPDK_NVMF_FC_POLLER_API_ADD_CONNECTION,
442 	SPDK_NVMF_FC_POLLER_API_DEL_CONNECTION,
443 	SPDK_NVMF_FC_POLLER_API_QUIESCE_QUEUE,
444 	SPDK_NVMF_FC_POLLER_API_ACTIVATE_QUEUE,
445 	SPDK_NVMF_FC_POLLER_API_ABTS_RECEIVED,
446 	SPDK_NVMF_FC_POLLER_API_REQ_ABORT_COMPLETE,
447 	SPDK_NVMF_FC_POLLER_API_ADAPTER_EVENT,
448 	SPDK_NVMF_FC_POLLER_API_AEN,
449 	SPDK_NVMF_FC_POLLER_API_QUEUE_SYNC,
450 	SPDK_NVMF_FC_POLLER_API_QUEUE_SYNC_DONE,
451 	SPDK_NVMF_FC_POLLER_API_ADD_HWQP,
452 	SPDK_NVMF_FC_POLLER_API_REMOVE_HWQP,
453 };
454 
455 /*
456  * Poller API callback function proto
457  */
458 typedef void (*spdk_nvmf_fc_poller_api_cb)(void *cb_data, enum spdk_nvmf_fc_poller_api_ret ret);
459 
460 /*
461  * Poller API callback data
462  */
463 struct spdk_nvmf_fc_poller_api_cb_info {
464 	struct spdk_thread *cb_thread;
465 	spdk_nvmf_fc_poller_api_cb cb_func;
466 	void *cb_data;
467 	enum spdk_nvmf_fc_poller_api_ret ret;
468 };
469 
470 /*
471  * Poller API structures
472  */
473 struct spdk_nvmf_fc_poller_api_add_connection_args {
474 	struct spdk_nvmf_fc_conn *fc_conn;
475 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
476 };
477 
478 struct spdk_nvmf_fc_poller_api_del_connection_args {
479 	struct spdk_nvmf_fc_conn *fc_conn;
480 	struct spdk_nvmf_fc_hwqp *hwqp;
481 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
482 	bool send_abts;
483 	/* internal */
484 	int fc_request_cnt;
485 	bool backend_initiated;
486 };
487 
488 struct spdk_nvmf_fc_poller_api_quiesce_queue_args {
489 	void   *ctx;
490 	struct spdk_nvmf_fc_hwqp *hwqp;
491 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
492 };
493 
494 struct spdk_nvmf_fc_poller_api_activate_queue_args {
495 	struct spdk_nvmf_fc_hwqp *hwqp;
496 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
497 };
498 
499 struct spdk_nvmf_fc_poller_api_abts_recvd_args {
500 	struct spdk_nvmf_fc_abts_ctx *ctx;
501 	struct spdk_nvmf_fc_hwqp *hwqp;
502 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
503 };
504 
505 struct spdk_nvmf_fc_poller_api_queue_sync_done_args {
506 	struct spdk_nvmf_fc_hwqp *hwqp;
507 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
508 	uint64_t tag;
509 };
510 
511 typedef void (*spdk_nvmf_fc_remove_hwqp_cb)(void *ctx, int err);
512 
513 struct spdk_nvmf_fc_poller_api_remove_hwqp_args {
514 	struct spdk_nvmf_fc_hwqp *hwqp;
515 	spdk_nvmf_fc_remove_hwqp_cb cb_fn;
516 	void *cb_ctx;
517 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
518 };
519 
520 struct spdk_nvmf_fc_hwqp_rport {
521 	uint16_t rpi;
522 	TAILQ_HEAD(, spdk_nvmf_fc_conn) conn_list;
523 };
524 
525 /*
526  * NVMF LS request structure
527  */
528 struct spdk_nvmf_fc_ls_rqst {
529 	struct spdk_nvmf_fc_buffer_desc rqstbuf;
530 	struct spdk_nvmf_fc_buffer_desc rspbuf;
531 	uint32_t rqst_len;
532 	uint32_t rsp_len;
533 	uint32_t rpi;
534 	struct spdk_nvmf_fc_xchg *xchg;
535 	uint16_t oxid;
536 	void *private_data; /* for LLD only (LS does not touch) */
537 	TAILQ_ENTRY(spdk_nvmf_fc_ls_rqst) ls_pending_link;
538 	uint32_t s_id;
539 	uint32_t d_id;
540 	struct spdk_nvmf_fc_nport *nport;
541 	struct spdk_nvmf_fc_remote_port_info *rport;
542 	struct spdk_nvmf_tgt *nvmf_tgt;
543 };
544 
545 /*
546  * RQ Buffer LS Overlay Structure
547  */
548 #define FCNVME_LS_RSVD_SIZE (FCNVME_MAX_LS_BUFFER_SIZE - \
549 	(sizeof(struct spdk_nvmf_fc_ls_rqst) + FCNVME_MAX_LS_REQ_SIZE + FCNVME_MAX_LS_RSP_SIZE))
550 
551 struct spdk_nvmf_fc_rq_buf_ls_request {
552 	uint8_t rqst[FCNVME_MAX_LS_REQ_SIZE];
553 	uint8_t resp[FCNVME_MAX_LS_RSP_SIZE];
554 	struct spdk_nvmf_fc_ls_rqst ls_rqst;
555 	uint8_t rsvd[FCNVME_LS_RSVD_SIZE];
556 };
557 
558 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_rq_buf_ls_request) ==
559 		   FCNVME_MAX_LS_BUFFER_SIZE, "LS RQ Buffer overflow");
560 
561 /* Poller API structures (arguments and callback data */
562 typedef void (*spdk_nvmf_fc_del_assoc_cb)(void *arg, uint32_t err);
563 typedef void (*spdk_nvmf_fc_del_conn_cb)(void *arg);
564 
565 struct spdk_nvmf_fc_ls_add_conn_api_data {
566 	struct spdk_nvmf_fc_poller_api_add_connection_args args;
567 	struct spdk_nvmf_fc_ls_rqst *ls_rqst;
568 	struct spdk_nvmf_fc_association *assoc;
569 	bool aq_conn; /* true if adding connection for new association */
570 };
571 
572 /* Disconnect (connection) request functions */
573 struct spdk_nvmf_fc_ls_del_conn_api_data {
574 	struct spdk_nvmf_fc_poller_api_del_connection_args args;
575 	struct spdk_nvmf_fc_ls_rqst *ls_rqst;
576 	struct spdk_nvmf_fc_association *assoc;
577 	bool aq_conn; /* true if deleting AQ connection */
578 	spdk_nvmf_fc_del_conn_cb del_conn_cb;
579 	void *del_conn_cb_data;
580 };
581 
582 /* used by LS disconnect association cmd handling */
583 struct spdk_nvmf_fc_ls_disconn_assoc_api_data {
584 	struct spdk_nvmf_fc_nport *tgtport;
585 	struct spdk_nvmf_fc_ls_rqst *ls_rqst;
586 };
587 
588 /* used by delete association call */
589 struct spdk_nvmf_fc_delete_assoc_api_data {
590 	struct spdk_nvmf_fc_poller_api_del_connection_args args;
591 	struct spdk_nvmf_fc_association *assoc;
592 	bool from_ls_rqst;   /* true = request came for LS */
593 	spdk_nvmf_fc_del_assoc_cb del_assoc_cb;
594 	void *del_assoc_cb_data;
595 };
596 
597 struct nvmf_fc_ls_op_ctx {
598 	union {
599 		struct spdk_nvmf_fc_ls_add_conn_api_data add_conn;
600 		struct spdk_nvmf_fc_ls_del_conn_api_data del_conn;
601 		struct spdk_nvmf_fc_ls_disconn_assoc_api_data disconn_assoc;
602 		struct spdk_nvmf_fc_delete_assoc_api_data del_assoc;
603 	} u;
604 	struct  nvmf_fc_ls_op_ctx *next_op_ctx;
605 };
606 
607 struct spdk_nvmf_fc_poller_api_queue_sync_args {
608 	uint64_t u_id;
609 	struct spdk_nvmf_fc_hwqp *hwqp;
610 	struct spdk_nvmf_fc_poller_api_cb_info cb_info;
611 
612 	/* Used internally by poller */
613 	TAILQ_ENTRY(spdk_nvmf_fc_poller_api_queue_sync_args) link;
614 };
615 
616 /**
617  * Following defines and structures are used to pass messages between main thread
618  * and FCT driver.
619  */
620 enum spdk_fc_event {
621 	SPDK_FC_HW_PORT_INIT,
622 	SPDK_FC_HW_PORT_FREE,
623 	SPDK_FC_HW_PORT_ONLINE,
624 	SPDK_FC_HW_PORT_OFFLINE,
625 	SPDK_FC_HW_PORT_RESET,
626 	SPDK_FC_NPORT_CREATE,
627 	SPDK_FC_NPORT_DELETE,
628 	SPDK_FC_IT_ADD,    /* PRLI */
629 	SPDK_FC_IT_DELETE, /* PRLI */
630 	SPDK_FC_ABTS_RECV,
631 	SPDK_FC_HW_PORT_DUMP,
632 	SPDK_FC_UNRECOVERABLE_ERR,
633 	SPDK_FC_EVENT_MAX,
634 };
635 
636 /**
637  * Arguments for to dump assoc id
638  */
639 struct spdk_nvmf_fc_dump_assoc_id_args {
640 	uint8_t                           pport_handle;
641 	uint16_t                          nport_handle;
642 	uint32_t                          assoc_id;
643 };
644 
645 /**
646  * Arguments for HW port init event.
647  */
648 struct spdk_nvmf_fc_hw_port_init_args {
649 	spdk_nvmf_fc_lld_fc_port_t     lld_fc_port;
650 	uint32_t                       ls_queue_size;
651 	spdk_nvmf_fc_lld_hwqp_t        ls_queue;
652 	uint32_t                       io_queue_size;
653 	uint32_t                       io_queue_cnt;
654 	spdk_nvmf_fc_lld_hwqp_t       *io_queues;
655 	void                          *cb_ctx;
656 	void                          *port_ctx;
657 	uint8_t                        port_handle;
658 	uint8_t                        nvme_aq_index;  /* io_queue used for nvme admin queue */
659 	uint16_t                       fcp_rq_id; /* Base rq ID of SCSI queue */
660 };
661 
662 /**
663  * Arguments for HW port online event.
664  */
665 struct spdk_nvmf_fc_hw_port_online_args {
666 	uint8_t port_handle;
667 	void   *cb_ctx;
668 };
669 
670 /**
671  * Arguments for HW port offline event.
672  */
673 struct spdk_nvmf_fc_hw_port_offline_args {
674 	uint8_t port_handle;
675 	void   *cb_ctx;
676 };
677 
678 /**
679  * Arguments for n-port add event.
680  */
681 struct spdk_nvmf_fc_nport_create_args {
682 	uint8_t                     port_handle;
683 	uint16_t                    nport_handle;
684 	struct spdk_uuid            container_uuid; /* UUID of the nports container */
685 	struct spdk_uuid            nport_uuid;     /* Unique UUID for the nport */
686 	uint32_t                    d_id;
687 	struct spdk_nvmf_fc_wwn fc_nodename;
688 	struct spdk_nvmf_fc_wwn fc_portname;
689 	uint32_t                    subsys_id; /* Subsystemid */
690 	char                        port_id[SPDK_NVMF_PORT_ID_MAX_LEN];
691 	void                       *cb_ctx;
692 };
693 
694 /**
695  * Arguments for n-port delete event.
696  */
697 struct spdk_nvmf_fc_nport_delete_args {
698 	uint8_t  port_handle;
699 	uint32_t nport_handle;
700 	uint32_t subsys_id; /* Subsystem id */
701 	void    *cb_ctx;
702 };
703 
704 /**
705  * Arguments for I_T add event.
706  */
707 struct spdk_nvmf_fc_hw_i_t_add_args {
708 	uint8_t                      port_handle;
709 	uint32_t                     nport_handle;
710 	uint16_t                     itn_handle;
711 	uint32_t                     rpi;
712 	uint32_t                     s_id;
713 	uint32_t                     initiator_prli_info;
714 	uint32_t                     target_prli_info; /* populated by the SPDK main */
715 	struct spdk_nvmf_fc_wwn  fc_nodename;
716 	struct spdk_nvmf_fc_wwn  fc_portname;
717 	void                        *cb_ctx;
718 };
719 
720 /**
721  * Arguments for I_T delete event.
722  */
723 struct spdk_nvmf_fc_hw_i_t_delete_args {
724 	uint8_t  port_handle;
725 	uint32_t nport_handle;
726 	uint16_t itn_handle;    /* Only used by FC LLD driver; unused in SPDK */
727 	uint32_t rpi;
728 	uint32_t s_id;
729 	void    *cb_ctx;
730 };
731 
732 /**
733  * Arguments for ABTS  event.
734  */
735 struct spdk_nvmf_fc_abts_args {
736 	uint8_t  port_handle;
737 	uint32_t nport_handle;
738 	uint32_t rpi;
739 	uint16_t oxid, rxid;
740 	void    *cb_ctx;
741 };
742 
743 /**
744  * Arguments for port reset event.
745  */
746 struct spdk_nvmf_fc_hw_port_reset_args {
747 	uint8_t    port_handle;
748 	bool       dump_queues;
749 	char       reason[SPDK_FC_HW_DUMP_REASON_STR_MAX_SIZE];
750 	uint32_t **dump_buf;
751 	void      *cb_ctx;
752 };
753 
754 /**
755  * Arguments for unrecoverable error event
756  */
757 struct spdk_nvmf_fc_unrecoverable_error_event_args {
758 };
759 
760 struct spdk_nvmf_fc_hw_port_free_args {
761 	uint8_t port_handle;
762 	void    *cb_ctx;
763 };
764 
765 /**
766  * Callback function to the FCT driver.
767  */
768 typedef void (*spdk_nvmf_fc_callback)(uint8_t port_handle,
769 				      enum spdk_fc_event event_type,
770 				      void *arg, int err);
771 
772 struct spdk_nvmf_fc_remove_hwqp_cb_args {
773 	uint16_t pending_remove_hwqp;
774 	spdk_nvmf_fc_callback cb_fn;
775 	void *cb_args;
776 };
777 
778 /**
779  * Enqueue an FCT event to main thread
780  *
781  * \param event_type Type of the event.
782  * \param args Pointer to the argument structure.
783  * \param cb_func Callback function into fc driver.
784  *
785  * \return 0 on success, non-zero on failure.
786  */
787 int nvmf_fc_main_enqueue_event(enum spdk_fc_event event_type,
788 			       void *args,
789 			       spdk_nvmf_fc_callback cb_func);
790 
791 /*
792  * dump info
793  */
794 struct spdk_nvmf_fc_queue_dump_info {
795 	char *buffer;
796 	int   offset;
797 };
798 #define SPDK_FC_HW_DUMP_BUF_SIZE (10 * 4096)
799 
800 static inline void
801 nvmf_fc_dump_buf_print(struct spdk_nvmf_fc_queue_dump_info *dump_info, char *fmt, ...)
802 {
803 	uint64_t buffer_size = SPDK_FC_HW_DUMP_BUF_SIZE;
804 	int32_t avail = (int32_t)(buffer_size - dump_info->offset);
805 
806 	if (avail > 0) {
807 		va_list ap;
808 		int32_t written;
809 
810 		va_start(ap, fmt);
811 		written = vsnprintf(dump_info->buffer + dump_info->offset, avail, fmt, ap);
812 		if (written >= avail) {
813 			dump_info->offset += avail;
814 		} else {
815 			dump_info->offset += written;
816 		}
817 		va_end(ap);
818 	}
819 }
820 
821 /*
822  * NVMF FC caller callback definitions
823  */
824 
825 struct spdk_nvmf_fc_caller_ctx {
826 	void *ctx;
827 	spdk_nvmf_fc_caller_cb cb;
828 	void *cb_args;
829 	TAILQ_ENTRY(spdk_nvmf_fc_caller_ctx) link;
830 };
831 
832 /*
833  * NVMF FC Exchange Info (for debug)
834  */
835 struct spdk_nvmf_fc_xchg_info {
836 	uint32_t xchg_base;
837 	uint32_t xchg_total_count;
838 	uint32_t xchg_avail_count;
839 	uint32_t send_frame_xchg_id;
840 	uint8_t send_frame_seqid;
841 };
842 
843 /*
844  * NVMF FC inline and function prototypes
845  */
846 
847 static inline struct spdk_nvmf_fc_request *
848 nvmf_fc_get_fc_req(struct spdk_nvmf_request *req)
849 {
850 	return (struct spdk_nvmf_fc_request *)
851 	       ((uintptr_t)req - offsetof(struct spdk_nvmf_fc_request, req));
852 }
853 
854 static inline bool
855 nvmf_fc_is_port_dead(struct spdk_nvmf_fc_hwqp *hwqp)
856 {
857 	switch (hwqp->fc_port->hw_port_status) {
858 	case SPDK_FC_PORT_QUIESCED:
859 		return true;
860 	default:
861 		return false;
862 	}
863 }
864 
865 static inline bool
866 nvmf_fc_req_in_xfer(struct spdk_nvmf_fc_request *fc_req)
867 {
868 	switch (fc_req->state) {
869 	case SPDK_NVMF_FC_REQ_READ_XFER:
870 	case SPDK_NVMF_FC_REQ_READ_RSP:
871 	case SPDK_NVMF_FC_REQ_WRITE_XFER:
872 	case SPDK_NVMF_FC_REQ_WRITE_RSP:
873 	case SPDK_NVMF_FC_REQ_NONE_RSP:
874 		return true;
875 	default:
876 		return false;
877 	}
878 }
879 
880 static inline void
881 nvmf_fc_create_trid(struct spdk_nvme_transport_id *trid, uint64_t n_wwn, uint64_t p_wwn)
882 {
883 	spdk_nvme_trid_populate_transport(trid, SPDK_NVME_TRANSPORT_FC);
884 	trid->adrfam = SPDK_NVMF_ADRFAM_FC;
885 	snprintf(trid->trsvcid, sizeof(trid->trsvcid), "none");
886 	snprintf(trid->traddr, sizeof(trid->traddr), "nn-0x%lx:pn-0x%lx", n_wwn, p_wwn);
887 }
888 
889 void nvmf_fc_ls_init(struct spdk_nvmf_fc_port *fc_port);
890 
891 void nvmf_fc_ls_fini(struct spdk_nvmf_fc_port *fc_port);
892 
893 void nvmf_fc_handle_ls_rqst(struct spdk_nvmf_fc_ls_rqst *ls_rqst);
894 void nvmf_fc_ls_add_conn_failure(
895 	struct spdk_nvmf_fc_association *assoc,
896 	struct spdk_nvmf_fc_ls_rqst *ls_rqst,
897 	struct spdk_nvmf_fc_conn *fc_conn,
898 	bool aq_conn);
899 
900 int nvmf_fc_init_hwqp(struct spdk_nvmf_fc_port *fc_port, struct spdk_nvmf_fc_hwqp *hwqp);
901 
902 struct spdk_nvmf_fc_conn *nvmf_fc_hwqp_find_fc_conn(struct spdk_nvmf_fc_hwqp *hwqp,
903 		uint64_t conn_id);
904 
905 struct spdk_nvmf_fc_port *nvmf_fc_port_lookup(uint8_t port_hdl);
906 
907 bool nvmf_fc_port_is_offline(struct spdk_nvmf_fc_port *fc_port);
908 
909 int nvmf_fc_port_set_offline(struct spdk_nvmf_fc_port *fc_port);
910 
911 bool nvmf_fc_port_is_online(struct spdk_nvmf_fc_port *fc_port);
912 
913 int nvmf_fc_port_set_online(struct spdk_nvmf_fc_port *fc_port);
914 
915 int nvmf_fc_rport_set_state(struct spdk_nvmf_fc_remote_port_info *rport,
916 			    enum spdk_nvmf_fc_object_state state);
917 
918 void nvmf_fc_port_add(struct spdk_nvmf_fc_port *fc_port);
919 
920 int nvmf_fc_port_add_nport(struct spdk_nvmf_fc_port *fc_port,
921 			   struct spdk_nvmf_fc_nport *nport);
922 
923 int nvmf_fc_port_remove_nport(struct spdk_nvmf_fc_port *fc_port,
924 			      struct spdk_nvmf_fc_nport *nport);
925 
926 struct spdk_nvmf_fc_nport *nvmf_fc_nport_find(uint8_t port_hdl, uint16_t nport_hdl);
927 
928 int nvmf_fc_nport_set_state(struct spdk_nvmf_fc_nport *nport,
929 			    enum spdk_nvmf_fc_object_state state);
930 
931 bool nvmf_fc_nport_add_rem_port(struct spdk_nvmf_fc_nport *nport,
932 				struct spdk_nvmf_fc_remote_port_info *rem_port);
933 
934 bool nvmf_fc_nport_remove_rem_port(struct spdk_nvmf_fc_nport *nport,
935 				   struct spdk_nvmf_fc_remote_port_info *rem_port);
936 
937 bool nvmf_fc_nport_has_no_rport(struct spdk_nvmf_fc_nport *nport);
938 
939 int nvmf_fc_assoc_set_state(struct spdk_nvmf_fc_association *assoc,
940 			    enum spdk_nvmf_fc_object_state state);
941 
942 int nvmf_fc_delete_association(struct spdk_nvmf_fc_nport *tgtport,
943 			       uint64_t assoc_id, bool send_abts, bool backend_initiated,
944 			       spdk_nvmf_fc_del_assoc_cb del_assoc_cb,
945 			       void *cb_data);
946 
947 int nvmf_fc_delete_connection(struct spdk_nvmf_fc_conn *fc_conn, bool send_abts,
948 			      bool backend_initiated, spdk_nvmf_fc_del_conn_cb cb_fn,
949 			      void *cb_data);
950 
951 bool nvmf_ctrlr_is_on_nport(uint8_t port_hdl, uint16_t nport_hdl,
952 			    struct spdk_nvmf_ctrlr *ctrlr);
953 
954 void nvmf_fc_assign_queue_to_main_thread(struct spdk_nvmf_fc_hwqp *hwqp);
955 
956 bool nvmf_fc_poll_group_valid(struct spdk_nvmf_fc_poll_group *fgroup);
957 
958 void nvmf_fc_poll_group_add_hwqp(struct spdk_nvmf_fc_hwqp *hwqp);
959 
960 void nvmf_fc_poll_group_remove_hwqp(struct spdk_nvmf_fc_hwqp *hwqp,
961 				    spdk_nvmf_fc_remove_hwqp_cb cb_fn, void *cb_ctx);
962 
963 int nvmf_fc_hwqp_set_online(struct spdk_nvmf_fc_hwqp *hwqp);
964 
965 int nvmf_fc_hwqp_set_offline(struct spdk_nvmf_fc_hwqp *hwqp);
966 
967 uint32_t nvmf_fc_get_prli_service_params(void);
968 
969 void nvmf_fc_handle_abts_frame(struct spdk_nvmf_fc_nport *nport, uint16_t rpi, uint16_t oxid,
970 			       uint16_t rxid);
971 
972 void nvmf_fc_request_abort(struct spdk_nvmf_fc_request *fc_req, bool send_abts,
973 			   spdk_nvmf_fc_caller_cb cb, void *cb_args);
974 
975 struct spdk_nvmf_tgt *nvmf_fc_get_tgt(void);
976 
977 struct spdk_thread *nvmf_fc_get_main_thread(void);
978 
979 /*
980  * These functions are called by low level FC driver
981  */
982 
983 static inline struct spdk_nvmf_fc_conn *
984 nvmf_fc_get_conn(struct spdk_nvmf_qpair *qpair)
985 {
986 	return (struct spdk_nvmf_fc_conn *)
987 	       ((uintptr_t)qpair - offsetof(struct spdk_nvmf_fc_conn, qpair));
988 }
989 
990 static inline uint16_t
991 nvmf_fc_advance_conn_sqhead(struct spdk_nvmf_qpair *qpair)
992 {
993 	/* advance sq_head pointer - wrap if needed */
994 	qpair->sq_head = (qpair->sq_head == qpair->sq_head_max) ?
995 			 0 : (qpair->sq_head + 1);
996 	return qpair->sq_head;
997 }
998 
999 static inline bool
1000 nvmf_fc_use_send_frame(struct spdk_nvmf_fc_request *fc_req)
1001 {
1002 	struct spdk_nvmf_request *req = &fc_req->req;
1003 
1004 	if (fc_req->app_id) {
1005 		return false;
1006 	}
1007 
1008 	/* For now use for only keepalives. */
1009 	if (req->qpair->qid == 0 &&
1010 	    (req->cmd->nvme_cmd.opc == SPDK_NVME_OPC_KEEP_ALIVE)) {
1011 		return true;
1012 	}
1013 	return false;
1014 }
1015 
1016 enum spdk_nvmf_fc_poller_api_ret nvmf_fc_poller_api_func(
1017 	struct spdk_nvmf_fc_hwqp *hwqp,
1018 	enum spdk_nvmf_fc_poller_api api,
1019 	void *api_args);
1020 
1021 int nvmf_fc_hwqp_process_frame(struct spdk_nvmf_fc_hwqp *hwqp, uint32_t buff_idx,
1022 			       struct spdk_nvmf_fc_frame_hdr *frame,
1023 			       struct spdk_nvmf_fc_buffer_desc *buffer, uint32_t plen);
1024 
1025 void nvmf_fc_hwqp_process_pending_reqs(struct spdk_nvmf_fc_hwqp *hwqp);
1026 
1027 void nvmf_fc_hwqp_process_pending_ls_rqsts(struct spdk_nvmf_fc_hwqp *hwqp);
1028 
1029 void nvmf_fc_request_set_state(struct spdk_nvmf_fc_request *fc_req,
1030 			       enum spdk_nvmf_fc_request_state state);
1031 
1032 char *nvmf_fc_request_get_state_str(int state);
1033 
1034 void _nvmf_fc_request_free(struct spdk_nvmf_fc_request *fc_req);
1035 
1036 void nvmf_fc_request_abort_complete(void *arg1);
1037 
1038 bool nvmf_fc_send_ersp_required(struct spdk_nvmf_fc_request *fc_req,
1039 				uint32_t rsp_cnt, uint32_t xfer_len);
1040 
1041 int nvmf_fc_handle_rsp(struct spdk_nvmf_fc_request *req);
1042 
1043 int nvmf_fc_create_conn_reqpool(struct spdk_nvmf_fc_conn *fc_conn);
1044 
1045 void nvmf_fc_free_conn_reqpool(struct spdk_nvmf_fc_conn *fc_conn);
1046 
1047 #endif
1048