]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ocs_fc/ocs_device.c
Use a template assembly file for firmware object files.
[FreeBSD/FreeBSD.git] / sys / dev / ocs_fc / ocs_device.c
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
48 static void *__ocs_d_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
49 static void *__ocs_d_wait_del_node(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
50 static void *__ocs_d_wait_del_ini_tgt(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
51 static 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
66 void
67 ocs_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
110 void *
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
237 static 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
288 void *
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
331 void *
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
397 void *
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
468 void
469 ocs_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
495 void
496 ocs_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
518 static int32_t
519 ocs_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
583 void *
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
631 void *
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
683 void *
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
730 void
731 ocs_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
760 void *
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
951 void *
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
1084 void *
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
1163 void *
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
1213 void *
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
1284 void *
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
1371 void *
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  */
1432 void *
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
1563 void *
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
1605 void *
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
1754 void *
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
1869 void *
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 }