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