The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ocs_fc/ocs_els.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * Functions to build and send ELS/CT/BLS commands and responses.
   37  */
   38 
   39 /*!
   40 @defgroup els_api ELS/BLS/CT Command and Response Functions
   41 */
   42 
   43 #include "ocs.h"
   44 #include "ocs_els.h"
   45 #include "ocs_scsi.h"
   46 #include "ocs_device.h"
   47 
   48 #define ELS_IOFMT "[i:%04x t:%04x h:%04x]"
   49 #define ELS_IOFMT_ARGS(els) els->init_task_tag, els->tgt_task_tag, els->hw_tag
   50 
   51 #define node_els_trace()  \
   52         do { \
   53                 if (OCS_LOG_ENABLE_ELS_TRACE(ocs)) \
   54                         ocs_log_info(ocs, "[%s] %-20s\n", node->display_name, __func__); \
   55         } while (0)
   56 
   57 #define els_io_printf(els, fmt, ...) \
   58         ocs_log_debug(els->node->ocs, "[%s]" ELS_IOFMT " %-8s " fmt, els->node->display_name, ELS_IOFMT_ARGS(els), els->display_name, ##__VA_ARGS__);
   59 
   60 static int32_t ocs_els_send(ocs_io_t *els, uint32_t reqlen, uint32_t timeout_sec, ocs_hw_srrs_cb_t cb);
   61 static int32_t ocs_els_send_rsp(ocs_io_t *els, uint32_t rsplen);
   62 static int32_t ocs_els_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg);
   63 static ocs_io_t *ocs_bls_send_acc(ocs_io_t *io, uint32_t s_id, uint16_t ox_id, uint16_t rx_id);
   64 static int32_t ocs_bls_send_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length,
   65         int32_t status, uint32_t ext_status, void *app);
   66 static void ocs_io_transition(ocs_io_t *els, ocs_sm_function_t state, void *data);
   67 static ocs_io_t *ocs_els_abort_io(ocs_io_t *els, int send_abts);
   68 static void _ocs_els_io_free(void *arg);
   69 static void ocs_els_delay_timer_cb(void *arg);
   70 
   71 /**
   72  * @ingroup els_api
   73  * @brief ELS state machine transition wrapper.
   74  *
   75  * <h3 class="desc">Description</h3>
   76  * This function is the transition wrapper for the ELS state machine. It grabs
   77  * the node lock prior to making the transition to protect
   78  * against multiple threads accessing a particular ELS. For example,
   79  * one thread transitioning from __els_init to
   80  * __ocs_els_wait_resp and another thread (tasklet) handling the
   81  * completion of that ELS request.
   82  *
   83  * @param els Pointer to the IO context.
   84  * @param state State to transition to.
   85  * @param data Data to pass in with the transition.
   86  *
   87  * @return None.
   88  */
   89 static void
   90 ocs_io_transition(ocs_io_t *els, ocs_sm_function_t state, void *data)
   91 {
   92         /* protect ELS events with node lock */
   93         ocs_node_t *node = els->node;
   94         ocs_node_lock(node);
   95                 ocs_sm_transition(&els->els_sm, state, data);
   96         ocs_node_unlock(node);
   97 }
   98 
   99 /**
  100  * @ingroup els_api
  101  * @brief ELS state machine post event wrapper.
  102  *
  103  * <h3 class="desc">Description</h3>
  104  * Post an event wrapper for the ELS state machine. This function grabs
  105  * the node lock prior to posting the event.
  106  *
  107  * @param els Pointer to the IO context.
  108  * @param evt Event to process.
  109  * @param data Data to pass in with the transition.
  110  *
  111  * @return None.
  112  */
  113 void
  114 ocs_els_post_event(ocs_io_t *els, ocs_sm_event_t evt, void *data)
  115 {
  116         /* protect ELS events with node lock */
  117         ocs_node_t *node = els->node;
  118         ocs_node_lock(node);
  119                 els->els_evtdepth ++;
  120                 ocs_sm_post_event(&els->els_sm, evt, data);
  121                 els->els_evtdepth --;
  122         ocs_node_unlock(node);
  123         if (els->els_evtdepth == 0 && els->els_req_free) {
  124                 ocs_els_io_free(els);
  125         }
  126 }
  127 
  128 /**
  129  * @ingroup els_api
  130  * @brief Allocate an IO structure for an ELS IO context.
  131  *
  132  * <h3 class="desc">Description</h3>
  133  * Allocate an IO for an ELS context.  Uses OCS_ELS_RSP_LEN as response size.
  134  *
  135  * @param node node to associate ELS IO with
  136  * @param reqlen Length of ELS request
  137  * @param role Role of ELS (originator/responder)
  138  *
  139  * @return pointer to IO structure allocated
  140  */
  141 
  142 ocs_io_t *
  143 ocs_els_io_alloc(ocs_node_t *node, uint32_t reqlen, ocs_els_role_e role)
  144 {
  145         return ocs_els_io_alloc_size(node, reqlen, OCS_ELS_RSP_LEN, role);
  146 }
  147 
  148 /**
  149  * @ingroup els_api
  150  * @brief Allocate an IO structure for an ELS IO context.
  151  *
  152  * <h3 class="desc">Description</h3>
  153  * Allocate an IO for an ELS context, allowing the caller to specify the size of the response.
  154  *
  155  * @param node node to associate ELS IO with
  156  * @param reqlen Length of ELS request
  157  * @param rsplen Length of ELS response
  158  * @param role Role of ELS (originator/responder)
  159  *
  160  * @return pointer to IO structure allocated
  161  */
  162 
  163 ocs_io_t *
  164 ocs_els_io_alloc_size(ocs_node_t *node, uint32_t reqlen, uint32_t rsplen, ocs_els_role_e role)
  165 {
  166 
  167         ocs_t *ocs;
  168         ocs_xport_t *xport;
  169         ocs_io_t *els;
  170         ocs_assert(node, NULL);
  171         ocs_assert(node->ocs, NULL);
  172         ocs = node->ocs;
  173         ocs_assert(ocs->xport, NULL);
  174         xport = ocs->xport;
  175 
  176         ocs_lock(&node->active_ios_lock);
  177                 if (!node->io_alloc_enabled) {
  178                         ocs_log_debug(ocs, "called with io_alloc_enabled = FALSE\n");
  179                         ocs_unlock(&node->active_ios_lock);
  180                         return NULL;
  181                 }
  182 
  183                 els = ocs_io_alloc(ocs);
  184                 if (els == NULL) {
  185                         ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
  186                         ocs_unlock(&node->active_ios_lock);
  187                         return NULL;
  188                 }
  189 
  190                 /* initialize refcount */
  191                 ocs_ref_init(&els->ref, _ocs_els_io_free, els);
  192 
  193                 switch (role) {
  194                 case OCS_ELS_ROLE_ORIGINATOR:
  195                         els->cmd_ini = TRUE;
  196                         els->cmd_tgt = FALSE;
  197                         break;
  198                 case OCS_ELS_ROLE_RESPONDER:
  199                         els->cmd_ini = FALSE;
  200                         els->cmd_tgt = TRUE;
  201                         break;
  202                 }
  203 
  204                 /* IO should not have an associated HW IO yet.  Assigned below. */
  205                 if (els->hio != NULL) {
  206                         ocs_log_err(ocs, "assertion failed.  HIO is not null\n");
  207                         ocs_io_free(ocs, els);
  208                         ocs_unlock(&node->active_ios_lock);
  209                         return NULL;
  210                 }
  211 
  212                 /* populate generic io fields */
  213                 els->ocs = ocs;
  214                 els->node = node;
  215 
  216                 /* set type and ELS-specific fields */
  217                 els->io_type = OCS_IO_TYPE_ELS;
  218                 els->display_name = "pending";
  219 
  220                 if (reqlen > OCS_ELS_REQ_LEN) {
  221                         ocs_log_err(ocs, "ELS command request len greater than allocated\n");
  222                         ocs_io_free(ocs, els);
  223                         ocs_unlock(&node->active_ios_lock);
  224                         return NULL;
  225                 }
  226 
  227                 if (rsplen > OCS_ELS_GID_PT_RSP_LEN) {
  228                         ocs_log_err(ocs, "ELS command response len: %d "
  229                                 "greater than allocated\n", rsplen);
  230                         ocs_io_free(ocs, els);
  231                         ocs_unlock(&node->active_ios_lock);
  232                         return NULL;
  233                 }
  234 
  235                 els->els_req.size = reqlen;
  236                 els->els_rsp.size = rsplen;
  237 
  238                 if (els != NULL) {
  239                         ocs_memset(&els->els_sm, 0, sizeof(els->els_sm));
  240                         els->els_sm.app = els;
  241 
  242                         /* initialize fields */
  243                         els->els_retries_remaining = OCS_FC_ELS_DEFAULT_RETRIES;
  244                         els->els_evtdepth = 0;
  245                         els->els_pend = 0;
  246                         els->els_active = 0;
  247 
  248                         /* add els structure to ELS IO list */
  249                         ocs_list_add_tail(&node->els_io_pend_list, els);
  250                         els->els_pend = 1;
  251                 }
  252         ocs_unlock(&node->active_ios_lock);
  253         return els;
  254 }
  255 
  256 /**
  257  * @ingroup els_api
  258  * @brief Free IO structure for an ELS IO context.
  259  *
  260  * <h3 class="desc">Description</h3> Free IO for an ELS
  261  * IO context
  262  *
  263  * @param els ELS IO structure for which IO is allocated
  264  *
  265  * @return None
  266  */
  267 
  268 void
  269 ocs_els_io_free(ocs_io_t *els)
  270 {
  271         ocs_ref_put(&els->ref);
  272 }
  273 
  274 /**
  275  * @ingroup els_api
  276  * @brief Free IO structure for an ELS IO context.
  277  *
  278  * <h3 class="desc">Description</h3> Free IO for an ELS
  279  * IO context
  280  *
  281  * @param arg ELS IO structure for which IO is allocated
  282  *
  283  * @return None
  284  */
  285 
  286 static void
  287 _ocs_els_io_free(void *arg)
  288 {
  289         ocs_io_t *els = (ocs_io_t *)arg;
  290         ocs_t *ocs;
  291         ocs_node_t *node;
  292         int send_empty_event = FALSE;
  293 
  294         ocs_assert(els);
  295         ocs_assert(els->node);
  296         ocs_assert(els->node->ocs);
  297         ocs = els->node->ocs;
  298 
  299         node = els->node;
  300         ocs = node->ocs;
  301 
  302         ocs_lock(&node->active_ios_lock);
  303                 if (els->els_active) {
  304                         /* if active, remove from active list and check empty */
  305                         ocs_list_remove(&node->els_io_active_list, els);
  306                         /* Send list empty event if the IO allocator is disabled, and the list is empty
  307                          * If node->io_alloc_enabled was not checked, the event would be posted continually
  308                          */
  309                         send_empty_event = (!node->io_alloc_enabled) && ocs_list_empty(&node->els_io_active_list);
  310                         els->els_active = 0;
  311                 } else if (els->els_pend) {
  312                         /* if pending, remove from pending list; node shutdown isn't
  313                          * gated off the pending list (only the active list), so no
  314                          * need to check if pending list is empty
  315                          */
  316                         ocs_list_remove(&node->els_io_pend_list, els);
  317                         els->els_pend = 0;
  318                 } else {
  319                         ocs_log_err(ocs, "assertion failed: niether els->els_pend nor els->active set\n");
  320                         ocs_unlock(&node->active_ios_lock);
  321                         return;
  322                 }
  323 
  324         ocs_unlock(&node->active_ios_lock);
  325 
  326         ocs_io_free(ocs, els);
  327 
  328         if (send_empty_event) {
  329                 ocs_node_post_event(node, OCS_EVT_ALL_CHILD_NODES_FREE, NULL);
  330         }
  331 
  332         ocs_scsi_check_pending(ocs);
  333 }
  334 
  335 /**
  336  * @ingroup els_api
  337  * @brief Make ELS IO active
  338  *
  339  * @param els Pointer to the IO context to make active.
  340  *
  341  * @return Returns 0 on success; or a negative error code value on failure.
  342  */
  343 
  344 static void
  345 ocs_els_make_active(ocs_io_t *els)
  346 {
  347         ocs_node_t *node = els->node;
  348 
  349         /* move ELS from pending list to active list */
  350         ocs_lock(&node->active_ios_lock);
  351                 if (els->els_pend) {
  352                         if (els->els_active) {
  353                                 ocs_log_err(node->ocs, "assertion failed: both els->els_pend and els->active set\n");
  354                                 ocs_unlock(&node->active_ios_lock);
  355                                 return;
  356                         } else {
  357                                 /* remove from pending list */
  358                                 ocs_list_remove(&node->els_io_pend_list, els);
  359                                 els->els_pend = 0;
  360 
  361                                 /* add els structure to ELS IO list */
  362                                 ocs_list_add_tail(&node->els_io_active_list, els);
  363                                 els->els_active = 1;
  364                         }
  365                 } else {
  366                         /* must be retrying; make sure it's already active */
  367                         if (!els->els_active) {
  368                                 ocs_log_err(node->ocs, "assertion failed: niether els->els_pend nor els->active set\n");
  369                         }
  370                 }
  371         ocs_unlock(&node->active_ios_lock);
  372 }
  373 
  374 /**
  375  * @ingroup els_api
  376  * @brief Send the ELS command.
  377  *
  378  * <h3 class="desc">Description</h3>
  379  * The command, given by the \c els IO context, is sent to the node that the IO was
  380  * configured with, using ocs_hw_srrs_send(). Upon completion,
  381  * the \c cb callback is invoked,
  382  * with the application-specific argument set to the \c els IO context.
  383  *
  384  * @param els Pointer to the IO context.
  385  * @param reqlen Byte count in the payload to send.
  386  * @param timeout_sec Command timeout, in seconds (0 -> 2*R_A_TOV).
  387  * @param cb Completion callback.
  388  *
  389  * @return Returns 0 on success; or a negative error code value on failure.
  390  */
  391 
  392 static int32_t
  393 ocs_els_send(ocs_io_t *els, uint32_t reqlen, uint32_t timeout_sec, ocs_hw_srrs_cb_t cb)
  394 {
  395         ocs_node_t *node = els->node;
  396 
  397         /* update ELS request counter */
  398         node->els_req_cnt++;
  399 
  400         /* move ELS from pending list to active list */
  401         ocs_els_make_active(els);
  402 
  403         els->wire_len = reqlen;
  404         return ocs_scsi_io_dispatch(els, cb);
  405 }
  406 
  407 /**
  408  * @ingroup els_api
  409  * @brief Send the ELS response.
  410  *
  411  * <h3 class="desc">Description</h3>
  412  * The ELS response, given by the \c els IO context, is sent to the node
  413  * that the IO was configured with, using ocs_hw_srrs_send().
  414  *
  415  * @param els Pointer to the IO context.
  416  * @param rsplen Byte count in the payload to send.
  417  *
  418  * @return Returns 0 on success; or a negative error value on failure.
  419  */
  420 
  421 static int32_t
  422 ocs_els_send_rsp(ocs_io_t *els, uint32_t rsplen)
  423 {
  424         ocs_node_t *node = els->node;
  425 
  426         /* increment ELS completion counter */
  427         node->els_cmpl_cnt++;
  428 
  429         /* move ELS from pending list to active list */
  430         ocs_els_make_active(els);
  431 
  432         els->wire_len = rsplen;
  433         return ocs_scsi_io_dispatch(els, ocs_els_acc_cb);
  434 }
  435 
  436 /**
  437  * @ingroup els_api
  438  * @brief Handle ELS IO request completions.
  439  *
  440  * <h3 class="desc">Description</h3>
  441  * This callback is used for several ELS send operations.
  442  *
  443  * @param hio Pointer to the HW IO context that completed.
  444  * @param rnode Pointer to the remote node.
  445  * @param length Length of the returned payload data.
  446  * @param status Status of the completion.
  447  * @param ext_status Extended status of the completion.
  448  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
  449  *
  450  * @return Returns 0 on success; or a negative error value on failure.
  451  */
  452 
  453 static int32_t
  454 ocs_els_req_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
  455 {
  456         ocs_io_t *els;
  457         ocs_node_t *node;
  458         ocs_t *ocs;
  459         ocs_node_cb_t cbdata;
  460         ocs_io_t *io;
  461 
  462         ocs_assert(arg, -1);
  463         io = arg;
  464         els = io;
  465         ocs_assert(els, -1);
  466         ocs_assert(els->node, -1);
  467         node = els->node;
  468         ocs_assert(node->ocs, -1);
  469         ocs = node->ocs;
  470 
  471         ocs_assert(io->hio, -1);
  472         ocs_assert(hio == io->hio, -1);
  473 
  474         if (status != 0) {
  475                 els_io_printf(els, "status x%x ext x%x\n", status, ext_status);
  476         }
  477 
  478         /* set the response len element of els->rsp */
  479         els->els_rsp.len = length;
  480 
  481         cbdata.status = status;
  482         cbdata.ext_status = ext_status;
  483         cbdata.header = NULL;
  484         cbdata.els = els;
  485 
  486         /* FW returns the number of bytes received on the link in
  487          * the WCQE, not the amount placed in the buffer; use this info to
  488          * check if there was an overrun.
  489          */
  490         if (length > els->els_rsp.size) {
  491                 ocs_log_warn(ocs, "ELS response returned len=%d > buflen=%zu\n",
  492                                 length, els->els_rsp.size);
  493                 ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
  494                 return 0;
  495         }
  496 
  497         /* Post event to ELS IO object */
  498         switch (status) {
  499         case SLI4_FC_WCQE_STATUS_SUCCESS:
  500                 ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_OK, &cbdata);
  501                 break;
  502 
  503         case SLI4_FC_WCQE_STATUS_LS_RJT:
  504                 ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_RJT, &cbdata);
  505                 break;
  506 
  507         case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
  508                 switch (ext_status) {
  509                 case SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT:
  510                         ocs_els_post_event(els, OCS_EVT_ELS_REQ_TIMEOUT, &cbdata);
  511                         break;
  512                 case SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED:
  513                         ocs_els_post_event(els, OCS_EVT_ELS_REQ_ABORTED, &cbdata);
  514                         break;
  515                 default:
  516                         ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
  517                         break;
  518                 }
  519                 break;
  520         default:
  521                 ocs_log_warn(ocs, "els req complete: failed status x%x, ext_status, x%x\n", status, ext_status);
  522                 ocs_els_post_event(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
  523                 break;
  524         }
  525 
  526         return 0;
  527 }
  528 
  529 /**
  530  * @ingroup els_api
  531  * @brief Handle ELS IO accept/response completions.
  532  *
  533  * <h3 class="desc">Description</h3>
  534  * This callback is used for several ELS send operations.
  535  *
  536  * @param hio Pointer to the HW IO context that completed.
  537  * @param rnode Pointer to the remote node.
  538  * @param length Length of the returned payload data.
  539  * @param status Status of the completion.
  540  * @param ext_status Extended status of the completion.
  541  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
  542  *
  543  * @return Returns 0 on success; or a negative error value on failure.
  544  */
  545 
  546 static int32_t
  547 ocs_els_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
  548 {
  549         ocs_io_t *els;
  550         ocs_node_t *node;
  551         ocs_t *ocs;
  552         ocs_node_cb_t cbdata;
  553         ocs_io_t *io;
  554 
  555         ocs_assert(arg, -1);
  556         io = arg;
  557         els = io;
  558         ocs_assert(els, -1);
  559         ocs_assert(els->node, -1);
  560         node = els->node;
  561         ocs_assert(node->ocs, -1);
  562         ocs = node->ocs;
  563 
  564         ocs_assert(io->hio, -1);
  565         ocs_assert(hio == io->hio, -1);
  566 
  567         cbdata.status = status;
  568         cbdata.ext_status = ext_status;
  569         cbdata.header = NULL;
  570         cbdata.els = els;
  571 
  572         /* Post node event */
  573         switch (status) {
  574         case SLI4_FC_WCQE_STATUS_SUCCESS:
  575                 ocs_node_post_event(node, OCS_EVT_SRRS_ELS_CMPL_OK, &cbdata);
  576                 break;
  577 
  578         default:
  579                 ocs_log_warn(ocs, "[%s] %-8s failed status x%x, ext_status x%x\n",
  580                         node->display_name, els->display_name, status, ext_status);
  581                 ocs_log_warn(ocs, "els acc complete: failed status x%x, ext_status, x%x\n", status, ext_status);
  582                 ocs_node_post_event(node, OCS_EVT_SRRS_ELS_CMPL_FAIL, &cbdata);
  583                 break;
  584         }
  585 
  586         /* If this IO has a callback, invoke it */
  587         if (els->els_callback) {
  588                 (*els->els_callback)(node, &cbdata, els->els_callback_arg);
  589         }
  590 
  591         ocs_els_io_free(els);
  592 
  593         return 0;
  594 }
  595 
  596 /**
  597  * @ingroup els_api
  598  * @brief Format and send a PLOGI ELS command.
  599  *
  600  * <h3 class="desc">Description</h3>
  601  * Construct a PLOGI payload using the domain SLI port service parameters,
  602  * and send to the \c node.
  603  *
  604  * @param node Node to which the PLOGI is sent.
  605  * @param timeout_sec Command timeout, in seconds.
  606  * @param retries Number of times to retry errors before reporting a failure.
  607  * @param cb Callback function.
  608  * @param cbarg Callback function argument.
  609  *
  610  * @return Returns pointer to IO object, or NULL if error.
  611  */
  612 
  613 ocs_io_t *
  614 ocs_send_plogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  615         void (*cb)(ocs_node_t *node, ocs_node_cb_t *cbdata, void *arg), void *cbarg)
  616 {
  617         ocs_io_t *els;
  618         ocs_t *ocs = node->ocs;
  619         fc_plogi_payload_t *plogi;
  620 
  621         node_els_trace();
  622 
  623         els = ocs_els_io_alloc(node, sizeof(*plogi), OCS_ELS_ROLE_ORIGINATOR);
  624         if (els == NULL) {
  625                 ocs_log_err(ocs, "IO alloc failed\n");
  626         } else {
  627                 els->els_timeout_sec = timeout_sec;
  628                 els->els_retries_remaining = retries;
  629                 els->els_callback = cb;
  630                 els->els_callback_arg = cbarg;
  631                 els->display_name = "plogi";
  632 
  633                 /* Build PLOGI request */
  634                 plogi = els->els_req.virt;
  635 
  636                 ocs_memcpy(plogi, node->sport->service_params, sizeof(*plogi));
  637 
  638                 plogi->command_code = FC_ELS_CMD_PLOGI;
  639                 plogi->resv1 = 0;
  640 
  641                 ocs_display_sparams(node->display_name, "plogi send req", 0, NULL, plogi->common_service_parameters);
  642 
  643                 els->hio_type = OCS_HW_ELS_REQ;
  644                 els->iparam.els.timeout = timeout_sec;
  645 
  646                 ocs_io_transition(els, __ocs_els_init, NULL);
  647         }
  648         return els;
  649 }
  650 
  651 /**
  652  * @ingroup els_api
  653  * @brief Format and send a FLOGI ELS command.
  654  *
  655  * <h3 class="desc">Description</h3>
  656  * Construct an FLOGI payload, and send to the \c node.
  657  *
  658  * @param node Node to which the FLOGI is sent.
  659  * @param timeout_sec Command timeout, in seconds.
  660  * @param retries Number of times to retry errors before reporting a failure.
  661  * @param cb Callback function.
  662  * @param cbarg Callback function argument.
  663  *
  664  * @return Returns pointer to IO object, or NULL if error.
  665  */
  666 
  667 ocs_io_t *
  668 ocs_send_flogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  669         els_cb_t cb, void *cbarg)
  670 {
  671         ocs_io_t *els;
  672         ocs_t *ocs;
  673         fc_plogi_payload_t *flogi;
  674 
  675         ocs_assert(node, NULL);
  676         ocs_assert(node->ocs, NULL);
  677         ocs_assert(node->sport, NULL);
  678         ocs = node->ocs;
  679 
  680         node_els_trace();
  681 
  682         els = ocs_els_io_alloc(node, sizeof(*flogi), OCS_ELS_ROLE_ORIGINATOR);
  683         if (els == NULL) {
  684                 ocs_log_err(ocs, "IO alloc failed\n");
  685         } else {
  686                 els->els_timeout_sec = timeout_sec;
  687                 els->els_retries_remaining = retries;
  688                 els->els_callback = cb;
  689                 els->els_callback_arg = cbarg;
  690                 els->display_name = "flogi";
  691 
  692                 /* Build FLOGI request */
  693                 flogi = els->els_req.virt;
  694 
  695                 ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
  696                 flogi->command_code = FC_ELS_CMD_FLOGI;
  697                 flogi->resv1 = 0;
  698 
  699                 /* Priority tagging support */
  700                 flogi->common_service_parameters[1] |= ocs_htobe32(1U << 23);
  701 
  702                 ocs_display_sparams(node->display_name, "flogi send req", 0, NULL, flogi->common_service_parameters);
  703 
  704                 els->hio_type = OCS_HW_ELS_REQ;
  705                 els->iparam.els.timeout = timeout_sec;
  706                 ocs_io_transition(els, __ocs_els_init, NULL);
  707         }
  708         return els;
  709 }
  710 
  711 /**
  712  * @ingroup els_api
  713  * @brief Format and send a FDISC ELS command.
  714  *
  715  * <h3 class="desc">Description</h3>
  716  * Construct an FDISC payload, and send to the \c node.
  717  *
  718  * @param node Node to which the FDISC is sent.
  719  * @param timeout_sec Command timeout, in seconds.
  720  * @param retries Number of times to retry errors before reporting a failure.
  721  * @param cb Callback function.
  722  * @param cbarg Callback function argument.
  723  *
  724  * @return Returns pointer to IO object, or NULL if error.
  725  */
  726 
  727 ocs_io_t *
  728 ocs_send_fdisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  729         els_cb_t cb, void *cbarg)
  730 {
  731         ocs_io_t *els;
  732         ocs_t *ocs;
  733         fc_plogi_payload_t *fdisc;
  734 
  735         ocs_assert(node, NULL);
  736         ocs_assert(node->ocs, NULL);
  737         ocs = node->ocs;
  738 
  739         node_els_trace();
  740 
  741         els = ocs_els_io_alloc(node, sizeof(*fdisc), OCS_ELS_ROLE_ORIGINATOR);
  742         if (els == NULL) {
  743                 ocs_log_err(ocs, "IO alloc failed\n");
  744         } else {
  745                 els->els_timeout_sec = timeout_sec;
  746                 els->els_retries_remaining = retries;
  747                 els->els_callback = cb;
  748                 els->els_callback_arg = cbarg;
  749                 els->display_name = "fdisc";
  750 
  751                 /* Build FDISC request */
  752                 fdisc = els->els_req.virt;
  753 
  754                 ocs_memcpy(fdisc, node->sport->service_params, sizeof(*fdisc));
  755                 fdisc->command_code = FC_ELS_CMD_FDISC;
  756                 fdisc->resv1 = 0;
  757 
  758                 ocs_display_sparams(node->display_name, "fdisc send req", 0, NULL, fdisc->common_service_parameters);
  759 
  760                 els->hio_type = OCS_HW_ELS_REQ;
  761                 els->iparam.els.timeout = timeout_sec;
  762                 ocs_io_transition(els, __ocs_els_init, NULL);
  763         }
  764         return els;
  765 }
  766 
  767 /**
  768  * @ingroup els_api
  769  * @brief Send a PRLI ELS command.
  770  *
  771  * <h3 class="desc">Description</h3>
  772  * Construct a PRLI ELS command, and send to the \c node.
  773  *
  774  * @param node Node to which the PRLI is sent.
  775  * @param timeout_sec Command timeout, in seconds.
  776  * @param retries Number of times to retry errors before reporting a failure.
  777  * @param cb Callback function.
  778  * @param cbarg Callback function argument.
  779  *
  780  * @return Returns pointer to IO object, or NULL if error.
  781  */
  782 
  783 ocs_io_t *
  784 ocs_send_prli(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  785         els_cb_t cb, void *cbarg)
  786 {
  787         ocs_t *ocs = node->ocs;
  788         ocs_io_t *els;
  789         fc_prli_payload_t *prli;
  790 
  791         node_els_trace();
  792 
  793         els = ocs_els_io_alloc(node, sizeof(*prli), OCS_ELS_ROLE_ORIGINATOR);
  794         if (els == NULL) {
  795                 ocs_log_err(ocs, "IO alloc failed\n");
  796         } else {
  797                 els->els_timeout_sec = timeout_sec;
  798                 els->els_retries_remaining = retries;
  799                 els->els_callback = cb;
  800                 els->els_callback_arg = cbarg;
  801                 els->display_name = "prli";
  802 
  803                 /* Build PRLI request */
  804                 prli = els->els_req.virt;
  805 
  806                 ocs_memset(prli, 0, sizeof(*prli));
  807 
  808                 prli->command_code = FC_ELS_CMD_PRLI;
  809                 prli->page_length = 16;
  810                 prli->payload_length = ocs_htobe16(sizeof(fc_prli_payload_t));
  811                 prli->type = FC_TYPE_FCP;
  812                 prli->type_ext = 0;
  813                 prli->flags = ocs_htobe16(FC_PRLI_ESTABLISH_IMAGE_PAIR);
  814                 prli->service_params = ocs_htobe16(FC_PRLI_READ_XRDY_DISABLED |
  815                         (node->sport->enable_ini ? FC_PRLI_INITIATOR_FUNCTION : 0) |
  816                         (node->sport->enable_tgt ? FC_PRLI_TARGET_FUNCTION : 0)); 
  817 
  818                 /* For Tape Drive support */
  819                 prli->service_params |= ocs_htobe16(FC_PRLI_CONFIRMED_COMPLETION | FC_PRLI_RETRY |
  820                                  FC_PRLI_TASK_RETRY_ID_REQ| FC_PRLI_REC_SUPPORT);
  821 
  822                 els->hio_type = OCS_HW_ELS_REQ;
  823                 els->iparam.els.timeout = timeout_sec;
  824                 ocs_io_transition(els, __ocs_els_init, NULL);
  825         }
  826 
  827         return els;
  828 }
  829 
  830 /**
  831  * @ingroup els_api
  832  * @brief Send a PRLO ELS command.
  833  *
  834  * <h3 class="desc">Description</h3>
  835  * Construct a PRLO ELS command, and send to the \c node.
  836  *
  837  * @param node Node to which the PRLO is sent.
  838  * @param timeout_sec Command timeout, in seconds.
  839  * @param retries Number of times to retry errors before reporting a failure.
  840  * @param cb Callback function.
  841  * @param cbarg Callback function argument.
  842  *
  843  * @return Returns pointer to IO object, or NULL if error.
  844  */
  845 
  846 ocs_io_t *
  847 ocs_send_prlo(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  848         els_cb_t cb, void *cbarg)
  849 {
  850         ocs_t *ocs = node->ocs;
  851         ocs_io_t *els;
  852         fc_prlo_payload_t *prlo;
  853 
  854         node_els_trace();
  855 
  856         els = ocs_els_io_alloc(node, sizeof(*prlo), OCS_ELS_ROLE_ORIGINATOR);
  857         if (els == NULL) {
  858                 ocs_log_err(ocs, "IO alloc failed\n");
  859         } else {
  860                 els->els_timeout_sec = timeout_sec;
  861                 els->els_retries_remaining = retries;
  862                 els->els_callback = cb;
  863                 els->els_callback_arg = cbarg;
  864                 els->display_name = "prlo";
  865 
  866                 /* Build PRLO request */
  867                 prlo = els->els_req.virt;
  868 
  869                 ocs_memset(prlo, 0, sizeof(*prlo));
  870                 prlo->command_code = FC_ELS_CMD_PRLO;
  871                 prlo->page_length = 16;
  872                 prlo->payload_length = ocs_htobe16(sizeof(fc_prlo_payload_t));
  873                 prlo->type = FC_TYPE_FCP;
  874                 prlo->type_ext = 0;
  875 
  876                 els->hio_type = OCS_HW_ELS_REQ;
  877                 els->iparam.els.timeout = timeout_sec;
  878                 ocs_io_transition(els, __ocs_els_init, NULL);
  879         }
  880         return els;
  881 }
  882 
  883 /**
  884  * @ingroup els_api
  885  * @brief Send a LOGO ELS command.
  886  *
  887  * <h3 class="desc">Description</h3>
  888  * Format a LOGO, and send to the \c node.
  889  *
  890  * @param node Node to which the LOGO is sent.
  891  * @param timeout_sec Command timeout, in seconds.
  892  * @param retries Number of times to retry errors before reporting a failure.
  893  * @param cb Callback function.
  894  * @param cbarg Callback function argument.
  895  *
  896  * @return Returns pointer to IO object, or NULL if error.
  897  */
  898 
  899 ocs_io_t *
  900 ocs_send_logo(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  901         els_cb_t cb, void *cbarg)
  902 {
  903         ocs_io_t *els;
  904         ocs_t *ocs;
  905         fc_logo_payload_t *logo;
  906         fc_plogi_payload_t *sparams;
  907 
  908         ocs = node->ocs;
  909 
  910         node_els_trace();
  911 
  912         sparams = (fc_plogi_payload_t*) node->sport->service_params;
  913 
  914         els = ocs_els_io_alloc(node, sizeof(*logo), OCS_ELS_ROLE_ORIGINATOR);
  915         if (els == NULL) {
  916                 ocs_log_err(ocs, "IO alloc failed\n");
  917         } else {
  918                 els->els_timeout_sec = timeout_sec;
  919                 els->els_retries_remaining = retries;
  920                 els->els_callback = cb;
  921                 els->els_callback_arg = cbarg;
  922                 els->display_name = "logo";
  923 
  924                 /* Build LOGO request */
  925 
  926                 logo = els->els_req.virt;
  927 
  928                 ocs_memset(logo, 0, sizeof(*logo));
  929                 logo->command_code = FC_ELS_CMD_LOGO;
  930                 logo->resv1 = 0;
  931                 logo->port_id = fc_htobe24(node->rnode.sport->fc_id);
  932                 logo->port_name_hi = sparams->port_name_hi;
  933                 logo->port_name_lo = sparams->port_name_lo;
  934 
  935                 els->hio_type = OCS_HW_ELS_REQ;
  936                 els->iparam.els.timeout = timeout_sec;
  937                 ocs_io_transition(els, __ocs_els_init, NULL);
  938         }
  939         return els;
  940 }
  941 
  942 /**
  943  * @ingroup els_api
  944  * @brief Send an ADISC ELS command.
  945  *
  946  * <h3 class="desc">Description</h3>
  947  * Construct an ADISC ELS command, and send to the \c node.
  948  *
  949  * @param node Node to which the ADISC is sent.
  950  * @param timeout_sec Command timeout, in seconds.
  951  * @param retries Number of times to retry errors before reporting a failure.
  952  * @param cb Callback function.
  953  * @param cbarg Callback function argument.
  954  *
  955  * @return Returns pointer to IO object, or NULL if error.
  956  */
  957 
  958 ocs_io_t *
  959 ocs_send_adisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
  960         els_cb_t cb, void *cbarg)
  961 {
  962         ocs_io_t *els;
  963         ocs_t *ocs;
  964         fc_adisc_payload_t *adisc;
  965         fc_plogi_payload_t *sparams;
  966         ocs_sport_t *sport = node->sport;
  967 
  968         ocs = node->ocs;
  969 
  970         node_els_trace();
  971 
  972         sparams = (fc_plogi_payload_t*) node->sport->service_params;
  973 
  974         els = ocs_els_io_alloc(node, sizeof(*adisc), OCS_ELS_ROLE_ORIGINATOR);
  975         if (els == NULL) {
  976                 ocs_log_err(ocs, "IO alloc failed\n");
  977         } else {
  978                 els->els_timeout_sec = timeout_sec;
  979                 els->els_retries_remaining = retries;
  980                 els->els_callback = cb;
  981                 els->els_callback_arg = cbarg;
  982                 els->display_name = "adisc";
  983 
  984                 /* Build ADISC request */
  985 
  986                 adisc = els->els_req.virt;
  987                 sparams = (fc_plogi_payload_t*) node->sport->service_params;
  988 
  989                 ocs_memset(adisc, 0, sizeof(*adisc));
  990                 adisc->command_code = FC_ELS_CMD_ADISC;
  991                 adisc->hard_address = fc_htobe24(sport->fc_id);
  992                 adisc->port_name_hi = sparams->port_name_hi;
  993                 adisc->port_name_lo = sparams->port_name_lo;
  994                 adisc->node_name_hi = sparams->node_name_hi;
  995                 adisc->node_name_lo = sparams->node_name_lo;
  996                 adisc->port_id = fc_htobe24(node->rnode.sport->fc_id);
  997 
  998                 els->hio_type = OCS_HW_ELS_REQ;
  999                 els->iparam.els.timeout = timeout_sec;
 1000                 ocs_io_transition(els, __ocs_els_init, NULL);
 1001         }
 1002         return els;
 1003 }
 1004 
 1005 /**
 1006  * @ingroup els_api
 1007  * @brief Send a PDISC ELS command.
 1008  *
 1009  * <h3 class="desc">Description</h3>
 1010  * Construct a PDISC ELS command, and send to the \c node.
 1011  *
 1012  * @param node Node to which the PDISC is sent.
 1013  * @param timeout_sec Command timeout, in seconds.
 1014  * @param retries Number of times to retry errors before reporting a failure.
 1015  * @param cb Callback function.
 1016  * @param cbarg Callback function argument.
 1017  *
 1018  * @return Returns pointer to IO object, or NULL if error.
 1019  */
 1020 
 1021 ocs_io_t *
 1022 ocs_send_pdisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1023         els_cb_t cb, void *cbarg)
 1024 {
 1025         ocs_io_t *els;
 1026         ocs_t *ocs = node->ocs;
 1027         fc_plogi_payload_t *pdisc;
 1028 
 1029         node_els_trace();
 1030 
 1031         els = ocs_els_io_alloc(node, sizeof(*pdisc), OCS_ELS_ROLE_ORIGINATOR);
 1032         if (els == NULL) {
 1033                 ocs_log_err(ocs, "IO alloc failed\n");
 1034         } else {
 1035                 els->els_timeout_sec = timeout_sec;
 1036                 els->els_retries_remaining = retries;
 1037                 els->els_callback = cb;
 1038                 els->els_callback_arg = cbarg;
 1039                 els->display_name = "pdisc";
 1040 
 1041                 pdisc = els->els_req.virt;
 1042 
 1043                 ocs_memcpy(pdisc, node->sport->service_params, sizeof(*pdisc));
 1044 
 1045                 pdisc->command_code = FC_ELS_CMD_PDISC;
 1046                 pdisc->resv1 = 0;
 1047 
 1048                 els->hio_type = OCS_HW_ELS_REQ;
 1049                 els->iparam.els.timeout = timeout_sec;
 1050                 ocs_io_transition(els, __ocs_els_init, NULL);
 1051         }
 1052         return els;
 1053 }
 1054 
 1055 /**
 1056  * @ingroup els_api
 1057  * @brief Send an SCR ELS command.
 1058  *
 1059  * <h3 class="desc">Description</h3>
 1060  * Format an SCR, and send to the \c node.
 1061  *
 1062  * @param node Node to which the SCR is sent.
 1063  * @param timeout_sec Command timeout, in seconds.
 1064  * @param retries Number of times to retry errors before reporting a failure.
 1065  * @param cb Callback function
 1066  * @param cbarg Callback function arg
 1067  *
 1068  * @return Returns pointer to IO object, or NULL if error.
 1069  */
 1070 
 1071 ocs_io_t *
 1072 ocs_send_scr(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1073         els_cb_t cb, void *cbarg)
 1074 {
 1075         ocs_io_t *els;
 1076         ocs_t *ocs = node->ocs;
 1077         fc_scr_payload_t *req;
 1078 
 1079         node_els_trace();
 1080 
 1081         els = ocs_els_io_alloc(node, sizeof(*req), OCS_ELS_ROLE_ORIGINATOR);
 1082         if (els == NULL) {
 1083                 ocs_log_err(ocs, "IO alloc failed\n");
 1084         } else {
 1085                 els->els_timeout_sec = timeout_sec;
 1086                 els->els_retries_remaining = retries;
 1087                 els->els_callback = cb;
 1088                 els->els_callback_arg = cbarg;
 1089                 els->display_name = "scr";
 1090 
 1091                 req = els->els_req.virt;
 1092 
 1093                 ocs_memset(req, 0, sizeof(*req));
 1094                 req->command_code = FC_ELS_CMD_SCR;
 1095                 req->function = FC_SCR_REG_FULL;
 1096 
 1097                 els->hio_type = OCS_HW_ELS_REQ;
 1098                 els->iparam.els.timeout = timeout_sec;
 1099                 ocs_io_transition(els, __ocs_els_init, NULL);
 1100         }
 1101         return els;
 1102 }
 1103 
 1104 /**
 1105  * @ingroup els_api
 1106  * @brief Send an RRQ ELS command.
 1107  *
 1108  * <h3 class="desc">Description</h3>
 1109  * Format an RRQ, and send to the \c node.
 1110  *
 1111  * @param node Node to which the RRQ is sent.
 1112  * @param timeout_sec Command timeout, in seconds.
 1113  * @param retries Number of times to retry errors before reporting a failure.
 1114  * @param cb Callback function
 1115  * @param cbarg Callback function arg
 1116  *
 1117  * @return Returns pointer to IO object, or NULL if error.
 1118  */
 1119 
 1120 ocs_io_t *
 1121 ocs_send_rrq(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1122         els_cb_t cb, void *cbarg)
 1123 {
 1124         ocs_io_t *els;
 1125         ocs_t *ocs = node->ocs;
 1126         fc_scr_payload_t *req;
 1127 
 1128         node_els_trace();
 1129 
 1130         els = ocs_els_io_alloc(node, sizeof(*req), OCS_ELS_ROLE_ORIGINATOR);
 1131         if (els == NULL) {
 1132                 ocs_log_err(ocs, "IO alloc failed\n");
 1133         } else {
 1134                 els->els_timeout_sec = timeout_sec;
 1135                 els->els_retries_remaining = retries;
 1136                 els->els_callback = cb;
 1137                 els->els_callback_arg = cbarg;
 1138                 els->display_name = "scr";
 1139 
 1140                 req = els->els_req.virt;
 1141 
 1142                 ocs_memset(req, 0, sizeof(*req));
 1143                 req->command_code = FC_ELS_CMD_RRQ;
 1144                 req->function = FC_SCR_REG_FULL;
 1145 
 1146                 els->hio_type = OCS_HW_ELS_REQ;
 1147                 els->iparam.els.timeout = timeout_sec;
 1148                 ocs_io_transition(els, __ocs_els_init, NULL);
 1149         }
 1150         return els;
 1151 }
 1152 
 1153 /**
 1154  * @ingroup els_api
 1155  * @brief Send an RSCN ELS command.
 1156  *
 1157  * <h3 class="desc">Description</h3>
 1158  * Format an RSCN, and send to the \c node.
 1159  *
 1160  * @param node Node to which the RRQ is sent.
 1161  * @param timeout_sec Command timeout, in seconds.
 1162  * @param retries Number of times to retry errors before reporting a failure.
 1163  * @param port_ids Pointer to port IDs
 1164  * @param port_ids_count Count of port IDs
 1165  * @param cb Callback function
 1166  * @param cbarg Callback function arg
 1167  *
 1168  * @return Returns pointer to IO object, or NULL if error.
 1169  */
 1170 ocs_io_t *
 1171 ocs_send_rscn(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1172         void *port_ids, uint32_t port_ids_count, els_cb_t cb, void *cbarg)
 1173 {
 1174         ocs_io_t *els;
 1175         ocs_t *ocs = node->ocs;
 1176         fc_rscn_payload_t *req;
 1177         uint32_t payload_length = sizeof(fc_rscn_affected_port_id_page_t)*(port_ids_count - 1) +
 1178                 sizeof(fc_rscn_payload_t);
 1179 
 1180         node_els_trace();
 1181 
 1182         els = ocs_els_io_alloc(node, payload_length, OCS_ELS_ROLE_ORIGINATOR);
 1183         if (els == NULL) {
 1184                 ocs_log_err(ocs, "IO alloc failed\n");
 1185         } else {
 1186                 els->els_timeout_sec = timeout_sec;
 1187                 els->els_retries_remaining = retries;
 1188                 els->els_callback = cb;
 1189                 els->els_callback_arg = cbarg;
 1190                 els->display_name = "rscn";
 1191 
 1192                 req = els->els_req.virt;
 1193 
 1194                 req->command_code = FC_ELS_CMD_RSCN;
 1195                 req->page_length = sizeof(fc_rscn_affected_port_id_page_t);
 1196                 req->payload_length = ocs_htobe16(sizeof(*req) +
 1197                         sizeof(fc_rscn_affected_port_id_page_t)*(port_ids_count-1));
 1198 
 1199                 els->hio_type = OCS_HW_ELS_REQ;
 1200                 els->iparam.els.timeout = timeout_sec;
 1201 
 1202                 /* copy in the payload */
 1203                 ocs_memcpy(req->port_list, port_ids, port_ids_count*sizeof(fc_rscn_affected_port_id_page_t));
 1204 
 1205                 /* Submit the request */
 1206                 ocs_io_transition(els, __ocs_els_init, NULL);
 1207         }
 1208         return els;
 1209 }
 1210 
 1211 /**
 1212  * @brief Send an LS_RJT ELS response.
 1213  *
 1214  * <h3 class="desc">Description</h3>
 1215  * Send an LS_RJT ELS response.
 1216  *
 1217  * @param io Pointer to a SCSI IO object.
 1218  * @param ox_id Originator exchange ID being responded to.
 1219  * @param reason_code Reason code value for LS_RJT.
 1220  * @param reason_code_expl Reason code explanation value for LS_RJT.
 1221  * @param vendor_unique Vendor-unique value for LS_RJT.
 1222  * @param cb Callback function.
 1223  * @param cbarg Callback function argument.
 1224  *
 1225  * @return Returns pointer to IO object, or NULL if error.
 1226  */
 1227 
 1228 ocs_io_t *
 1229 ocs_send_ls_rjt(ocs_io_t *io, uint32_t ox_id, uint32_t reason_code, uint32_t reason_code_expl,
 1230                 uint32_t vendor_unique, els_cb_t cb, void *cbarg)
 1231 {
 1232         ocs_node_t *node = io->node;
 1233         int32_t rc;
 1234         ocs_t *ocs = node->ocs;
 1235         fc_ls_rjt_payload_t *rjt;
 1236 
 1237         node_els_trace();
 1238 
 1239         io->els_callback = cb;
 1240         io->els_callback_arg = cbarg;
 1241         io->display_name = "ls_rjt";
 1242         io->init_task_tag = ox_id;
 1243 
 1244         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1245         io->iparam.els.ox_id = ox_id;
 1246 
 1247         rjt = io->els_req.virt;
 1248         ocs_memset(rjt, 0, sizeof(*rjt));
 1249 
 1250         rjt->command_code = FC_ELS_CMD_RJT;
 1251         rjt->reason_code = reason_code;
 1252         rjt->reason_code_exp = reason_code_expl;
 1253 
 1254         io->hio_type = OCS_HW_ELS_RSP;
 1255         if ((rc = ocs_els_send_rsp(io, sizeof(*rjt)))) {
 1256                 ocs_els_io_free(io);
 1257                 io = NULL;
 1258         }
 1259 
 1260         return io;
 1261 }
 1262 
 1263 /**
 1264  * @ingroup els_api
 1265  * @brief Send a PLOGI accept response.
 1266  *
 1267  * <h3 class="desc">Description</h3>
 1268  * Construct a PLOGI LS_ACC, and send to the \c node, using the originator exchange ID
 1269  * \c ox_id.
 1270  *
 1271  * @param io Pointer to a SCSI IO object.
 1272  * @param ox_id Originator exchange ID being responsed to.
 1273  * @param cb Callback function.
 1274  * @param cbarg Callback function argument.
 1275  *
 1276  * @return Returns pointer to IO object, or NULL if error.
 1277  */
 1278 ocs_io_t *
 1279 ocs_send_plogi_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
 1280 {
 1281         ocs_node_t *node = io->node;
 1282         int32_t rc;
 1283         ocs_t *ocs = node->ocs;
 1284         fc_plogi_payload_t *plogi;
 1285         fc_plogi_payload_t *req = (fc_plogi_payload_t *)node->service_params;
 1286 
 1287         node_els_trace();
 1288 
 1289         io->els_callback = cb;
 1290         io->els_callback_arg = cbarg;
 1291         io->display_name = "plog_acc";
 1292         io->init_task_tag = ox_id;
 1293 
 1294         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1295         io->iparam.els.ox_id = ox_id;
 1296 
 1297         plogi = io->els_req.virt;
 1298 
 1299         /* copy our port's service parameters to payload */
 1300         ocs_memcpy(plogi, node->sport->service_params, sizeof(*plogi));
 1301         plogi->command_code = FC_ELS_CMD_ACC;
 1302         plogi->resv1 = 0;
 1303 
 1304         /* Set Application header support bit if requested */
 1305         if (req->common_service_parameters[1] & ocs_htobe32(1U << 24)) {
 1306                 plogi->common_service_parameters[1] |= ocs_htobe32(1U << 24);
 1307         }
 1308 
 1309         /* Priority tagging support. */
 1310         if (req->common_service_parameters[1] & ocs_htobe32(1U << 23)) {
 1311                 plogi->common_service_parameters[1] |= ocs_htobe32(1U << 23);
 1312         }
 1313 
 1314         ocs_display_sparams(node->display_name, "plogi send resp", 0, NULL, plogi->common_service_parameters);
 1315 
 1316         io->hio_type = OCS_HW_ELS_RSP;
 1317         if ((rc = ocs_els_send_rsp(io, sizeof(*plogi)))) {
 1318                 ocs_els_io_free(io);
 1319                 io = NULL;
 1320         }
 1321         return io;
 1322 }
 1323 
 1324 /**
 1325  * @ingroup els_api
 1326  * @brief Send an FLOGI accept response for point-to-point negotiation.
 1327  *
 1328  * <h3 class="desc">Description</h3>
 1329  * Construct an FLOGI accept response, and send to the \c node using the originator
 1330  * exchange id \c ox_id. The \c s_id is used for the response frame source FC ID.
 1331  *
 1332  * @param io Pointer to a SCSI IO object.
 1333  * @param ox_id Originator exchange ID for the response.
 1334  * @param s_id Source FC ID to be used in the response frame.
 1335  * @param cb Callback function.
 1336  * @param cbarg Callback function argument.
 1337  *
 1338  * @return Returns pointer to IO object, or NULL if error.
 1339  */
 1340 ocs_io_t *
 1341 ocs_send_flogi_p2p_acc(ocs_io_t *io, uint32_t ox_id, uint32_t s_id, els_cb_t cb, void *cbarg)
 1342 {
 1343         ocs_node_t *node = io->node;
 1344         int32_t rc;
 1345         ocs_t *ocs = node->ocs;
 1346         fc_plogi_payload_t *flogi;
 1347 
 1348         node_els_trace();
 1349 
 1350         io->els_callback = cb;
 1351         io->els_callback_arg = cbarg;
 1352         io->display_name = "flogi_p2p_acc";
 1353         io->init_task_tag = ox_id;
 1354 
 1355         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1356         io->iparam.els_sid.ox_id = ox_id;
 1357         io->iparam.els_sid.s_id = s_id;
 1358 
 1359         flogi = io->els_req.virt;
 1360 
 1361         /* copy our port's service parameters to payload */
 1362         ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
 1363         flogi->command_code = FC_ELS_CMD_ACC;
 1364         flogi->resv1 = 0;
 1365         ocs_memset(flogi->class1_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1366         ocs_memset(flogi->class2_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1367         ocs_memset(flogi->class3_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1368         ocs_memset(flogi->class4_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1369 
 1370         io->hio_type = OCS_HW_ELS_RSP_SID;
 1371         if ((rc = ocs_els_send_rsp(io, sizeof(*flogi)))) {
 1372                 ocs_els_io_free(io);
 1373                 io = NULL;
 1374         }
 1375 
 1376         return io;
 1377 }
 1378 
 1379 ocs_io_t *
 1380 ocs_send_flogi_acc(ocs_io_t *io, uint32_t ox_id, uint32_t is_fport, els_cb_t cb, void *cbarg)
 1381 {
 1382         ocs_node_t *node = io->node;
 1383         int32_t rc;
 1384         ocs_t *ocs = node->ocs;
 1385         fc_plogi_payload_t *flogi;
 1386 
 1387         node_els_trace();
 1388 
 1389         io->els_callback = cb;
 1390         io->els_callback_arg = cbarg;
 1391         io->display_name = "flogi_acc";
 1392         io->init_task_tag = ox_id;
 1393 
 1394         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1395         io->iparam.els_sid.ox_id = ox_id;
 1396         io->iparam.els_sid.s_id = io->node->sport->fc_id;
 1397 
 1398         flogi = io->els_req.virt;
 1399 
 1400         /* copy our port's service parameters to payload */
 1401         ocs_memcpy(flogi, node->sport->service_params, sizeof(*flogi));
 1402 
 1403         /* Set F_port */
 1404         if (is_fport) {
 1405                 /* Set F_PORT and Multiple N_PORT_ID Assignment */
 1406                 flogi->common_service_parameters[1] |= ocs_be32toh(3U << 28);
 1407         }
 1408 
 1409         flogi->command_code = FC_ELS_CMD_ACC;
 1410         flogi->resv1 = 0;
 1411 
 1412         ocs_display_sparams(node->display_name, "flogi send resp", 0, NULL, flogi->common_service_parameters);
 1413 
 1414         ocs_memset(flogi->class1_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1415         ocs_memset(flogi->class2_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1416         ocs_memset(flogi->class3_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1417         ocs_memset(flogi->class4_service_parameters, 0, sizeof(flogi->class1_service_parameters));
 1418 
 1419         io->hio_type = OCS_HW_ELS_RSP_SID;
 1420         if ((rc = ocs_els_send_rsp(io, sizeof(*flogi)))) {
 1421                 ocs_els_io_free(io);
 1422                 io = NULL;
 1423         }
 1424 
 1425         return io;
 1426 }
 1427 
 1428 /**
 1429  * @ingroup els_api
 1430  * @brief Send a PRLI accept response
 1431  *
 1432  * <h3 class="desc">Description</h3>
 1433  * Construct a PRLI LS_ACC response, and send to the \c node, using the originator
 1434  * \c ox_id exchange ID.
 1435  *
 1436  * @param io Pointer to a SCSI IO object.
 1437  * @param ox_id Originator exchange ID.
 1438  * @param cb Callback function.
 1439  * @param cbarg Callback function argument.
 1440  *
 1441  * @return Returns pointer to IO object, or NULL if error.
 1442  */
 1443 
 1444 ocs_io_t *
 1445 ocs_send_prli_acc(ocs_io_t *io, uint32_t ox_id, uint8_t fc_type, els_cb_t cb, void *cbarg)
 1446 {
 1447         ocs_node_t *node = io->node;
 1448         int32_t rc;
 1449         ocs_t *ocs = node->ocs;
 1450         fc_prli_payload_t *prli;
 1451 
 1452         node_els_trace();
 1453 
 1454         io->els_callback = cb;
 1455         io->els_callback_arg = cbarg;
 1456         io->display_name = "prli_acc";
 1457         io->init_task_tag = ox_id;
 1458 
 1459         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1460         io->iparam.els.ox_id = ox_id;
 1461 
 1462         prli = io->els_req.virt;
 1463         ocs_memset(prli, 0, sizeof(*prli));
 1464 
 1465         prli->command_code = FC_ELS_CMD_ACC;
 1466         prli->page_length = 16;
 1467         prli->payload_length = ocs_htobe16(sizeof(fc_prli_payload_t));
 1468         prli->type = fc_type;
 1469         prli->type_ext = 0;
 1470         prli->flags = ocs_htobe16(FC_PRLI_ESTABLISH_IMAGE_PAIR | FC_PRLI_REQUEST_EXECUTED);
 1471 
 1472         prli->service_params = ocs_htobe16(FC_PRLI_READ_XRDY_DISABLED |
 1473                                 (node->sport->enable_ini ? FC_PRLI_INITIATOR_FUNCTION : 0) |
 1474                                 (node->sport->enable_tgt ? FC_PRLI_TARGET_FUNCTION : 0)); 
 1475 
 1476         io->hio_type = OCS_HW_ELS_RSP;
 1477         if ((rc = ocs_els_send_rsp(io, sizeof(*prli)))) {
 1478                 ocs_els_io_free(io);
 1479                 io = NULL;
 1480         }
 1481 
 1482         return io;
 1483 }
 1484 
 1485 /**
 1486  * @ingroup els_api
 1487  * @brief Send a PRLO accept response.
 1488  *
 1489  * <h3 class="desc">Description</h3>
 1490  * Construct a PRLO LS_ACC response, and send to the \c node, using the originator
 1491  * exchange ID \c ox_id.
 1492  *
 1493  * @param io Pointer to a SCSI IO object.
 1494  * @param ox_id Originator exchange ID.
 1495  * @param cb Callback function.
 1496  * @param cbarg Callback function argument.
 1497  *
 1498  * @return Returns pointer to IO object, or NULL if error.
 1499  */
 1500 
 1501 ocs_io_t *
 1502 ocs_send_prlo_acc(ocs_io_t *io, uint32_t ox_id, uint8_t fc_type, els_cb_t cb, void *cbarg)
 1503 {
 1504         ocs_node_t *node = io->node;
 1505         int32_t rc;
 1506         ocs_t *ocs = node->ocs;
 1507         fc_prlo_acc_payload_t *prlo_acc;
 1508 
 1509         node_els_trace();
 1510 
 1511         io->els_callback = cb;
 1512         io->els_callback_arg = cbarg;
 1513         io->display_name = "prlo_acc";
 1514         io->init_task_tag = ox_id;
 1515 
 1516         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1517         io->iparam.els.ox_id = ox_id;
 1518 
 1519         prlo_acc = io->els_req.virt;
 1520         ocs_memset(prlo_acc, 0, sizeof(*prlo_acc));
 1521 
 1522         prlo_acc->command_code = FC_ELS_CMD_ACC;
 1523         prlo_acc->page_length = 16;
 1524         prlo_acc->payload_length = ocs_htobe16(sizeof(fc_prlo_acc_payload_t));
 1525         prlo_acc->type = fc_type;
 1526         prlo_acc->type_ext = 0;
 1527         prlo_acc->response_code = FC_PRLO_REQUEST_EXECUTED;
 1528 
 1529         io->hio_type = OCS_HW_ELS_RSP;
 1530         if ((rc = ocs_els_send_rsp(io, sizeof(*prlo_acc)))) {
 1531                 ocs_els_io_free(io);
 1532                 io = NULL;
 1533         }
 1534 
 1535         return io;
 1536 }
 1537 
 1538 /**
 1539  * @ingroup els_api
 1540  * @brief Send a generic LS_ACC response without a payload.
 1541  *
 1542  * <h3 class="desc">Description</h3>
 1543  * A generic LS_ACC response is sent to the \c node using the originator exchange ID
 1544  * \c ox_id.
 1545  *
 1546  * @param io Pointer to a SCSI IO object.
 1547  * @param ox_id Originator exchange id.
 1548  * @param cb Callback function.
 1549  * @param cbarg Callback function argument.
 1550  *
 1551  * @return Returns pointer to IO object, or NULL if error.
 1552  */
 1553 ocs_io_t *
 1554 ocs_send_ls_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
 1555 {
 1556         ocs_node_t *node = io->node;
 1557         int32_t rc;
 1558         ocs_t *ocs = node->ocs;
 1559         fc_acc_payload_t *acc;
 1560 
 1561         node_els_trace();
 1562 
 1563         io->els_callback = cb;
 1564         io->els_callback_arg = cbarg;
 1565         io->display_name = "ls_acc";
 1566         io->init_task_tag = ox_id;
 1567 
 1568         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1569         io->iparam.els.ox_id = ox_id;
 1570 
 1571         acc = io->els_req.virt;
 1572         ocs_memset(acc, 0, sizeof(*acc));
 1573 
 1574         acc->command_code = FC_ELS_CMD_ACC;
 1575 
 1576         io->hio_type = OCS_HW_ELS_RSP;
 1577         if ((rc = ocs_els_send_rsp(io, sizeof(*acc)))) {
 1578                 ocs_els_io_free(io);
 1579                 io = NULL;
 1580         }
 1581 
 1582         return io;
 1583 }
 1584 
 1585 /**
 1586  * @ingroup els_api
 1587  * @brief Send a LOGO accept response.
 1588  *
 1589  * <h3 class="desc">Description</h3>
 1590  * Construct a LOGO LS_ACC response, and send to the \c node, using the originator
 1591  * exchange ID \c ox_id.
 1592  *
 1593  * @param io Pointer to a SCSI IO object.
 1594  * @param ox_id Originator exchange ID.
 1595  * @param cb Callback function.
 1596  * @param cbarg Callback function argument.
 1597  *
 1598  * @return Returns pointer to IO object, or NULL if error.
 1599  */
 1600 ocs_io_t *
 1601 ocs_send_logo_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
 1602 {
 1603         ocs_node_t *node = io->node;
 1604         int32_t rc;
 1605         ocs_t *ocs = node->ocs;
 1606         fc_acc_payload_t *logo;
 1607 
 1608         node_els_trace();
 1609 
 1610         io->els_callback = cb;
 1611         io->els_callback_arg = cbarg;
 1612         io->display_name = "logo_acc";
 1613         io->init_task_tag = ox_id;
 1614 
 1615         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1616         io->iparam.els.ox_id = ox_id;
 1617 
 1618         logo = io->els_req.virt;
 1619         ocs_memset(logo, 0, sizeof(*logo));
 1620 
 1621         logo->command_code = FC_ELS_CMD_ACC;
 1622         logo->resv1 = 0;
 1623 
 1624         io->hio_type = OCS_HW_ELS_RSP;
 1625         if ((rc = ocs_els_send_rsp(io, sizeof(*logo)))) {
 1626                 ocs_els_io_free(io);
 1627                 io = NULL;
 1628         }
 1629 
 1630         return io;
 1631 }
 1632 
 1633 /**
 1634  * @ingroup els_api
 1635  * @brief Send an ADISC accept response.
 1636  *
 1637  * <h3 class="desc">Description</h3>
 1638  * Construct an ADISC LS__ACC, and send to the \c node, using the originator
 1639  * exchange id \c ox_id.
 1640  *
 1641  * @param io Pointer to a SCSI IO object.
 1642  * @param ox_id Originator exchange ID.
 1643  * @param cb Callback function.
 1644  * @param cbarg Callback function argument.
 1645  *
 1646  * @return Returns pointer to IO object, or NULL if error.
 1647  */
 1648 
 1649 ocs_io_t *
 1650 ocs_send_adisc_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
 1651 {
 1652         ocs_node_t *node = io->node;
 1653         int32_t rc;
 1654         fc_adisc_payload_t *adisc;
 1655         fc_plogi_payload_t *sparams;
 1656         ocs_t *ocs;
 1657 
 1658         ocs_assert(node, NULL);
 1659         ocs_assert(node->ocs, NULL);
 1660         ocs = node->ocs;
 1661 
 1662         node_els_trace();
 1663 
 1664         io->els_callback = cb;
 1665         io->els_callback_arg = cbarg;
 1666         io->display_name = "adisc_acc";
 1667         io->init_task_tag = ox_id;
 1668 
 1669         /* Go ahead and send the ELS_ACC */
 1670         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1671         io->iparam.els.ox_id = ox_id;
 1672 
 1673         sparams = (fc_plogi_payload_t*) node->sport->service_params;
 1674         adisc = io->els_req.virt;
 1675         ocs_memset(adisc, 0, sizeof(fc_adisc_payload_t));
 1676         adisc->command_code = FC_ELS_CMD_ACC;
 1677         adisc->hard_address = 0;
 1678         adisc->port_name_hi = sparams->port_name_hi;
 1679         adisc->port_name_lo = sparams->port_name_lo;
 1680         adisc->node_name_hi = sparams->node_name_hi;
 1681         adisc->node_name_lo = sparams->node_name_lo;
 1682         adisc->port_id = fc_htobe24(node->rnode.sport->fc_id);
 1683 
 1684         io->hio_type = OCS_HW_ELS_RSP;
 1685         if ((rc = ocs_els_send_rsp(io, sizeof(*adisc)))) {
 1686                 ocs_els_io_free(io);
 1687                 io = NULL;
 1688         }
 1689 
 1690         return io;
 1691 }
 1692 
 1693 /**
 1694  * @ingroup els_api
 1695  * @brief Send a RFTID CT request.
 1696  *
 1697  * <h3 class="desc">Description</h3>
 1698  * Construct an RFTID CT request, and send to the \c node.
 1699  *
 1700  * @param node Node to which the RFTID request is sent.
 1701  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
 1702  * @param retries Number of times to retry errors before reporting a failure.
 1703  * @param cb Callback function.
 1704  * @param cbarg Callback function argument.
 1705  *
 1706  * @return Returns pointer to IO object, or NULL if error.
 1707  */
 1708 ocs_io_t *
 1709 ocs_ns_send_rftid(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1710         els_cb_t cb, void *cbarg)
 1711 {
 1712         ocs_io_t *els;
 1713         ocs_t *ocs = node->ocs;
 1714         fcct_rftid_req_t *rftid;
 1715 
 1716         node_els_trace();
 1717 
 1718         els = ocs_els_io_alloc(node, sizeof(*rftid), OCS_ELS_ROLE_ORIGINATOR);
 1719         if (els == NULL) {
 1720                 ocs_log_err(ocs, "IO alloc failed\n");
 1721         } else {
 1722                 els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
 1723                 els->iparam.fc_ct.type = FC_TYPE_GS;
 1724                 els->iparam.fc_ct.df_ctl = 0;
 1725                 els->iparam.fc_ct.timeout = timeout_sec;
 1726 
 1727                 els->els_callback = cb;
 1728                 els->els_callback_arg = cbarg;
 1729                 els->display_name = "rftid";
 1730 
 1731                 rftid = els->els_req.virt;
 1732 
 1733                 ocs_memset(rftid, 0, sizeof(*rftid));
 1734                 fcct_build_req_header(&rftid->hdr, FC_GS_NAMESERVER_RFT_ID, (OCS_ELS_RSP_LEN - sizeof(rftid->hdr)));
 1735                 rftid->port_id = ocs_htobe32(node->rnode.sport->fc_id);
 1736                 rftid->fc4_types[FC_GS_TYPE_WORD(FC_TYPE_FCP)] = ocs_htobe32(1 << FC_GS_TYPE_BIT(FC_TYPE_FCP));
 1737 
 1738                 els->hio_type = OCS_HW_FC_CT;
 1739 
 1740                 ocs_io_transition(els, __ocs_els_init, NULL);
 1741         }
 1742         return els;
 1743 }
 1744 
 1745 /**
 1746  * @ingroup els_api
 1747  * @brief Send a RFFID CT request.
 1748  *
 1749  * <h3 class="desc">Description</h3>
 1750  * Construct an RFFID CT request, and send to the \c node.
 1751  *
 1752  * @param node Node to which the RFFID request is sent.
 1753  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
 1754  * @param retries Number of times to retry errors before reporting a failure.
 1755  * @param cb Callback function
 1756  * @param cbarg Callback function argument.
 1757  *
 1758  * @return Returns pointer to IO object, or NULL if error.
 1759  */
 1760 ocs_io_t *
 1761 ocs_ns_send_rffid(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1762         els_cb_t cb, void *cbarg)
 1763 {
 1764         ocs_io_t *els;
 1765         ocs_t *ocs = node->ocs;
 1766         fcct_rffid_req_t *rffid;
 1767 
 1768         node_els_trace();
 1769 
 1770         els = ocs_els_io_alloc(node, sizeof(*rffid), OCS_ELS_ROLE_ORIGINATOR);
 1771         if (els == NULL) {
 1772                 ocs_log_err(ocs, "IO alloc failed\n");
 1773         } else {
 1774                 els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
 1775                 els->iparam.fc_ct.type = FC_TYPE_GS;
 1776                 els->iparam.fc_ct.df_ctl = 0;
 1777                 els->iparam.fc_ct.timeout = timeout_sec;
 1778 
 1779                 els->els_callback = cb;
 1780                 els->els_callback_arg = cbarg;
 1781                 els->display_name = "rffid";
 1782 
 1783                 rffid = els->els_req.virt;
 1784 
 1785                 ocs_memset(rffid, 0, sizeof(*rffid));
 1786 
 1787                 fcct_build_req_header(&rffid->hdr, FC_GS_NAMESERVER_RFF_ID, (OCS_ELS_RSP_LEN - sizeof(rffid->hdr)));
 1788                 rffid->port_id = ocs_htobe32(node->rnode.sport->fc_id);
 1789                 if (node->sport->enable_ini) {
 1790                         rffid->fc4_feature_bits |= FC4_FEATURE_INITIATOR;
 1791                 }
 1792                 if (node->sport->enable_tgt) {
 1793                         rffid->fc4_feature_bits |= FC4_FEATURE_TARGET;
 1794                 }
 1795                 rffid->type = FC_TYPE_FCP;
 1796 
 1797                 els->hio_type = OCS_HW_FC_CT;
 1798 
 1799                 ocs_io_transition(els, __ocs_els_init, NULL);
 1800         }
 1801         return els;
 1802 }
 1803 
 1804 /**
 1805  * @ingroup els_api
 1806  * @brief Send a GIDPT CT request.
 1807  *
 1808  * <h3 class="desc">Description</h3>
 1809  * Construct a GIDPT CT request, and send to the \c node.
 1810  *
 1811  * @param node Node to which the GIDPT request is sent.
 1812  * @param timeout_sec Time, in seconds, to wait before timing out the ELS.
 1813  * @param retries Number of times to retry errors before reporting a failure.
 1814  * @param cb Callback function.
 1815  * @param cbarg Callback function argument.
 1816  *
 1817  * @return Returns pointer to IO object, or NULL if error.
 1818  */
 1819 
 1820 ocs_io_t *
 1821 ocs_ns_send_gidpt(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries,
 1822         els_cb_t cb, void *cbarg)
 1823 {
 1824         ocs_io_t *els;
 1825         ocs_t *ocs = node->ocs;
 1826         fcct_gidpt_req_t *gidpt;
 1827 
 1828         node_els_trace();
 1829 
 1830         els = ocs_els_io_alloc_size(node, sizeof(*gidpt), OCS_ELS_GID_PT_RSP_LEN, OCS_ELS_ROLE_ORIGINATOR);
 1831         if (els == NULL) {
 1832                 ocs_log_err(ocs, "IO alloc failed\n");
 1833         } else {
 1834                 els->iparam.fc_ct.r_ctl = FC_RCTL_ELS;
 1835                 els->iparam.fc_ct.type = FC_TYPE_GS;
 1836                 els->iparam.fc_ct.df_ctl = 0;
 1837                 els->iparam.fc_ct.timeout = timeout_sec;
 1838 
 1839                 els->els_callback = cb;
 1840                 els->els_callback_arg = cbarg;
 1841                 els->display_name = "gidpt";
 1842 
 1843                 gidpt = els->els_req.virt;
 1844 
 1845                 ocs_memset(gidpt, 0, sizeof(*gidpt));
 1846                 fcct_build_req_header(&gidpt->hdr, FC_GS_NAMESERVER_GID_PT, (OCS_ELS_GID_PT_RSP_LEN - sizeof(gidpt->hdr)) );
 1847                 gidpt->domain_id_scope = 0;
 1848                 gidpt->area_id_scope = 0;
 1849                 gidpt->port_type = 0x7f;
 1850 
 1851                 els->hio_type = OCS_HW_FC_CT;
 1852 
 1853                 ocs_io_transition(els, __ocs_els_init, NULL);
 1854         }
 1855         return els;
 1856 }
 1857 
 1858 /**
 1859  * @ingroup els_api
 1860  * @brief Send a BA_ACC given the request's FC header
 1861  *
 1862  * <h3 class="desc">Description</h3>
 1863  * Using the S_ID/D_ID from the request's FC header, generate a BA_ACC.
 1864  *
 1865  * @param io Pointer to a SCSI IO object.
 1866  * @param hdr Pointer to the FC header.
 1867  *
 1868  * @return Returns pointer to IO object, or NULL if error.
 1869  */
 1870 
 1871 ocs_io_t *
 1872 ocs_bls_send_acc_hdr(ocs_io_t *io, fc_header_t *hdr)
 1873 {
 1874         uint16_t ox_id = ocs_be16toh(hdr->ox_id);
 1875         uint16_t rx_id = ocs_be16toh(hdr->rx_id);
 1876         uint32_t d_id = fc_be24toh(hdr->d_id);
 1877 
 1878         return ocs_bls_send_acc(io, d_id, ox_id, rx_id);
 1879 }
 1880 
 1881 /**
 1882  * @ingroup els_api
 1883  * @brief Send a BLS BA_ACC response.
 1884  *
 1885  * <h3 class="desc">Description</h3>
 1886  * Construct a BLS BA_ACC response, and send to the \c node.
 1887  *
 1888  * @param io Pointer to a SCSI IO object.
 1889  * @param s_id S_ID to use for the response. If UINT32_MAX, then use our SLI port
 1890  * (sport) S_ID.
 1891  * @param ox_id Originator exchange ID.
 1892  * @param rx_id Responder exchange ID.
 1893  *
 1894  * @return Returns pointer to IO object, or NULL if error.
 1895  */
 1896 
 1897 static ocs_io_t *
 1898 ocs_bls_send_acc(ocs_io_t *io, uint32_t s_id, uint16_t ox_id, uint16_t rx_id)
 1899 {
 1900         ocs_node_t *node = io->node;
 1901         int32_t rc;
 1902         fc_ba_acc_payload_t *acc;
 1903         ocs_t *ocs;
 1904 
 1905         ocs_assert(node, NULL);
 1906         ocs_assert(node->ocs, NULL);
 1907         ocs = node->ocs;
 1908 
 1909         if (node->rnode.sport->fc_id == s_id) {
 1910                 s_id = UINT32_MAX;
 1911         }
 1912 
 1913         /* fill out generic fields */
 1914         io->ocs = ocs;
 1915         io->node = node;
 1916         io->cmd_tgt = TRUE;
 1917 
 1918         /* fill out BLS Response-specific fields */
 1919         io->io_type = OCS_IO_TYPE_BLS_RESP;
 1920         io->display_name = "ba_acc";
 1921         io->hio_type = OCS_HW_BLS_ACC_SID;
 1922         io->init_task_tag = ox_id;
 1923 
 1924         /* fill out iparam fields */
 1925         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 1926         io->iparam.bls_sid.s_id = s_id;
 1927         io->iparam.bls_sid.ox_id = ox_id;
 1928         io->iparam.bls_sid.rx_id = rx_id;
 1929 
 1930         acc = (void *)io->iparam.bls_sid.payload;
 1931 
 1932         ocs_memset(io->iparam.bls_sid.payload, 0, sizeof(io->iparam.bls_sid.payload));
 1933         acc->ox_id = io->iparam.bls_sid.ox_id;
 1934         acc->rx_id = io->iparam.bls_sid.rx_id;
 1935         acc->high_seq_cnt = UINT16_MAX;
 1936 
 1937         if ((rc = ocs_scsi_io_dispatch(io, ocs_bls_send_acc_cb))) {
 1938                 ocs_log_err(ocs, "ocs_scsi_io_dispatch() failed: %d\n", rc);
 1939                 ocs_scsi_io_free(io);
 1940                 io = NULL;
 1941         }
 1942         return io;
 1943 }
 1944 
 1945 /**
 1946  * @brief Handle the BLS accept completion.
 1947  *
 1948  * <h3 class="desc">Description</h3>
 1949  * Upon completion of sending a BA_ACC, this callback is invoked by the HW.
 1950  *
 1951  * @param hio Pointer to the HW IO object.
 1952  * @param rnode Pointer to the HW remote node.
 1953  * @param length Length of the response payload, in bytes.
 1954  * @param status Completion status.
 1955  * @param ext_status Extended completion status.
 1956  * @param app Callback private argument.
 1957  *
 1958  * @return Returns 0 on success; or a negative error value on failure.
 1959  */
 1960 
 1961 static int32_t
 1962 ocs_bls_send_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
 1963 {
 1964         ocs_io_t *io = app;
 1965 
 1966         ocs_assert(io, -1);
 1967 
 1968         ocs_scsi_io_free(io);
 1969         return 0;
 1970 }
 1971 
 1972 /**
 1973  * @brief ELS abort callback.
 1974  *
 1975  * <h3 class="desc">Description</h3>
 1976  * This callback is invoked by the HW when an ELS IO is aborted.
 1977  *
 1978  * @param hio Pointer to the HW IO object.
 1979  * @param rnode Pointer to the HW remote node.
 1980  * @param length Length of the response payload, in bytes.
 1981  * @param status Completion status.
 1982  * @param ext_status Extended completion status.
 1983  * @param app Callback private argument.
 1984  *
 1985  * @return Returns 0 on success; or a negative error value on failure.
 1986  */
 1987 
 1988 static int32_t
 1989 ocs_els_abort_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
 1990 {
 1991         ocs_io_t *els;
 1992         ocs_io_t *abort_io = NULL; /* IO structure used to abort ELS */
 1993         ocs_t *ocs;
 1994 
 1995         ocs_assert(app, -1);
 1996         abort_io = app;
 1997         els = abort_io->io_to_abort;
 1998         ocs_assert(els->node, -1);
 1999         ocs_assert(els->node->ocs, -1);
 2000 
 2001         ocs = els->node->ocs;
 2002 
 2003         if (status != 0) {
 2004                 ocs_log_warn(ocs, "status x%x ext x%x\n", status, ext_status);
 2005         }
 2006 
 2007         /* now free the abort IO */
 2008         ocs_io_free(ocs, abort_io);
 2009 
 2010         /* send completion event to indicate abort process is complete
 2011          * Note: The ELS SM will already be receiving ELS_REQ_OK/FAIL/RJT/ABORTED
 2012          */
 2013         ocs_els_post_event(els, OCS_EVT_ELS_ABORT_CMPL, NULL);
 2014 
 2015         /* done with ELS IO to abort */
 2016         ocs_ref_put(&els->ref); /* ocs_ref_get(): ocs_els_abort_io() */
 2017         return 0;
 2018 }
 2019 
 2020 /**
 2021  * @brief Abort an ELS IO.
 2022  *
 2023  * <h3 class="desc">Description</h3>
 2024  * The ELS IO is aborted by making a HW abort IO request,
 2025  * optionally requesting that an ABTS is sent.
 2026  *
 2027  * \b Note: This function allocates a HW IO, and associates the HW IO
 2028  * with the ELS IO that it is aborting. It does not associate
 2029  * the HW IO with the node directly, like for ELS requests. The
 2030  * abort completion is propagated up to the node once the
 2031  * original WQE and the abort WQE are complete (the original WQE
 2032  * completion is not propagated up to node).
 2033  *
 2034  * @param els Pointer to the ELS IO.
 2035  * @param send_abts Boolean to indicate if hardware will automatically generate an ABTS.
 2036  *
 2037  * @return Returns pointer to Abort IO object, or NULL if error.
 2038  */
 2039 
 2040 static ocs_io_t *
 2041 ocs_els_abort_io(ocs_io_t *els, int send_abts)
 2042 {
 2043         ocs_t *ocs;
 2044         ocs_xport_t *xport;
 2045         int32_t rc;
 2046         ocs_io_t *abort_io = NULL;
 2047 
 2048         ocs_assert(els, NULL);
 2049         ocs_assert(els->node, NULL);
 2050         ocs_assert(els->node->ocs, NULL);
 2051 
 2052         ocs = els->node->ocs;
 2053         ocs_assert(ocs->xport, NULL);
 2054         xport = ocs->xport;
 2055 
 2056         /* take a reference on IO being aborted */
 2057         if ((ocs_ref_get_unless_zero(&els->ref) == 0)) {
 2058                 /* command no longer active */
 2059                 ocs_log_debug(ocs, "els no longer active\n");
 2060                 return NULL;
 2061         }
 2062 
 2063         /* allocate IO structure to send abort */
 2064         abort_io = ocs_io_alloc(ocs);
 2065         if (abort_io == NULL) {
 2066                 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
 2067         } else {
 2068                 ocs_assert(abort_io->hio == NULL, NULL);
 2069 
 2070                 /* set generic fields */
 2071                 abort_io->ocs = ocs;
 2072                 abort_io->node = els->node;
 2073                 abort_io->cmd_ini = TRUE;
 2074 
 2075                 /* set type and ABORT-specific fields */
 2076                 abort_io->io_type = OCS_IO_TYPE_ABORT;
 2077                 abort_io->display_name = "abort_els";
 2078                 abort_io->io_to_abort = els;
 2079                 abort_io->send_abts = send_abts;
 2080 
 2081                 /* now dispatch IO */
 2082                 if ((rc = ocs_scsi_io_dispatch_abort(abort_io, ocs_els_abort_cb))) {
 2083                         ocs_log_err(ocs, "ocs_scsi_io_dispatch failed: %d\n", rc);
 2084                         ocs_io_free(ocs, abort_io);
 2085                         abort_io = NULL;
 2086                 }
 2087         }
 2088 
 2089         /* if something failed, put reference on ELS to abort */
 2090         if (abort_io == NULL) {
 2091                 ocs_ref_put(&els->ref); /* ocs_ref_get(): same function */
 2092         }
 2093         return abort_io;
 2094 }
 2095 
 2096 /*
 2097  * ELS IO State Machine
 2098  */
 2099 
 2100 #define std_els_state_decl(...) \
 2101         ocs_io_t *els = NULL; \
 2102         ocs_node_t *node = NULL; \
 2103         ocs_t *ocs = NULL; \
 2104         ocs_assert(ctx != NULL, NULL); \
 2105         els = ctx->app; \
 2106         ocs_assert(els != NULL, NULL); \
 2107         node = els->node; \
 2108         ocs_assert(node != NULL, NULL); \
 2109         ocs = node->ocs; \
 2110         ocs_assert(ocs != NULL, NULL);
 2111 
 2112 #define els_sm_trace(...) \
 2113         do { \
 2114                 if (OCS_LOG_ENABLE_ELS_TRACE(ocs)) \
 2115                         ocs_log_info(ocs, "[%s] %-8s %-20s %-20s\n", node->display_name, els->display_name, \
 2116                                 __func__, ocs_sm_event_name(evt)); \
 2117         } while (0)
 2118 
 2119 /**
 2120  * @brief Cleanup an ELS IO
 2121  *
 2122  * <h3 class="desc">Description</h3>
 2123  * Cleans up an ELS IO by posting the requested event to the owning node object;
 2124  * invoking the callback, if one is provided; and then freeing the
 2125  * ELS IO object.
 2126  *
 2127  * @param els Pointer to the ELS IO.
 2128  * @param node_evt Node SM event to post.
 2129  * @param arg Node SM event argument.
 2130  *
 2131  * @return None.
 2132  */
 2133 
 2134 void
 2135 ocs_els_io_cleanup(ocs_io_t *els, ocs_sm_event_t node_evt, void *arg)
 2136 {
 2137         ocs_assert(els);
 2138 
 2139         /* don't want further events that could come; e.g. abort requests
 2140          * from the node state machine; thus, disable state machine
 2141          */
 2142         ocs_sm_disable(&els->els_sm);
 2143         ocs_node_post_event(els->node, node_evt, arg);
 2144 
 2145         /* If this IO has a callback, invoke it */
 2146         if (els->els_callback) {
 2147                 (*els->els_callback)(els->node, arg, els->els_callback_arg);
 2148         }
 2149         els->els_req_free = 1;
 2150 }
 2151 
 2152 /**
 2153  * @brief Common event handler for the ELS IO state machine.
 2154  *
 2155  * <h3 class="desc">Description</h3>
 2156  * Provide handler for events for which default actions are desired.
 2157  *
 2158  * @param funcname Name of the calling function (for logging).
 2159  * @param ctx Remote node SM context.
 2160  * @param evt Event to process.
 2161  * @param arg Per event optional argument.
 2162  *
 2163  * @return Returns NULL.
 2164  */
 2165 
 2166 void *
 2167 __ocs_els_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2168 {
 2169         std_els_state_decl();
 2170 
 2171         switch(evt) {
 2172         case OCS_EVT_ENTER:
 2173         case OCS_EVT_REENTER:
 2174         case OCS_EVT_EXIT:
 2175                 break;
 2176 
 2177         /* If ELS_REQ_FAIL is not handled in state, then we'll terminate this ELS and
 2178          * pass the event to the node
 2179          */
 2180         case OCS_EVT_SRRS_ELS_REQ_FAIL:
 2181                 ocs_log_warn(els->node->ocs, "[%s] %-20s %-20s not handled - terminating ELS\n", node->display_name, funcname,
 2182                         ocs_sm_event_name(evt));
 2183                 ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
 2184                 break;
 2185         default:
 2186                 ocs_log_warn(els->node->ocs, "[%s] %-20s %-20s not handled\n", node->display_name, funcname,
 2187                         ocs_sm_event_name(evt));
 2188                 break;
 2189         }
 2190         return NULL;
 2191 }
 2192 
 2193 /**
 2194  * @brief Initial ELS IO state
 2195  *
 2196  * <h3 class="desc">Description</h3>
 2197  * This is the initial ELS IO state. Upon entry, the requested ELS/CT is submitted to
 2198  * the hardware.
 2199  *
 2200  * @param ctx Remote node SM context.
 2201  * @param evt Event to process.
 2202  * @param arg Per event optional argument.
 2203  *
 2204  * @return Returns NULL.
 2205  */
 2206 
 2207 void *
 2208 __ocs_els_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2209 {
 2210         int32_t rc = 0;
 2211         std_els_state_decl();
 2212 
 2213         els_sm_trace();
 2214 
 2215         switch(evt) {
 2216         case OCS_EVT_ENTER: {
 2217                 rc = ocs_els_send(els, els->els_req.size, els->els_timeout_sec, ocs_els_req_cb);
 2218                 if (rc) {
 2219                         ocs_node_cb_t cbdata;
 2220                         cbdata.status = cbdata.ext_status = (~0);
 2221                         cbdata.els = els;
 2222                         ocs_log_err(ocs, "ocs_els_send failed: %d\n", rc);
 2223                         ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &cbdata);
 2224                 } else {
 2225                         ocs_io_transition(els, __ocs_els_wait_resp, NULL);
 2226                 }
 2227                 break;
 2228         }
 2229         default:
 2230                 __ocs_els_common(__func__, ctx, evt, arg);
 2231                 break;
 2232         }
 2233 
 2234         return NULL;
 2235 }
 2236 
 2237 /**
 2238  * @brief Wait for the ELS request to complete.
 2239  *
 2240  * <h3 class="desc">Description</h3>
 2241  * This is the ELS IO state that waits for the submitted ELS event to complete.
 2242  * If an error completion event is received, the requested ELS is aborted.
 2243  *
 2244  * @param ctx Remote node SM context.
 2245  * @param evt Event to process.
 2246  * @param arg Per event optional argument.
 2247  *
 2248  * @return Returns NULL.
 2249  */
 2250 
 2251 void *
 2252 __ocs_els_wait_resp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2253 {
 2254         ocs_io_t *io;
 2255         std_els_state_decl();
 2256 
 2257         els_sm_trace();
 2258 
 2259         switch(evt) {
 2260         case OCS_EVT_SRRS_ELS_REQ_OK: {
 2261                 ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_OK, arg);
 2262                 break;
 2263         }
 2264 
 2265         case OCS_EVT_SRRS_ELS_REQ_FAIL: {
 2266                 ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
 2267                 break;
 2268         }
 2269 
 2270         case OCS_EVT_ELS_REQ_TIMEOUT: {
 2271                 els_io_printf(els, "Timed out, retry (%d tries remaining)\n",
 2272                                 els->els_retries_remaining-1);
 2273                 ocs_io_transition(els, __ocs_els_retry, NULL);
 2274                 break;
 2275         }
 2276 
 2277         case OCS_EVT_SRRS_ELS_REQ_RJT: {
 2278                 ocs_node_cb_t *cbdata = arg;
 2279                 uint32_t reason_code = (cbdata->ext_status >> 16) & 0xff;
 2280 
 2281                 /* delay and retry if reason code is Logical Busy */
 2282                 switch (reason_code) {
 2283                 case FC_REASON_LOGICAL_BUSY:
 2284                         els->node->els_req_cnt--;
 2285                         els_io_printf(els, "LS_RJT Logical Busy response, delay and retry\n");
 2286                         ocs_io_transition(els, __ocs_els_delay_retry, NULL);
 2287                         break;
 2288                 default:
 2289                         ocs_els_io_cleanup(els, evt, arg);
 2290                         break;
 2291                 }
 2292                 break;
 2293         }
 2294 
 2295         case OCS_EVT_ABORT_ELS: {
 2296                 /* request to abort this ELS without an ABTS */
 2297                 els_io_printf(els, "ELS abort requested\n");
 2298                 els->els_retries_remaining = 0;         /* Set retries to zero, we are done */
 2299                 io = ocs_els_abort_io(els, FALSE);
 2300                 if (io == NULL) {
 2301                         ocs_log_err(ocs, "ocs_els_send failed\n");
 2302                         ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
 2303                 } else {
 2304                         ocs_io_transition(els, __ocs_els_aborting, NULL);
 2305                 }
 2306                 break;
 2307         }
 2308 
 2309         default:
 2310                 __ocs_els_common(__func__, ctx, evt, arg);
 2311                 break;
 2312         }
 2313         return NULL;
 2314 }
 2315 
 2316 /**
 2317  * @brief Wait for the ELS IO abort request to complete, and retry the ELS.
 2318  *
 2319  * <h3 class="desc">Description</h3>
 2320  * This state is entered when waiting for an abort of an ELS
 2321  * request to complete so the request can be retried.
 2322  *
 2323  * @param ctx Remote node SM context.
 2324  * @param evt Event to process.
 2325  * @param arg Per event optional argument.
 2326  *
 2327  * @return Returns NULL.
 2328  */
 2329 
 2330 void *
 2331 __ocs_els_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2332 {
 2333         int32_t rc = 0;
 2334         std_els_state_decl();
 2335 
 2336         els_sm_trace();
 2337 
 2338         switch(evt) {
 2339         case OCS_EVT_ENTER: {
 2340                 /* handle event for ABORT_XRI WQE
 2341                  * once abort is complete, retry if retries left;
 2342                  * don't need to wait for OCS_EVT_SRRS_ELS_REQ_* event because we got
 2343                  * by receiving OCS_EVT_ELS_REQ_TIMEOUT
 2344                  */
 2345                 ocs_node_cb_t node_cbdata;
 2346                 node_cbdata.status = node_cbdata.ext_status = (~0);
 2347                 node_cbdata.els = els;
 2348                 if (els->els_retries_remaining && --els->els_retries_remaining) {
 2349                         /* Use a different XRI for the retry (would like a new oxid),
 2350                          * so free the HW IO (dispatch will allocate a new one). It's an
 2351                          * optimization to only free the HW IO here and not the ocs_io_t;
 2352                          * Freeing the ocs_io_t object would require copying all the necessary
 2353                          * info from the old ocs_io_t object to the * new one; and allocating
 2354                          * a new ocs_io_t could fail.
 2355                          */
 2356                         ocs_assert(els->hio, NULL);
 2357                         ocs_hw_io_free(&ocs->hw, els->hio);
 2358                         els->hio = NULL;
 2359 
 2360                         /* result isn't propagated up to node sm, need to decrement req cnt */
 2361                         ocs_assert(els->node->els_req_cnt, NULL);
 2362                         els->node->els_req_cnt--;
 2363                         rc = ocs_els_send(els, els->els_req.size, els->els_timeout_sec, ocs_els_req_cb);
 2364                         if (rc) {
 2365                                 ocs_log_err(ocs, "ocs_els_send failed: %d\n", rc);
 2366                                 ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &node_cbdata);
 2367                         }
 2368                         ocs_io_transition(els, __ocs_els_wait_resp, NULL);
 2369                 } else {
 2370                         els_io_printf(els, "Retries exhausted\n");
 2371                         ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, &node_cbdata);
 2372                 }
 2373                 break;
 2374         }
 2375 
 2376         default:
 2377                 __ocs_els_common(__func__, ctx, evt, arg);
 2378                 break;
 2379         }
 2380         return NULL;
 2381 }
 2382 
 2383 /**
 2384  * @brief Wait for a retry timer to expire having received an abort request
 2385  *
 2386  * <h3 class="desc">Description</h3>
 2387  * This state is entered when waiting for a timer event, after having received
 2388  * an abort request, to avoid a race condition with the timer handler
 2389  *
 2390  * @param ctx Remote node SM context.
 2391  * @param evt Event to process.
 2392  * @param arg Per event optional argument.
 2393  *
 2394  * @return Returns NULL.
 2395  */
 2396 void *
 2397 __ocs_els_aborted_delay_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2398 {
 2399         std_els_state_decl();
 2400 
 2401         els_sm_trace();
 2402 
 2403         switch(evt) {
 2404         case OCS_EVT_ENTER:
 2405                 /* mod/resched the timer for a short duration */
 2406                 ocs_mod_timer(&els->delay_timer, 1);
 2407                 break;
 2408         case OCS_EVT_TIMER_EXPIRED:
 2409                 /* Cancel the timer, skip post node event, and free the io */
 2410                 node->els_req_cnt++;
 2411                 ocs_els_io_cleanup(els, OCS_EVT_SRRS_ELS_REQ_FAIL, arg);
 2412                 break;
 2413         default:
 2414                 __ocs_els_common(__func__, ctx, evt, arg);
 2415                 break;
 2416         }
 2417         return NULL;
 2418 }
 2419 
 2420 /**
 2421  * @brief Wait for a retry timer to expire
 2422  *
 2423  * <h3 class="desc">Description</h3>
 2424  * This state is entered when waiting for a timer event, so that
 2425  * the ELS request can be retried.
 2426  *
 2427  * @param ctx Remote node SM context.
 2428  * @param evt Event to process.
 2429  * @param arg Per event optional argument.
 2430  *
 2431  * @return Returns NULL.
 2432  */
 2433 void *
 2434 __ocs_els_delay_retry(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2435 {
 2436         std_els_state_decl();
 2437 
 2438         els_sm_trace();
 2439 
 2440         switch(evt) {
 2441         case OCS_EVT_ENTER:
 2442                 ocs_setup_timer(ocs, &els->delay_timer, ocs_els_delay_timer_cb, els, 5000);
 2443                 break;
 2444         case OCS_EVT_TIMER_EXPIRED:
 2445                 /* Retry delay timer expired, retry the ELS request, Free the HW IO so
 2446                  * that a new oxid is used.
 2447                  */
 2448                 if (els->hio != NULL) {
 2449                         ocs_hw_io_free(&ocs->hw, els->hio);
 2450                         els->hio = NULL;
 2451                 }
 2452                 ocs_io_transition(els, __ocs_els_init, NULL);
 2453                 break;
 2454         case OCS_EVT_ABORT_ELS:
 2455                 ocs_io_transition(els, __ocs_els_aborted_delay_retry, NULL);
 2456                 break;
 2457         default:
 2458                 __ocs_els_common(__func__, ctx, evt, arg);
 2459                 break;
 2460         }
 2461         return NULL;
 2462 }
 2463 
 2464 /**
 2465  * @brief Wait for the ELS IO abort request to complete.
 2466  *
 2467  * <h3 class="desc">Description</h3>
 2468  * This state is entered after we abort an ELS WQE and are
 2469  * waiting for either the original ELS WQE request or the abort
 2470  * to complete.
 2471  *
 2472  * @param ctx Remote node SM context.
 2473  * @param evt Event to process.
 2474  * @param arg Per event optional argument.
 2475  *
 2476  * @return Returns NULL.
 2477  */
 2478 
 2479 void *
 2480 __ocs_els_aborting(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2481 {
 2482         std_els_state_decl();
 2483 
 2484         els_sm_trace();
 2485 
 2486         switch(evt) {
 2487         case OCS_EVT_SRRS_ELS_REQ_OK:
 2488         case OCS_EVT_SRRS_ELS_REQ_FAIL:
 2489         case OCS_EVT_SRRS_ELS_REQ_RJT:
 2490         case OCS_EVT_ELS_REQ_TIMEOUT:
 2491         case OCS_EVT_ELS_REQ_ABORTED: {
 2492                 /* completion for ELS received first, transition to wait for abort cmpl */
 2493                 els_io_printf(els, "request cmpl evt=%s\n", ocs_sm_event_name(evt));
 2494                 ocs_io_transition(els, __ocs_els_aborting_wait_abort_cmpl, NULL);
 2495                 break;
 2496         }
 2497         case OCS_EVT_ELS_ABORT_CMPL: {
 2498                 /* completion for abort was received first, transition to wait for req cmpl */
 2499                 els_io_printf(els, "abort cmpl evt=%s\n", ocs_sm_event_name(evt));
 2500                 ocs_io_transition(els, __ocs_els_aborting_wait_req_cmpl, NULL);
 2501                 break;
 2502         }
 2503         case OCS_EVT_ABORT_ELS:
 2504                 /* nothing we can do but wait */
 2505                 break;
 2506 
 2507         default:
 2508                 __ocs_els_common(__func__, ctx, evt, arg);
 2509                 break;
 2510         }
 2511         return NULL;
 2512 }
 2513 
 2514 /**
 2515  * @brief cleanup ELS after abort
 2516  *
 2517  * @param els ELS IO to cleanup
 2518  *
 2519  * @return Returns None.
 2520  */
 2521 
 2522 static void
 2523 ocs_els_abort_cleanup(ocs_io_t *els)
 2524 {
 2525         /* handle event for ABORT_WQE
 2526          * whatever state ELS happened to be in, propagate aborted event up
 2527          * to node state machine in lieu of OCS_EVT_SRRS_ELS_* event
 2528          */
 2529         ocs_node_cb_t cbdata;
 2530         cbdata.status = cbdata.ext_status = 0;
 2531         cbdata.els = els;
 2532         els_io_printf(els, "Request aborted\n");
 2533         ocs_els_io_cleanup(els, OCS_EVT_ELS_REQ_ABORTED, &cbdata);
 2534 }
 2535 
 2536 /**
 2537  * @brief Wait for the ELS IO abort request to complete.
 2538  *
 2539  * <h3 class="desc">Description</h3>
 2540  * This state is entered after we abort an ELS WQE, we received
 2541  * the abort completion first and are waiting for the original
 2542  * ELS WQE request to complete.
 2543  *
 2544  * @param ctx Remote node SM context.
 2545  * @param evt Event to process.
 2546  * @param arg Per event optional argument.
 2547  *
 2548  * @return Returns NULL.
 2549  */
 2550 
 2551 void *
 2552 __ocs_els_aborting_wait_req_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2553 {
 2554         std_els_state_decl();
 2555 
 2556         els_sm_trace();
 2557 
 2558         switch(evt) {
 2559         case OCS_EVT_SRRS_ELS_REQ_OK:
 2560         case OCS_EVT_SRRS_ELS_REQ_FAIL:
 2561         case OCS_EVT_SRRS_ELS_REQ_RJT:
 2562         case OCS_EVT_ELS_REQ_TIMEOUT:
 2563         case OCS_EVT_ELS_REQ_ABORTED: {
 2564                 /* completion for ELS that was aborted */
 2565                 ocs_els_abort_cleanup(els);
 2566                 break;
 2567         }
 2568         case OCS_EVT_ABORT_ELS:
 2569                 /* nothing we can do but wait */
 2570                 break;
 2571 
 2572         default:
 2573                 __ocs_els_common(__func__, ctx, evt, arg);
 2574                 break;
 2575         }
 2576         return NULL;
 2577 }
 2578 
 2579 /**
 2580  * @brief Wait for the ELS IO abort request to complete.
 2581  *
 2582  * <h3 class="desc">Description</h3>
 2583  * This state is entered after we abort an ELS WQE, we received
 2584  * the original ELS WQE request completion first and are waiting
 2585  * for the abort to complete.
 2586  *
 2587  * @param ctx Remote node SM context.
 2588  * @param evt Event to process.
 2589  * @param arg Per event optional argument.
 2590  *
 2591  * @return Returns NULL.
 2592  */
 2593 
 2594 void *
 2595 __ocs_els_aborting_wait_abort_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
 2596 {
 2597         std_els_state_decl();
 2598 
 2599         els_sm_trace();
 2600 
 2601         switch(evt) {
 2602         case OCS_EVT_ELS_ABORT_CMPL: {
 2603                 ocs_els_abort_cleanup(els);
 2604                 break;
 2605         }
 2606         case OCS_EVT_ABORT_ELS:
 2607                 /* nothing we can do but wait */
 2608                 break;
 2609 
 2610         default:
 2611                 __ocs_els_common(__func__, ctx, evt, arg);
 2612                 break;
 2613         }
 2614         return NULL;
 2615 }
 2616 
 2617 /**
 2618  * @brief Generate ELS context ddump data.
 2619  *
 2620  * <h3 class="desc">Description</h3>
 2621  * Generate the ddump data for an ELS context.
 2622  *
 2623  * @param textbuf Pointer to the text buffer.
 2624  * @param els Pointer to the ELS context.
 2625  *
 2626  * @return None.
 2627  */
 2628 
 2629 void
 2630 ocs_ddump_els(ocs_textbuf_t *textbuf, ocs_io_t *els)
 2631 {
 2632         ocs_ddump_section(textbuf, "els", -1);
 2633         ocs_ddump_value(textbuf, "req_free", "%d", els->els_req_free);
 2634         ocs_ddump_value(textbuf, "evtdepth", "%d", els->els_evtdepth);
 2635         ocs_ddump_value(textbuf, "pend", "%d", els->els_pend);
 2636         ocs_ddump_value(textbuf, "active", "%d", els->els_active);
 2637         ocs_ddump_io(textbuf, els);
 2638         ocs_ddump_endsection(textbuf, "els", -1);
 2639 }
 2640 
 2641 /**
 2642  * @brief return TRUE if given ELS list is empty (while taking proper locks)
 2643  *
 2644  * Test if given ELS list is empty while holding the node->active_ios_lock.
 2645  *
 2646  * @param node pointer to node object
 2647  * @param list pointer to list
 2648  *
 2649  * @return TRUE if els_io_list is empty
 2650  */
 2651 
 2652 int32_t
 2653 ocs_els_io_list_empty(ocs_node_t *node, ocs_list_t *list)
 2654 {
 2655         int empty;
 2656         ocs_lock(&node->active_ios_lock);
 2657                 empty = ocs_list_empty(list);
 2658         ocs_unlock(&node->active_ios_lock);
 2659         return empty;
 2660 }
 2661 
 2662 /**
 2663  * @brief Handle CT send response completion
 2664  *
 2665  * Called when CT response completes, free IO
 2666  *
 2667  * @param hio Pointer to the HW IO context that completed.
 2668  * @param rnode Pointer to the remote node.
 2669  * @param length Length of the returned payload data.
 2670  * @param status Status of the completion.
 2671  * @param ext_status Extended status of the completion.
 2672  * @param arg Application-specific argument (generally a pointer to the ELS IO context).
 2673  *
 2674  * @return returns 0
 2675  */
 2676 static int32_t
 2677 ocs_ct_acc_cb(ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg)
 2678 {
 2679         ocs_io_t *io = arg;
 2680 
 2681         ocs_els_io_free(io);
 2682 
 2683         return 0;
 2684 }
 2685 
 2686 /**
 2687  * @brief Send CT response
 2688  *
 2689  * Sends a CT response frame with payload
 2690  *
 2691  * @param io Pointer to the IO context.
 2692  * @param ox_id Originator exchange ID
 2693  * @param ct_hdr Pointer to the CT IU
 2694  * @param cmd_rsp_code CT response code
 2695  * @param reason_code Reason code
 2696  * @param reason_code_explanation Reason code explanation
 2697  *
 2698  * @return returns 0 for success, a negative error code value for failure.
 2699  */
 2700 int32_t
 2701 ocs_send_ct_rsp(ocs_io_t *io, uint32_t ox_id, fcct_iu_header_t *ct_hdr, uint32_t cmd_rsp_code, uint32_t reason_code, uint32_t reason_code_explanation)
 2702 {
 2703         fcct_iu_header_t *rsp = io->els_rsp.virt;
 2704 
 2705         io->io_type = OCS_IO_TYPE_CT_RESP;
 2706 
 2707         *rsp = *ct_hdr;
 2708 
 2709         fcct_build_req_header(rsp, cmd_rsp_code, 0);
 2710         rsp->reason_code = reason_code;
 2711         rsp->reason_code_explanation = reason_code_explanation;
 2712 
 2713         io->display_name = "ct response";
 2714         io->init_task_tag = ox_id;
 2715         io->wire_len += sizeof(*rsp);
 2716 
 2717         ocs_memset(&io->iparam, 0, sizeof(io->iparam));
 2718 
 2719         io->io_type = OCS_IO_TYPE_CT_RESP;
 2720         io->hio_type = OCS_HW_FC_CT_RSP;
 2721         io->iparam.fc_ct_rsp.ox_id = ocs_htobe16(ox_id);
 2722         io->iparam.fc_ct_rsp.r_ctl = 3;
 2723         io->iparam.fc_ct_rsp.type = FC_TYPE_GS;
 2724         io->iparam.fc_ct_rsp.df_ctl = 0;
 2725         io->iparam.fc_ct_rsp.timeout = 5;
 2726 
 2727         if (ocs_scsi_io_dispatch(io, ocs_ct_acc_cb) < 0) {
 2728                 ocs_els_io_free(io);
 2729                 return -1;
 2730         }
 2731         return 0;
 2732 }
 2733 
 2734 /**
 2735  * @brief Handle delay retry timeout
 2736  *
 2737  * Callback is invoked when the delay retry timer expires.
 2738  *
 2739  * @param arg pointer to the ELS IO object
 2740  *
 2741  * @return none
 2742  */
 2743 static void
 2744 ocs_els_delay_timer_cb(void *arg)
 2745 {
 2746         ocs_io_t *els = arg;
 2747         ocs_node_t *node = els->node;
 2748 
 2749         /*
 2750          * There is a potential deadlock here since is Linux executes timers
 2751          * in a soft IRQ context. The lock may be aready locked by the interrupt
 2752          * thread. Handle this case by attempting to take the node lock and reset the
 2753          * timer if we fail to acquire the lock.
 2754          *
 2755          * Note: This code relies on the fact that the node lock is recursive.
 2756          */
 2757         if (ocs_node_lock_try(node)) {
 2758                 ocs_els_post_event(els, OCS_EVT_TIMER_EXPIRED, NULL);
 2759                 ocs_node_unlock(node);
 2760         } else {
 2761                 ocs_setup_timer(els->ocs, &els->delay_timer, ocs_els_delay_timer_cb, els, 1);
 2762         }
 2763 }

Cache object: 08fde06f1d0b9fd2b07cbaaafea293a0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.