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