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