1/*-
2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 *    this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 *    this list of conditions and the following disclaimer in the documentation
13 *    and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34/**
35 * @file
36 * Implement remote device state machine for target and initiator.
37 */
38
39/*!
40@defgroup device_sm Node State Machine: Remote Device States
41*/
42
43#include "ocs.h"
44#include "ocs_device.h"
45#include "ocs_fabric.h"
46#include "ocs_els.h"
47
48static void *__ocs_d_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
49static void *__ocs_d_wait_del_node(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
50static void *__ocs_d_wait_del_ini_tgt(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
51static int32_t ocs_process_abts(ocs_io_t *io, fc_header_t *hdr);
52
53/**
54 * @ingroup device_sm
55 * @brief Send response to PRLI.
56 *
57 * <h3 class="desc">Description</h3>
58 * For device nodes, this function sends a PRLI response.
59 *
60 * @param io Pointer to a SCSI IO object.
61 * @param ox_id OX_ID of PRLI
62 *
63 * @return Returns None.
64 */
65
66void
67ocs_d_send_prli_rsp(ocs_io_t *io, uint16_t ox_id)
68{
69	ocs_t *ocs = io->ocs;
70	ocs_node_t *node = io->node;
71
72	/* If the back-end doesn't support the fc-type, we send an LS_RJT */
73	if (ocs->fc_type != node->fc_type) {
74		node_printf(node, "PRLI rejected by target-server, fc-type not supported\n");
75		ocs_send_ls_rjt(io, ox_id, FC_REASON_UNABLE_TO_PERFORM,
76				FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL);
77		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
78		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
79	}
80
81	/* If the back-end doesn't want to talk to this initiator, we send an LS_RJT */
82	if (node->sport->enable_tgt && (ocs_scsi_validate_initiator(node) == 0)) {
83		node_printf(node, "PRLI rejected by target-server\n");
84		ocs_send_ls_rjt(io, ox_id, FC_REASON_UNABLE_TO_PERFORM,
85				FC_EXPL_NO_ADDITIONAL, 0, NULL, NULL);
86		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
87		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
88	} else {
89		/*sm:  process PRLI payload, send PRLI acc */
90		ocs_send_prli_acc(io, ox_id, ocs->fc_type, NULL, NULL);
91
92		/* Immediately go to ready state to avoid window where we're
93		 * waiting for the PRLI LS_ACC to complete while holding FCP_CMNDs
94		 */
95		ocs_node_transition(node, __ocs_d_device_ready, NULL);
96	}
97}
98
99/**
100 * @ingroup device_sm
101 * @brief Device node state machine: Initiate node shutdown
102 *
103 * @param ctx Remote node state machine context.
104 * @param evt Event to process.
105 * @param arg Per event optional argument.
106 *
107 * @return Returns NULL.
108 */
109
110void *
111__ocs_d_initiate_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
112{
113	std_node_state_decl();
114
115	node_sm_trace();
116
117	switch(evt) {
118	case OCS_EVT_ENTER: {
119		int32_t rc = OCS_SCSI_CALL_COMPLETE; /* assume no wait needed */
120
121		ocs_scsi_io_alloc_disable(node);
122
123		/* make necessary delete upcall(s) */
124		if (node->init && !node->targ) {
125			ocs_log_debug(node->ocs,
126				"[%s] delete (initiator) WWPN %s WWNN %s\n",
127				node->display_name, node->wwpn, node->wwnn);
128			ocs_node_transition(node, __ocs_d_wait_del_node, NULL);
129			if (node->sport->enable_tgt) {
130				rc = ocs_scsi_del_initiator(node,
131						OCS_SCSI_INITIATOR_DELETED);
132			}
133			if (rc == OCS_SCSI_CALL_COMPLETE) {
134				ocs_node_post_event(node,
135					OCS_EVT_NODE_DEL_INI_COMPLETE, NULL);
136			}
137		} else if (node->targ && !node->init) {
138			ocs_log_debug(node->ocs,
139				"[%s] delete (target)    WWPN %s WWNN %s\n",
140				node->display_name, node->wwpn, node->wwnn);
141			ocs_node_transition(node, __ocs_d_wait_del_node, NULL);
142			if (node->sport->enable_ini) {
143				rc = ocs_scsi_del_target(node,
144						OCS_SCSI_TARGET_DELETED);
145			}
146			if (rc == OCS_SCSI_CALL_COMPLETE) {
147				ocs_node_post_event(node,
148					OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL);
149			}
150		} else if (node->init && node->targ) {
151			ocs_log_debug(node->ocs,
152				"[%s] delete (initiator+target) WWPN %s WWNN %s\n",
153				node->display_name, node->wwpn, node->wwnn);
154			ocs_node_transition(node, __ocs_d_wait_del_ini_tgt, NULL);
155			if (node->sport->enable_tgt) {
156				rc = ocs_scsi_del_initiator(node,
157						OCS_SCSI_INITIATOR_DELETED);
158			}
159			if (rc == OCS_SCSI_CALL_COMPLETE) {
160				ocs_node_post_event(node,
161					OCS_EVT_NODE_DEL_INI_COMPLETE, NULL);
162			}
163			rc = OCS_SCSI_CALL_COMPLETE; /* assume no wait needed */
164			if (node->sport->enable_ini) {
165				rc = ocs_scsi_del_target(node,
166						OCS_SCSI_TARGET_DELETED);
167			}
168			if (rc == OCS_SCSI_CALL_COMPLETE) {
169				ocs_node_post_event(node,
170					OCS_EVT_NODE_DEL_TGT_COMPLETE, NULL);
171			}
172		}
173
174		/* we've initiated the upcalls as needed, now kick off the node
175		 * detach to precipitate the aborting of outstanding exchanges
176		 * associated with said node
177		 *
178		 * Beware: if we've made upcall(s), we've already transitioned
179		 * to a new state by the time we execute this.
180		 * TODO: consider doing this before the upcalls...
181		 */
182		if (node->attached) {
183			/* issue hw node free; don't care if succeeds right away
184			 * or sometime later, will check node->attached later in
185			 * shutdown process
186			 */
187			rc = ocs_hw_node_detach(&ocs->hw, &node->rnode);
188			if (node->rnode.free_group) {
189				ocs_remote_node_group_free(node->node_group);
190				node->node_group = NULL;
191				node->rnode.free_group = FALSE;
192			}
193			if (rc != OCS_HW_RTN_SUCCESS &&
194				rc != OCS_HW_RTN_SUCCESS_SYNC) {
195				node_printf(node,
196					"Failed freeing HW node, rc=%d\n", rc);
197			}
198		}
199
200		/* if neither initiator nor target, proceed to cleanup */
201		if (!node->init && !node->targ){
202			/*
203			 * node has either been detached or is in the process
204			 * of being detached, call common node's initiate
205			 * cleanup function.
206			 */
207			ocs_node_initiate_cleanup(node);
208		}
209		break;
210	}
211	case OCS_EVT_ALL_CHILD_NODES_FREE:
212		/* Ignore, this can happen if an ELS is aborted,
213		 * while in a delay/retry state */
214		break;
215	default:
216		__ocs_d_common(__func__, ctx, evt, arg);
217		return NULL;
218	}
219	return NULL;
220}
221
222/**
223 * @ingroup device_sm
224 * @brief Device node state machine: Common device event handler.
225 *
226 * <h3 class="desc">Description</h3>
227 * For device nodes, this event handler manages default and common events.
228 *
229 * @param funcname Function name text.
230 * @param ctx Remote node state machine context.
231 * @param evt Event to process.
232 * @param arg Per event optional argument.
233 *
234 * @return Returns NULL.
235 */
236
237static void *
238__ocs_d_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
239{
240	ocs_node_t *node = NULL;
241	ocs_t *ocs = NULL;
242	ocs_assert(ctx, NULL);
243	node = ctx->app;
244	ocs_assert(node, NULL);
245	ocs = node->ocs;
246	ocs_assert(ocs, NULL);
247
248	switch(evt) {
249	/* Handle shutdown events */
250	case OCS_EVT_SHUTDOWN:
251		ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt));
252		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
253		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
254		break;
255	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
256		ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt));
257		node->shutdown_reason = OCS_NODE_SHUTDOWN_EXPLICIT_LOGO;
258		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
259		break;
260	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
261		ocs_log_debug(ocs, "[%s] %-20s %-20s\n", node->display_name, funcname, ocs_sm_event_name(evt));
262		node->shutdown_reason = OCS_NODE_SHUTDOWN_IMPLICIT_LOGO;
263		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
264		break;
265
266	default:
267		/* call default event handler common to all nodes */
268		__ocs_node_common(funcname, ctx, evt, arg);
269		break;
270	}
271	return NULL;
272}
273
274/**
275 * @ingroup device_sm
276 * @brief Device node state machine: Wait for a domain-attach completion in loop topology.
277 *
278 * <h3 class="desc">Description</h3>
279 * State waits for a domain-attached completion while in loop topology.
280 *
281 * @param ctx Remote node state machine context.
282 * @param evt Event to process.
283 * @param arg Per event optional argument.
284 *
285 * @return Returns NULL.
286 */
287
288void *
289__ocs_d_wait_loop(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
290{
291	std_node_state_decl();
292
293	node_sm_trace();
294
295	switch(evt) {
296	case OCS_EVT_ENTER:
297		ocs_node_hold_frames(node);
298		break;
299
300	case OCS_EVT_EXIT:
301		ocs_node_accept_frames(node);
302		break;
303
304	case OCS_EVT_DOMAIN_ATTACH_OK: {
305		/* send PLOGI automatically if initiator */
306		ocs_node_init_device(node, TRUE);
307		break;
308	}
309	default:
310		__ocs_d_common(__func__, ctx, evt, arg);
311		return NULL;
312	}
313
314	return NULL;
315}
316
317/**
318 * @ingroup device_sm
319 * @brief state: wait for node resume event
320 *
321 * State is entered when a node is in I+T mode and sends a delete initiator/target
322 * call to the target-server/initiator-client and needs to wait for that work to complete.
323 *
324 * @param ctx Remote node state machine context.
325 * @param evt Event to process.
326 * @param arg per event optional argument
327 *
328 * @return returns NULL
329 */
330
331void *
332__ocs_d_wait_del_ini_tgt(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
333{
334	std_node_state_decl();
335
336	node_sm_trace();
337
338	switch(evt) {
339	case OCS_EVT_ENTER:
340		ocs_node_hold_frames(node);
341		/* Fall through */
342
343	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
344	case OCS_EVT_ALL_CHILD_NODES_FREE:
345		/* These are expected events. */
346		break;
347
348	case OCS_EVT_NODE_DEL_INI_COMPLETE:
349	case OCS_EVT_NODE_DEL_TGT_COMPLETE:
350		ocs_node_transition(node, __ocs_d_wait_del_node, NULL);
351		break;
352
353	case OCS_EVT_EXIT:
354		ocs_node_accept_frames(node);
355		break;
356
357	case OCS_EVT_SRRS_ELS_REQ_FAIL:
358		/* Can happen as ELS IO IO's complete */
359		ocs_assert(node->els_req_cnt, NULL);
360		node->els_req_cnt--;
361		break;
362
363	/* ignore shutdown events as we're already in shutdown path */
364	case OCS_EVT_SHUTDOWN:
365		/* have default shutdown event take precedence */
366		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
367		/* fall through */
368	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
369	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
370		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
371		break;
372	case OCS_EVT_DOMAIN_ATTACH_OK:
373		/* don't care about domain_attach_ok */
374		break;
375	default:
376		__ocs_d_common(__func__, ctx, evt, arg);
377		return NULL;
378	}
379
380	return NULL;
381}
382
383/**
384 * @ingroup device_sm
385 * @brief state: Wait for node resume event.
386 *
387 * State is entered when a node sends a delete initiator/target call to the
388 * target-server/initiator-client and needs to wait for that work to complete.
389 *
390 * @param ctx Remote node state machine context.
391 * @param evt Event to process.
392 * @param arg Per event optional argument.
393 *
394 * @return Returns NULL.
395 */
396
397void *
398__ocs_d_wait_del_node(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
399{
400	std_node_state_decl();
401
402	node_sm_trace();
403
404	switch(evt) {
405	case OCS_EVT_ENTER:
406		ocs_node_hold_frames(node);
407		/* Fall through */
408
409	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
410	case OCS_EVT_ALL_CHILD_NODES_FREE:
411		/* These are expected events. */
412		break;
413
414	case OCS_EVT_NODE_DEL_INI_COMPLETE:
415	case OCS_EVT_NODE_DEL_TGT_COMPLETE:
416		/*
417		 * node has either been detached or is in the process of being detached,
418		 * call common node's initiate cleanup function
419		 */
420		ocs_node_initiate_cleanup(node);
421		break;
422
423	case OCS_EVT_EXIT:
424		ocs_node_accept_frames(node);
425		break;
426
427	case OCS_EVT_SRRS_ELS_REQ_FAIL:
428		/* Can happen as ELS IO IO's complete */
429		ocs_assert(node->els_req_cnt, NULL);
430		node->els_req_cnt--;
431		break;
432
433	/* ignore shutdown events as we're already in shutdown path */
434	case OCS_EVT_SHUTDOWN:
435		/* have default shutdown event take precedence */
436		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
437		/* fall through */
438	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
439	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
440		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
441		break;
442	case OCS_EVT_DOMAIN_ATTACH_OK:
443		/* don't care about domain_attach_ok */
444		break;
445	default:
446		__ocs_d_common(__func__, ctx, evt, arg);
447		return NULL;
448	}
449
450	return NULL;
451}
452
453/**
454 * @brief Save the OX_ID for sending LS_ACC sometime later.
455 *
456 * <h3 class="desc">Description</h3>
457 * When deferring the response to an ELS request, the OX_ID of the request
458 * is saved using this function.
459 *
460 * @param io Pointer to a SCSI IO object.
461 * @param hdr Pointer to the FC header.
462 * @param ls Defines the type of ELS to send: LS_ACC, LS_ACC for PLOGI;
463 * or LSS_ACC for PRLI.
464 *
465 * @return None.
466 */
467
468void
469ocs_send_ls_acc_after_attach(ocs_io_t *io, fc_header_t *hdr, ocs_node_send_ls_acc_e ls)
470{
471	ocs_node_t *node = io->node;
472	uint16_t ox_id = ocs_be16toh(hdr->ox_id);
473
474	ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_NONE);
475
476	node->ls_acc_oxid = ox_id;
477	node->send_ls_acc = ls;
478	node->ls_acc_io = io;
479	node->ls_acc_did = fc_be24toh(hdr->d_id);
480}
481
482/**
483 * @brief Process the PRLI payload.
484 *
485 * <h3 class="desc">Description</h3>
486 * The PRLI payload is processed; the initiator/target capabilities of the
487 * remote node are extracted and saved in the node object.
488 *
489 * @param node Pointer to the node object.
490 * @param prli Pointer to the PRLI payload.
491 *
492 * @return None.
493 */
494
495void
496ocs_process_prli_payload(ocs_node_t *node, fc_prli_payload_t *prli)
497{
498	node->init = (ocs_be16toh(prli->service_params) & FC_PRLI_INITIATOR_FUNCTION) != 0;
499	node->targ = (ocs_be16toh(prli->service_params) & FC_PRLI_TARGET_FUNCTION) != 0;
500	node->fcp2device = (ocs_be16toh(prli->service_params) & FC_PRLI_RETRY) != 0;
501	node->fc_type = prli->type;
502}
503
504/**
505 * @brief Process the ABTS.
506 *
507 * <h3 class="desc">Description</h3>
508 * Common code to process a received ABTS. If an active IO can be found
509 * that matches the OX_ID of the ABTS request, a call is made to the
510 * backend. Otherwise, a BA_ACC is returned to the initiator.
511 *
512 * @param io Pointer to a SCSI IO object.
513 * @param hdr Pointer to the FC header.
514 *
515 * @return Returns 0 on success, or a negative error value on failure.
516 */
517
518static int32_t
519ocs_process_abts(ocs_io_t *io, fc_header_t *hdr)
520{
521	ocs_node_t *node = io->node;
522	ocs_t *ocs = node->ocs;
523	uint16_t ox_id = ocs_be16toh(hdr->ox_id);
524	uint16_t rx_id = ocs_be16toh(hdr->rx_id);
525	ocs_io_t *abortio;
526
527	abortio = ocs_io_find_tgt_io(ocs, node, ox_id, rx_id);
528
529	/* If an IO was found, attempt to take a reference on it */
530	if (abortio != NULL && (ocs_ref_get_unless_zero(&abortio->ref) != 0)) {
531		/* Got a reference on the IO. Hold it until backend is notified below */
532		node_printf(node, "Abort request: ox_id [%04x] rx_id [%04x]\n",
533			    ox_id, rx_id);
534
535		/*
536		 * Save the ox_id for the ABTS as the init_task_tag in our manufactured
537		 * TMF IO object
538		 */
539		io->display_name = "abts";
540		io->init_task_tag = ox_id;
541		/* don't set tgt_task_tag, don't want to confuse with XRI */
542
543		/*
544		 * Save the rx_id from the ABTS as it is needed for the BLS response,
545		 * regardless of the IO context's rx_id
546		 */
547		io->abort_rx_id = rx_id;
548
549		/* Call target server command abort */
550		io->tmf_cmd = OCS_SCSI_TMF_ABORT_TASK;
551		ocs_scsi_recv_tmf(io, abortio->tgt_io.lun, OCS_SCSI_TMF_ABORT_TASK, abortio, 0);
552
553		/*
554		 * Backend will have taken an additional reference on the IO if needed;
555		 * done with current reference.
556		 */
557		ocs_ref_put(&abortio->ref); /* ocs_ref_get(): same function */
558	} else {
559		/*
560		 * Either IO was not found or it has been freed between finding it
561		 * and attempting to get the reference,
562		 */
563		node_printf(node, "Abort request: ox_id [%04x], IO not found (exists=%d)\n",
564			    ox_id, (abortio != NULL));
565
566		/* Send a BA_ACC */
567		ocs_bls_send_acc_hdr(io, hdr);
568	}
569	return 0;
570}
571
572/**
573 * @ingroup device_sm
574 * @brief Device node state machine: Wait for the PLOGI accept to complete.
575 *
576 * @param ctx Remote node state machine context.
577 * @param evt Event to process.
578 * @param arg Per event optional argument.
579 *
580 * @return Returns NULL.
581 */
582
583void *
584__ocs_d_wait_plogi_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
585{
586	std_node_state_decl();
587
588	node_sm_trace();
589
590	switch(evt) {
591	case OCS_EVT_ENTER:
592		ocs_node_hold_frames(node);
593		break;
594
595	case OCS_EVT_EXIT:
596		ocs_node_accept_frames(node);
597		break;
598
599	case OCS_EVT_SRRS_ELS_CMPL_FAIL:
600		ocs_assert(node->els_cmpl_cnt, NULL);
601		node->els_cmpl_cnt--;
602		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
603		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
604		break;
605
606	case OCS_EVT_SRRS_ELS_CMPL_OK:	/* PLOGI ACC completions */
607		ocs_assert(node->els_cmpl_cnt, NULL);
608		node->els_cmpl_cnt--;
609		ocs_node_transition(node, __ocs_d_port_logged_in, NULL);
610		break;
611
612	default:
613		__ocs_d_common(__func__, ctx, evt, arg);
614		return NULL;
615	}
616
617	return NULL;
618}
619
620/**
621 * @ingroup device_sm
622 * @brief Device node state machine: Wait for the LOGO response.
623 *
624 * @param ctx Remote node state machine context.
625 * @param evt Event to process.
626 * @param arg Per event optional argument.
627 *
628 * @return Returns NULL.
629 */
630
631void *
632__ocs_d_wait_logo_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
633{
634	std_node_state_decl();
635
636	node_sm_trace();
637
638	switch(evt) {
639	case OCS_EVT_ENTER:
640		/* TODO: may want to remove this;
641		 * if we'll want to know about PLOGI */
642		ocs_node_hold_frames(node);
643		break;
644
645	case OCS_EVT_EXIT:
646		ocs_node_accept_frames(node);
647		break;
648
649	case OCS_EVT_SRRS_ELS_REQ_OK:
650	case OCS_EVT_SRRS_ELS_REQ_RJT:
651	case OCS_EVT_SRRS_ELS_REQ_FAIL:
652		/* LOGO response received, sent shutdown */
653		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_LOGO, __ocs_d_common, __func__)) {
654			return NULL;
655		}
656		ocs_assert(node->els_req_cnt, NULL);
657		node->els_req_cnt--;
658		node_printf(node, "LOGO sent (evt=%s), shutdown node\n", ocs_sm_event_name(evt));
659		/* sm: post explicit logout */
660		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
661		break;
662
663	/* TODO: PLOGI: abort LOGO and process PLOGI? (SHUTDOWN_EXPLICIT/IMPLICIT_LOGO?) */
664
665	default:
666		__ocs_d_common(__func__, ctx, evt, arg);
667		return NULL;
668	}
669	return NULL;
670}
671
672/**
673 * @ingroup device_sm
674 * @brief Device node state machine: Wait for the PRLO response.
675 *
676 * @param ctx Remote node state machine context.
677 * @param evt Event to process.
678 * @param arg Per event optional argument.
679 *
680 * @return Returns NULL.
681 */
682
683void *
684__ocs_d_wait_prlo_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
685{
686	std_node_state_decl();
687
688	node_sm_trace();
689
690	switch(evt) {
691		case OCS_EVT_ENTER:
692			ocs_node_hold_frames(node);
693			break;
694
695		case OCS_EVT_EXIT:
696			ocs_node_accept_frames(node);
697			break;
698
699		case OCS_EVT_SRRS_ELS_REQ_OK:
700		case OCS_EVT_SRRS_ELS_REQ_RJT:
701		case OCS_EVT_SRRS_ELS_REQ_FAIL:
702			if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLO, __ocs_d_common, __func__)) {
703				return NULL;
704			}
705			ocs_assert(node->els_req_cnt, NULL);
706			node->els_req_cnt--;
707			node_printf(node, "PRLO sent (evt=%s)\n", ocs_sm_event_name(evt));
708			ocs_node_transition(node, __ocs_d_port_logged_in, NULL);
709			break;
710
711		default:
712			__ocs_node_common(__func__, ctx, evt, arg);
713			return NULL;
714	}
715	return NULL;
716}
717
718/**
719 * @brief Initialize device node.
720 *
721 * Initialize device node. If a node is an initiator, then send a PLOGI and transition
722 * to __ocs_d_wait_plogi_rsp, otherwise transition to __ocs_d_init.
723 *
724 * @param node Pointer to the node object.
725 * @param send_plogi Boolean indicating to send PLOGI command or not.
726 *
727 * @return none
728 */
729
730void
731ocs_node_init_device(ocs_node_t *node, int send_plogi)
732{
733	node->send_plogi = send_plogi;
734	if ((node->ocs->nodedb_mask & OCS_NODEDB_PAUSE_NEW_NODES) && !FC_ADDR_IS_DOMAIN_CTRL(node->rnode.fc_id)) {
735		node->nodedb_state = __ocs_d_init;
736		ocs_node_transition(node, __ocs_node_paused, NULL);
737	} else {
738		ocs_node_transition(node, __ocs_d_init, NULL);
739	}
740}
741
742/**
743 * @ingroup device_sm
744 * @brief Device node state machine: Initial node state for an initiator or a target.
745 *
746 * <h3 class="desc">Description</h3>
747 * This state is entered when a node is instantiated, either having been
748 * discovered from a name services query, or having received a PLOGI/FLOGI.
749 *
750 * @param ctx Remote node state machine context.
751 * @param evt Event to process.
752 * @param arg Per event optional argument.
753 * - OCS_EVT_ENTER: (uint8_t *) - 1 to send a PLOGI on
754 * entry (initiator-only); 0 indicates a PLOGI is
755 * not sent on entry (initiator-only). Not applicable for a target.
756 *
757 * @return Returns NULL.
758 */
759
760void *
761__ocs_d_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
762{
763	int32_t rc;
764	ocs_node_cb_t *cbdata = arg;
765	std_node_state_decl();
766
767	node_sm_trace();
768
769	switch(evt) {
770	case OCS_EVT_ENTER:
771		/* check if we need to send PLOGI */
772		if (node->send_plogi) {
773			/* only send if we have initiator capability, and domain is attached */
774			if (node->sport->enable_ini && node->sport->domain->attached) {
775				ocs_send_plogi(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT,
776						OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
777				ocs_node_transition(node, __ocs_d_wait_plogi_rsp, NULL);
778			} else {
779				node_printf(node, "not sending plogi sport.ini=%d, domain attached=%d\n",
780					    node->sport->enable_ini, node->sport->domain->attached);
781			}
782		}
783		break;
784	case OCS_EVT_PLOGI_RCVD: {
785		/* T, or I+T */
786		fc_header_t *hdr = cbdata->header->dma.virt;
787		uint32_t d_id = fc_be24toh(hdr->d_id);
788
789		ocs_node_save_sparms(node, cbdata->payload->dma.virt);
790		ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI);
791
792		/* domain already attached */
793		if (node->sport->domain->attached) {
794			rc = ocs_node_attach(node);
795			ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
796			if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
797				ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
798			}
799			break;
800		}
801
802		/* domain not attached; several possibilities: */
803		switch (node->sport->topology) {
804		case OCS_SPORT_TOPOLOGY_P2P:
805			/* we're not attached and sport is p2p, need to attach */
806			ocs_domain_attach(node->sport->domain, d_id);
807			ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL);
808			break;
809		case OCS_SPORT_TOPOLOGY_FABRIC:
810			/* we're not attached and sport is fabric, domain attach should have
811			 * already been requested as part of the fabric state machine, wait for it
812			 */
813			ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL);
814			break;
815		case OCS_SPORT_TOPOLOGY_UNKNOWN:
816			/* Two possibilities:
817			 * 1. received a PLOGI before our FLOGI has completed (possible since
818			 *    completion comes in on another CQ), thus we don't know what we're
819			 *    connected to yet; transition to a state to wait for the fabric
820			 *    node to tell us;
821			 * 2. PLOGI received before link went down and we haven't performed
822			 *    domain attach yet.
823			 * Note: we cannot distinguish between 1. and 2. so have to assume PLOGI
824			 * was received after link back up.
825			 */
826			node_printf(node, "received PLOGI, with unknown topology did=0x%x\n", d_id);
827			ocs_node_transition(node, __ocs_d_wait_topology_notify, NULL);
828			break;
829		default:
830			node_printf(node, "received PLOGI, with unexpectd topology %d\n",
831				    node->sport->topology);
832			ocs_assert(FALSE, NULL);
833			break;
834		}
835		break;
836	}
837
838	case OCS_EVT_FDISC_RCVD: {
839		__ocs_d_common(__func__, ctx, evt, arg);
840		break;
841	}
842
843	case OCS_EVT_FLOGI_RCVD: {
844		fc_header_t *hdr = cbdata->header->dma.virt;
845
846		/* this better be coming from an NPort */
847		ocs_assert(ocs_rnode_is_nport(cbdata->payload->dma.virt), NULL);
848
849		/* sm: save sparams, send FLOGI acc */
850		ocs_domain_save_sparms(node->sport->domain, cbdata->payload->dma.virt);
851
852		/* send FC LS_ACC response, override s_id */
853		ocs_fabric_set_topology(node, OCS_SPORT_TOPOLOGY_P2P);
854		ocs_send_flogi_p2p_acc(cbdata->io, ocs_be16toh(hdr->ox_id), fc_be24toh(hdr->d_id), NULL, NULL);
855		if (ocs_p2p_setup(node->sport)) {
856			node_printf(node, "p2p setup failed, shutting down node\n");
857			ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL);
858		} else {
859			ocs_node_transition(node, __ocs_p2p_wait_flogi_acc_cmpl, NULL);
860		}
861
862		break;
863	}
864
865	case OCS_EVT_LOGO_RCVD: {
866		fc_header_t *hdr = cbdata->header->dma.virt;
867
868		if (!node->sport->domain->attached) {
869			 /* most likely a frame left over from before a link down; drop and
870			  * shut node down w/ "explicit logout" so pending frames are processed */
871			node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt));
872			ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
873			break;
874		}
875		ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
876		ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL);
877		break;
878	}
879
880	case OCS_EVT_PRLI_RCVD:
881	case OCS_EVT_PRLO_RCVD:
882	case OCS_EVT_PDISC_RCVD:
883	case OCS_EVT_ADISC_RCVD:
884	case OCS_EVT_RSCN_RCVD: {
885		fc_header_t *hdr = cbdata->header->dma.virt;
886		if (!node->sport->domain->attached) {
887			 /* most likely a frame left over from before a link down; drop and
888			  * shut node down w/ "explicit logout" so pending frames are processed */
889			node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt));
890			ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
891			break;
892		}
893		node_printf(node, "%s received, sending reject\n", ocs_sm_event_name(evt));
894		ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
895			FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NPORT_LOGIN_REQUIRED, 0,
896			NULL, NULL);
897
898		break;
899	}
900
901	case OCS_EVT_FCP_CMD_RCVD: {
902		/* note: problem, we're now expecting an ELS REQ completion
903		 * from both the LOGO and PLOGI */
904		if (!node->sport->domain->attached) {
905			 /* most likely a frame left over from before a link down; drop and
906			  * shut node down w/ "explicit logout" so pending frames are processed */
907			node_printf(node, "%s domain not attached, dropping\n", ocs_sm_event_name(evt));
908			ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
909			break;
910		}
911
912		/* Send LOGO */
913		node_printf(node, "FCP_CMND received, send LOGO\n");
914		if (ocs_send_logo(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, 0, NULL, NULL) == NULL) {
915			/* failed to send LOGO, go ahead and cleanup node anyways */
916			node_printf(node, "Failed to send LOGO\n");
917			ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
918		} else {
919			/* sent LOGO, wait for response */
920			ocs_node_transition(node, __ocs_d_wait_logo_rsp, NULL);
921		}
922		break;
923	}
924	case OCS_EVT_DOMAIN_ATTACH_OK:
925		/* don't care about domain_attach_ok */
926		break;
927
928	default:
929		__ocs_d_common(__func__, ctx, evt, arg);
930		return NULL;
931	}
932
933	return NULL;
934}
935
936/**
937 * @ingroup device_sm
938 * @brief Device node state machine: Wait on a response for a sent PLOGI.
939 *
940 * <h3 class="desc">Description</h3>
941 * State is entered when an initiator-capable node has sent
942 * a PLOGI and is waiting for a response.
943 *
944 * @param ctx Remote node state machine context.
945 * @param evt Event to process.
946 * @param arg Per event optional argument.
947 *
948 * @return Returns NULL.
949 */
950
951void *
952__ocs_d_wait_plogi_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
953{
954	int32_t rc;
955	ocs_node_cb_t *cbdata = arg;
956	std_node_state_decl();
957
958	node_sm_trace();
959
960	switch(evt) {
961	case OCS_EVT_PLOGI_RCVD: {
962		/* T, or I+T */
963		/* received PLOGI with svc parms, go ahead and attach node
964		 * when PLOGI that was sent ultimately completes, it'll be a no-op
965		 */
966
967		/* TODO: there is an outstanding PLOGI sent, can we set a flag
968		 * to indicate that we don't want to retry it if it times out? */
969		ocs_node_save_sparms(node, cbdata->payload->dma.virt);
970		ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI);
971		/* sm: domain->attached / ocs_node_attach */
972		rc = ocs_node_attach(node);
973		ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
974		if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
975			ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
976		}
977		break;
978	}
979
980	case OCS_EVT_PRLI_RCVD:
981		/* I, or I+T */
982		/* sent PLOGI and before completion was seen, received the
983		 * PRLI from the remote node (WCQEs and RCQEs come in on
984		 * different queues and order of processing cannot be assumed)
985		 * Save OXID so PRLI can be sent after the attach and continue
986		 * to wait for PLOGI response
987		 */
988		ocs_process_prli_payload(node, cbdata->payload->dma.virt);
989		if (ocs->fc_type == node->fc_type) {
990			ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PRLI);
991			ocs_node_transition(node, __ocs_d_wait_plogi_rsp_recvd_prli, NULL);
992		} else {
993			/* TODO this need to be looked at. What do we do here ? */
994		}
995		break;
996
997	/* TODO this need to be looked at. we could very well be logged in */
998	case OCS_EVT_LOGO_RCVD: /* why don't we do a shutdown here?? */
999	case OCS_EVT_PRLO_RCVD:
1000	case OCS_EVT_PDISC_RCVD:
1001	case OCS_EVT_FDISC_RCVD:
1002	case OCS_EVT_ADISC_RCVD:
1003	case OCS_EVT_RSCN_RCVD:
1004	case OCS_EVT_SCR_RCVD: {
1005		fc_header_t *hdr = cbdata->header->dma.virt;
1006		node_printf(node, "%s received, sending reject\n", ocs_sm_event_name(evt));
1007		ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
1008			FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NPORT_LOGIN_REQUIRED, 0,
1009			NULL, NULL);
1010
1011		break;
1012	}
1013
1014	case OCS_EVT_SRRS_ELS_REQ_OK:	/* PLOGI response received */
1015		/* Completion from PLOGI sent */
1016		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) {
1017			return NULL;
1018		}
1019		ocs_assert(node->els_req_cnt, NULL);
1020		node->els_req_cnt--;
1021		/* sm:  save sparams, ocs_node_attach */
1022		ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
1023		ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL,
1024			((uint8_t*)cbdata->els->els_rsp.virt) + 4);
1025		rc = ocs_node_attach(node);
1026		ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
1027		if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
1028			ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
1029		}
1030		break;
1031
1032	case OCS_EVT_SRRS_ELS_REQ_FAIL:	/* PLOGI response received */
1033		/* PLOGI failed, shutdown the node */
1034		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) {
1035			return NULL;
1036		}
1037		ocs_assert(node->els_req_cnt, NULL);
1038		node->els_req_cnt--;
1039		ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL);
1040		break;
1041
1042	case OCS_EVT_SRRS_ELS_REQ_RJT:	/* Our PLOGI was rejected, this is ok in some cases */
1043		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) {
1044			return NULL;
1045		}
1046		ocs_assert(node->els_req_cnt, NULL);
1047		node->els_req_cnt--;
1048		break;
1049
1050	case OCS_EVT_FCP_CMD_RCVD: {
1051		/* not logged in yet and outstanding PLOGI so don't send LOGO,
1052		 * just drop
1053		 */
1054		node_printf(node, "FCP_CMND received, drop\n");
1055		break;
1056	}
1057
1058	default:
1059		__ocs_d_common(__func__, ctx, evt, arg);
1060		return NULL;
1061	}
1062
1063	return NULL;
1064}
1065
1066/**
1067 * @ingroup device_sm
1068 * @brief Device node state machine: Waiting on a response for a
1069 *	sent PLOGI.
1070 *
1071 * <h3 class="desc">Description</h3>
1072 * State is entered when an initiator-capable node has sent
1073 * a PLOGI and is waiting for a response. Before receiving the
1074 * response, a PRLI was received, implying that the PLOGI was
1075 * successful.
1076 *
1077 * @param ctx Remote node state machine context.
1078 * @param evt Event to process.
1079 * @param arg Per event optional argument.
1080 *
1081 * @return Returns NULL.
1082 */
1083
1084void *
1085__ocs_d_wait_plogi_rsp_recvd_prli(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1086{
1087	int32_t rc;
1088	ocs_node_cb_t *cbdata = arg;
1089	std_node_state_decl();
1090
1091	node_sm_trace();
1092
1093	switch(evt) {
1094	case OCS_EVT_ENTER:
1095		/*
1096		 * Since we've received a PRLI, we have a port login and will
1097		 * just need to wait for the PLOGI response to do the node
1098		 * attach and then we can send the LS_ACC for the PRLI. If,
1099		 * during this time, we receive FCP_CMNDs (which is possible
1100		 * since we've already sent a PRLI and our peer may have accepted).
1101		 * At this time, we are not waiting on any other unsolicited
1102		 * frames to continue with the login process. Thus, it will not
1103		 * hurt to hold frames here.
1104		 */
1105		ocs_node_hold_frames(node);
1106		break;
1107
1108	case OCS_EVT_EXIT:
1109		ocs_node_accept_frames(node);
1110		break;
1111
1112	case OCS_EVT_SRRS_ELS_REQ_OK:	/* PLOGI response received */
1113		/* Completion from PLOGI sent */
1114		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) {
1115			return NULL;
1116		}
1117		ocs_assert(node->els_req_cnt, NULL);
1118		node->els_req_cnt--;
1119		/* sm:  save sparams, ocs_node_attach */
1120		ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
1121		ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL,
1122			((uint8_t*)cbdata->els->els_rsp.virt) + 4);
1123		rc = ocs_node_attach(node);
1124		ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
1125		if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
1126			ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
1127		}
1128		break;
1129
1130	case OCS_EVT_SRRS_ELS_REQ_FAIL:	/* PLOGI response received */
1131	case OCS_EVT_SRRS_ELS_REQ_RJT:
1132		/* PLOGI failed, shutdown the node */
1133		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_d_common, __func__)) {
1134			return NULL;
1135		}
1136		ocs_assert(node->els_req_cnt, NULL);
1137		node->els_req_cnt--;
1138		ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL);
1139		break;
1140
1141	default:
1142		__ocs_d_common(__func__, ctx, evt, arg);
1143		return NULL;
1144	}
1145
1146	return NULL;
1147}
1148
1149/**
1150 * @ingroup device_sm
1151 * @brief Device node state machine: Wait for a domain attach.
1152 *
1153 * <h3 class="desc">Description</h3>
1154 * Waits for a domain-attach complete ok event.
1155 *
1156 * @param ctx Remote node state machine context.
1157 * @param evt Event to process.
1158 * @param arg Per event optional argument.
1159 *
1160 * @return Returns NULL.
1161 */
1162
1163void *
1164__ocs_d_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1165{
1166	int32_t rc;
1167	std_node_state_decl();
1168
1169	node_sm_trace();
1170
1171	switch(evt) {
1172	case OCS_EVT_ENTER:
1173		ocs_node_hold_frames(node);
1174		break;
1175
1176	case OCS_EVT_EXIT:
1177		ocs_node_accept_frames(node);
1178		break;
1179
1180	case OCS_EVT_DOMAIN_ATTACH_OK:
1181		ocs_assert(node->sport->domain->attached, NULL);
1182		/* sm: ocs_node_attach */
1183		rc = ocs_node_attach(node);
1184		ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
1185		if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
1186			ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
1187		}
1188		break;
1189
1190	default:
1191		__ocs_d_common(__func__, ctx, evt, arg);
1192		return NULL;
1193	}
1194	return NULL;
1195}
1196
1197/**
1198 * @ingroup device_sm
1199 * @brief Device node state machine: Wait for topology
1200 *	notification
1201 *
1202 * <h3 class="desc">Description</h3>
1203 * Waits for topology notification from fabric node, then
1204 * attaches domain and node.
1205 *
1206 * @param ctx Remote node state machine context.
1207 * @param evt Event to process.
1208 * @param arg Per event optional argument.
1209 *
1210 * @return Returns NULL.
1211 */
1212
1213void *
1214__ocs_d_wait_topology_notify(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1215{
1216	int32_t rc;
1217	std_node_state_decl();
1218
1219	node_sm_trace();
1220
1221	switch(evt) {
1222	case OCS_EVT_ENTER:
1223		ocs_node_hold_frames(node);
1224		break;
1225
1226	case OCS_EVT_EXIT:
1227		ocs_node_accept_frames(node);
1228		break;
1229
1230	case OCS_EVT_SPORT_TOPOLOGY_NOTIFY: {
1231		ocs_sport_topology_e topology = (ocs_sport_topology_e)(uintptr_t)arg;
1232		ocs_assert(!node->sport->domain->attached, NULL);
1233		ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI, NULL);
1234		node_printf(node, "topology notification, topology=%d\n", topology);
1235
1236		/* At the time the PLOGI was received, the topology was unknown,
1237		 * so we didn't know which node would perform the domain attach:
1238		 * 1. The node from which the PLOGI was sent (p2p) or
1239		 * 2. The node to which the FLOGI was sent (fabric).
1240		 */
1241		if (topology == OCS_SPORT_TOPOLOGY_P2P) {
1242			/* if this is p2p, need to attach to the domain using the
1243			 * d_id from the PLOGI received
1244			 */
1245			ocs_domain_attach(node->sport->domain, node->ls_acc_did);
1246		}
1247		/* else, if this is fabric, the domain attach should be performed
1248		 * by the fabric node (node sending FLOGI); just wait for attach
1249		 * to complete
1250		 */
1251
1252		ocs_node_transition(node, __ocs_d_wait_domain_attach, NULL);
1253		break;
1254	}
1255	case OCS_EVT_DOMAIN_ATTACH_OK:
1256		ocs_assert(node->sport->domain->attached, NULL);
1257		node_printf(node, "domain attach ok\n");
1258		/*sm:  ocs_node_attach */
1259		rc = ocs_node_attach(node);
1260		ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
1261		if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
1262			ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
1263		}
1264		break;
1265
1266	default:
1267		__ocs_d_common(__func__, ctx, evt, arg);
1268		return NULL;
1269	}
1270	return NULL;
1271}
1272
1273/**
1274 * @ingroup device_sm
1275 * @brief Device node state machine: Wait for a node attach when found by a remote node.
1276 *
1277 * @param ctx Remote node state machine context.
1278 * @param evt Event to process.
1279 * @param arg Per event optional argument.
1280 *
1281 * @return Returns NULL.
1282 */
1283
1284void *
1285__ocs_d_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1286{
1287	std_node_state_decl();
1288
1289	node_sm_trace();
1290
1291	switch(evt) {
1292	case OCS_EVT_ENTER:
1293		ocs_node_hold_frames(node);
1294		break;
1295
1296	case OCS_EVT_EXIT:
1297		ocs_node_accept_frames(node);
1298		break;
1299
1300	case OCS_EVT_NODE_ATTACH_OK:
1301		node->attached = TRUE;
1302		switch (node->send_ls_acc) {
1303		case OCS_NODE_SEND_LS_ACC_PLOGI: {
1304			/* sm: send_plogi_acc is set / send PLOGI acc */
1305			/* Normal case for T, or I+T */
1306			ocs_send_plogi_acc(node->ls_acc_io, node->ls_acc_oxid, NULL, NULL);
1307			ocs_node_transition(node, __ocs_d_wait_plogi_acc_cmpl, NULL);
1308			node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE;
1309			node->ls_acc_io = NULL;
1310			break;
1311		}
1312		case OCS_NODE_SEND_LS_ACC_PRLI: {
1313			ocs_d_send_prli_rsp(node->ls_acc_io, node->ls_acc_oxid);
1314			node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE;
1315			node->ls_acc_io = NULL;
1316			break;
1317		}
1318		case OCS_NODE_SEND_LS_ACC_NONE:
1319		default:
1320			/* Normal case for I */
1321			/* sm: send_plogi_acc is not set / send PLOGI acc */
1322			ocs_node_transition(node, __ocs_d_port_logged_in, NULL);
1323			break;
1324		}
1325		break;
1326
1327	case OCS_EVT_NODE_ATTACH_FAIL:
1328		/* node attach failed, shutdown the node */
1329		node->attached = FALSE;
1330		node_printf(node, "node attach failed\n");
1331		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1332		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
1333		break;
1334
1335	/* Handle shutdown events */
1336	case OCS_EVT_SHUTDOWN:
1337		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1338		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1339		ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL);
1340		break;
1341	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1342		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1343		node->shutdown_reason = OCS_NODE_SHUTDOWN_EXPLICIT_LOGO;
1344		ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL);
1345		break;
1346	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1347		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1348		node->shutdown_reason = OCS_NODE_SHUTDOWN_IMPLICIT_LOGO;
1349		ocs_node_transition(node, __ocs_d_wait_attach_evt_shutdown, NULL);
1350		break;
1351	default:
1352		__ocs_d_common(__func__, ctx, evt, arg);
1353		return NULL;
1354	}
1355
1356	return NULL;
1357}
1358
1359/**
1360 * @ingroup device_sm
1361 * @brief Device node state machine: Wait for a node/domain
1362 * attach then shutdown node.
1363 *
1364 * @param ctx Remote node state machine context.
1365 * @param evt Event to process.
1366 * @param arg Per event optional argument.
1367 *
1368 * @return Returns NULL.
1369 */
1370
1371void *
1372__ocs_d_wait_attach_evt_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1373{
1374	std_node_state_decl();
1375
1376	node_sm_trace();
1377
1378	switch(evt) {
1379	case OCS_EVT_ENTER:
1380		ocs_node_hold_frames(node);
1381		break;
1382
1383	case OCS_EVT_EXIT:
1384		ocs_node_accept_frames(node);
1385		break;
1386
1387	/* wait for any of these attach events and then shutdown */
1388	case OCS_EVT_NODE_ATTACH_OK:
1389		node->attached = TRUE;
1390		node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt));
1391		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
1392		break;
1393
1394	case OCS_EVT_NODE_ATTACH_FAIL:
1395		/* node attach failed, shutdown the node */
1396		node->attached = FALSE;
1397		node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt));
1398		ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL);
1399		break;
1400
1401	/* ignore shutdown events as we're already in shutdown path */
1402	case OCS_EVT_SHUTDOWN:
1403		/* have default shutdown event take precedence */
1404		node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1405		/* fall through */
1406	case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1407	case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1408		node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1409		break;
1410
1411	default:
1412		__ocs_d_common(__func__, ctx, evt, arg);
1413		return NULL;
1414	}
1415
1416	return NULL;
1417}
1418
1419/**
1420 * @ingroup device_sm
1421 * @brief Device node state machine: Port is logged in.
1422 *
1423 * <h3 class="desc">Description</h3>
1424 * This state is entered when a remote port has completed port login (PLOGI).
1425 *
1426 * @param ctx Remote node state machine context.
1427 * @param evt Event to process
1428 * @param arg Per event optional argument
1429 *
1430 * @return Returns NULL.
1431 */
1432void *
1433__ocs_d_port_logged_in(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1434{
1435	ocs_node_cb_t *cbdata = arg;
1436	std_node_state_decl();
1437
1438	node_sm_trace();
1439
1440	/* TODO: I+T: what if PLOGI response not yet received ? */
1441
1442	switch(evt) {
1443	case OCS_EVT_ENTER:
1444		/* Normal case for I or I+T */
1445		if (node->sport->enable_ini && !FC_ADDR_IS_DOMAIN_CTRL(node->rnode.fc_id)
1446				&& !node->sent_prli) {
1447			/* sm: if enable_ini / send PRLI */
1448			ocs_send_prli(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
1449			node->sent_prli = TRUE;
1450			/* can now expect ELS_REQ_OK/FAIL/RJT */
1451		}
1452		break;
1453
1454	case OCS_EVT_FCP_CMD_RCVD: {
1455		/* For target functionality send PRLO and drop the CMD frame. */
1456		if (node->sport->enable_tgt) {
1457			if (ocs_send_prlo(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT,
1458				OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL)) {
1459				ocs_node_transition(node, __ocs_d_wait_prlo_rsp, NULL);
1460			}
1461		}
1462		break;
1463	}
1464
1465	case OCS_EVT_PRLI_RCVD: {
1466		fc_header_t *hdr = cbdata->header->dma.virt;
1467
1468		/* Normal for T or I+T */
1469
1470		ocs_process_prli_payload(node, cbdata->payload->dma.virt);
1471		ocs_d_send_prli_rsp(cbdata->io, ocs_be16toh(hdr->ox_id));
1472		break;
1473	}
1474
1475	case OCS_EVT_SRRS_ELS_REQ_OK: {	/* PRLI response */
1476		/* Normal case for I or I+T */
1477		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) {
1478			return NULL;
1479		}
1480		ocs_assert(node->els_req_cnt, NULL);
1481		node->els_req_cnt--;
1482		/* sm: process PRLI payload */
1483		ocs_process_prli_payload(node, cbdata->els->els_rsp.virt);
1484		ocs_node_transition(node, __ocs_d_device_ready, NULL);
1485		break;
1486	}
1487
1488	case OCS_EVT_SRRS_ELS_REQ_FAIL: {	/* PRLI response failed */
1489		/* I, I+T, assume some link failure, shutdown node */
1490		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) {
1491			return NULL;
1492		}
1493		ocs_assert(node->els_req_cnt, NULL);
1494		node->els_req_cnt--;
1495		ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL);
1496		break;
1497	}
1498
1499	case OCS_EVT_SRRS_ELS_REQ_RJT: {/* PRLI rejected by remote */
1500		/* Normal for I, I+T (connected to an I) */
1501		/* Node doesn't want to be a target, stay here and wait for a PRLI from the remote node
1502		 * if it really wants to connect to us as target */
1503		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PRLI, __ocs_d_common, __func__)) {
1504			return NULL;
1505		}
1506		ocs_assert(node->els_req_cnt, NULL);
1507		node->els_req_cnt--;
1508		break;
1509	}
1510
1511	case OCS_EVT_SRRS_ELS_CMPL_OK: {
1512		/* Normal T, I+T, target-server rejected the process login */
1513		/* This would be received only in the case where we sent LS_RJT for the PRLI, so
1514		 * do nothing.   (note: as T only we could shutdown the node)
1515		 */
1516		ocs_assert(node->els_cmpl_cnt, NULL);
1517		node->els_cmpl_cnt--;
1518		break;
1519	}
1520
1521	case OCS_EVT_PLOGI_RCVD: {
1522		/* sm: save sparams, set send_plogi_acc, post implicit logout
1523		 * Save plogi parameters */
1524		ocs_node_save_sparms(node, cbdata->payload->dma.virt);
1525		ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI);
1526
1527		/* Restart node attach with new service parameters, and send ACC */
1528		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL);
1529		break;
1530	}
1531
1532	case OCS_EVT_LOGO_RCVD: {
1533		/* I, T, I+T */
1534		fc_header_t *hdr = cbdata->header->dma.virt;
1535		node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached);
1536		ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1537		ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL);
1538		break;
1539	}
1540
1541	default:
1542		__ocs_d_common(__func__, ctx, evt, arg);
1543		return NULL;
1544	}
1545
1546	return NULL;
1547}
1548
1549/**
1550 * @ingroup device_sm
1551 * @brief Device node state machine: Wait for a LOGO accept.
1552 *
1553 * <h3 class="desc">Description</h3>
1554 * Waits for a LOGO accept completion.
1555 *
1556 * @param ctx Remote node state machine context.
1557 * @param evt Event to process
1558 * @param arg Per event optional argument
1559 *
1560 * @return Returns NULL.
1561 */
1562
1563void *
1564__ocs_d_wait_logo_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1565{
1566	std_node_state_decl();
1567
1568	node_sm_trace();
1569
1570	switch(evt) {
1571	case OCS_EVT_ENTER:
1572		ocs_node_hold_frames(node);
1573		break;
1574
1575	case OCS_EVT_EXIT:
1576		ocs_node_accept_frames(node);
1577		break;
1578
1579	case OCS_EVT_SRRS_ELS_CMPL_OK:
1580	case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1581		/* sm: / post explicit logout */
1582		ocs_assert(node->els_cmpl_cnt, NULL);
1583		node->els_cmpl_cnt--;
1584		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
1585		break;
1586	default:
1587		__ocs_d_common(__func__, ctx, evt, arg);
1588		return NULL;
1589	}
1590
1591	return NULL;
1592}
1593
1594/**
1595 * @ingroup device_sm
1596 * @brief Device node state machine: Device is ready.
1597 *
1598 * @param ctx Remote node state machine context.
1599 * @param evt Event to process.
1600 * @param arg Per event optional argument.
1601 *
1602 * @return Returns NULL.
1603 */
1604
1605void *
1606__ocs_d_device_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1607{
1608	ocs_node_cb_t *cbdata = arg;
1609	std_node_state_decl();
1610
1611	if (evt != OCS_EVT_FCP_CMD_RCVD) {
1612		node_sm_trace();
1613	}
1614
1615	switch(evt) {
1616	case OCS_EVT_ENTER:
1617		node->fcp_enabled = TRUE;
1618		if (node->init) {
1619			device_printf(ocs->dev, "[%s] found  (initiator) WWPN %s WWNN %s\n", node->display_name,
1620				node->wwpn, node->wwnn);
1621			if (node->sport->enable_tgt)
1622				ocs_scsi_new_initiator(node);
1623		}
1624		if (node->targ) {
1625			device_printf(ocs->dev, "[%s] found  (target)    WWPN %s WWNN %s\n", node->display_name,
1626				node->wwpn, node->wwnn);
1627			if (node->sport->enable_ini)
1628				ocs_scsi_new_target(node);
1629		}
1630		break;
1631
1632	case OCS_EVT_EXIT:
1633		node->fcp_enabled = FALSE;
1634		break;
1635
1636	case OCS_EVT_PLOGI_RCVD: {
1637		/* sm: save sparams, set send_plogi_acc, post implicit logout
1638		 * Save plogi parameters */
1639		ocs_node_save_sparms(node, cbdata->payload->dma.virt);
1640		ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI);
1641
1642		/* Restart node attach with new service parameters, and send ACC */
1643		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL);
1644		break;
1645	}
1646
1647	case OCS_EVT_PDISC_RCVD: {
1648		fc_header_t *hdr = cbdata->header->dma.virt;
1649		ocs_send_plogi_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1650		break;
1651	}
1652
1653	case OCS_EVT_PRLI_RCVD: {
1654		/* T, I+T: remote initiator is slow to get started */
1655		fc_header_t *hdr = cbdata->header->dma.virt;
1656
1657		ocs_process_prli_payload(node, cbdata->payload->dma.virt);
1658
1659		/* sm: send PRLI acc/reject */
1660		if (ocs->fc_type == node->fc_type)
1661			ocs_send_prli_acc(cbdata->io, ocs_be16toh(hdr->ox_id), ocs->fc_type, NULL, NULL);
1662		else
1663			ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), FC_REASON_UNABLE_TO_PERFORM,
1664				FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL);
1665		break;
1666	}
1667
1668	case OCS_EVT_PRLO_RCVD: {
1669		fc_header_t *hdr = cbdata->header->dma.virt;
1670		fc_prlo_payload_t *prlo = cbdata->payload->dma.virt;
1671
1672		/* sm: send PRLO acc/reject */
1673		if (ocs->fc_type == prlo->type)
1674			ocs_send_prlo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), ocs->fc_type, NULL, NULL);
1675		else
1676			ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id), FC_REASON_UNABLE_TO_PERFORM,
1677				FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL);
1678		/*TODO: need implicit logout */
1679		break;
1680	}
1681
1682	case OCS_EVT_LOGO_RCVD: {
1683		fc_header_t *hdr = cbdata->header->dma.virt;
1684		node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached);
1685		ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1686		ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL);
1687		break;
1688	}
1689
1690	case OCS_EVT_ADISC_RCVD: {
1691		fc_header_t *hdr = cbdata->header->dma.virt;
1692		ocs_send_adisc_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1693		break;
1694	}
1695
1696	case OCS_EVT_RRQ_RCVD: {
1697		fc_header_t *hdr = cbdata->header->dma.virt;
1698		/* Send LS_ACC */
1699		ocs_send_ls_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1700		break;
1701	}
1702
1703	case OCS_EVT_ABTS_RCVD:
1704		ocs_process_abts(cbdata->io, cbdata->header->dma.virt);
1705		break;
1706
1707	case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1708		break;
1709
1710	case OCS_EVT_NODE_REFOUND:
1711		break;
1712
1713	case OCS_EVT_NODE_MISSING:
1714		if (node->sport->enable_rscn) {
1715			ocs_node_transition(node, __ocs_d_device_gone, NULL);
1716		}
1717		break;
1718
1719	case OCS_EVT_SRRS_ELS_CMPL_OK:
1720		/* T, or I+T, PRLI accept completed ok */
1721		ocs_assert(node->els_cmpl_cnt, NULL);
1722		node->els_cmpl_cnt--;
1723		break;
1724
1725	case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1726		/* T, or I+T, PRLI accept failed to complete */
1727		ocs_assert(node->els_cmpl_cnt, NULL);
1728		node->els_cmpl_cnt--;
1729		node_printf(node, "Failed to send PRLI LS_ACC\n");
1730		break;
1731
1732	default:
1733		__ocs_d_common(__func__, ctx, evt, arg);
1734		return NULL;
1735	}
1736
1737	return NULL;
1738}
1739
1740/**
1741 * @ingroup device_sm
1742 * @brief Device node state machine: Node is gone (absent from GID_PT).
1743 *
1744 * <h3 class="desc">Description</h3>
1745 * State entered when a node is detected as being gone (absent from GID_PT).
1746 *
1747 * @param ctx Remote node state machine context.
1748 * @param evt Event to process
1749 * @param arg Per event optional argument
1750 *
1751 * @return Returns NULL.
1752 */
1753
1754void *
1755__ocs_d_device_gone(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1756{
1757	int32_t rc = OCS_SCSI_CALL_COMPLETE;
1758	int32_t rc_2 = OCS_SCSI_CALL_COMPLETE;
1759	ocs_node_cb_t *cbdata = arg;
1760	std_node_state_decl();
1761
1762	node_sm_trace();
1763
1764	switch(evt) {
1765	case OCS_EVT_ENTER: {
1766		const char *labels[] = {"none", "initiator", "target", "initiator+target"};
1767
1768		device_printf(ocs->dev, "[%s] missing (%s)    WWPN %s WWNN %s\n", node->display_name,
1769				labels[(node->targ << 1) | (node->init)], node->wwpn, node->wwnn);
1770
1771		switch(ocs_node_get_enable(node)) {
1772		case OCS_NODE_ENABLE_T_TO_T:
1773		case OCS_NODE_ENABLE_I_TO_T:
1774		case OCS_NODE_ENABLE_IT_TO_T:
1775			rc = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING);
1776			break;
1777
1778		case OCS_NODE_ENABLE_T_TO_I:
1779		case OCS_NODE_ENABLE_I_TO_I:
1780		case OCS_NODE_ENABLE_IT_TO_I:
1781			rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING);
1782			break;
1783
1784		case OCS_NODE_ENABLE_T_TO_IT:
1785			rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING);
1786			break;
1787
1788		case OCS_NODE_ENABLE_I_TO_IT:
1789			rc = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING);
1790			break;
1791
1792		case OCS_NODE_ENABLE_IT_TO_IT:
1793			rc = ocs_scsi_del_initiator(node, OCS_SCSI_INITIATOR_MISSING);
1794			rc_2 = ocs_scsi_del_target(node, OCS_SCSI_TARGET_MISSING);
1795			break;
1796
1797		default:
1798			rc = OCS_SCSI_CALL_COMPLETE;
1799			break;
1800		}
1801
1802		if ((rc == OCS_SCSI_CALL_COMPLETE) && (rc_2 == OCS_SCSI_CALL_COMPLETE)) {
1803			ocs_node_post_event(node, OCS_EVT_SHUTDOWN, NULL);
1804		}
1805
1806		break;
1807	}
1808	case OCS_EVT_NODE_REFOUND:
1809		/* two approaches, reauthenticate with PLOGI/PRLI, or ADISC */
1810
1811		/* reauthenticate with PLOGI/PRLI */
1812		/* ocs_node_transition(node, __ocs_d_discovered, NULL); */
1813
1814		/* reauthenticate with ADISC
1815		 * sm: send ADISC */
1816		ocs_send_adisc(node, OCS_FC_ELS_SEND_DEFAULT_TIMEOUT, OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
1817		ocs_node_transition(node, __ocs_d_wait_adisc_rsp, NULL);
1818		break;
1819
1820	case OCS_EVT_PLOGI_RCVD: {
1821		/* sm: save sparams, set send_plogi_acc, post implicit logout
1822		 * Save plogi parameters */
1823		ocs_node_save_sparms(node, cbdata->payload->dma.virt);
1824		ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PLOGI);
1825
1826		/* Restart node attach with new service parameters, and send ACC */
1827		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_IMPLICIT_LOGO, NULL);
1828		break;
1829	}
1830
1831	case OCS_EVT_FCP_CMD_RCVD: {
1832		/* most likely a stale frame (received prior to link down), if attempt
1833		 * to send LOGO, will probably timeout and eat up 20s; thus, drop FCP_CMND
1834		 */
1835		node_printf(node, "FCP_CMND received, drop\n");
1836		break;
1837	}
1838	case OCS_EVT_LOGO_RCVD: {
1839		/* I, T, I+T */
1840		fc_header_t *hdr = cbdata->header->dma.virt;
1841		node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached);
1842		/* sm: send LOGO acc */
1843		ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1844		ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL);
1845		break;
1846	}
1847	default:
1848		__ocs_d_common(__func__, ctx, evt, arg);
1849		return NULL;
1850	}
1851
1852	return NULL;
1853}
1854
1855/**
1856 * @ingroup device_sm
1857 * @brief Device node state machine: Wait for the ADISC response.
1858 *
1859 * <h3 class="desc">Description</h3>
1860 * Waits for the ADISC response from the remote node.
1861 *
1862 * @param ctx Remote node state machine context.
1863 * @param evt Event to process.
1864 * @param arg Per event optional argument.
1865 *
1866 * @return Returns NULL.
1867 */
1868
1869void *
1870__ocs_d_wait_adisc_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1871{
1872	ocs_node_cb_t *cbdata = arg;
1873	std_node_state_decl();
1874
1875	node_sm_trace();
1876
1877	switch(evt) {
1878	case OCS_EVT_SRRS_ELS_REQ_OK:
1879		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_ADISC, __ocs_d_common, __func__)) {
1880			return NULL;
1881		}
1882		ocs_assert(node->els_req_cnt, NULL);
1883		node->els_req_cnt--;
1884		ocs_node_transition(node, __ocs_d_device_ready, NULL);
1885		break;
1886
1887	case OCS_EVT_SRRS_ELS_REQ_RJT:
1888		/* received an LS_RJT, in this case, send shutdown (explicit logo)
1889		 * event which will unregister the node, and start over with PLOGI
1890		 */
1891		if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_ADISC, __ocs_d_common, __func__)) {
1892			return NULL;
1893		}
1894		ocs_assert(node->els_req_cnt, NULL);
1895		node->els_req_cnt--;
1896		/*sm: post explicit logout */
1897		ocs_node_post_event(node, OCS_EVT_SHUTDOWN_EXPLICIT_LOGO, NULL);
1898		break;
1899
1900	case OCS_EVT_LOGO_RCVD: {
1901		/* In this case, we have the equivalent of an LS_RJT for the ADISC,
1902		 * so we need to abort the ADISC, and re-login with PLOGI
1903		 */
1904		/*sm: request abort, send LOGO acc */
1905		fc_header_t *hdr = cbdata->header->dma.virt;
1906		node_printf(node, "%s received attached=%d\n", ocs_sm_event_name(evt), node->attached);
1907		ocs_send_logo_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1908		ocs_node_transition(node, __ocs_d_wait_logo_acc_cmpl, NULL);
1909		break;
1910	}
1911	default:
1912		__ocs_d_common(__func__, ctx, evt, arg);
1913		return NULL;
1914	}
1915
1916	return NULL;
1917}
1918