2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
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.
36 * OCS driver remote node handler. This file contains code that is shared
37 * between fabric (ocs_fabric.c) and device (ocs_device.c) nodes.
41 * @defgroup node_common Node common support
42 * @defgroup node_alloc Node allocation
47 #include "ocs_device.h"
49 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]"
50 #define SCSI_ITT_SIZE(ocs) ((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8)
52 #define SCSI_IOFMT_ARGS(io) io->instance_index, SCSI_ITT_SIZE(io->ocs), io->init_task_tag, SCSI_ITT_SIZE(io->ocs), io->tgt_task_tag, io->hw_tag
54 #define scsi_io_printf(io, fmt, ...) ocs_log_debug(io->ocs, "[%s]" SCSI_IOFMT fmt, \
55 io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__)
57 void ocs_mgmt_node_list(ocs_textbuf_t *textbuf, void *node);
58 void ocs_mgmt_node_get_all(ocs_textbuf_t *textbuf, void *node);
59 int ocs_mgmt_node_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *node);
60 int ocs_mgmt_node_set(char *parent, char *name, char *value, void *node);
61 int ocs_mgmt_node_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
62 void *arg_out, uint32_t arg_out_length, void *node);
63 static ocs_mgmt_functions_t node_mgmt_functions = {
64 .get_list_handler = ocs_mgmt_node_list,
65 .get_handler = ocs_mgmt_node_get,
66 .get_all_handler = ocs_mgmt_node_get_all,
67 .set_handler = ocs_mgmt_node_set,
68 .exec_handler = ocs_mgmt_node_exec,
73 * @ingroup node_common
74 * @brief Device node state machine wait for all ELS's to
77 * Abort all ELS's for given node.
79 * @param node node for which ELS's will be aborted
83 ocs_node_abort_all_els(ocs_node_t *node)
87 ocs_node_cb_t cbdata = {0};
89 ocs_node_hold_frames(node);
90 ocs_lock(&node->active_ios_lock);
91 ocs_list_foreach_safe(&node->els_io_active_list, els, els_next) {
92 ocs_log_debug(node->ocs, "[%s] initiate ELS abort %s\n", node->display_name, els->display_name);
93 ocs_unlock(&node->active_ios_lock);
95 ocs_els_post_event(els, OCS_EVT_ABORT_ELS, &cbdata);
96 ocs_lock(&node->active_ios_lock);
98 ocs_unlock(&node->active_ios_lock);
102 * @ingroup node_common
103 * @brief Handle remote node events from HW
105 * Handle remote node events from HW. Essentially the HW event is translated into
106 * a node state machine event that is posted to the affected node.
108 * @param arg pointer to ocs
109 * @param event HW event to proceoss
110 * @param data application specific data (pointer to the affected node)
112 * @return returns 0 for success, a negative error code value for failure.
115 ocs_remote_node_cb(void *arg, ocs_hw_remote_node_event_e event, void *data)
118 ocs_sm_event_t sm_event = OCS_EVT_LAST;
119 ocs_remote_node_t *rnode = data;
120 ocs_node_t *node = rnode->node;
123 case OCS_HW_NODE_ATTACH_OK:
124 sm_event = OCS_EVT_NODE_ATTACH_OK;
127 case OCS_HW_NODE_ATTACH_FAIL:
128 sm_event = OCS_EVT_NODE_ATTACH_FAIL;
131 case OCS_HW_NODE_FREE_OK:
132 sm_event = OCS_EVT_NODE_FREE_OK;
135 case OCS_HW_NODE_FREE_FAIL:
136 sm_event = OCS_EVT_NODE_FREE_FAIL;
140 ocs_log_test(ocs, "unhandled event %#x\n", event);
144 /* If we're using HLM, forward the NODE_ATTACH_OK/FAIL event to all nodes in the node group */
145 if ((node->node_group != NULL) &&
146 ((sm_event == OCS_EVT_NODE_ATTACH_OK) || (sm_event == OCS_EVT_NODE_ATTACH_FAIL))) {
147 ocs_node_t *n = NULL;
148 uint8_t attach_ok = sm_event == OCS_EVT_NODE_ATTACH_OK;
150 ocs_sport_lock(node->sport);
152 ocs_list_foreach(&node->sport->node_list, n) {
157 if ((!n->rnode.attached) && (node->node_group == n->node_group)) {
158 n->rnode.attached = attach_ok;
159 node_printf(n, "rpi[%d] deferred HLM node attach %s posted\n",
160 n->rnode.index, attach_ok ? "ok" : "fail");
161 ocs_node_post_event(n, sm_event, NULL);
167 ocs_sport_unlock(node->sport);
170 ocs_node_post_event(node, sm_event, NULL);
176 * @ingroup node_alloc
177 * @brief Find an FC node structure given the FC port ID
179 * @param sport the SPORT to search
180 * @param port_id FC port ID
182 * @return pointer to the object or NULL if not found
185 ocs_node_find(ocs_sport_t *sport, uint32_t port_id)
189 ocs_assert(sport->lookup, NULL);
190 ocs_sport_lock(sport);
191 node = spv_get(sport->lookup, port_id);
192 ocs_sport_unlock(sport);
197 * @ingroup node_alloc
198 * @brief Find an FC node structure given the WWPN
200 * @param sport the SPORT to search
201 * @param wwpn the WWPN to search for (host endian)
203 * @return pointer to the object or NULL if not found
206 ocs_node_find_wwpn(ocs_sport_t *sport, uint64_t wwpn)
208 ocs_node_t *node = NULL;;
210 ocs_assert(sport, NULL);
212 ocs_sport_lock(sport);
213 ocs_list_foreach(&sport->node_list, node) {
214 if (ocs_node_get_wwpn(node) == wwpn) {
215 ocs_sport_unlock(sport);
219 ocs_sport_unlock(sport);
224 * @ingroup node_alloc
225 * @brief allocate node object pool
227 * A pool of ocs_node_t objects is allocated.
229 * @param ocs pointer to driver instance context
230 * @param node_count count of nodes to allocate
232 * @return returns 0 for success, a negative error code value for failure.
236 ocs_node_create_pool(ocs_t *ocs, uint32_t node_count)
238 ocs_xport_t *xport = ocs->xport;
243 uint64_t max_xfer_size;
246 xport->nodes_count = node_count;
248 xport->nodes = ocs_malloc(ocs, node_count * sizeof(ocs_node_t *), OCS_M_ZERO | OCS_M_NOWAIT);
249 if (xport->nodes == NULL) {
250 ocs_log_err(ocs, "node ptrs allocation failed");
254 if (0 == ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &max_sge) &&
255 0 == ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &num_sgl)) {
256 max_xfer_size = (max_sge * (uint64_t)num_sgl);
258 max_xfer_size = 65536;
261 if (max_xfer_size > 65536)
262 max_xfer_size = 65536;
264 ocs_list_init(&xport->nodes_free_list, ocs_node_t, link);
267 for (i = 0; i < node_count; i ++) {
268 node = ocs_malloc(ocs, sizeof(ocs_node_t), OCS_M_ZERO | OCS_M_NOWAIT);
270 ocs_log_err(ocs, "node allocation failed");
274 /* Assign any persistent field values */
275 node->instance_index = i;
276 node->max_wr_xfer_size = max_xfer_size;
277 node->rnode.indicator = UINT32_MAX;
279 rc = ocs_dma_alloc(ocs, &node->sparm_dma_buf, 256, 16);
281 ocs_free(ocs, node, sizeof(ocs_node_t));
282 ocs_log_err(ocs, "ocs_dma_alloc failed: %d\n", rc);
286 xport->nodes[i] = node;
287 ocs_list_add_tail(&xport->nodes_free_list, node);
292 ocs_node_free_pool(ocs);
297 * @ingroup node_alloc
298 * @brief free node object pool
300 * The pool of previously allocated node objects is freed
302 * @param ocs pointer to driver instance context
308 ocs_node_free_pool(ocs_t *ocs)
310 ocs_xport_t *xport = ocs->xport;
317 ocs_device_lock(ocs);
319 for (i = 0; i < xport->nodes_count; i ++) {
320 node = xport->nodes[i];
322 /* free sparam_dma_buf */
323 ocs_dma_free(ocs, &node->sparm_dma_buf);
324 ocs_free(ocs, node, sizeof(ocs_node_t));
326 xport->nodes[i] = NULL;
329 ocs_free(ocs, xport->nodes, (xport->nodes_count * sizeof(ocs_node_t *)));
331 ocs_device_unlock(ocs);
335 * @ingroup node_alloc
336 * @brief return pointer to node object given instance index
338 * A pointer to the node object given by an instance index is returned.
340 * @param ocs pointer to driver instance context
341 * @param index instance index
343 * @return returns pointer to node object, or NULL
347 ocs_node_get_instance(ocs_t *ocs, uint32_t index)
349 ocs_xport_t *xport = ocs->xport;
350 ocs_node_t *node = NULL;
352 if (index >= (xport->nodes_count)) {
353 ocs_log_test(ocs, "invalid index: %d\n", index);
356 node = xport->nodes[index];
357 return node->attached ? node : NULL;
361 * @ingroup node_alloc
362 * @brief Allocate an fc node structure and add to node list
364 * @param sport pointer to the SPORT from which this node is allocated
365 * @param port_id FC port ID of new node
366 * @param init Port is an inititiator (sent a plogi)
367 * @param targ Port is potentially a target
369 * @return pointer to the object or NULL if none available
373 ocs_node_alloc(ocs_sport_t *sport, uint32_t port_id, uint8_t init, uint8_t targ)
376 ocs_node_t *node = NULL;
377 uint32_t instance_index;
378 uint32_t max_wr_xfer_size;
379 ocs_t *ocs = sport->ocs;
380 ocs_xport_t *xport = ocs->xport;
381 ocs_dma_t sparm_dma_buf;
383 ocs_assert(sport, NULL);
385 if (sport->shutting_down) {
386 ocs_log_debug(ocs, "node allocation when shutting down %06x", port_id);
390 ocs_device_lock(ocs);
391 node = ocs_list_remove_head(&xport->nodes_free_list);
392 ocs_device_unlock(ocs);
394 ocs_log_err(ocs, "node allocation failed %06x", port_id);
398 /* Save persistent values across memset zero */
399 instance_index = node->instance_index;
400 max_wr_xfer_size = node->max_wr_xfer_size;
401 sparm_dma_buf = node->sparm_dma_buf;
403 ocs_memset(node, 0, sizeof(*node));
404 node->instance_index = instance_index;
405 node->max_wr_xfer_size = max_wr_xfer_size;
406 node->sparm_dma_buf = sparm_dma_buf;
407 node->rnode.indicator = UINT32_MAX;
410 ocs_sport_lock(sport);
416 rc = ocs_hw_node_alloc(&ocs->hw, &node->rnode, port_id, sport);
418 ocs_log_err(ocs, "ocs_hw_node_alloc failed: %d\n", rc);
419 ocs_sport_unlock(sport);
421 /* Return back to pool. */
422 ocs_device_lock(ocs);
423 ocs_list_add_tail(&xport->nodes_free_list, node);
424 ocs_device_unlock(ocs);
428 ocs_list_add_tail(&sport->node_list, node);
430 ocs_node_lock_init(node);
431 ocs_lock_init(ocs, &node->pend_frames_lock, "pend_frames_lock[%d]", node->instance_index);
432 ocs_list_init(&node->pend_frames, ocs_hw_sequence_t, link);
433 ocs_lock_init(ocs, &node->active_ios_lock, "active_ios[%d]", node->instance_index);
434 ocs_list_init(&node->active_ios, ocs_io_t, link);
435 ocs_list_init(&node->els_io_pend_list, ocs_io_t, link);
436 ocs_list_init(&node->els_io_active_list, ocs_io_t, link);
437 ocs_scsi_io_alloc_enable(node);
439 /* zero the service parameters */
440 ocs_memset(node->sparm_dma_buf.virt, 0, node->sparm_dma_buf.size);
442 node->rnode.node = node;
446 ocs_node_update_display_name(node);
448 spv_set(sport->lookup, port_id, node);
449 ocs_sport_unlock(sport);
450 node->mgmt_functions = &node_mgmt_functions;
456 * @ingroup node_alloc
457 * @brief free a node structure
459 * The node structure given by 'node' is free'd
461 * @param node the node to free
463 * @return returns 0 for success, a negative error code value for failure.
467 ocs_node_free(ocs_node_t *node)
473 ocs_node_t *ns = NULL;
474 int post_all_free = FALSE;
476 ocs_assert(node, -1);
477 ocs_assert(node->sport, -1);
478 ocs_assert(node->ocs, -1);
480 ocs_assert(sport, -1);
482 ocs_assert(ocs->xport, -1);
485 node_printf(node, "Free'd\n");
489 * Save the name server node. We will send fake RSCN event at
490 * the end to handle ignored RSCN event during node deletion
492 ns = ocs_node_find(node->sport, FC_ADDR_NAMESERVER);
495 /* Remove from node list */
496 ocs_sport_lock(sport);
497 ocs_list_remove(&sport->node_list, node);
499 /* Free HW resources */
500 if (OCS_HW_RTN_IS_ERROR((rc = ocs_hw_node_free_resources(&ocs->hw, &node->rnode)))) {
501 ocs_log_test(ocs, "ocs_hw_node_free failed: %d\n", rc);
505 /* if the gidpt_delay_timer is still running, then delete it */
506 if (ocs_timer_pending(&node->gidpt_delay_timer)) {
507 ocs_del_timer(&node->gidpt_delay_timer);
510 if (node->fcp2device) {
514 /* remove entry from sparse vector list */
515 if (sport->lookup == NULL) {
516 ocs_log_test(node->ocs, "assertion failed: sport lookup is NULL\n");
517 ocs_sport_unlock(sport);
521 spv_set(sport->lookup, node->rnode.fc_id, NULL);
524 * If the node_list is empty, then post a ALL_CHILD_NODES_FREE event to the sport,
525 * after the lock is released. The sport may be free'd as a result of the event.
527 if (ocs_list_empty(&sport->node_list)) {
528 post_all_free = TRUE;
531 ocs_sport_unlock(sport);
534 ocs_sm_post_event(&sport->sm, OCS_EVT_ALL_CHILD_NODES_FREE, NULL);
538 node->sm.current_state = NULL;
540 ocs_node_lock_free(node);
541 ocs_lock_free(&node->pend_frames_lock);
542 ocs_lock_free(&node->active_ios_lock);
544 /* return to free list */
545 ocs_device_lock(ocs);
546 ocs_list_add_tail(&xport->nodes_free_list, node);
547 ocs_device_unlock(ocs);
550 /* sending fake RSCN event to name server node */
551 ocs_node_post_event(ns, OCS_EVT_RSCN_RCVD, NULL);
558 * @brief free memory resources of a node object
560 * The node object's child objects are freed after which the
561 * node object is freed.
563 * @param node pointer to a node object
569 ocs_node_force_free(ocs_node_t *node)
576 /* shutdown sm processing */
577 ocs_sm_disable(&node->sm);
578 ocs_strncpy(node->prev_state_name, node->current_state_name, sizeof(node->prev_state_name));
579 ocs_strncpy(node->current_state_name, "disabled", sizeof(node->current_state_name));
581 /* Let the backend cleanup if needed */
582 ocs_scsi_notify_node_force_free(node);
584 ocs_lock(&node->active_ios_lock);
585 ocs_list_foreach_safe(&node->active_ios, io, next) {
586 ocs_list_remove(&io->node->active_ios, io);
587 ocs_io_free(node->ocs, io);
589 ocs_unlock(&node->active_ios_lock);
591 /* free all pending ELS IOs */
592 ocs_lock(&node->active_ios_lock);
593 ocs_list_foreach_safe(&node->els_io_pend_list, els, els_next) {
594 /* can't call ocs_els_io_free() because lock is held; cleanup manually */
595 ocs_list_remove(&node->els_io_pend_list, els);
597 ocs_io_free(node->ocs, els);
599 ocs_unlock(&node->active_ios_lock);
601 /* free all active ELS IOs */
602 ocs_lock(&node->active_ios_lock);
603 ocs_list_foreach_safe(&node->els_io_active_list, els, els_next) {
604 /* can't call ocs_els_io_free() because lock is held; cleanup manually */
605 ocs_list_remove(&node->els_io_active_list, els);
607 ocs_io_free(node->ocs, els);
609 ocs_unlock(&node->active_ios_lock);
611 /* manually purge pending frames (if any) */
612 ocs_node_purge_pending(node);
618 * @ingroup node_common
619 * @brief Perform HW call to attach a remote node
621 * @param node pointer to node object
623 * @return 0 on success, non-zero otherwise
626 ocs_node_attach(ocs_node_t *node)
629 ocs_sport_t *sport = node->sport;
630 ocs_domain_t *domain = sport->domain;
631 ocs_t *ocs = node->ocs;
633 if (!domain->attached) {
634 ocs_log_test(ocs, "Warning: ocs_node_attach with unattached domain\n");
637 /* Update node->wwpn/wwnn */
639 ocs_node_build_eui_name(node->wwpn, sizeof(node->wwpn), ocs_node_get_wwpn(node));
640 ocs_node_build_eui_name(node->wwnn, sizeof(node->wwnn), ocs_node_get_wwnn(node));
642 if (ocs->enable_hlm) {
643 ocs_node_group_init(node);
646 ocs_dma_copy_in(&node->sparm_dma_buf, node->service_params+4, sizeof(node->service_params)-4);
648 /* take lock to protect node->rnode.attached */
650 rc = ocs_hw_node_attach(&ocs->hw, &node->rnode, &node->sparm_dma_buf);
651 if (OCS_HW_RTN_IS_ERROR(rc)) {
652 ocs_log_test(ocs, "ocs_hw_node_attach failed: %d\n", rc);
654 ocs_node_unlock(node);
660 * @ingroup node_common
661 * @brief Generate text for a node's fc_id
663 * The text for a nodes fc_id is generated, either as a well known name, or a 6 digit
667 * @param buffer text buffer
668 * @param buffer_length text buffer length in bytes
674 ocs_node_fcid_display(uint32_t fc_id, char *buffer, uint32_t buffer_length)
678 ocs_snprintf(buffer, buffer_length, "fabric");
680 case FC_ADDR_CONTROLLER:
681 ocs_snprintf(buffer, buffer_length, "fabctl");
683 case FC_ADDR_NAMESERVER:
684 ocs_snprintf(buffer, buffer_length, "nserve");
687 if (FC_ADDR_IS_DOMAIN_CTRL(fc_id)) {
688 ocs_snprintf(buffer, buffer_length, "dctl%02x",
689 FC_ADDR_GET_DOMAIN_CTRL(fc_id));
691 ocs_snprintf(buffer, buffer_length, "%06x", fc_id);
699 * @brief update the node's display name
701 * The node's display name is updated, sometimes needed because the sport part
702 * is updated after the node is allocated.
704 * @param node pointer to the node object
710 ocs_node_update_display_name(ocs_node_t *node)
712 uint32_t port_id = node->rnode.fc_id;
713 ocs_sport_t *sport = node->sport;
714 char portid_display[16];
718 ocs_node_fcid_display(port_id, portid_display, sizeof(portid_display));
720 ocs_snprintf(node->display_name, sizeof(node->display_name), "%s.%s", sport->display_name, portid_display);
724 * @brief cleans up an XRI for the pending link services accept by aborting the
727 * <h3 class="desc">Description</h3>
728 * This function is called when the LS accept is not sent.
730 * @param node Node for which should be cleaned up
734 ocs_node_send_ls_io_cleanup(ocs_node_t *node)
736 ocs_t *ocs = node->ocs;
738 if (node->send_ls_acc != OCS_NODE_SEND_LS_ACC_NONE) {
739 ocs_assert(node->ls_acc_io);
740 ocs_log_debug(ocs, "[%s] cleaning up LS_ACC oxid=0x%x\n",
741 node->display_name, node->ls_acc_oxid);
743 node->ls_acc_io->hio = NULL;
744 ocs_els_io_free(node->ls_acc_io);
745 node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE;
746 node->ls_acc_io = NULL;
751 * @ingroup node_common
752 * @brief state: shutdown a node
754 * A node is shutdown,
756 * @param ctx remote node sm context
757 * @param evt event to process
758 * @param arg per event optional argument
760 * @return returns NULL
766 __ocs_node_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
769 std_node_state_decl();
774 case OCS_EVT_ENTER: {
775 ocs_node_hold_frames(node);
776 ocs_assert(ocs_node_active_ios_empty(node), NULL);
777 ocs_assert(ocs_els_io_list_empty(node, &node->els_io_active_list), NULL);
779 /* by default, we will be freeing node after we unwind */
782 switch (node->shutdown_reason) {
783 case OCS_NODE_SHUTDOWN_IMPLICIT_LOGO:
784 /* sm: if shutdown reason is implicit logout / ocs_node_attach
785 * Node shutdown b/c of PLOGI received when node already
786 * logged in. We have PLOGI service parameters, so submit
787 * node attach; we won't be freeing this node
790 /* currently, only case for implicit logo is PLOGI recvd. Thus,
791 * node's ELS IO pending list won't be empty (PLOGI will be on it)
793 ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI, NULL);
794 node_printf(node, "Shutdown reason: implicit logout, re-authenticate\n");
796 ocs_scsi_io_alloc_enable(node);
798 /* Re-attach node with the same HW node resources */
800 rc = ocs_node_attach(node);
801 ocs_node_transition(node, __ocs_d_wait_node_attach, NULL);
802 if (rc == OCS_HW_RTN_SUCCESS_SYNC) {
803 ocs_node_post_event(node, OCS_EVT_NODE_ATTACH_OK, NULL);
806 case OCS_NODE_SHUTDOWN_EXPLICIT_LOGO: {
807 int8_t pend_frames_empty;
809 /* cleanup any pending LS_ACC ELSs */
810 ocs_node_send_ls_io_cleanup(node);
811 ocs_assert(ocs_els_io_list_empty(node, &node->els_io_pend_list), NULL);
813 ocs_lock(&node->pend_frames_lock);
814 pend_frames_empty = ocs_list_empty(&node->pend_frames);
815 ocs_unlock(&node->pend_frames_lock);
817 /* there are two scenarios where we want to keep this node alive:
818 * 1. there are pending frames that need to be processed or
819 * 2. we're an initiator and the remote node is a target and we
820 * need to re-authenticate
822 node_printf(node, "Shutdown: explicit logo pend=%d sport.ini=%d node.tgt=%d\n",
823 !pend_frames_empty, node->sport->enable_ini, node->targ);
825 if((!pend_frames_empty) || (node->sport->enable_ini && node->targ)) {
826 uint8_t send_plogi = FALSE;
827 if (node->sport->enable_ini && node->targ) {
828 /* we're an initiator and node shutting down is a target; we'll
829 * need to re-authenticate in initial state
834 /* transition to __ocs_d_init (will retain HW node resources) */
835 ocs_scsi_io_alloc_enable(node);
838 /* either pending frames exist, or we're re-authenticating with PLOGI
839 * (or both); in either case, return to initial state
841 ocs_node_init_device(node, send_plogi);
844 /* else: let node shutdown occur */
847 case OCS_NODE_SHUTDOWN_DEFAULT:
849 /* shutdown due to link down, node going away (xport event) or
850 * sport shutdown, purge pending and proceed to cleanup node
853 /* cleanup any pending LS_ACC ELSs */
854 ocs_node_send_ls_io_cleanup(node);
855 ocs_assert(ocs_els_io_list_empty(node, &node->els_io_pend_list), NULL);
857 node_printf(node, "Shutdown reason: default, purge pending\n");
858 ocs_node_purge_pending(node);
865 ocs_node_accept_frames(node);
869 __ocs_node_common(__func__, ctx, evt, arg);
877 * @ingroup common_node
878 * @brief Checks to see if ELS's have been quiesced
880 * Check if ELS's have been quiesced. If so, transition to the
881 * next state in the shutdown process.
883 * @param node Node for which ELS's are checked
885 * @return Returns 1 if ELS's have been quiesced, 0 otherwise.
888 ocs_node_check_els_quiesced(ocs_node_t *node)
890 ocs_assert(node, -1);
892 /* check to see if ELS requests, completions are quiesced */
893 if ((node->els_req_cnt == 0) && (node->els_cmpl_cnt == 0) &&
894 ocs_els_io_list_empty(node, &node->els_io_active_list)) {
895 if (!node->attached) {
896 /* hw node detach already completed, proceed */
897 node_printf(node, "HW node not attached\n");
898 ocs_node_transition(node, __ocs_node_wait_ios_shutdown, NULL);
900 /* hw node detach hasn't completed, transition and wait */
901 node_printf(node, "HW node still attached\n");
902 ocs_node_transition(node, __ocs_node_wait_node_free, NULL);
910 * @ingroup common_node
911 * @brief Initiate node IO cleanup.
913 * Note: this function must be called with a non-attached node
914 * or a node for which the node detach (ocs_hw_node_detach())
915 * has already been initiated.
917 * @param node Node for which shutdown is initiated
919 * @return Returns None.
923 ocs_node_initiate_cleanup(ocs_node_t *node)
931 /* first cleanup ELS's that are pending (not yet active) */
932 ocs_lock(&node->active_ios_lock);
933 ocs_list_foreach_safe(&node->els_io_pend_list, els, els_next) {
935 /* skip the ELS IO for which a response will be sent after shutdown */
936 if ((node->send_ls_acc != OCS_NODE_SEND_LS_ACC_NONE) &&
937 (els == node->ls_acc_io)) {
940 /* can't call ocs_els_io_free() because lock is held; cleanup manually */
941 node_printf(node, "Freeing pending els %s\n", els->display_name);
942 ocs_list_remove(&node->els_io_pend_list, els);
944 ocs_io_free(node->ocs, els);
946 ocs_unlock(&node->active_ios_lock);
948 if (node->ls_acc_io && node->ls_acc_io->hio != NULL) {
950 * if there's an IO that will result in an LS_ACC after
951 * shutdown and its HW IO is non-NULL, it better be an
952 * implicit logout in vanilla sequence coalescing. In this
953 * case, force the LS_ACC to go out on another XRI (hio)
954 * since the previous will have been aborted by the UNREG_RPI
956 ocs_assert(node->shutdown_reason == OCS_NODE_SHUTDOWN_IMPLICIT_LOGO);
957 ocs_assert(node->send_ls_acc == OCS_NODE_SEND_LS_ACC_PLOGI);
958 node_printf(node, "invalidating ls_acc_io due to implicit logo\n");
960 /* No need to abort because the unreg_rpi takes care of it, just free */
961 ocs_hw_io_free(&ocs->hw, node->ls_acc_io->hio);
963 /* NULL out hio to force the LS_ACC to grab a new XRI */
964 node->ls_acc_io->hio = NULL;
968 * if ELS's have already been quiesced, will move to next state
969 * if ELS's have not been quiesced, abort them
971 if (ocs_node_check_els_quiesced(node) == 0) {
973 * Abort all ELS's since ELS's won't be aborted by HW
976 ocs_node_abort_all_els(node);
977 ocs_node_transition(node, __ocs_node_wait_els_shutdown, NULL);
982 * @ingroup node_common
983 * @brief Node state machine: Wait for all ELSs to complete.
985 * <h3 class="desc">Description</h3>
986 * State waits for all ELSs to complete after aborting all
989 * @param ctx Remote node state machine context.
990 * @param evt Event to process.
991 * @param arg Per event optional argument.
993 * @return Returns NULL.
997 __ocs_node_wait_els_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
999 uint8_t check_quiesce = FALSE;
1000 std_node_state_decl();
1006 case OCS_EVT_ENTER: {
1007 ocs_node_hold_frames(node);
1008 if (ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1009 node_printf(node, "All ELS IOs complete\n");
1010 check_quiesce = TRUE;
1015 ocs_node_accept_frames(node);
1018 case OCS_EVT_SRRS_ELS_REQ_OK:
1019 case OCS_EVT_SRRS_ELS_REQ_FAIL:
1020 case OCS_EVT_SRRS_ELS_REQ_RJT:
1021 case OCS_EVT_ELS_REQ_ABORTED:
1022 ocs_assert(node->els_req_cnt, NULL);
1023 node->els_req_cnt--;
1024 check_quiesce = TRUE;
1027 case OCS_EVT_SRRS_ELS_CMPL_OK:
1028 case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1029 ocs_assert(node->els_cmpl_cnt, NULL);
1030 node->els_cmpl_cnt--;
1031 check_quiesce = TRUE;
1034 case OCS_EVT_ALL_CHILD_NODES_FREE:
1035 /* all ELS IO's complete */
1036 node_printf(node, "All ELS IOs complete\n");
1037 ocs_assert(ocs_els_io_list_empty(node, &node->els_io_active_list), NULL);
1038 check_quiesce = TRUE;
1041 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1044 case OCS_EVT_DOMAIN_ATTACH_OK:
1045 /* don't care about domain_attach_ok */
1048 /* ignore shutdown events as we're already in shutdown path */
1049 case OCS_EVT_SHUTDOWN:
1050 /* have default shutdown event take precedence */
1051 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1053 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1054 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1055 node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1059 __ocs_node_common(__func__, ctx, evt, arg);
1063 if (check_quiesce) {
1064 ocs_node_check_els_quiesced(node);
1070 * @ingroup node_command
1071 * @brief Node state machine: Wait for a HW node free event to
1074 * <h3 class="desc">Description</h3>
1075 * State waits for the node free event to be received from the HW.
1077 * @param ctx Remote node state machine context.
1078 * @param evt Event to process.
1079 * @param arg Per event optional argument.
1081 * @return Returns NULL.
1085 __ocs_node_wait_node_free(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1087 std_node_state_decl();
1094 ocs_node_hold_frames(node);
1098 ocs_node_accept_frames(node);
1101 case OCS_EVT_NODE_FREE_OK:
1102 /* node is officially no longer attached */
1103 node->attached = FALSE;
1104 ocs_node_transition(node, __ocs_node_wait_ios_shutdown, NULL);
1107 case OCS_EVT_ALL_CHILD_NODES_FREE:
1108 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1109 /* As IOs and ELS IO's complete we expect to get these events */
1112 case OCS_EVT_DOMAIN_ATTACH_OK:
1113 /* don't care about domain_attach_ok */
1116 /* ignore shutdown events as we're already in shutdown path */
1117 case OCS_EVT_SHUTDOWN:
1118 /* have default shutdown event take precedence */
1119 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1121 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1122 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1123 node_printf(node, "%s received\n", ocs_sm_event_name(evt));
1126 __ocs_node_common(__func__, ctx, evt, arg);
1134 * @ingroup node_common
1135 * @brief state: initiate node shutdown
1137 * State is entered when a node receives a shutdown event, and it's waiting
1138 * for all the active IOs and ELS IOs associated with the node to complete.
1140 * @param ctx remote node sm context
1141 * @param evt event to process
1142 * @param arg per event optional argument
1144 * @return returns NULL
1148 __ocs_node_wait_ios_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1152 std_node_state_decl();
1158 ocs_node_hold_frames(node);
1160 /* first check to see if no ELS IOs are outstanding */
1161 if (ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1162 /* If there are any active IOS, Free them. */
1163 if (!ocs_node_active_ios_empty(node)) {
1164 ocs_lock(&node->active_ios_lock);
1165 ocs_list_foreach_safe(&node->active_ios, io, next) {
1166 ocs_list_remove(&io->node->active_ios, io);
1167 ocs_io_free(node->ocs, io);
1169 ocs_unlock(&node->active_ios_lock);
1171 ocs_node_transition(node, __ocs_node_shutdown, NULL);
1175 case OCS_EVT_NODE_ACTIVE_IO_LIST_EMPTY:
1176 case OCS_EVT_ALL_CHILD_NODES_FREE: {
1177 if (ocs_node_active_ios_empty(node) &&
1178 ocs_els_io_list_empty(node, &node->els_io_active_list)) {
1179 ocs_node_transition(node, __ocs_node_shutdown, NULL);
1185 ocs_node_accept_frames(node);
1188 case OCS_EVT_SRRS_ELS_REQ_FAIL:
1189 /* Can happen as ELS IO IO's complete */
1190 ocs_assert(node->els_req_cnt, NULL);
1191 node->els_req_cnt--;
1194 /* ignore shutdown events as we're already in shutdown path */
1195 case OCS_EVT_SHUTDOWN:
1196 /* have default shutdown event take precedence */
1197 node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1199 case OCS_EVT_SHUTDOWN_EXPLICIT_LOGO:
1200 case OCS_EVT_SHUTDOWN_IMPLICIT_LOGO:
1201 ocs_log_debug(ocs, "[%s] %-20s\n", node->display_name, ocs_sm_event_name(evt));
1203 case OCS_EVT_DOMAIN_ATTACH_OK:
1204 /* don't care about domain_attach_ok */
1207 __ocs_node_common(__func__, ctx, evt, arg);
1215 * @ingroup node_common
1216 * @brief state: common node event handler
1218 * Handle common/shared node events
1220 * @param funcname calling function's name
1221 * @param ctx remote node sm context
1222 * @param evt event to process
1223 * @param arg per event optional argument
1225 * @return returns NULL
1229 __ocs_node_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1231 ocs_node_t *node = NULL;
1233 ocs_node_cb_t *cbdata = arg;
1234 ocs_assert(ctx, NULL);
1235 ocs_assert(ctx->app, NULL);
1237 ocs_assert(node->ocs, NULL);
1242 case OCS_EVT_REENTER:
1244 case OCS_EVT_SPORT_TOPOLOGY_NOTIFY:
1245 case OCS_EVT_NODE_MISSING:
1246 case OCS_EVT_FCP_CMD_RCVD:
1249 case OCS_EVT_NODE_REFOUND:
1253 /* node->attached must be set appropriately for all node attach/detach events */
1254 case OCS_EVT_NODE_ATTACH_OK:
1255 node->attached = TRUE;
1258 case OCS_EVT_NODE_FREE_OK:
1259 case OCS_EVT_NODE_ATTACH_FAIL:
1260 node->attached = FALSE;
1263 /* handle any ELS completions that other states either didn't care about
1266 case OCS_EVT_SRRS_ELS_CMPL_OK:
1267 case OCS_EVT_SRRS_ELS_CMPL_FAIL:
1268 ocs_assert(node->els_cmpl_cnt, NULL);
1269 node->els_cmpl_cnt--;
1272 /* handle any ELS request completions that other states either didn't care about
1275 case OCS_EVT_SRRS_ELS_REQ_OK:
1276 case OCS_EVT_SRRS_ELS_REQ_FAIL:
1277 case OCS_EVT_SRRS_ELS_REQ_RJT:
1278 case OCS_EVT_ELS_REQ_ABORTED:
1279 ocs_assert(node->els_req_cnt, NULL);
1280 node->els_req_cnt--;
1283 case OCS_EVT_ELS_RCVD: {
1284 fc_header_t *hdr = cbdata->header->dma.virt;
1286 /* Unsupported ELS was received, send LS_RJT, command not supported */
1287 ocs_log_debug(ocs, "[%s] (%s) ELS x%02x, LS_RJT not supported\n",
1288 node->display_name, funcname, ((uint8_t*)cbdata->payload->dma.virt)[0]);
1289 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
1290 FC_REASON_COMMAND_NOT_SUPPORTED, FC_EXPL_NO_ADDITIONAL, 0,
1295 case OCS_EVT_PLOGI_RCVD:
1296 case OCS_EVT_FLOGI_RCVD:
1297 case OCS_EVT_LOGO_RCVD:
1298 case OCS_EVT_PRLI_RCVD:
1299 case OCS_EVT_PRLO_RCVD:
1300 case OCS_EVT_PDISC_RCVD:
1301 case OCS_EVT_FDISC_RCVD:
1302 case OCS_EVT_ADISC_RCVD:
1303 case OCS_EVT_RSCN_RCVD:
1304 case OCS_EVT_SCR_RCVD: {
1305 fc_header_t *hdr = cbdata->header->dma.virt;
1306 /* sm: / send ELS_RJT */
1307 ocs_log_debug(ocs, "[%s] (%s) %s sending ELS_RJT\n",
1308 node->display_name, funcname, ocs_sm_event_name(evt));
1309 /* if we didn't catch this in a state, send generic LS_RJT */
1310 ocs_send_ls_rjt(cbdata->io, ocs_be16toh(hdr->ox_id),
1311 FC_REASON_UNABLE_TO_PERFORM, FC_EXPL_NO_ADDITIONAL, 0,
1316 case OCS_EVT_GID_PT_RCVD:
1317 case OCS_EVT_RFT_ID_RCVD:
1318 case OCS_EVT_RFF_ID_RCVD: {
1319 fc_header_t *hdr = cbdata->header->dma.virt;
1320 ocs_log_debug(ocs, "[%s] (%s) %s sending CT_REJECT\n",
1321 node->display_name, funcname, ocs_sm_event_name(evt));
1322 ocs_send_ct_rsp(cbdata->io, hdr->ox_id, cbdata->payload->dma.virt, FCCT_HDR_CMDRSP_REJECT, FCCT_COMMAND_NOT_SUPPORTED, 0);
1326 case OCS_EVT_ABTS_RCVD: {
1327 fc_header_t *hdr = cbdata->header->dma.virt;
1328 ocs_log_debug(ocs, "[%s] (%s) %s sending BA_ACC\n",
1329 node->display_name, funcname, ocs_sm_event_name(evt));
1331 /* sm: send BA_ACC */
1332 ocs_bls_send_acc_hdr(cbdata->io, hdr);
1337 ocs_log_test(node->ocs, "[%s] %-20s %-20s not handled\n", node->display_name, funcname,
1338 ocs_sm_event_name(evt));
1346 * @ingroup node_common
1347 * @brief save node service parameters
1349 * Service parameters are copyed into the node structure
1351 * @param node pointer to node structure
1352 * @param payload pointer to service parameters to save
1358 ocs_node_save_sparms(ocs_node_t *node, void *payload)
1360 ocs_memcpy(node->service_params, payload, sizeof(node->service_params));
1364 * @ingroup node_common
1365 * @brief Post event to node state machine context
1367 * This is used by the node state machine code to post events to the nodes. Upon
1368 * completion of the event posting, if the nesting depth is zero and we're not holding
1369 * inbound frames, then the pending frames are processed.
1371 * @param node pointer to node
1372 * @param evt event to post
1373 * @param arg event posting argument
1379 ocs_node_post_event(ocs_node_t *node, ocs_sm_event_t evt, void *arg)
1381 int free_node = FALSE;
1384 ocs_node_lock(node);
1387 ocs_sm_post_event(&node->sm, evt, arg);
1389 /* If our event call depth is one and we're not holding frames
1390 * then we can dispatch any pending frames. We don't want to allow
1391 * the ocs_process_node_pending() call to recurse.
1393 if (!node->hold_frames && (node->evtdepth == 1)) {
1394 ocs_process_node_pending(node);
1398 /* Free the node object if so requested, and we're at an event
1399 * call depth of zero
1401 if ((node->evtdepth == 0) && node->req_free) {
1404 ocs_node_unlock(node);
1407 ocs_node_free(node);
1414 * @ingroup node_common
1415 * @brief transition state of a node
1417 * The node's state is transitioned to the requested state. Entry/Exit
1418 * events are posted as needed.
1420 * @param node pointer to node
1421 * @param state state to transition to
1422 * @param data transition data
1428 ocs_node_transition(ocs_node_t *node, ocs_sm_function_t state, void *data)
1430 ocs_sm_ctx_t *ctx = &node->sm;
1432 ocs_node_lock(node);
1433 if (ctx->current_state == state) {
1434 ocs_node_post_event(node, OCS_EVT_REENTER, data);
1436 ocs_node_post_event(node, OCS_EVT_EXIT, data);
1437 ctx->current_state = state;
1438 ocs_node_post_event(node, OCS_EVT_ENTER, data);
1440 ocs_node_unlock(node);
1444 * @ingroup node_common
1445 * @brief build EUI formatted WWN
1447 * Build a WWN given the somewhat transport agnostic iScsi naming specification, for FC
1448 * use the eui. format, an ascii string such as: "eui.10000000C9A19501"
1450 * @param buffer buffer to place formatted name into
1451 * @param buffer_len length in bytes of the buffer
1452 * @param eui_name cpu endian 64 bit WWN value
1458 ocs_node_build_eui_name(char *buffer, uint32_t buffer_len, uint64_t eui_name)
1460 ocs_memset(buffer, 0, buffer_len);
1462 ocs_snprintf(buffer, buffer_len, "eui.%016llx", (unsigned long long)eui_name);
1466 * @ingroup node_common
1467 * @brief return nodes' WWPN as a uint64_t
1469 * The WWPN is computed from service parameters and returned as a uint64_t
1471 * @param node pointer to node structure
1478 ocs_node_get_wwpn(ocs_node_t *node)
1480 fc_plogi_payload_t *sp = (fc_plogi_payload_t*) node->service_params;
1482 return (((uint64_t)ocs_be32toh(sp->port_name_hi) << 32ll) | (ocs_be32toh(sp->port_name_lo)));
1486 * @ingroup node_common
1487 * @brief return nodes' WWNN as a uint64_t
1489 * The WWNN is computed from service parameters and returned as a uint64_t
1491 * @param node pointer to node structure
1498 ocs_node_get_wwnn(ocs_node_t *node)
1500 fc_plogi_payload_t *sp = (fc_plogi_payload_t*) node->service_params;
1502 return (((uint64_t)ocs_be32toh(sp->node_name_hi) << 32ll) | (ocs_be32toh(sp->node_name_lo)));
1506 * @brief Generate node ddump data
1508 * Generates the node ddumpdata
1510 * @param textbuf pointer to text buffer
1511 * @param node pointer to node context
1513 * @return Returns 0 on success, or a negative value on failure.
1517 ocs_ddump_node(ocs_textbuf_t *textbuf, ocs_node_t *node)
1523 ocs_ddump_section(textbuf, "node", node->instance_index);
1524 ocs_ddump_value(textbuf, "display_name", "%s", node->display_name);
1525 ocs_ddump_value(textbuf, "current_state", "%s", node->current_state_name);
1526 ocs_ddump_value(textbuf, "prev_state", "%s", node->prev_state_name);
1527 ocs_ddump_value(textbuf, "current_evt", "%s", ocs_sm_event_name(node->current_evt));
1528 ocs_ddump_value(textbuf, "prev_evt", "%s", ocs_sm_event_name(node->prev_evt));
1530 ocs_ddump_value(textbuf, "indicator", "%#x", node->rnode.indicator);
1531 ocs_ddump_value(textbuf, "fc_id", "%#06x", node->rnode.fc_id);
1532 ocs_ddump_value(textbuf, "attached", "%d", node->rnode.attached);
1534 ocs_ddump_value(textbuf, "hold_frames", "%d", node->hold_frames);
1535 ocs_ddump_value(textbuf, "io_alloc_enabled", "%d", node->io_alloc_enabled);
1536 ocs_ddump_value(textbuf, "shutdown_reason", "%d", node->shutdown_reason);
1537 ocs_ddump_value(textbuf, "send_ls_acc", "%d", node->send_ls_acc);
1538 ocs_ddump_value(textbuf, "ls_acc_did", "%d", node->ls_acc_did);
1539 ocs_ddump_value(textbuf, "ls_acc_oxid", "%#04x", node->ls_acc_oxid);
1540 ocs_ddump_value(textbuf, "req_free", "%d", node->req_free);
1541 ocs_ddump_value(textbuf, "els_req_cnt", "%d", node->els_req_cnt);
1542 ocs_ddump_value(textbuf, "els_cmpl_cnt", "%d", node->els_cmpl_cnt);
1544 ocs_ddump_value(textbuf, "targ", "%d", node->targ);
1545 ocs_ddump_value(textbuf, "init", "%d", node->init);
1546 ocs_ddump_value(textbuf, "wwnn", "%s", node->wwnn);
1547 ocs_ddump_value(textbuf, "wwpn", "%s", node->wwpn);
1548 ocs_ddump_value(textbuf, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1549 ocs_ddump_value(textbuf, "chained_io_count", "%d", node->chained_io_count);
1550 ocs_ddump_value(textbuf, "abort_cnt", "%d", node->abort_cnt);
1552 ocs_display_sparams(NULL, "node_sparams", 1, textbuf, node->service_params+4);
1554 ocs_lock(&node->pend_frames_lock);
1555 if (!ocs_list_empty(&node->pend_frames)) {
1556 ocs_hw_sequence_t *frame;
1557 ocs_ddump_section(textbuf, "pending_frames", 0);
1558 ocs_list_foreach(&node->pend_frames, frame) {
1562 hdr = frame->header->dma.virt;
1563 ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu",
1564 hdr->r_ctl, ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1565 frame->payload->dma.len);
1566 ocs_ddump_value(textbuf, "frame", "%s", buf);
1568 ocs_ddump_endsection(textbuf, "pending_frames", 0);
1570 ocs_unlock(&node->pend_frames_lock);
1572 ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_NODE, node);
1573 ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_NODE, node);
1575 ocs_lock(&node->active_ios_lock);
1576 ocs_ddump_section(textbuf, "active_ios", 0);
1577 ocs_list_foreach(&node->active_ios, io) {
1578 ocs_ddump_io(textbuf, io);
1580 ocs_ddump_endsection(textbuf, "active_ios", 0);
1582 ocs_ddump_section(textbuf, "els_io_pend_list", 0);
1583 ocs_list_foreach(&node->els_io_pend_list, els) {
1584 ocs_ddump_els(textbuf, els);
1586 ocs_ddump_endsection(textbuf, "els_io_pend_list", 0);
1588 ocs_ddump_section(textbuf, "els_io_active_list", 0);
1589 ocs_list_foreach(&node->els_io_active_list, els) {
1590 ocs_ddump_els(textbuf, els);
1592 ocs_ddump_endsection(textbuf, "els_io_active_list", 0);
1593 ocs_unlock(&node->active_ios_lock);
1595 ocs_ddump_endsection(textbuf, "node", node->instance_index);
1601 * @brief check ELS request completion
1603 * Check ELS request completion event to make sure it's for the
1604 * ELS request we expect. If not, invoke given common event
1605 * handler and return an error.
1607 * @param ctx state machine context
1608 * @param evt ELS request event
1609 * @param arg event argument
1610 * @param cmd ELS command expected
1611 * @param node_common_func common event handler to call if ELS
1613 * @param funcname function name that called this
1615 * @return zero if ELS command matches, -1 otherwise
1618 node_check_els_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint8_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
1620 ocs_node_t *node = NULL;
1622 ocs_node_cb_t *cbdata = arg;
1623 fc_els_gen_t *els_gen = NULL;
1624 ocs_assert(ctx, -1);
1626 ocs_assert(node, -1);
1628 ocs_assert(ocs, -1);
1630 ocs_assert(cbdata, -1);
1631 ocs_assert(cbdata->els, -1);
1632 els_gen = (fc_els_gen_t *)cbdata->els->els_req.virt;
1633 ocs_assert(els_gen, -1);
1635 if ((cbdata->els->hio_type != OCS_HW_ELS_REQ) || (els_gen->command_code != cmd)) {
1636 if (cbdata->els->hio_type != OCS_HW_ELS_REQ) {
1637 ocs_log_debug(node->ocs, "[%s] %-20s expecting ELS cmd=x%x received type=%d\n",
1638 node->display_name, funcname, cmd, cbdata->els->hio_type);
1640 ocs_log_debug(node->ocs, "[%s] %-20s expecting ELS cmd=x%x received cmd=x%x\n",
1641 node->display_name, funcname, cmd, els_gen->command_code);
1643 /* send event to common handler */
1644 node_common_func(funcname, ctx, evt, arg);
1651 * @brief check NS request completion
1653 * Check ELS request completion event to make sure it's for the
1654 * nameserver request we expect. If not, invoke given common
1655 * event handler and return an error.
1657 * @param ctx state machine context
1658 * @param evt ELS request event
1659 * @param arg event argument
1660 * @param cmd nameserver command expected
1661 * @param node_common_func common event handler to call if
1662 * nameserver cmd doesn't match
1663 * @param funcname function name that called this
1665 * @return zero if NS command matches, -1 otherwise
1668 node_check_ns_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint32_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
1670 ocs_node_t *node = NULL;
1672 ocs_node_cb_t *cbdata = arg;
1673 fcct_iu_header_t *fcct = NULL;
1674 ocs_assert(ctx, -1);
1676 ocs_assert(node, -1);
1678 ocs_assert(ocs, -1);
1680 ocs_assert(cbdata, -1);
1681 ocs_assert(cbdata->els, -1);
1682 fcct = (fcct_iu_header_t *)cbdata->els->els_req.virt;
1683 ocs_assert(fcct, -1);
1685 if ((cbdata->els->hio_type != OCS_HW_FC_CT) || fcct->cmd_rsp_code != ocs_htobe16(cmd)) {
1686 if (cbdata->els->hio_type != OCS_HW_FC_CT) {
1687 ocs_log_debug(node->ocs, "[%s] %-20s expecting NS cmd=x%x received type=%d\n",
1688 node->display_name, funcname, cmd, cbdata->els->hio_type);
1690 ocs_log_debug(node->ocs, "[%s] %-20s expecting NS cmd=x%x received cmd=x%x\n",
1691 node->display_name, funcname, cmd, fcct->cmd_rsp_code);
1693 /* send event to common handler */
1694 node_common_func(funcname, ctx, evt, arg);
1702 ocs_mgmt_node_list(ocs_textbuf_t *textbuf, void *object)
1705 ocs_node_t *node = (ocs_node_t *)object;
1707 ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1709 /* Readonly values */
1710 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "display_name");
1711 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "indicator");
1712 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "fc_id");
1713 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "attached");
1714 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hold_frames");
1715 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "shutting_down");
1716 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "req_free");
1717 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ox_id");
1718 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ox_id_in_use");
1719 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "abort_cnt");
1720 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "targ");
1721 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "init");
1722 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "wwpn");
1723 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "wwnn");
1724 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "pend_frames");
1725 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "chained_io_count");
1728 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "resume");
1730 ocs_lock(&node->active_ios_lock);
1731 ocs_list_foreach(&node->active_ios, io) {
1732 if ((io->mgmt_functions) && (io->mgmt_functions->get_list_handler)) {
1733 io->mgmt_functions->get_list_handler(textbuf, io);
1736 ocs_unlock(&node->active_ios_lock);
1738 ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1742 ocs_mgmt_node_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
1745 ocs_node_t *node = (ocs_node_t *)object;
1749 ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1751 ocs_snprintf(qualifier, sizeof(qualifier), "%s/node[%d]", parent, node->instance_index);
1753 /* If it doesn't start with my qualifier I don't know what to do with it */
1754 if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1755 char *unqualified_name = name + strlen(qualifier) +1;
1757 /* See if it's a value I can supply */
1758 if (ocs_strcmp(unqualified_name, "display_name") == 0) {
1759 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", node->display_name);
1761 } else if (ocs_strcmp(unqualified_name, "indicator") == 0) {
1762 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "0x%x", node->rnode.indicator);
1764 } else if (ocs_strcmp(unqualified_name, "fc_id") == 0) {
1765 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", node->rnode.fc_id);
1767 } else if (ocs_strcmp(unqualified_name, "attached") == 0) {
1768 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", node->rnode.attached);
1770 } else if (ocs_strcmp(unqualified_name, "hold_frames") == 0) {
1771 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "hold_frames", node->hold_frames);
1773 } else if (ocs_strcmp(unqualified_name, "io_alloc_enabled") == 0) {
1774 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "io_alloc_enabled", node->io_alloc_enabled);
1776 } else if (ocs_strcmp(unqualified_name, "req_free") == 0) {
1777 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "req_free", node->req_free);
1779 } else if (ocs_strcmp(unqualified_name, "ls_acc_oxid") == 0) {
1780 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_oxid", "0x%#04x", node->ls_acc_oxid);
1782 } else if (ocs_strcmp(unqualified_name, "ls_acc_did") == 0) {
1783 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_did", "0x%#04x", node->ls_acc_did);
1785 } else if (ocs_strcmp(unqualified_name, "abort_cnt") == 0) {
1786 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "abort_cnt", "%d", node->abort_cnt);
1788 } else if (ocs_strcmp(unqualified_name, "targ") == 0) {
1789 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "targ", node->targ);
1791 } else if (ocs_strcmp(unqualified_name, "init") == 0) {
1792 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "init", node->init);
1794 } else if (ocs_strcmp(unqualified_name, "wwpn") == 0) {
1795 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "%s", node->wwpn);
1797 } else if (ocs_strcmp(unqualified_name, "wwnn") == 0) {
1798 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "%s", node->wwnn);
1800 } else if (ocs_strcmp(unqualified_name, "current_state") == 0) {
1801 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_state", node->current_state_name);
1803 } else if (ocs_strcmp(unqualified_name, "login_state") == 0) {
1804 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1806 } else if (ocs_strcmp(unqualified_name, "pend_frames") == 0) {
1807 ocs_hw_sequence_t *frame;
1808 ocs_lock(&node->pend_frames_lock);
1809 ocs_list_foreach(&node->pend_frames, frame) {
1813 hdr = frame->header->dma.virt;
1814 ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu", hdr->r_ctl,
1815 ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1816 frame->payload->dma.len);
1817 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pend_frames", buf);
1819 ocs_unlock(&node->pend_frames_lock);
1821 } else if (ocs_strcmp(unqualified_name, "chained_io_count") == 0) {
1822 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "chained_io_count", "%d", node->chained_io_count);
1825 /* If I didn't know the value of this status pass the request to each of my children */
1826 ocs_lock(&node->active_ios_lock);
1827 ocs_list_foreach(&node->active_ios, io) {
1828 if ((io->mgmt_functions) && (io->mgmt_functions->get_handler)) {
1829 retval = io->mgmt_functions->get_handler(textbuf, qualifier, name, io);
1836 ocs_unlock(&node->active_ios_lock);
1840 ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1846 ocs_mgmt_node_get_all(ocs_textbuf_t *textbuf, void *object)
1849 ocs_node_t *node = (ocs_node_t *)object;
1850 ocs_hw_sequence_t *frame;
1852 ocs_mgmt_start_section(textbuf, "node", node->instance_index);
1854 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", node->display_name);
1855 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "0x%x", node->rnode.indicator);
1856 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", node->rnode.fc_id);
1857 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", node->rnode.attached);
1858 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "hold_frames", node->hold_frames);
1859 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "io_alloc_enabled", node->io_alloc_enabled);
1860 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "req_free", node->req_free);
1861 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_oxid", "0x%#04x", node->ls_acc_oxid);
1862 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ls_acc_did", "0x%#04x", node->ls_acc_did);
1863 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "abort_cnt", "%d", node->abort_cnt);
1864 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "targ", node->targ);
1865 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "init", node->init);
1866 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "%s", node->wwpn);
1867 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "%s", node->wwnn);
1869 ocs_lock(&node->pend_frames_lock);
1870 ocs_list_foreach(&node->pend_frames, frame) {
1874 hdr = frame->header->dma.virt;
1875 ocs_snprintf(buf, sizeof(buf), "%02x/%04x/%04x len %zu", hdr->r_ctl,
1876 ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id),
1877 frame->payload->dma.len);
1878 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pend_frames", buf);
1880 ocs_unlock(&node->pend_frames_lock);
1882 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "chained_io_count", "%d", node->chained_io_count);
1883 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "resume");
1884 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_state", node->current_state_name);
1885 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "login_state", "%d", (node->sm.current_state == __ocs_d_device_ready) ? 1 : 0);
1887 ocs_lock(&node->active_ios_lock);
1888 ocs_list_foreach(&node->active_ios, io) {
1889 if ((io->mgmt_functions) && (io->mgmt_functions->get_all_handler)) {
1890 io->mgmt_functions->get_all_handler(textbuf,io);
1893 ocs_unlock(&node->active_ios_lock);
1895 ocs_mgmt_end_section(textbuf, "node", node->instance_index);
1899 ocs_mgmt_node_set(char *parent, char *name, char *value, void *object)
1902 ocs_node_t *node = (ocs_node_t *)object;
1906 ocs_snprintf(qualifier, sizeof(qualifier), "%s/node[%d]", parent, node->instance_index);
1908 /* If it doesn't start with my qualifier I don't know what to do with it */
1909 if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1911 ocs_lock(&node->active_ios_lock);
1912 ocs_list_foreach(&node->active_ios, io) {
1913 if ((io->mgmt_functions) && (io->mgmt_functions->set_handler)) {
1914 retval = io->mgmt_functions->set_handler(qualifier, name, value, io);
1922 ocs_unlock(&node->active_ios_lock);
1930 ocs_mgmt_node_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
1931 void *arg_out, uint32_t arg_out_length, void *object)
1934 ocs_node_t *node = (ocs_node_t *)object;
1938 ocs_snprintf(qualifier, sizeof(qualifier), "%s.node%d", parent, node->instance_index);
1940 /* If it doesn't start with my qualifier I don't know what to do with it */
1941 if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
1942 char *unqualified_name = action + strlen(qualifier) +1;
1944 if (ocs_strcmp(unqualified_name, "resume") == 0) {
1945 ocs_node_post_event(node, OCS_EVT_RESUME, NULL);
1949 /* If I didn't know how to do this action pass the request to each of my children */
1950 ocs_lock(&node->active_ios_lock);
1951 ocs_list_foreach(&node->active_ios, io) {
1952 if ((io->mgmt_functions) && (io->mgmt_functions->exec_handler)) {
1953 retval = io->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
1954 arg_out, arg_out_length, io);
1962 ocs_unlock(&node->active_ios_lock);
1972 * @brief Return TRUE if active ios list is empty
1974 * Test if node->active_ios list is empty while holding the node->active_ios_lock.
1976 * @param node pointer to node object
1978 * @return TRUE if node active ios list is empty
1982 ocs_node_active_ios_empty(ocs_node_t *node)
1986 ocs_lock(&node->active_ios_lock);
1987 empty = ocs_list_empty(&node->active_ios);
1988 ocs_unlock(&node->active_ios_lock);
1993 * @brief Pause a node
1995 * The node is placed in the __ocs_node_paused state after saving the state
1998 * @param node Pointer to node object
1999 * @param state State to resume to
2005 ocs_node_pause(ocs_node_t *node, ocs_sm_function_t state)
2007 node->nodedb_state = state;
2008 ocs_node_transition(node, __ocs_node_paused, NULL);
2012 * @brief Paused node state
2014 * This state is entered when a state is "paused". When resumed, the node
2015 * is transitioned to a previously saved state (node->ndoedb_state)
2017 * @param ctx Remote node state machine context.
2018 * @param evt Event to process.
2019 * @param arg Per event optional argument.
2021 * @return returns NULL
2025 __ocs_node_paused(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2027 std_node_state_decl();
2033 node_printf(node, "Paused\n");
2036 case OCS_EVT_RESUME: {
2037 ocs_sm_function_t pf = node->nodedb_state;
2039 node->nodedb_state = NULL;
2040 ocs_node_transition(node, pf, NULL);
2044 case OCS_EVT_DOMAIN_ATTACH_OK:
2047 case OCS_EVT_SHUTDOWN:
2052 __ocs_node_common(__func__, ctx, evt, arg);
2059 * @brief Resume a paused state
2061 * Posts a resume event to the paused node.
2063 * @param node Pointer to node object
2065 * @return returns 0 for success, a negative error code value for failure.
2069 ocs_node_resume(ocs_node_t *node)
2071 ocs_assert(node != NULL, -1);
2073 ocs_node_post_event(node, OCS_EVT_RESUME, NULL);
2079 * @ingroup node_common
2080 * @brief Dispatch a ELS frame.
2082 * <h3 class="desc">Description</h3>
2083 * An ELS frame is dispatched to the \c node state machine.
2084 * RQ Pair mode: this function is always called with a NULL hw
2087 * @param node Node that originated the frame.
2088 * @param seq header/payload sequence buffers
2090 * @return Returns 0 if frame processed and RX buffers cleaned
2091 * up appropriately, -1 if frame not handled and RX buffers need
2096 ocs_node_recv_els_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2101 uint32_t payload_size;
2102 } els_cmd_list[] = {
2103 {FC_ELS_CMD_PLOGI, OCS_EVT_PLOGI_RCVD, sizeof(fc_plogi_payload_t)},
2104 {FC_ELS_CMD_FLOGI, OCS_EVT_FLOGI_RCVD, sizeof(fc_plogi_payload_t)},
2105 {FC_ELS_CMD_LOGO, OCS_EVT_LOGO_RCVD, sizeof(fc_acc_payload_t)},
2106 {FC_ELS_CMD_RRQ, OCS_EVT_RRQ_RCVD, sizeof(fc_acc_payload_t)},
2107 {FC_ELS_CMD_PRLI, OCS_EVT_PRLI_RCVD, sizeof(fc_prli_payload_t)},
2108 {FC_ELS_CMD_PRLO, OCS_EVT_PRLO_RCVD, sizeof(fc_prlo_payload_t)},
2109 {FC_ELS_CMD_PDISC, OCS_EVT_PDISC_RCVD, MAX_ACC_REJECT_PAYLOAD},
2110 {FC_ELS_CMD_FDISC, OCS_EVT_FDISC_RCVD, MAX_ACC_REJECT_PAYLOAD},
2111 {FC_ELS_CMD_ADISC, OCS_EVT_ADISC_RCVD, sizeof(fc_adisc_payload_t)},
2112 {FC_ELS_CMD_RSCN, OCS_EVT_RSCN_RCVD, MAX_ACC_REJECT_PAYLOAD},
2113 {FC_ELS_CMD_SCR , OCS_EVT_SCR_RCVD, MAX_ACC_REJECT_PAYLOAD},
2115 ocs_t *ocs = node->ocs;
2116 ocs_node_cb_t cbdata;
2117 fc_header_t *hdr = seq->header->dma.virt;
2118 uint8_t *buf = seq->payload->dma.virt;
2119 ocs_sm_event_t evt = OCS_EVT_ELS_RCVD;
2120 uint32_t payload_size = MAX_ACC_REJECT_PAYLOAD;
2123 ocs_memset(&cbdata, 0, sizeof(cbdata));
2124 cbdata.header = seq->header;
2125 cbdata.payload = seq->payload;
2127 /* find a matching event for the ELS command */
2128 for (i = 0; i < ARRAY_SIZE(els_cmd_list); i ++) {
2129 if (els_cmd_list[i].cmd == buf[0]) {
2130 evt = els_cmd_list[i].evt;
2131 payload_size = els_cmd_list[i].payload_size;
2137 case OCS_EVT_FLOGI_RCVD:
2138 ocs_display_sparams(node->display_name, "flogi rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2140 case OCS_EVT_FDISC_RCVD:
2141 ocs_display_sparams(node->display_name, "fdisc rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2143 case OCS_EVT_PLOGI_RCVD:
2144 ocs_display_sparams(node->display_name, "plogi rcvd req", 0, NULL, ((uint8_t*)seq->payload->dma.virt)+4);
2150 cbdata.io = ocs_els_io_alloc(node, payload_size, OCS_ELS_ROLE_RESPONDER);
2152 if (cbdata.io != NULL) {
2153 cbdata.io->hw_priv = seq->hw_priv;
2154 /* if we're here, sequence initiative has been transferred */
2155 cbdata.io->seq_init = 1;
2157 ocs_node_post_event(node, evt, &cbdata);
2159 node_printf(node, "failure to allocate SCSI IO for ELS s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2160 fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id), ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2162 ocs_hw_sequence_free(&ocs->hw, seq);
2167 * @ingroup node_common
2168 * @brief Dispatch a ABTS frame (RQ Pair/sequence coalescing).
2170 * <h3 class="desc">Description</h3>
2171 * An ABTS frame is dispatched to the node state machine. This
2172 * function is used for both RQ Pair and sequence coalescing.
2174 * @param node Node that originated the frame.
2175 * @param seq Header/payload sequence buffers
2177 * @return Returns 0 if frame processed and RX buffers cleaned
2178 * up appropriately, -1 if frame not handled and RX buffers need
2183 ocs_node_recv_abts_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2185 ocs_t *ocs = node->ocs;
2186 ocs_xport_t *xport = ocs->xport;
2187 fc_header_t *hdr = seq->header->dma.virt;
2188 uint16_t ox_id = ocs_be16toh(hdr->ox_id);
2189 uint16_t rx_id = ocs_be16toh(hdr->rx_id);
2190 ocs_node_cb_t cbdata;
2196 * Check to see if the IO we want to abort is active, if it not active,
2197 * then we can send the BA_ACC using the send frame option
2199 if (ocs_io_find_tgt_io(ocs, node, ox_id, rx_id) == NULL) {
2200 uint32_t send_frame_capable;
2202 ocs_log_debug(ocs, "IO not found (ox_id %04x)\n", ox_id);
2204 /* If we have SEND_FRAME capability, then use it to send BA_ACC */
2205 rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
2206 if ((rc == 0) && send_frame_capable) {
2207 rc = ocs_sframe_send_bls_acc(node, seq);
2209 ocs_log_test(ocs, "ocs_bls_acc_send_frame failed\n");
2216 ocs_memset(&cbdata, 0, sizeof(cbdata));
2217 cbdata.header = seq->header;
2218 cbdata.payload = seq->payload;
2220 cbdata.io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
2221 if (cbdata.io != NULL) {
2222 cbdata.io->hw_priv = seq->hw_priv;
2223 /* If we got this far, SIT=1 */
2224 cbdata.io->seq_init = 1;
2226 /* fill out generic fields */
2227 cbdata.io->ocs = ocs;
2228 cbdata.io->node = node;
2229 cbdata.io->cmd_tgt = TRUE;
2231 ocs_node_post_event(node, OCS_EVT_ABTS_RCVD, &cbdata);
2233 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
2234 node_printf(node, "SCSI IO allocation failed for ABTS received s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2235 fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id), ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2238 /* ABTS processed, return RX buffer to the chip */
2239 ocs_hw_sequence_free(&ocs->hw, seq);
2244 * @ingroup node_common
2245 * @brief Dispatch a CT frame.
2247 * <h3 class="desc">Description</h3>
2248 * A CT frame is dispatched to the \c node state machine.
2249 * RQ Pair mode: this function is always called with a NULL hw
2252 * @param node Node that originated the frame.
2253 * @param seq header/payload sequence buffers
2255 * @return Returns 0 if frame processed and RX buffers cleaned
2256 * up appropriately, -1 if frame not handled and RX buffers need
2261 ocs_node_recv_ct_frame(ocs_node_t *node, ocs_hw_sequence_t *seq)
2263 ocs_t *ocs = node->ocs;
2264 fc_header_t *hdr = seq->header->dma.virt;
2265 fcct_iu_header_t *iu = seq->payload->dma.virt;
2266 ocs_sm_event_t evt = OCS_EVT_ELS_RCVD;
2267 uint32_t payload_size = MAX_ACC_REJECT_PAYLOAD;
2268 uint16_t gscmd = ocs_be16toh(iu->cmd_rsp_code);
2269 ocs_node_cb_t cbdata;
2274 uint32_t payload_size;
2276 {FC_GS_NAMESERVER_RFF_ID, OCS_EVT_RFF_ID_RCVD, 100},
2277 {FC_GS_NAMESERVER_RFT_ID, OCS_EVT_RFT_ID_RCVD, 100},
2278 {FC_GS_NAMESERVER_GNN_ID, OCS_EVT_GNN_ID_RCVD, 100},
2279 {FC_GS_NAMESERVER_GPN_ID, OCS_EVT_GPN_ID_RCVD, 100},
2280 {FC_GS_NAMESERVER_GFPN_ID, OCS_EVT_GFPN_ID_RCVD, 100},
2281 {FC_GS_NAMESERVER_GFF_ID, OCS_EVT_GFF_ID_RCVD, 100},
2282 {FC_GS_NAMESERVER_GID_FT, OCS_EVT_GID_FT_RCVD, 256},
2283 {FC_GS_NAMESERVER_GID_PT, OCS_EVT_GID_PT_RCVD, 256},
2284 {FC_GS_NAMESERVER_RPN_ID, OCS_EVT_RPN_ID_RCVD, 100},
2285 {FC_GS_NAMESERVER_RNN_ID, OCS_EVT_RNN_ID_RCVD, 100},
2286 {FC_GS_NAMESERVER_RCS_ID, OCS_EVT_RCS_ID_RCVD, 100},
2287 {FC_GS_NAMESERVER_RSNN_NN, OCS_EVT_RSNN_NN_RCVD, 100},
2288 {FC_GS_NAMESERVER_RSPN_ID, OCS_EVT_RSPN_ID_RCVD, 100},
2289 {FC_GS_NAMESERVER_RHBA, OCS_EVT_RHBA_RCVD, 100},
2290 {FC_GS_NAMESERVER_RPA, OCS_EVT_RPA_RCVD, 100},
2293 ocs_memset(&cbdata, 0, sizeof(cbdata));
2294 cbdata.header = seq->header;
2295 cbdata.payload = seq->payload;
2297 /* find a matching event for the ELS/GS command */
2298 for (i = 0; i < ARRAY_SIZE(ct_cmd_list); i ++) {
2299 if (ct_cmd_list[i].cmd == gscmd) {
2300 evt = ct_cmd_list[i].evt;
2301 payload_size = ct_cmd_list[i].payload_size;
2306 /* Allocate an IO and send a reject */
2307 cbdata.io = ocs_els_io_alloc(node, payload_size, OCS_ELS_ROLE_RESPONDER);
2308 if (cbdata.io == NULL) {
2309 node_printf(node, "GS IO failed for s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2310 fc_be24toh(hdr->s_id), fc_be24toh(hdr->d_id),
2311 ocs_be16toh(hdr->ox_id), ocs_be16toh(hdr->rx_id));
2314 cbdata.io->hw_priv = seq->hw_priv;
2315 ocs_node_post_event(node, evt, &cbdata);
2317 ocs_hw_sequence_free(&ocs->hw, seq);
2322 * @ingroup node_common
2323 * @brief Dispatch a FCP command frame when the node is not ready.
2325 * <h3 class="desc">Description</h3>
2326 * A frame is dispatched to the \c node state machine.
2328 * @param node Node that originated the frame.
2329 * @param seq header/payload sequence buffers
2331 * @return Returns 0 if frame processed and RX buffers cleaned
2332 * up appropriately, -1 if frame not handled.
2336 ocs_node_recv_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq)
2338 ocs_node_cb_t cbdata;
2339 ocs_t *ocs = node->ocs;
2341 ocs_memset(&cbdata, 0, sizeof(cbdata));
2342 cbdata.header = seq->header;
2343 cbdata.payload = seq->payload;
2344 ocs_node_post_event(node, OCS_EVT_FCP_CMD_RCVD, &cbdata);
2345 ocs_hw_sequence_free(&ocs->hw, seq);
2350 * @ingroup node_common
2351 * @brief Stub handler for non-ABTS BLS frames
2353 * <h3 class="desc">Description</h3>
2354 * Log message and drop. Customer can plumb it to their back-end as needed
2356 * @param node Node that originated the frame.
2357 * @param seq header/payload sequence buffers
2363 ocs_node_recv_bls_no_sit(ocs_node_t *node, ocs_hw_sequence_t *seq)
2365 fc_header_t *hdr = seq->header->dma.virt;
2367 node_printf(node, "Dropping frame hdr = %08x %08x %08x %08x %08x %08x\n",
2368 ocs_htobe32(((uint32_t *)hdr)[0]),
2369 ocs_htobe32(((uint32_t *)hdr)[1]),
2370 ocs_htobe32(((uint32_t *)hdr)[2]),
2371 ocs_htobe32(((uint32_t *)hdr)[3]),
2372 ocs_htobe32(((uint32_t *)hdr)[4]),
2373 ocs_htobe32(((uint32_t *)hdr)[5]));