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/sli4.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  * @defgroup sli SLI-4 Base APIs
   36  */
   37 
   38 /**
   39  * @file
   40  * All common (i.e. transport-independent) SLI-4 functions are implemented
   41  * in this file.
   42  */
   43 
   44 #include "sli4.h"
   45 
   46 #if defined(OCS_INCLUDE_DEBUG)
   47 #include "ocs_utils.h"
   48 #endif
   49 
   50 #define SLI4_BMBX_DELAY_US 1000 /* 1 ms */
   51 #define SLI4_INIT_PORT_DELAY_US 10000 /* 10 ms */
   52 
   53 static int32_t sli_fw_init(sli4_t *);
   54 static int32_t sli_fw_term(sli4_t *);
   55 static int32_t sli_sliport_control(sli4_t *sli4, uint32_t endian);
   56 static int32_t sli_cmd_fw_deinitialize(sli4_t *, void *, size_t);
   57 static int32_t sli_cmd_fw_initialize(sli4_t *, void *, size_t);
   58 static int32_t sli_queue_doorbell(sli4_t *, sli4_queue_t *);
   59 static uint8_t sli_queue_entry_is_valid(sli4_queue_t *, uint8_t *, uint8_t);
   60 
   61 const uint8_t sli4_fw_initialize[] = {
   62         0xff, 0x12, 0x34, 0xff,
   63         0xff, 0x56, 0x78, 0xff,
   64 };
   65 
   66 const uint8_t sli4_fw_deinitialize[] = {
   67         0xff, 0xaa, 0xbb, 0xff,
   68         0xff, 0xcc, 0xdd, 0xff,
   69 };
   70 
   71 typedef struct {
   72         uint32_t rev_id;
   73         uint32_t family;        /* generation */
   74         sli4_asic_type_e type;
   75         sli4_asic_rev_e rev;
   76 } sli4_asic_entry_t;
   77 
   78 sli4_asic_entry_t sli4_asic_table[] = {
   79         {       0x00,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A0},
   80         {       0x01,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A1},
   81         {       0x02,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_A2},
   82         {       0x00,   4,      SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0},
   83         {       0x00,   2,      SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_A0},
   84         {       0x10,   1,      SLI4_ASIC_TYPE_BE3,     SLI4_ASIC_REV_B0},
   85         {       0x10,   0x04,   SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B0},
   86         {       0x11,   0x04,   SLI4_ASIC_TYPE_SKYHAWK, SLI4_ASIC_REV_B1},
   87         {       0x0,    0x0a,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_A0},
   88         {       0x10,   0x0b,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_B0},
   89         {       0x30,   0x0b,   SLI4_ASIC_TYPE_LANCER,  SLI4_ASIC_REV_D0},
   90         {       0x3,    0x0b,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
   91         {       0x0,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A0},
   92         {       0x1,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A1},
   93         {       0x3,    0x0c,   SLI4_ASIC_TYPE_LANCERG6,SLI4_ASIC_REV_A3},
   94 
   95         {       0x00,   0x05,   SLI4_ASIC_TYPE_CORSAIR, SLI4_ASIC_REV_A0},
   96 };
   97 
   98 /*
   99  * @brief Convert queue type enum (SLI_QTYPE_*) into a string.
  100  */
  101 const char *SLI_QNAME[] = {
  102         "Event Queue",
  103         "Completion Queue",
  104         "Mailbox Queue",
  105         "Work Queue",
  106         "Receive Queue",
  107         "Undefined"
  108 };
  109 
  110 /**
  111  * @brief Define the mapping of registers to their BAR and offset.
  112  *
  113  * @par Description
  114  * Although SLI-4 specification defines a common set of registers, their locations
  115  * (both BAR and offset) depend on the interface type. This array maps a register
  116  * enum to an array of BAR/offset pairs indexed by the interface type. For
  117  * example, to access the bootstrap mailbox register on an interface type 0
  118  * device, code can refer to the offset using regmap[SLI4_REG_BMBX][0].offset.
  119  *
  120  * @b Note: A value of UINT32_MAX for either the register set (rset) or offset (off)
  121  * indicates an invalid mapping.
  122  */
  123 const sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES] = {
  124         /* SLI4_REG_BMBX */
  125         {
  126                 { 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG },
  127         },
  128         /* SLI4_REG_EQCQ_DOORBELL */
  129         {
  130                 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  131                 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  132         },
  133         /* SLI4_REG_FCOE_RQ_DOORBELL */
  134         {
  135                 { 2, SLI4_RQ_DOORBELL_REG }, { 0, SLI4_RQ_DOORBELL_REG },
  136                 { 0, SLI4_RQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
  137         },
  138         /* SLI4_REG_IO_WQ_DOORBELL */
  139         {
  140                 { 2, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
  141         },
  142         /* SLI4_REG_MQ_DOORBELL */
  143         {
  144                 { 2, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
  145                 { 0, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
  146         },
  147         /* SLI4_REG_PHYSDEV_CONTROL */
  148         {
  149                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_PHSDEV_CONTROL_REG_23 }, { 0, SLI4_PHSDEV_CONTROL_REG_23 },
  150         },
  151         /* SLI4_REG_SLIPORT_CONTROL */
  152         {
  153                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_CONTROL_REG }, { UINT32_MAX, UINT32_MAX },
  154         },
  155         /* SLI4_REG_SLIPORT_ERROR1 */
  156         {
  157                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_ERROR1 }, { UINT32_MAX, UINT32_MAX },
  158         },
  159         /* SLI4_REG_SLIPORT_ERROR2 */
  160         {
  161                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_SLIPORT_ERROR2 }, { UINT32_MAX, UINT32_MAX },
  162         },
  163         /* SLI4_REG_SLIPORT_SEMAPHORE */
  164         {
  165                 { 1, SLI4_PORT_SEMAPHORE_REG_0 },  { 0, SLI4_PORT_SEMAPHORE_REG_1 },
  166                 { 0, SLI4_PORT_SEMAPHORE_REG_23 }, { 0, SLI4_PORT_SEMAPHORE_REG_23 },
  167         },
  168         /* SLI4_REG_SLIPORT_STATUS */
  169         {
  170                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { 0, SLI4_PORT_STATUS_REG_23 }, { 0, SLI4_PORT_STATUS_REG_23 },
  171         },
  172         /* SLI4_REG_UERR_MASK_HI */
  173         {
  174                 { 0, SLI4_UERR_MASK_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  175         },
  176         /* SLI4_REG_UERR_MASK_LO */
  177         {
  178                 { 0, SLI4_UERR_MASK_LOW_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  179         },
  180         /* SLI4_REG_UERR_STATUS_HI */
  181         {
  182                 { 0, SLI4_UERR_STATUS_HIGH_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  183         },
  184         /* SLI4_REG_UERR_STATUS_LO */
  185         {
  186                 { 0, SLI4_UERR_STATUS_LOW_REG }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  187         },
  188         /* SLI4_REG_SW_UE_CSR1 */
  189         {
  190                 { 1, SLI4_SW_UE_CSR1}, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  191         },
  192         /* SLI4_REG_SW_UE_CSR2 */
  193         {
  194                 { 1, SLI4_SW_UE_CSR2}, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  195         },
  196 };
  197 
  198 /**
  199  * @brief Read the given SLI register.
  200  *
  201  * @param sli Pointer to the SLI context.
  202  * @param reg Register name enum.
  203  *
  204  * @return Returns the register value.
  205  */
  206 uint32_t
  207 sli_reg_read(sli4_t *sli, sli4_regname_e reg)
  208 {
  209         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
  210 
  211         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
  212                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
  213                 return UINT32_MAX;
  214         }
  215 
  216         return ocs_reg_read32(sli->os, r->rset, r->off);
  217 }
  218 
  219 /**
  220  * @brief Write the value to the given SLI register.
  221  *
  222  * @param sli Pointer to the SLI context.
  223  * @param reg Register name enum.
  224  * @param val Value to write.
  225  *
  226  * @return None.
  227  */
  228 void
  229 sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
  230 {
  231         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
  232 
  233         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
  234                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
  235                 return;
  236         }
  237 
  238         ocs_reg_write32(sli->os, r->rset, r->off, val);
  239 }
  240 
  241 /**
  242  * @brief Check if the SLI_INTF register is valid.
  243  *
  244  * @param val 32-bit SLI_INTF register value.
  245  *
  246  * @return Returns 0 on success, or a non-zero value on failure.
  247  */
  248 static uint8_t
  249 sli_intf_valid_check(uint32_t val)
  250 {
  251         return ((val >> SLI4_INTF_VALID_SHIFT) & SLI4_INTF_VALID_MASK) != SLI4_INTF_VALID;
  252 }
  253 
  254 /**
  255  * @brief Retrieve the SLI revision level.
  256  *
  257  * @param val 32-bit SLI_INTF register value.
  258  *
  259  * @return Returns the SLI revision level.
  260  */
  261 static uint8_t
  262 sli_intf_sli_revision(uint32_t val)
  263 {
  264         return ((val >> SLI4_INTF_SLI_REVISION_SHIFT) & SLI4_INTF_SLI_REVISION_MASK);
  265 }
  266 
  267 static uint8_t
  268 sli_intf_sli_family(uint32_t val)
  269 {
  270         return ((val >> SLI4_INTF_SLI_FAMILY_SHIFT) & SLI4_INTF_SLI_FAMILY_MASK);
  271 }
  272 
  273 /**
  274  * @brief Retrieve the SLI interface type.
  275  *
  276  * @param val 32-bit SLI_INTF register value.
  277  *
  278  * @return Returns the SLI interface type.
  279  */
  280 static uint8_t
  281 sli_intf_if_type(uint32_t val)
  282 {
  283         return ((val >> SLI4_INTF_IF_TYPE_SHIFT) & SLI4_INTF_IF_TYPE_MASK);
  284 }
  285 
  286 /**
  287  * @brief Retrieve PCI revision ID.
  288  *
  289  * @param val 32-bit PCI CLASS_REVISION register value.
  290  *
  291  * @return Returns the PCI revision ID.
  292  */
  293 static uint8_t
  294 sli_pci_rev_id(uint32_t val)
  295 {
  296         return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK);
  297 }
  298 
  299 /**
  300  * @brief retrieve SLI ASIC generation
  301  *
  302  * @param val 32-bit SLI_ASIC_ID register value
  303  *
  304  * @return SLI ASIC generation
  305  */
  306 static uint8_t
  307 sli_asic_gen(uint32_t val)
  308 {
  309         return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK);
  310 }
  311 
  312 /**
  313  * @brief Wait for the bootstrap mailbox to report "ready".
  314  *
  315  * @param sli4 SLI context pointer.
  316  * @param msec Number of milliseconds to wait.
  317  *
  318  * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. time out occurred).
  319  */
  320 static int32_t
  321 sli_bmbx_wait(sli4_t *sli4, uint32_t msec)
  322 {
  323         uint32_t        val = 0;
  324 
  325         do {
  326                 ocs_udelay(SLI4_BMBX_DELAY_US);
  327                 val = sli_reg_read(sli4, SLI4_REG_BMBX);
  328                 msec--;
  329         } while(msec && !(val & SLI4_BMBX_RDY));
  330 
  331         return(!(val & SLI4_BMBX_RDY));
  332 }
  333 
  334 /**
  335  * @brief Write bootstrap mailbox.
  336  *
  337  * @param sli4 SLI context pointer.
  338  *
  339  * @return Returns 0 if command succeeded, or non-zero otherwise.
  340  */
  341 static int32_t
  342 sli_bmbx_write(sli4_t *sli4)
  343 {
  344         uint32_t        val = 0;
  345 
  346         /* write buffer location to bootstrap mailbox register */
  347         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE);
  348         val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys);
  349         sli_reg_write(sli4, SLI4_REG_BMBX, val);
  350 
  351         if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
  352                 ocs_log_crit(sli4->os, "BMBX WRITE_HI failed\n");
  353                 return -1;
  354         }
  355         val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys);
  356         sli_reg_write(sli4, SLI4_REG_BMBX, val);
  357 
  358         /* wait for SLI Port to set ready bit */
  359         return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC/*XXX*/);
  360 }
  361 
  362 #if defined(OCS_INCLUDE_DEBUG)
  363 /**
  364  * @ingroup sli
  365  * @brief Dump BMBX mailbox command.
  366  *
  367  * @par Description
  368  * Convenience function for dumping BMBX mailbox commands. Takes
  369  * into account which mailbox command is given since SLI_CONFIG
  370  * commands are special.
  371  *
  372  * @b Note: This function takes advantage of
  373  * the one-command-at-a-time nature of the BMBX to be able to
  374  * display non-embedded SLI_CONFIG commands. This will not work
  375  * for mailbox commands on the MQ. Luckily, all current non-emb
  376  * mailbox commands go through the BMBX.
  377  *
  378  * @param sli4 SLI context pointer.
  379  * @param mbx Pointer to mailbox command to dump.
  380  * @param prefix Prefix for dump label.
  381  *
  382  * @return None.
  383  */
  384 static void
  385 sli_dump_bmbx_command(sli4_t *sli4, void *mbx, const char *prefix)
  386 {
  387         uint32_t size = 0;
  388         char label[64];
  389         uint32_t i;
  390         /* Mailbox diagnostic logging */
  391         sli4_mbox_command_header_t *hdr = (sli4_mbox_command_header_t *)mbx;
  392 
  393         if (!ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)) {
  394                 return;
  395         }
  396 
  397         if (hdr->command == SLI4_MBOX_COMMAND_SLI_CONFIG) {
  398                 sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)hdr;
  399                 sli4_req_hdr_t  *sli_config_hdr;
  400                 if (sli_config->emb) {
  401                         ocs_snprintf(label, sizeof(label), "%s (emb)", prefix);
  402 
  403                         /*  if embedded, dump entire command */
  404                         sli_config_hdr = (sli4_req_hdr_t *)sli_config->payload.embed;
  405                         size = sizeof(*sli_config) - sizeof(sli_config->payload) +
  406                                 sli_config_hdr->request_length + (4*sizeof(uint32_t));
  407                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  408                                    (uint8_t *)sli4->bmbx.virt, size);
  409                 } else {
  410                         sli4_sli_config_pmd_t *pmd;
  411                         ocs_snprintf(label, sizeof(label), "%s (non-emb hdr)", prefix);
  412 
  413                         /* if non-embedded, break up into two parts: SLI_CONFIG hdr
  414                            and the payload(s) */
  415                         size = sizeof(*sli_config) - sizeof(sli_config->payload) + (12 * sli_config->pmd_count);
  416                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  417                                    (uint8_t *)sli4->bmbx.virt, size);
  418 
  419                         /* as sanity check, make sure first PMD matches what was saved */
  420                         pmd = &sli_config->payload.mem;
  421                         if ((pmd->address_high == ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys)) &&
  422                             (pmd->address_low == ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys))) {
  423                                 for (i = 0; i < sli_config->pmd_count; i++, pmd++) {
  424                                         sli_config_hdr = sli4->bmbx_non_emb_pmd->virt;
  425                                         ocs_snprintf(label, sizeof(label), "%s (non-emb pay[%d])",
  426                                                      prefix, i);
  427                                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  428                                                    (uint8_t *)sli4->bmbx_non_emb_pmd->virt,
  429                                                    sli_config_hdr->request_length + (4*sizeof(uint32_t)));
  430                                 }
  431                         } else {
  432                                 ocs_log_debug(sli4->os, "pmd addr does not match pmd:%x %x (%x %x)\n",
  433                                         pmd->address_high, pmd->address_low,
  434                                         ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys),
  435                                         ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys));
  436                         }
  437                 }
  438         } else {
  439                 /* not an SLI_CONFIG command, just display first 64 bytes, like we do
  440                    for MQEs */
  441                 size = 64;
  442                 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, prefix,
  443                            (uint8_t *)mbx, size);
  444         }
  445 }
  446 #endif
  447 
  448 /**
  449  * @ingroup sli
  450  * @brief Submit a command to the bootstrap mailbox and check the status.
  451  *
  452  * @param sli4 SLI context pointer.
  453  *
  454  * @return Returns 0 on success, or a non-zero value on failure.
  455  */
  456 int32_t
  457 sli_bmbx_command(sli4_t *sli4)
  458 {
  459         void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
  460 
  461 #if defined(OCS_INCLUDE_DEBUG)
  462         sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmd");
  463 #endif
  464 
  465         if (sli_fw_error_status(sli4) > 0) {
  466                 ocs_log_crit(sli4->os, "Chip is in an error state - Mailbox "
  467                         "command rejected status=%#x error1=%#x error2=%#x\n",
  468                         sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
  469                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
  470                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
  471                 return -1;
  472         }
  473 
  474         if (sli_bmbx_write(sli4)) {
  475                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail phys=%p reg=%#x\n",
  476                         (void*)sli4->bmbx.phys,
  477                         sli_reg_read(sli4, SLI4_REG_BMBX));
  478                 return -1;
  479         }
  480 
  481         /* check completion queue entry status */
  482         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD);
  483         if (((sli4_mcqe_t *)cqe)->val) {
  484 #if defined(OCS_INCLUDE_DEBUG)
  485                 sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmpl");
  486         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "bmbx cqe", cqe, sizeof(sli4_mcqe_t));
  487 #endif
  488                 return sli_cqe_mq(cqe);
  489         } else {
  490                 ocs_log_err(sli4->os, "invalid or wrong type\n");
  491                 return -1;
  492         }
  493 }
  494 
  495 /****************************************************************************
  496  * Messages
  497  */
  498 
  499 /**
  500  * @ingroup sli
  501  * @brief Write a CONFIG_LINK command to the provided buffer.
  502  *
  503  * @param sli4 SLI context pointer.
  504  * @param buf Virtual pointer to the destination buffer.
  505  * @param size Buffer size, in bytes.
  506  *
  507  * @return Returns the number of bytes written.
  508  */
  509 int32_t
  510 sli_cmd_config_link(sli4_t *sli4, void *buf, size_t size)
  511 {
  512         sli4_cmd_config_link_t  *config_link = buf;
  513 
  514         ocs_memset(buf, 0, size);
  515 
  516         config_link->hdr.command = SLI4_MBOX_COMMAND_CONFIG_LINK;
  517 
  518         /* Port interprets zero in a field as "use default value" */
  519 
  520         return sizeof(sli4_cmd_config_link_t);
  521 }
  522 
  523 /**
  524  * @ingroup sli
  525  * @brief Write a DOWN_LINK command to the provided buffer.
  526  *
  527  * @param sli4 SLI context pointer.
  528  * @param buf Virtual pointer to the destination buffer.
  529  * @param size Buffer size, in bytes.
  530  *
  531  * @return Returns the number of bytes written.
  532  */
  533 int32_t
  534 sli_cmd_down_link(sli4_t *sli4, void *buf, size_t size)
  535 {
  536         sli4_mbox_command_header_t      *hdr = buf;
  537 
  538         ocs_memset(buf, 0, size);
  539 
  540         hdr->command = SLI4_MBOX_COMMAND_DOWN_LINK;
  541 
  542         /* Port interprets zero in a field as "use default value" */
  543 
  544         return sizeof(sli4_mbox_command_header_t);
  545 }
  546 
  547 /**
  548  * @ingroup sli
  549  * @brief Write a DUMP Type 4 command to the provided buffer.
  550  *
  551  * @param sli4 SLI context pointer.
  552  * @param buf Virtual pointer to the destination buffer.
  553  * @param size Buffer size, in bytes.
  554  * @param wki The well known item ID.
  555  *
  556  * @return Returns the number of bytes written.
  557  */
  558 int32_t
  559 sli_cmd_dump_type4(sli4_t *sli4, void *buf, size_t size, uint16_t wki)
  560 {
  561         sli4_cmd_dump4_t        *cmd = buf;
  562 
  563         ocs_memset(buf, 0, size);
  564 
  565         cmd->hdr.command = SLI4_MBOX_COMMAND_DUMP;
  566         cmd->type = 4;
  567         cmd->wki_selection = wki;
  568         return sizeof(sli4_cmd_dump4_t);
  569 }
  570 
  571 /**
  572  * @ingroup sli
  573  * @brief Write a COMMON_READ_TRANSCEIVER_DATA command.
  574  *
  575  * @param sli4 SLI context.
  576  * @param buf Destination buffer for the command.
  577  * @param size Buffer size, in bytes.
  578  * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2).
  579  * @param dma DMA structure from which the data will be copied.
  580  *
  581  * @note This creates a Version 0 message.
  582  *
  583  * @return Returns the number of bytes written.
  584  */
  585 int32_t
  586 sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint32_t page_num,
  587                                      ocs_dma_t *dma)
  588 {
  589         sli4_req_common_read_transceiver_data_t *req = NULL;
  590         uint32_t        sli_config_off = 0;
  591         uint32_t        payload_size;
  592 
  593         if (dma == NULL) {
  594                 /* Payload length must accommodate both request and response */
  595                 payload_size = max(sizeof(sli4_req_common_read_transceiver_data_t),
  596                                    sizeof(sli4_res_common_read_transceiver_data_t));
  597         } else {
  598                 payload_size = dma->size;
  599         }
  600 
  601         if (sli4->port_type == SLI4_PORT_TYPE_FC) {
  602                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, dma);
  603         }
  604 
  605         if (dma == NULL) {
  606                 req = (sli4_req_common_read_transceiver_data_t *)((uint8_t *)buf + sli_config_off);
  607         } else {
  608                 req = (sli4_req_common_read_transceiver_data_t *)dma->virt;
  609                 ocs_memset(req, 0, dma->size);
  610         }
  611 
  612         req->hdr.opcode = SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA;
  613         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
  614         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
  615 
  616         req->page_number = page_num;
  617         req->port = sli4->physical_port;
  618 
  619         return(sli_config_off + sizeof(sli4_req_common_read_transceiver_data_t));
  620 }
  621 
  622 /**
  623  * @ingroup sli
  624  * @brief Write a READ_LINK_STAT command to the provided buffer.
  625  *
  626  * @param sli4 SLI context pointer.
  627  * @param buf Virtual pointer to the destination buffer.
  628  * @param size Buffer size, in bytes.
  629  * @param req_ext_counters If TRUE, then the extended counters will be requested.
  630  * @param clear_overflow_flags If TRUE, then overflow flags will be cleared.
  631  * @param clear_all_counters If TRUE, the counters will be cleared.
  632  *
  633  * @return Returns the number of bytes written.
  634  */
  635 int32_t
  636 sli_cmd_read_link_stats(sli4_t *sli4, void *buf, size_t size,
  637                         uint8_t req_ext_counters,
  638                         uint8_t clear_overflow_flags,
  639                         uint8_t clear_all_counters)
  640 {
  641         sli4_cmd_read_link_stats_t      *cmd = buf;
  642 
  643         ocs_memset(buf, 0, size);
  644 
  645         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_LNK_STAT;
  646         cmd->rec = req_ext_counters;
  647         cmd->clrc = clear_all_counters;
  648         cmd->clof = clear_overflow_flags;
  649         return sizeof(sli4_cmd_read_link_stats_t);
  650 }
  651 
  652 /**
  653  * @ingroup sli
  654  * @brief Write a READ_STATUS command to the provided buffer.
  655  *
  656  * @param sli4 SLI context pointer.
  657  * @param buf Virtual pointer to the destination buffer.
  658  * @param size Buffer size, in bytes.
  659  * @param clear_counters If TRUE, the counters will be cleared.
  660  *
  661  * @return Returns the number of bytes written.
  662  */
  663 int32_t
  664 sli_cmd_read_status(sli4_t *sli4, void *buf, size_t size,
  665                         uint8_t clear_counters)
  666 {
  667         sli4_cmd_read_status_t  *cmd = buf;
  668 
  669         ocs_memset(buf, 0, size);
  670 
  671         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_STATUS;
  672         cmd->cc = clear_counters;
  673         return sizeof(sli4_cmd_read_status_t);
  674 }
  675 
  676 /**
  677  * @brief Write a FW_DEINITIALIZE command to the provided buffer.
  678  *
  679  * @param sli4 SLI context pointer.
  680  * @param buf Virtual pointer to the destination buffer.
  681  * @param size Buffer size, in bytes.
  682  *
  683  * @return Returns the number of bytes written.
  684  */
  685 static int32_t
  686 sli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size)
  687 {
  688 
  689         ocs_memset(buf, 0, size);
  690         ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize));
  691 
  692         return sizeof(sli4_fw_deinitialize);
  693 }
  694 
  695 /**
  696  * @brief Write a FW_INITIALIZE command to the provided buffer.
  697  *
  698  * @param sli4 SLI context pointer.
  699  * @param buf Virtual pointer to the destination buffer.
  700  * @param size Buffer size, in bytes.
  701  *
  702  * @return Returns the number of bytes written.
  703  */
  704 static int32_t
  705 sli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size)
  706 {
  707 
  708         ocs_memset(buf, 0, size);
  709         ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize));
  710 
  711         return sizeof(sli4_fw_initialize);
  712 }
  713 
  714 /**
  715  * @ingroup sli
  716  * @brief Write an INIT_LINK command to the provided buffer.
  717  *
  718  * @param sli4 SLI context pointer.
  719  * @param buf Virtual pointer to the destination buffer.
  720  * @param size Buffer size, in bytes.
  721  * @param speed Link speed.
  722  * @param reset_alpa For native FC, this is the selective reset AL_PA
  723  *
  724  * @return Returns the number of bytes written.
  725  */
  726 int32_t
  727 sli_cmd_init_link(sli4_t *sli4, void *buf, size_t size, uint32_t speed, uint8_t reset_alpa)
  728 {
  729         sli4_cmd_init_link_t    *init_link = buf;
  730 
  731         ocs_memset(buf, 0, size);
  732 
  733         init_link->hdr.command = SLI4_MBOX_COMMAND_INIT_LINK;
  734 
  735         /* Most fields only have meaning for FC links */
  736         if (sli4->config.topology != SLI4_READ_CFG_TOPO_FCOE) {
  737                 init_link->selective_reset_al_pa = reset_alpa;
  738                 init_link->link_flags.loopback = FALSE;
  739 
  740                 init_link->link_speed_selection_code = speed;
  741                 switch (speed) {
  742                 case FC_LINK_SPEED_1G:
  743                 case FC_LINK_SPEED_2G:
  744                 case FC_LINK_SPEED_4G:
  745                 case FC_LINK_SPEED_8G:
  746                 case FC_LINK_SPEED_16G:
  747                 case FC_LINK_SPEED_32G:
  748                         init_link->link_flags.fixed_speed = TRUE;
  749                         break;
  750                 case FC_LINK_SPEED_10G:
  751                         ocs_log_test(sli4->os, "unsupported FC speed %d\n", speed);
  752                         return 0;
  753                 }
  754 
  755                 switch (sli4->config.topology) {
  756                 case SLI4_READ_CFG_TOPO_FC:
  757                         /* Attempt P2P but failover to FC-AL */
  758                         init_link->link_flags.enable_topology_failover = TRUE;
  759 
  760                         if (sli_get_asic_type(sli4) == SLI4_ASIC_TYPE_LANCER)
  761                                 init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_FAIL_OVER;
  762                         else
  763                                 init_link->link_flags.topology = SLI4_INIT_LINK_F_P2P_FAIL_OVER;
  764 
  765                         break;
  766                 case SLI4_READ_CFG_TOPO_FC_AL:
  767                         init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_ONLY;
  768                         if ((init_link->link_speed_selection_code == FC_LINK_SPEED_16G) ||
  769                             (init_link->link_speed_selection_code == FC_LINK_SPEED_32G)) {
  770                                 ocs_log_test(sli4->os, "unsupported FC-AL speed %d\n", speed);
  771                                 return 0;
  772                         }
  773                         break;
  774                 case SLI4_READ_CFG_TOPO_FC_DA:
  775                         init_link->link_flags.topology = FC_TOPOLOGY_P2P;
  776                         break;
  777                 default:
  778                         ocs_log_test(sli4->os, "unsupported topology %#x\n", sli4->config.topology);
  779                         return 0;
  780                 }
  781 
  782                 init_link->link_flags.unfair = FALSE;
  783                 init_link->link_flags.skip_lirp_lilp = FALSE;
  784                 init_link->link_flags.gen_loop_validity_check = FALSE;
  785                 init_link->link_flags.skip_lisa = FALSE;
  786                 init_link->link_flags.select_hightest_al_pa = FALSE;
  787         }
  788 
  789         return sizeof(sli4_cmd_init_link_t);
  790 }
  791 
  792 /**
  793  * @ingroup sli
  794  * @brief Write an INIT_VFI command to the provided buffer.
  795  *
  796  * @param sli4 SLI context pointer.
  797  * @param buf Virtual pointer to the destination buffer.
  798  * @param size Buffer size, in bytes.
  799  * @param vfi VFI
  800  * @param fcfi FCFI
  801  * @param vpi VPI (Set to -1 if unused.)
  802  *
  803  * @return Returns the number of bytes written.
  804  */
  805 int32_t
  806 sli_cmd_init_vfi(sli4_t *sli4, void *buf, size_t size, uint16_t vfi,
  807                 uint16_t fcfi, uint16_t vpi)
  808 {
  809         sli4_cmd_init_vfi_t     *init_vfi = buf;
  810 
  811         ocs_memset(buf, 0, size);
  812 
  813         init_vfi->hdr.command = SLI4_MBOX_COMMAND_INIT_VFI;
  814 
  815         init_vfi->vfi = vfi;
  816         init_vfi->fcfi = fcfi;
  817 
  818         /*
  819          * If the VPI is valid, initialize it at the same time as
  820          * the VFI
  821          */
  822         if (0xffff != vpi) {
  823                 init_vfi->vp  = TRUE;
  824                 init_vfi->vpi = vpi;
  825         }
  826 
  827         return sizeof(sli4_cmd_init_vfi_t);
  828 }
  829 
  830 /**
  831  * @ingroup sli
  832  * @brief Write an INIT_VPI command to the provided buffer.
  833  *
  834  * @param sli4 SLI context pointer.
  835  * @param buf Virtual pointer to the destination buffer.
  836  * @param size Buffer size, in bytes.
  837  * @param vpi VPI allocated.
  838  * @param vfi VFI associated with this VPI.
  839  *
  840  * @return Returns the number of bytes written.
  841  */
  842 int32_t
  843 sli_cmd_init_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t vpi, uint16_t vfi)
  844 {
  845         sli4_cmd_init_vpi_t     *init_vpi = buf;
  846 
  847         ocs_memset(buf, 0, size);
  848 
  849         init_vpi->hdr.command = SLI4_MBOX_COMMAND_INIT_VPI;
  850         init_vpi->vpi = vpi;
  851         init_vpi->vfi = vfi;
  852 
  853         return sizeof(sli4_cmd_init_vpi_t);
  854 }
  855 
  856 /**
  857  * @ingroup sli
  858  * @brief Write a POST_XRI command to the provided buffer.
  859  *
  860  * @param sli4 SLI context pointer.
  861  * @param buf Virtual pointer to the destination buffer.
  862  * @param size Buffer size, in bytes.
  863  * @param xri_base Starting XRI value for range of XRI given to SLI Port.
  864  * @param xri_count Number of XRIs provided to the SLI Port.
  865  *
  866  * @return Returns the number of bytes written.
  867  */
  868 int32_t
  869 sli_cmd_post_xri(sli4_t *sli4, void *buf, size_t size,  uint16_t xri_base, uint16_t xri_count)
  870 {
  871         sli4_cmd_post_xri_t     *post_xri = buf;
  872 
  873         ocs_memset(buf, 0, size);
  874 
  875         post_xri->hdr.command = SLI4_MBOX_COMMAND_POST_XRI;
  876         post_xri->xri_base = xri_base;
  877         post_xri->xri_count = xri_count;
  878 
  879         if (sli4->config.auto_xfer_rdy == 0) {
  880                 post_xri->enx = TRUE;
  881                 post_xri->val = TRUE;
  882         }
  883 
  884         return sizeof(sli4_cmd_post_xri_t);
  885 }
  886 
  887 /**
  888  * @ingroup sli
  889  * @brief Write a RELEASE_XRI command to the provided buffer.
  890  *
  891  * @param sli4 SLI context pointer.
  892  * @param buf Virtual pointer to the destination buffer.
  893  * @param size Buffer size, in bytes.
  894  * @param num_xri The number of XRIs to be released.
  895  *
  896  * @return Returns the number of bytes written.
  897  */
  898 int32_t
  899 sli_cmd_release_xri(sli4_t *sli4, void *buf, size_t size,  uint8_t num_xri)
  900 {
  901         sli4_cmd_release_xri_t  *release_xri = buf;
  902 
  903         ocs_memset(buf, 0, size);
  904 
  905         release_xri->hdr.command = SLI4_MBOX_COMMAND_RELEASE_XRI;
  906         release_xri->xri_count = num_xri;
  907 
  908         return sizeof(sli4_cmd_release_xri_t);
  909 }
  910 
  911 /**
  912  * @brief Write a READ_CONFIG command to the provided buffer.
  913  *
  914  * @param sli4 SLI context pointer.
  915  * @param buf Virtual pointer to the destination buffer.
  916  * @param size Buffer size, in bytes
  917  *
  918  * @return Returns the number of bytes written.
  919  */
  920 static int32_t
  921 sli_cmd_read_config(sli4_t *sli4, void *buf, size_t size)
  922 {
  923         sli4_cmd_read_config_t  *read_config = buf;
  924 
  925         ocs_memset(buf, 0, size);
  926 
  927         read_config->hdr.command = SLI4_MBOX_COMMAND_READ_CONFIG;
  928 
  929         return sizeof(sli4_cmd_read_config_t);
  930 }
  931 
  932 /**
  933  * @brief Write a READ_NVPARMS command to the provided buffer.
  934  *
  935  * @param sli4 SLI context pointer.
  936  * @param buf Virtual pointer to the destination buffer.
  937  * @param size Buffer size, in bytes.
  938  *
  939  * @return Returns the number of bytes written.
  940  */
  941 int32_t
  942 sli_cmd_read_nvparms(sli4_t *sli4, void *buf, size_t size)
  943 {
  944         sli4_cmd_read_nvparms_t *read_nvparms = buf;
  945 
  946         ocs_memset(buf, 0, size);
  947 
  948         read_nvparms->hdr.command = SLI4_MBOX_COMMAND_READ_NVPARMS;
  949 
  950         return sizeof(sli4_cmd_read_nvparms_t);
  951 }
  952 
  953 /**
  954  * @brief Write a WRITE_NVPARMS command to the provided buffer.
  955  *
  956  * @param sli4 SLI context pointer.
  957  * @param buf Virtual pointer to the destination buffer.
  958  * @param size Buffer size, in bytes.
  959  * @param wwpn WWPN to write - pointer to array of 8 uint8_t.
  960  * @param wwnn WWNN to write - pointer to array of 8 uint8_t.
  961  * @param hard_alpa Hard ALPA to write.
  962  * @param preferred_d_id  Preferred D_ID to write.
  963  *
  964  * @return Returns the number of bytes written.
  965  */
  966 int32_t
  967 sli_cmd_write_nvparms(sli4_t *sli4, void *buf, size_t size, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
  968                 uint32_t preferred_d_id)
  969 {
  970         sli4_cmd_write_nvparms_t        *write_nvparms = buf;
  971 
  972         ocs_memset(buf, 0, size);
  973 
  974         write_nvparms->hdr.command = SLI4_MBOX_COMMAND_WRITE_NVPARMS;
  975         ocs_memcpy(write_nvparms->wwpn, wwpn, 8);
  976         ocs_memcpy(write_nvparms->wwnn, wwnn, 8);
  977         write_nvparms->hard_alpa = hard_alpa;
  978         write_nvparms->preferred_d_id = preferred_d_id;
  979 
  980         return sizeof(sli4_cmd_write_nvparms_t);
  981 }
  982 
  983 /**
  984  * @brief Write a READ_REV command to the provided buffer.
  985  *
  986  * @param sli4 SLI context pointer.
  987  * @param buf Virtual pointer to the destination buffer.
  988  * @param size Buffer size, in bytes.
  989  * @param vpd Pointer to the buffer.
  990  *
  991  * @return Returns the number of bytes written.
  992  */
  993 static int32_t
  994 sli_cmd_read_rev(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *vpd)
  995 {
  996         sli4_cmd_read_rev_t     *read_rev = buf;
  997 
  998         ocs_memset(buf, 0, size);
  999 
 1000         read_rev->hdr.command = SLI4_MBOX_COMMAND_READ_REV;
 1001 
 1002         if (vpd && vpd->size) {
 1003                 read_rev->vpd = TRUE;
 1004 
 1005                 read_rev->available_length = vpd->size;
 1006 
 1007                 read_rev->physical_address_low  = ocs_addr32_lo(vpd->phys);
 1008                 read_rev->physical_address_high = ocs_addr32_hi(vpd->phys);
 1009         }
 1010 
 1011         return sizeof(sli4_cmd_read_rev_t);
 1012 }
 1013 
 1014 /**
 1015  * @ingroup sli
 1016  * @brief Write a READ_SPARM64 command to the provided buffer.
 1017  *
 1018  * @param sli4 SLI context pointer.
 1019  * @param buf Virtual pointer to the destination buffer.
 1020  * @param size Buffer size, in bytes.
 1021  * @param dma DMA buffer for the service parameters.
 1022  * @param vpi VPI used to determine the WWN.
 1023  *
 1024  * @return Returns the number of bytes written.
 1025  */
 1026 int32_t
 1027 sli_cmd_read_sparm64(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 1028                 uint16_t vpi)
 1029 {
 1030         sli4_cmd_read_sparm64_t *read_sparm64 = buf;
 1031 
 1032         ocs_memset(buf, 0, size);
 1033 
 1034         if (SLI4_READ_SPARM64_VPI_SPECIAL == vpi) {
 1035                 ocs_log_test(sli4->os, "special VPI not supported!!!\n");
 1036                 return -1;
 1037         }
 1038 
 1039         if (!dma || !dma->phys) {
 1040                 ocs_log_test(sli4->os, "bad DMA buffer\n");
 1041                 return -1;
 1042         }
 1043 
 1044         read_sparm64->hdr.command = SLI4_MBOX_COMMAND_READ_SPARM64;
 1045 
 1046         read_sparm64->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
 1047         read_sparm64->bde_64.buffer_length = dma->size;
 1048         read_sparm64->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1049         read_sparm64->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1050 
 1051         read_sparm64->vpi = vpi;
 1052 
 1053         return sizeof(sli4_cmd_read_sparm64_t);
 1054 }
 1055 
 1056 /**
 1057  * @ingroup sli
 1058  * @brief Write a READ_TOPOLOGY command to the provided buffer.
 1059  *
 1060  * @param sli4 SLI context pointer.
 1061  * @param buf Virtual pointer to the destination buffer.
 1062  * @param size Buffer size, in bytes.
 1063  * @param dma DMA buffer for loop map (optional).
 1064  *
 1065  * @return Returns the number of bytes written.
 1066  */
 1067 int32_t
 1068 sli_cmd_read_topology(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 1069 {
 1070         sli4_cmd_read_topology_t *read_topo = buf;
 1071 
 1072         ocs_memset(buf, 0, size);
 1073 
 1074         read_topo->hdr.command = SLI4_MBOX_COMMAND_READ_TOPOLOGY;
 1075 
 1076         if (dma && dma->size) {
 1077                 if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) {
 1078                         ocs_log_test(sli4->os, "loop map buffer too small %jd\n",
 1079                                         dma->size);
 1080                         return 0;
 1081                 }
 1082 
 1083                 ocs_memset(dma->virt, 0, dma->size);
 1084 
 1085                 read_topo->bde_loop_map.bde_type = SLI4_BDE_TYPE_BDE_64;
 1086                 read_topo->bde_loop_map.buffer_length = dma->size;
 1087                 read_topo->bde_loop_map.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1088                 read_topo->bde_loop_map.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1089         }
 1090 
 1091         return sizeof(sli4_cmd_read_topology_t);
 1092 }
 1093 
 1094 /**
 1095  * @ingroup sli
 1096  * @brief Write a REG_FCFI command to the provided buffer.
 1097  *
 1098  * @param sli4 SLI context pointer.
 1099  * @param buf Virtual pointer to the destination buffer.
 1100  * @param size Buffer size, in bytes.
 1101  * @param index FCF index returned by READ_FCF_TABLE.
 1102  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
 1103  * @param vlan_id VLAN ID tag.
 1104  *
 1105  * @return Returns the number of bytes written.
 1106  */
 1107 int32_t
 1108 sli_cmd_reg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t index, sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG], uint16_t vlan_id)
 1109 {
 1110         sli4_cmd_reg_fcfi_t     *reg_fcfi = buf;
 1111         uint32_t                i;
 1112 
 1113         ocs_memset(buf, 0, size);
 1114 
 1115         reg_fcfi->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI;
 1116 
 1117         reg_fcfi->fcf_index = index;
 1118 
 1119         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
 1120                 switch(i) {
 1121                 case 0: reg_fcfi->rq_id_0 = rq_cfg[0].rq_id; break;
 1122                 case 1: reg_fcfi->rq_id_1 = rq_cfg[1].rq_id; break;
 1123                 case 2: reg_fcfi->rq_id_2 = rq_cfg[2].rq_id; break;
 1124                 case 3: reg_fcfi->rq_id_3 = rq_cfg[3].rq_id; break;
 1125                 }
 1126                 reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
 1127                 reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
 1128                 reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
 1129                 reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match;
 1130         }
 1131 
 1132         if (vlan_id) {
 1133                 reg_fcfi->vv = TRUE;
 1134                 reg_fcfi->vlan_tag = vlan_id;
 1135         }
 1136 
 1137         return sizeof(sli4_cmd_reg_fcfi_t);
 1138 }
 1139 
 1140 /**
 1141  * @brief Write REG_FCFI_MRQ to provided command buffer
 1142  *
 1143  * @param sli4 SLI context pointer.
 1144  * @param buf Virtual pointer to the destination buffer.
 1145  * @param size Buffer size, in bytes.
 1146  * @param fcf_index FCF index returned by READ_FCF_TABLE.
 1147  * @param vlan_id VLAN ID tag.
 1148  * @param rr_quant Round robin quanta if RQ selection policy is 2
 1149  * @param rq_selection_policy RQ selection policy
 1150  * @param num_rqs Array of count of RQs per filter
 1151  * @param rq_ids Array of RQ ids per filter
 1152  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
 1153  *
 1154  * @return returns 0 for success, a negative error code value for failure.
 1155  */
 1156 int32_t
 1157 sli_cmd_reg_fcfi_mrq(sli4_t *sli4, void *buf, size_t size, uint8_t mode,
 1158                      uint16_t fcf_index, uint16_t vlan_id, uint8_t rq_selection_policy,
 1159                      uint8_t mrq_bit_mask, uint16_t num_mrqs,
 1160                      sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG])
 1161 {
 1162         sli4_cmd_reg_fcfi_mrq_t *reg_fcfi_mrq = buf;
 1163         uint32_t i;
 1164 
 1165         ocs_memset(buf, 0, size);
 1166 
 1167         reg_fcfi_mrq->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI_MRQ;
 1168         if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) {
 1169                 reg_fcfi_mrq->fcf_index = fcf_index;
 1170                 if (vlan_id) {
 1171                         reg_fcfi_mrq->vv = TRUE;
 1172                         reg_fcfi_mrq->vlan_tag = vlan_id;
 1173                 }
 1174                 goto done;
 1175         }
 1176 
 1177         reg_fcfi_mrq->mode = mode;
 1178         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
 1179                 reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
 1180                 reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
 1181                 reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
 1182                 reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match;
 1183 
 1184                 switch(i) {
 1185                 case 3: reg_fcfi_mrq->rq_id_3 = rq_cfg[i].rq_id; break;
 1186                 case 2: reg_fcfi_mrq->rq_id_2 = rq_cfg[i].rq_id; break;
 1187                 case 1: reg_fcfi_mrq->rq_id_1 = rq_cfg[i].rq_id; break;
 1188                 case 0: reg_fcfi_mrq->rq_id_0 = rq_cfg[i].rq_id; break;
 1189                 }
 1190         }
 1191 
 1192         reg_fcfi_mrq->rq_selection_policy = rq_selection_policy;
 1193         reg_fcfi_mrq->mrq_filter_bitmask = mrq_bit_mask;
 1194         reg_fcfi_mrq->num_mrq_pairs = num_mrqs;
 1195 done:
 1196         return sizeof(sli4_cmd_reg_fcfi_mrq_t);
 1197 }
 1198 
 1199 /**
 1200  * @ingroup sli
 1201  * @brief Write a REG_RPI command to the provided buffer.
 1202  *
 1203  * @param sli4 SLI context pointer.
 1204  * @param buf Virtual pointer to the destination buffer.
 1205  * @param size Buffer size, in bytes.
 1206  * @param nport_id Remote F/N_Port_ID.
 1207  * @param rpi Previously-allocated Remote Port Indicator.
 1208  * @param vpi Previously-allocated Virtual Port Indicator.
 1209  * @param dma DMA buffer that contains the remote port's service parameters.
 1210  * @param update Boolean indicating an update to an existing RPI (TRUE)
 1211  * or a new registration (FALSE).
 1212  *
 1213  * @return Returns the number of bytes written.
 1214  */
 1215 int32_t
 1216 sli_cmd_reg_rpi(sli4_t *sli4, void *buf, size_t size, uint32_t nport_id, uint16_t rpi, 
 1217                         uint16_t vpi, ocs_dma_t *dma, uint8_t update,  uint8_t enable_t10_pi)
 1218 {
 1219         sli4_cmd_reg_rpi_t *reg_rpi = buf;
 1220 
 1221         ocs_memset(buf, 0, size);
 1222 
 1223         reg_rpi->hdr.command = SLI4_MBOX_COMMAND_REG_RPI;
 1224 
 1225         reg_rpi->rpi = rpi;
 1226         reg_rpi->remote_n_port_id = nport_id;
 1227         reg_rpi->upd = update;
 1228         reg_rpi->etow = enable_t10_pi;
 1229 
 1230         reg_rpi->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
 1231         reg_rpi->bde_64.buffer_length = SLI4_REG_RPI_BUF_LEN;
 1232         reg_rpi->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1233         reg_rpi->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1234 
 1235         reg_rpi->vpi = vpi;
 1236 
 1237         return sizeof(sli4_cmd_reg_rpi_t);
 1238 }
 1239 
 1240 /**
 1241  * @ingroup sli
 1242  * @brief Write a REG_VFI command to the provided buffer.
 1243  *
 1244  * @param sli4 SLI context pointer.
 1245  * @param buf Virtual pointer to the destination buffer.
 1246  * @param size Buffer size, in bytes.
 1247  * @param domain Pointer to the domain object.
 1248  *
 1249  * @return Returns the number of bytes written.
 1250  */
 1251 int32_t
 1252 sli_cmd_reg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain)
 1253 {
 1254         sli4_cmd_reg_vfi_t      *reg_vfi = buf;
 1255 
 1256         if (!sli4 || !buf || !domain) {
 1257                 return 0;
 1258         }
 1259 
 1260         ocs_memset(buf, 0, size);
 1261 
 1262         reg_vfi->hdr.command = SLI4_MBOX_COMMAND_REG_VFI;
 1263 
 1264         reg_vfi->vfi = domain->indicator;
 1265 
 1266         reg_vfi->fcfi = domain->fcf_indicator;
 1267 
 1268         /* TODO contents of domain->dma only valid if topo == FABRIC */
 1269         reg_vfi->sparm.bde_type = SLI4_BDE_TYPE_BDE_64;
 1270         reg_vfi->sparm.buffer_length = 0x70;
 1271         reg_vfi->sparm.u.data.buffer_address_low  = ocs_addr32_lo(domain->dma.phys);
 1272         reg_vfi->sparm.u.data.buffer_address_high = ocs_addr32_hi(domain->dma.phys);
 1273 
 1274         reg_vfi->e_d_tov = sli4->config.e_d_tov;
 1275         reg_vfi->r_a_tov = sli4->config.r_a_tov;
 1276 
 1277         reg_vfi->vp = TRUE;
 1278         reg_vfi->vpi = domain->sport->indicator;
 1279         ocs_memcpy(reg_vfi->wwpn, &domain->sport->sli_wwpn, sizeof(reg_vfi->wwpn));
 1280         reg_vfi->local_n_port_id = domain->sport->fc_id;
 1281 
 1282         return sizeof(sli4_cmd_reg_vfi_t);
 1283 }
 1284 
 1285 /**
 1286  * @ingroup sli
 1287  * @brief Write a REG_VPI command to the provided buffer.
 1288  *
 1289  * @param sli4 SLI context pointer.
 1290  * @param buf Virtual pointer to the destination buffer.
 1291  * @param size Buffer size, in bytes.
 1292  * @param sport Point to SLI Port object.
 1293  * @param update Boolean indicating whether to update the existing VPI (true)
 1294  * or create a new VPI (false).
 1295  *
 1296  * @return Returns the number of bytes written.
 1297  */
 1298 int32_t
 1299 sli_cmd_reg_vpi(sli4_t *sli4, void *buf, size_t size, ocs_sli_port_t *sport, uint8_t update)
 1300 {
 1301         sli4_cmd_reg_vpi_t      *reg_vpi = buf;
 1302 
 1303         if (!sli4 || !buf || !sport) {
 1304                 return 0;
 1305         }
 1306 
 1307         ocs_memset(buf, 0, size);
 1308 
 1309         reg_vpi->hdr.command = SLI4_MBOX_COMMAND_REG_VPI;
 1310 
 1311         reg_vpi->local_n_port_id = sport->fc_id;
 1312         reg_vpi->upd = update != 0;
 1313         ocs_memcpy(reg_vpi->wwpn, &sport->sli_wwpn, sizeof(reg_vpi->wwpn));
 1314         reg_vpi->vpi = sport->indicator;
 1315         reg_vpi->vfi = sport->domain->indicator;
 1316 
 1317         return sizeof(sli4_cmd_reg_vpi_t);
 1318 }
 1319 
 1320 /**
 1321  * @brief Write a REQUEST_FEATURES command to the provided buffer.
 1322  *
 1323  * @param sli4 SLI context pointer.
 1324  * @param buf Virtual pointer to the destination buffer.
 1325  * @param size Buffer size, in bytes.
 1326  * @param mask Features to request.
 1327  * @param query Use feature query mode (does not change FW).
 1328  *
 1329  * @return Returns the number of bytes written.
 1330  */
 1331 static int32_t
 1332 sli_cmd_request_features(sli4_t *sli4, void *buf, size_t size, sli4_features_t mask, uint8_t query)
 1333 {
 1334         sli4_cmd_request_features_t *features = buf;
 1335 
 1336         ocs_memset(buf, 0, size);
 1337 
 1338         features->hdr.command = SLI4_MBOX_COMMAND_REQUEST_FEATURES;
 1339 
 1340         if (query) {
 1341                 features->qry = TRUE;
 1342         }
 1343         features->command.dword = mask.dword;
 1344 
 1345         return sizeof(sli4_cmd_request_features_t);
 1346 }
 1347 
 1348 /**
 1349  * @ingroup sli
 1350  * @brief Write a SLI_CONFIG command to the provided buffer.
 1351  *
 1352  * @param sli4 SLI context pointer.
 1353  * @param buf Virtual pointer to the destination buffer.
 1354  * @param size Buffer size, in bytes.
 1355  * @param length Length in bytes of attached command.
 1356  * @param dma DMA buffer for non-embedded commands.
 1357  *
 1358  * @return Returns the number of bytes written.
 1359  */
 1360 int32_t
 1361 sli_cmd_sli_config(sli4_t *sli4, void *buf, size_t size, uint32_t length, ocs_dma_t *dma)
 1362 {
 1363         sli4_cmd_sli_config_t   *sli_config = NULL;
 1364 
 1365         if ((length > sizeof(sli_config->payload.embed)) && (dma == NULL)) {
 1366                 ocs_log_test(sli4->os, "length(%d) > payload(%ld)\n",
 1367                                 length, sizeof(sli_config->payload.embed));
 1368                 return -1;
 1369         }
 1370 
 1371         sli_config = buf;
 1372 
 1373         ocs_memset(buf, 0, size);
 1374 
 1375         sli_config->hdr.command = SLI4_MBOX_COMMAND_SLI_CONFIG;
 1376         if (NULL == dma) {
 1377                 sli_config->emb = TRUE;
 1378                 sli_config->payload_length = length;
 1379         } else {
 1380                 sli_config->emb = FALSE;
 1381 
 1382                 sli_config->pmd_count = 1;
 1383 
 1384                 sli_config->payload.mem.address_low = ocs_addr32_lo(dma->phys);
 1385                 sli_config->payload.mem.address_high = ocs_addr32_hi(dma->phys);
 1386                 sli_config->payload.mem.length = dma->size;
 1387                 sli_config->payload_length = dma->size;
 1388 #if defined(OCS_INCLUDE_DEBUG)
 1389                 /* save pointer to DMA for BMBX dumping purposes */
 1390                 sli4->bmbx_non_emb_pmd = dma;
 1391 #endif
 1392         }
 1393 
 1394         return offsetof(sli4_cmd_sli_config_t, payload.embed);
 1395 }
 1396 
 1397 /**
 1398  * @brief Initialize SLI Port control register.
 1399  *
 1400  * @param sli4 SLI context pointer.
 1401  * @param endian Endian value to write.
 1402  *
 1403  * @return Returns 0 on success, or a negative error code value on failure.
 1404  */
 1405 
 1406 static int32_t
 1407 sli_sliport_control(sli4_t *sli4, uint32_t endian)
 1408 {
 1409         uint32_t iter;
 1410         int32_t rc;
 1411 
 1412         rc = -1;
 1413 
 1414         /* Initialize port, endian */
 1415         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, endian | SLI4_SLIPORT_CONTROL_IP);
 1416 
 1417         for (iter = 0; iter < 3000; iter ++) {
 1418                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
 1419                 if (sli_fw_ready(sli4) == 1) {
 1420                         rc = 0;
 1421                         break;
 1422                 }
 1423         }
 1424 
 1425         if (rc != 0) {
 1426                 ocs_log_crit(sli4->os, "port failed to become ready after initialization\n");
 1427         }
 1428 
 1429         return rc;
 1430 }
 1431 
 1432 /**
 1433  * @ingroup sli
 1434  * @brief Write a UNREG_FCFI command to the provided buffer.
 1435  *
 1436  * @param sli4 SLI context pointer.
 1437  * @param buf Virtual pointer to the destination buffer.
 1438  * @param size Buffer size, in bytes.
 1439  * @param indicator Indicator value.
 1440  *
 1441  * @return Returns the number of bytes written.
 1442  */
 1443 int32_t
 1444 sli_cmd_unreg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator)
 1445 {
 1446         sli4_cmd_unreg_fcfi_t   *unreg_fcfi = buf;
 1447 
 1448         if (!sli4 || !buf) {
 1449                 return 0;
 1450         }
 1451 
 1452         ocs_memset(buf, 0, size);
 1453 
 1454         unreg_fcfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_FCFI;
 1455 
 1456         unreg_fcfi->fcfi = indicator;
 1457 
 1458         return sizeof(sli4_cmd_unreg_fcfi_t);
 1459 }
 1460 
 1461 /**
 1462  * @ingroup sli
 1463  * @brief Write an UNREG_RPI command to the provided buffer.
 1464  *
 1465  * @param sli4 SLI context pointer.
 1466  * @param buf Virtual pointer to the destination buffer.
 1467  * @param size Buffer size, in bytes.
 1468  * @param indicator Indicator value.
 1469  * @param which Type of unregister, such as node, port, domain, or FCF.
 1470  * @param fc_id FC address.
 1471  *
 1472  * @return Returns the number of bytes written.
 1473  */
 1474 int32_t
 1475 sli_cmd_unreg_rpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, sli4_resource_e which,
 1476                 uint32_t fc_id)
 1477 {
 1478         sli4_cmd_unreg_rpi_t    *unreg_rpi = buf;
 1479         uint8_t         index_indicator = 0;
 1480 
 1481         if (!sli4 || !buf) {
 1482                 return 0;
 1483         }
 1484 
 1485         ocs_memset(buf, 0, size);
 1486 
 1487         unreg_rpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_RPI;
 1488 
 1489         switch (which) {
 1490         case SLI_RSRC_FCOE_RPI:
 1491                 index_indicator = SLI4_UNREG_RPI_II_RPI;
 1492                 if (fc_id != UINT32_MAX) {
 1493                         unreg_rpi->dp = TRUE;
 1494                         unreg_rpi->destination_n_port_id = fc_id & 0x00ffffff;
 1495                 }
 1496                 break;
 1497         case SLI_RSRC_FCOE_VPI:
 1498                 index_indicator = SLI4_UNREG_RPI_II_VPI;
 1499                 break;
 1500         case SLI_RSRC_FCOE_VFI:
 1501                 index_indicator = SLI4_UNREG_RPI_II_VFI;
 1502                 break;
 1503         case SLI_RSRC_FCOE_FCFI:
 1504                 index_indicator = SLI4_UNREG_RPI_II_FCFI;
 1505                 break;
 1506         default:
 1507                 ocs_log_test(sli4->os, "unknown type %#x\n", which);
 1508                 return 0;
 1509         }
 1510 
 1511         unreg_rpi->ii = index_indicator;
 1512         unreg_rpi->index = indicator;
 1513 
 1514         return sizeof(sli4_cmd_unreg_rpi_t);
 1515 }
 1516 
 1517 /**
 1518  * @ingroup sli
 1519  * @brief Write an UNREG_VFI command to the provided buffer.
 1520  *
 1521  * @param sli4 SLI context pointer.
 1522  * @param buf Virtual pointer to the destination buffer.
 1523  * @param size Buffer size, in bytes.
 1524  * @param domain Pointer to the domain object
 1525  * @param which Type of unregister, such as domain, FCFI, or everything.
 1526  *
 1527  * @return Returns the number of bytes written.
 1528  */
 1529 int32_t
 1530 sli_cmd_unreg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain, uint32_t which)
 1531 {
 1532         sli4_cmd_unreg_vfi_t    *unreg_vfi = buf;
 1533 
 1534         if (!sli4 || !buf || !domain) {
 1535                 return 0;
 1536         }
 1537 
 1538         ocs_memset(buf, 0, size);
 1539 
 1540         unreg_vfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VFI;
 1541         switch (which) {
 1542         case SLI4_UNREG_TYPE_DOMAIN:
 1543                 unreg_vfi->index = domain->indicator;
 1544                 break;
 1545         case SLI4_UNREG_TYPE_FCF:
 1546                 unreg_vfi->index = domain->fcf_indicator;
 1547                 break;
 1548         case SLI4_UNREG_TYPE_ALL:
 1549                 unreg_vfi->index = UINT16_MAX;
 1550                 break;
 1551         default:
 1552                 return 0;
 1553         }
 1554 
 1555         if (SLI4_UNREG_TYPE_DOMAIN != which) {
 1556                 unreg_vfi->ii = SLI4_UNREG_VFI_II_FCFI;
 1557         }
 1558 
 1559         return sizeof(sli4_cmd_unreg_vfi_t);
 1560 }
 1561 
 1562 /**
 1563  * @ingroup sli
 1564  * @brief Write an UNREG_VPI command to the provided buffer.
 1565  *
 1566  * @param sli4 SLI context pointer.
 1567  * @param buf Virtual pointer to the destination buffer.
 1568  * @param size Buffer size, in bytes.
 1569  * @param indicator Indicator value.
 1570  * @param which Type of unregister: port, domain, FCFI, everything
 1571  *
 1572  * @return Returns the number of bytes written.
 1573  */
 1574 int32_t
 1575 sli_cmd_unreg_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, uint32_t which)
 1576 {
 1577         sli4_cmd_unreg_vpi_t    *unreg_vpi = buf;
 1578 
 1579         if (!sli4 || !buf) {
 1580                 return 0;
 1581         }
 1582 
 1583         ocs_memset(buf, 0, size);
 1584 
 1585         unreg_vpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VPI;
 1586         unreg_vpi->index = indicator;
 1587         switch (which) {
 1588         case SLI4_UNREG_TYPE_PORT:
 1589                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VPI;
 1590                 break;
 1591         case SLI4_UNREG_TYPE_DOMAIN:
 1592                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VFI;
 1593                 break;
 1594         case SLI4_UNREG_TYPE_FCF:
 1595                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
 1596                 break;
 1597         case SLI4_UNREG_TYPE_ALL:
 1598                 unreg_vpi->index = UINT16_MAX;  /* override indicator */
 1599                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
 1600                 break;
 1601         default:
 1602                 return 0;
 1603         }
 1604 
 1605         return sizeof(sli4_cmd_unreg_vpi_t);
 1606 }
 1607 
 1608 /**
 1609  * @ingroup sli
 1610  * @brief Write an CONFIG_AUTO_XFER_RDY command to the provided buffer.
 1611  *
 1612  * @param sli4 SLI context pointer.
 1613  * @param buf Virtual pointer to the destination buffer.
 1614  * @param size Buffer size, in bytes.
 1615  * @param max_burst_len if the write FCP_DL is less than this size,
 1616  * then the SLI port will generate the auto XFER_RDY.
 1617  *
 1618  * @return Returns the number of bytes written.
 1619  */
 1620 int32_t
 1621 sli_cmd_config_auto_xfer_rdy(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len)
 1622 {
 1623         sli4_cmd_config_auto_xfer_rdy_t *req = buf;
 1624 
 1625         if (!sli4 || !buf) {
 1626                 return 0;
 1627         }
 1628 
 1629         ocs_memset(buf, 0, size);
 1630 
 1631         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY;
 1632         req->max_burst_len = max_burst_len;
 1633 
 1634         return sizeof(sli4_cmd_config_auto_xfer_rdy_t);
 1635 }
 1636 
 1637 /**
 1638  * @ingroup sli
 1639  * @brief Write an CONFIG_AUTO_XFER_RDY_HP command to the provided buffer.
 1640  *
 1641  * @param sli4 SLI context pointer.
 1642  * @param buf Virtual pointer to the destination buffer.
 1643  * @param size Buffer size, in bytes.
 1644  * @param max_burst_len if the write FCP_DL is less than this size,
 1645  * @param esoc enable start offset computation,
 1646  * @param block_size block size,
 1647  * then the SLI port will generate the auto XFER_RDY.
 1648  *
 1649  * @return Returns the number of bytes written.
 1650  */
 1651 int32_t
 1652 sli_cmd_config_auto_xfer_rdy_hp(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len,
 1653                                                 uint32_t esoc, uint32_t block_size )
 1654 {
 1655         sli4_cmd_config_auto_xfer_rdy_hp_t      *req = buf;
 1656 
 1657         if (!sli4 || !buf) {
 1658                 return 0;
 1659         }
 1660 
 1661         ocs_memset(buf, 0, size);
 1662 
 1663         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY_HP;
 1664         req->max_burst_len = max_burst_len;
 1665         req->esoc = esoc;
 1666         req->block_size = block_size;
 1667         return sizeof(sli4_cmd_config_auto_xfer_rdy_hp_t);
 1668 }
 1669 
 1670 /**
 1671  * @brief Write a COMMON_FUNCTION_RESET command.
 1672  *
 1673  * @param sli4 SLI context.
 1674  * @param buf Destination buffer for the command.
 1675  * @param size Buffer size, in bytes.
 1676  *
 1677  * @return Returns the number of bytes written.
 1678  */
 1679 static int32_t
 1680 sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size)
 1681 {
 1682         sli4_req_common_function_reset_t *reset = NULL;
 1683         uint32_t        sli_config_off = 0;
 1684 
 1685         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1686                 uint32_t payload_size;
 1687 
 1688                 /* Payload length must accommodate both request and response */
 1689                 payload_size = max(sizeof(sli4_req_common_function_reset_t),
 1690                                 sizeof(sli4_res_common_function_reset_t));
 1691 
 1692                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 1693                                 NULL);
 1694         }
 1695         reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + sli_config_off);
 1696 
 1697         reset->hdr.opcode = SLI4_OPC_COMMON_FUNCTION_RESET;
 1698         reset->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1699 
 1700         return(sli_config_off + sizeof(sli4_req_common_function_reset_t));
 1701 }
 1702 
 1703 /**
 1704  * @brief Write a COMMON_CREATE_CQ command.
 1705  *
 1706  * @param sli4 SLI context.
 1707  * @param buf Destination buffer for the command.
 1708  * @param size Buffer size, in bytes.
 1709  * @param qmem DMA memory for the queue.
 1710  * @param eq_id Associated EQ_ID
 1711  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
 1712  *
 1713  * @note This creates a Version 0 message.
 1714  *
 1715  * @return Returns the number of bytes written.
 1716  */
 1717 static int32_t
 1718 sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size,
 1719                 ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
 1720 {
 1721         sli4_req_common_create_cq_v0_t  *cqv0 = NULL;
 1722         sli4_req_common_create_cq_v2_t  *cqv2 = NULL;
 1723         uint32_t        sli_config_off = 0;
 1724         uint32_t        p;
 1725         uintptr_t       addr;
 1726         uint32_t        if_type = sli4->if_type;
 1727         uint32_t        page_bytes = 0;
 1728         uint32_t        num_pages = 0;
 1729         uint32_t        cmd_size = 0;
 1730         uint32_t        page_size = 0;
 1731         uint32_t        n_cqe = 0;
 1732 
 1733         /* First calculate number of pages and the mailbox cmd length */
 1734         switch (if_type)
 1735         {
 1736         case SLI4_IF_TYPE_BE3_SKH_PF:
 1737                 page_bytes = SLI_PAGE_SIZE;
 1738                 num_pages = sli_page_count(qmem->size, page_bytes);
 1739                 cmd_size = sizeof(sli4_req_common_create_cq_v0_t) + (8 * num_pages);
 1740                 break;
 1741         case SLI4_IF_TYPE_LANCER_FC_ETH:
 1742                 n_cqe = qmem->size / SLI4_CQE_BYTES;
 1743                 switch (n_cqe) {
 1744                 case 256:
 1745                 case 512:
 1746                 case 1024:
 1747                 case 2048:
 1748                         page_size = 1;
 1749                         break;
 1750                 case 4096:
 1751                         page_size = 2;
 1752                         break;
 1753                 default:
 1754                         return 0;
 1755                 }
 1756                 page_bytes = page_size * SLI_PAGE_SIZE;
 1757                 num_pages = sli_page_count(qmem->size, page_bytes);
 1758                 cmd_size = sizeof(sli4_req_common_create_cq_v2_t) + (8 * num_pages);
 1759                 break;
 1760         default:
 1761                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type);
 1762                 return -1;
 1763         }
 1764 
 1765         /* now that we have the mailbox command size, we can set SLI_CONFIG fields */
 1766         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1767                 uint32_t payload_size;
 1768 
 1769                 /* Payload length must accommodate both request and response */
 1770                 payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_t));
 1771 
 1772                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 1773                                 NULL);
 1774         }
 1775 
 1776         switch (if_type)
 1777         {
 1778         case SLI4_IF_TYPE_BE3_SKH_PF:
 1779                 cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + sli_config_off);
 1780                 cqv0->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
 1781                 cqv0->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1782                 cqv0->hdr.version = 0;
 1783                 cqv0->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 1784 
 1785                 /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
 1786                 cqv0->num_pages = num_pages;
 1787                 switch (cqv0->num_pages) {
 1788                 case 1:
 1789                         cqv0->cqecnt = SLI4_CQ_CNT_256;
 1790                         break;
 1791                 case 2:
 1792                         cqv0->cqecnt = SLI4_CQ_CNT_512;
 1793                         break;
 1794                 case 4:
 1795                         cqv0->cqecnt = SLI4_CQ_CNT_1024;
 1796                         break;
 1797                 default:
 1798                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv0->num_pages);
 1799                         return -1;
 1800                 }
 1801                 cqv0->evt = TRUE;
 1802                 cqv0->valid = TRUE;
 1803                 /* TODO cq->nodelay = ???; */
 1804                 /* TODO cq->clswm = ???; */
 1805                 cqv0->arm = FALSE;
 1806                 cqv0->eq_id = eq_id;
 1807 
 1808                 for (p = 0, addr = qmem->phys;
 1809                                 p < cqv0->num_pages;
 1810                                 p++, addr += page_bytes) {
 1811                         cqv0->page_physical_address[p].low = ocs_addr32_lo(addr);
 1812                         cqv0->page_physical_address[p].high = ocs_addr32_hi(addr);
 1813                 }
 1814 
 1815                 break;
 1816         case SLI4_IF_TYPE_LANCER_FC_ETH:
 1817         {
 1818                 cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + sli_config_off);
 1819                 cqv2->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
 1820                 cqv2->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1821                 cqv2->hdr.version = 2;
 1822                 cqv2->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 1823 
 1824                 cqv2->page_size = page_size;
 1825 
 1826                 /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */
 1827                 cqv2->num_pages = num_pages;
 1828                 if (!cqv2->num_pages || (cqv2->num_pages > SLI4_COMMON_CREATE_CQ_V2_MAX_PAGES)) {
 1829                         return 0;
 1830                 }
 1831 
 1832                 switch (cqv2->num_pages) {
 1833                 case 1:
 1834                         cqv2->cqecnt = SLI4_CQ_CNT_256;
 1835                         break;
 1836                 case 2:
 1837                         cqv2->cqecnt = SLI4_CQ_CNT_512;
 1838                         break;
 1839                 case 4:
 1840                         cqv2->cqecnt = SLI4_CQ_CNT_1024;
 1841                         break;
 1842                 case 8:
 1843                         cqv2->cqecnt = SLI4_CQ_CNT_LARGE;
 1844                         cqv2->cqe_count = n_cqe;
 1845                         break;
 1846                 default:
 1847                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv2->num_pages);
 1848                         return -1;
 1849                 }
 1850 
 1851                 cqv2->evt = TRUE;
 1852                 cqv2->valid = TRUE;
 1853                 /* TODO cq->nodelay = ???; */
 1854                 /* TODO cq->clswm = ???; */
 1855                 cqv2->arm = FALSE;
 1856                 cqv2->eq_id = eq_id;
 1857 
 1858                 for (p = 0, addr = qmem->phys;
 1859                                 p < cqv2->num_pages;
 1860                                 p++, addr += page_bytes) {
 1861                         cqv2->page_physical_address[p].low = ocs_addr32_lo(addr);
 1862                         cqv2->page_physical_address[p].high = ocs_addr32_hi(addr);
 1863                 }
 1864         }
 1865                 break;
 1866         }       
 1867 
 1868         return (sli_config_off + cmd_size);
 1869 }
 1870 
 1871 /**
 1872  * @brief Write a COMMON_DESTROY_CQ command.
 1873  *
 1874  * @param sli4 SLI context.
 1875  * @param buf Destination buffer for the command.
 1876  * @param size Buffer size, in bytes.
 1877  * @param cq_id CQ ID
 1878  *
 1879  * @note This creates a Version 0 message.
 1880  *
 1881  * @return Returns the number of bytes written.
 1882  */
 1883 static int32_t
 1884 sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint16_t cq_id)
 1885 {
 1886         sli4_req_common_destroy_cq_t    *cq = NULL;
 1887         uint32_t        sli_config_off = 0;
 1888 
 1889         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1890                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 1891                                 /* Payload length must accommodate both request and response */
 1892                                 max(sizeof(sli4_req_common_destroy_cq_t),
 1893                                         sizeof(sli4_res_hdr_t)),
 1894                                 NULL);
 1895         }
 1896         cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + sli_config_off);
 1897 
 1898         cq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_CQ;
 1899         cq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1900         cq->hdr.request_length = sizeof(sli4_req_common_destroy_cq_t) -
 1901                                         sizeof(sli4_req_hdr_t);
 1902         cq->cq_id = cq_id;
 1903 
 1904         return(sli_config_off + sizeof(sli4_req_common_destroy_cq_t));
 1905 }
 1906 
 1907 /**
 1908  * @brief Write a COMMON_MODIFY_EQ_DELAY command.
 1909  *
 1910  * @param sli4 SLI context.
 1911  * @param buf Destination buffer for the command.
 1912  * @param size Buffer size, in bytes.
 1913  * @param q Queue object array.
 1914  * @param num_q Queue object array count.
 1915  * @param shift Phase shift for staggering interrupts.
 1916  * @param delay_mult Delay multiplier for limiting interrupt frequency.
 1917  *
 1918  * @return Returns the number of bytes written.
 1919  */
 1920 static int32_t
 1921 sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift,
 1922                                 uint32_t delay_mult)
 1923 {
 1924         sli4_req_common_modify_eq_delay_t *modify_delay = NULL;
 1925         uint32_t        sli_config_off = 0;
 1926         int i;
 1927 
 1928         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1929                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 1930                                 /* Payload length must accommodate both request and response */
 1931                                 max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)),
 1932                                 NULL);
 1933         }
 1934 
 1935         modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + sli_config_off);
 1936 
 1937         modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY;
 1938         modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1939         modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) -
 1940                                         sizeof(sli4_req_hdr_t);
 1941 
 1942         modify_delay->num_eq = num_q;
 1943 
 1944         for (i = 0; i<num_q; i++) {
 1945                 modify_delay->eq_delay_record[i].eq_id = q[i].id;
 1946                 modify_delay->eq_delay_record[i].phase = shift;
 1947                 modify_delay->eq_delay_record[i].delay_multiplier = delay_mult;
 1948         }
 1949 
 1950         return(sli_config_off + sizeof(sli4_req_common_modify_eq_delay_t));
 1951 }
 1952 
 1953 /**
 1954  * @brief Write a COMMON_CREATE_EQ command.
 1955  *
 1956  * @param sli4 SLI context.
 1957  * @param buf Destination buffer for the command.
 1958  * @param size Buffer size, in bytes.
 1959  * @param qmem DMA memory for the queue.
 1960  * @param ignored1 Ignored (used for consistency among queue creation functions).
 1961  * @param ignored2 Ignored (used for consistency among queue creation functions).
 1962  *
 1963  * @note Other queue creation routines use the last parameter to pass in
 1964  * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP,
 1965  * so these parameters are ignored
 1966  *
 1967  * @note This creates a Version 0 message
 1968  *
 1969  * @return Returns the number of bytes written.
 1970  */
 1971 static int32_t
 1972 sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
 1973                 uint16_t ignored1, uint16_t ignored2)
 1974 {
 1975         sli4_req_common_create_eq_t     *eq = NULL;
 1976         uint32_t        sli_config_off = 0;
 1977         uint32_t        p;
 1978         uintptr_t       addr;
 1979 
 1980         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1981                 uint32_t payload_size;
 1982 
 1983                 /* Payload length must accommodate both request and response */
 1984                 payload_size = max(sizeof(sli4_req_common_create_eq_t),
 1985                                 sizeof(sli4_res_common_create_queue_t));
 1986 
 1987                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 1988                                 NULL);
 1989         }
 1990         eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + sli_config_off);
 1991 
 1992         eq->hdr.opcode = SLI4_OPC_COMMON_CREATE_EQ;
 1993         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1994         eq->hdr.request_length = sizeof(sli4_req_common_create_eq_t) -
 1995                                         sizeof(sli4_req_hdr_t);
 1996         /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
 1997         eq->num_pages = qmem->size / SLI_PAGE_SIZE;
 1998         switch (eq->num_pages) {
 1999         case 1:
 2000                 eq->eqesz = SLI4_EQE_SIZE_4;
 2001                 eq->count = SLI4_EQ_CNT_1024;
 2002                 break;
 2003         case 2:
 2004                 eq->eqesz = SLI4_EQE_SIZE_4;
 2005                 eq->count = SLI4_EQ_CNT_2048;
 2006                 break;
 2007         case 4:
 2008                 eq->eqesz = SLI4_EQE_SIZE_4;
 2009                 eq->count = SLI4_EQ_CNT_4096;
 2010                 break;
 2011         default:
 2012                 ocs_log_test(sli4->os, "num_pages %d not valid\n", eq->num_pages);
 2013                 return -1;
 2014         }
 2015         eq->valid = TRUE;
 2016         eq->arm = FALSE;
 2017         eq->delay_multiplier = 32;
 2018 
 2019         for (p = 0, addr = qmem->phys;
 2020                         p < eq->num_pages;
 2021                         p++, addr += SLI_PAGE_SIZE) {
 2022                 eq->page_address[p].low = ocs_addr32_lo(addr);
 2023                 eq->page_address[p].high = ocs_addr32_hi(addr);
 2024         }
 2025 
 2026         return(sli_config_off + sizeof(sli4_req_common_create_eq_t));
 2027 }
 2028 
 2029 /**
 2030  * @brief Write a COMMON_DESTROY_EQ command.
 2031  *
 2032  * @param sli4 SLI context.
 2033  * @param buf Destination buffer for the command.
 2034  * @param size Buffer size, in bytes.
 2035  * @param eq_id Queue ID to destroy.
 2036  *
 2037  * @note Other queue creation routines use the last parameter to pass in
 2038  * the associated Q_ID. EQ doesn't have an associated queue so this
 2039  * parameter is ignored.
 2040  *
 2041  * @note This creates a Version 0 message.
 2042  *
 2043  * @return Returns the number of bytes written.
 2044  */
 2045 static int32_t
 2046 sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint16_t eq_id)
 2047 {
 2048         sli4_req_common_destroy_eq_t    *eq = NULL;
 2049         uint32_t        sli_config_off = 0;
 2050 
 2051         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2052                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2053                                 /* Payload length must accommodate both request and response */
 2054                                 max(sizeof(sli4_req_common_destroy_eq_t),
 2055                                         sizeof(sli4_res_hdr_t)),
 2056                                 NULL);
 2057         }
 2058         eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + sli_config_off);
 2059 
 2060         eq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_EQ;
 2061         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2062         eq->hdr.request_length = sizeof(sli4_req_common_destroy_eq_t) -
 2063                                         sizeof(sli4_req_hdr_t);
 2064 
 2065         eq->eq_id = eq_id;
 2066 
 2067         return(sli_config_off + sizeof(sli4_req_common_destroy_eq_t));
 2068 }
 2069 
 2070 /**
 2071  * @brief Write a LOWLEVEL_SET_WATCHDOG command.
 2072  *
 2073  * @param sli4 SLI context.
 2074  * @param buf Destination buffer for the command.
 2075  * @param size Buffer size, in bytes.
 2076  * @param timeout watchdog timer timeout in seconds
 2077  *
 2078  * @return void
 2079  */
 2080 void
 2081 sli4_cmd_lowlevel_set_watchdog(sli4_t *sli4, void *buf, size_t size, uint16_t timeout)
 2082 {
 2083 
 2084         sli4_req_lowlevel_set_watchdog_t *req = NULL;
 2085         uint32_t        sli_config_off = 0;
 2086 
 2087         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2088                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2089                                 /* Payload length must accommodate both request and response */
 2090                                 max(sizeof(sli4_req_lowlevel_set_watchdog_t),
 2091                                         sizeof(sli4_res_lowlevel_set_watchdog_t)),
 2092                                 NULL);
 2093         }
 2094         req = (sli4_req_lowlevel_set_watchdog_t *)((uint8_t *)buf + sli_config_off);
 2095 
 2096         req->hdr.opcode = SLI4_OPC_LOWLEVEL_SET_WATCHDOG;
 2097         req->hdr.subsystem = SLI4_SUBSYSTEM_LOWLEVEL;
 2098         req->hdr.request_length = sizeof(sli4_req_lowlevel_set_watchdog_t) - sizeof(sli4_req_hdr_t);
 2099         req->watchdog_timeout = timeout;
 2100 
 2101         return;
 2102 }
 2103 
 2104 static int32_t
 2105 sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2106 {
 2107         sli4_req_hdr_t *hdr = NULL;
 2108         uint32_t        sli_config_off = 0;
 2109 
 2110         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2111                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2112                                 sizeof(sli4_req_hdr_t),
 2113                                 dma);
 2114         }
 2115 
 2116         if (dma == NULL) {
 2117                 return 0;
 2118         }
 2119 
 2120         ocs_memset(dma->virt, 0, dma->size);
 2121 
 2122         hdr = dma->virt;
 2123 
 2124         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES;
 2125         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2126         hdr->request_length = dma->size;
 2127 
 2128         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2129 }
 2130 
 2131 /**
 2132  * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command.
 2133  *
 2134  * @param sli4 SLI context.
 2135  * @param buf Destination buffer for the command.
 2136  * @param size Buffer size, in bytes.
 2137  * @param dma DMA structure from which the data will be copied.
 2138  *
 2139  * @note This creates a Version 0 message.
 2140  *
 2141  * @return Returns the number of bytes written.
 2142  */
 2143 static int32_t
 2144 sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2145 {
 2146         sli4_req_hdr_t *hdr = NULL;
 2147         uint32_t        sli_config_off = 0;
 2148 
 2149         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2150                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, sizeof(sli4_req_hdr_t), dma);
 2151         }
 2152 
 2153         if (dma == NULL) {
 2154                 return 0;
 2155         }
 2156 
 2157         ocs_memset(dma->virt, 0, dma->size);
 2158 
 2159         hdr = dma->virt;
 2160 
 2161         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES;
 2162         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2163         hdr->request_length = dma->size;
 2164 
 2165         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2166 }
 2167 
 2168 /**
 2169  * @brief Write a COMMON_CREATE_MQ_EXT command.
 2170  *
 2171  * @param sli4 SLI context.
 2172  * @param buf Destination buffer for the command.
 2173  * @param size Buffer size, in bytes.
 2174  * @param qmem DMA memory for the queue.
 2175  * @param cq_id Associated CQ_ID.
 2176  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
 2177  *
 2178  * @note This creates a Version 0 message.
 2179  *
 2180  * @return Returns the number of bytes written.
 2181  */
 2182 static int32_t
 2183 sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size,
 2184                              ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
 2185 {
 2186         sli4_req_common_create_mq_ext_t *mq = NULL;
 2187         uint32_t        sli_config_off = 0;
 2188         uint32_t        p;
 2189         uintptr_t       addr;
 2190 
 2191         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2192                 uint32_t payload_size;
 2193 
 2194                 /* Payload length must accommodate both request and response */
 2195                 payload_size = max(sizeof(sli4_req_common_create_mq_ext_t),
 2196                                 sizeof(sli4_res_common_create_queue_t));
 2197 
 2198                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 2199                                 NULL);
 2200         }
 2201         mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + sli_config_off);
 2202 
 2203         mq->hdr.opcode = SLI4_OPC_COMMON_CREATE_MQ_EXT;
 2204         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2205         mq->hdr.request_length = sizeof(sli4_req_common_create_mq_ext_t) -
 2206                                         sizeof(sli4_req_hdr_t);
 2207         /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
 2208         mq->num_pages = qmem->size / SLI_PAGE_SIZE;
 2209         switch (mq->num_pages) {
 2210         case 1:
 2211                 mq->ring_size = SLI4_MQE_SIZE_16;
 2212                 break;
 2213         case 2:
 2214                 mq->ring_size = SLI4_MQE_SIZE_32;
 2215                 break;
 2216         case 4:
 2217                 mq->ring_size = SLI4_MQE_SIZE_64;
 2218                 break;
 2219         case 8:
 2220                 mq->ring_size = SLI4_MQE_SIZE_128;
 2221                 break;
 2222         default:
 2223                 ocs_log_test(sli4->os, "num_pages %d not valid\n", mq->num_pages);
 2224                 return -1;
 2225         }
 2226 
 2227         /* TODO break this down by sli4->config.topology */
 2228         mq->async_event_bitmap = SLI4_ASYNC_EVT_FC_FCOE;
 2229 
 2230         if (sli4->config.mq_create_version) {
 2231                 mq->cq_id_v1 = cq_id;
 2232                 mq->hdr.version = 1;
 2233         }
 2234         else {
 2235                 mq->cq_id_v0 = cq_id;
 2236         }
 2237         mq->val = TRUE;
 2238 
 2239         for (p = 0, addr = qmem->phys;
 2240                         p < mq->num_pages;
 2241                         p++, addr += SLI_PAGE_SIZE) {
 2242                 mq->page_physical_address[p].low = ocs_addr32_lo(addr);
 2243                 mq->page_physical_address[p].high = ocs_addr32_hi(addr);
 2244         }
 2245 
 2246         return(sli_config_off + sizeof(sli4_req_common_create_mq_ext_t));
 2247 }
 2248 
 2249 /**
 2250  * @brief Write a COMMON_DESTROY_MQ command.
 2251  *
 2252  * @param sli4 SLI context.
 2253  * @param buf Destination buffer for the command.
 2254  * @param size Buffer size, in bytes.
 2255  * @param mq_id MQ ID
 2256  *
 2257  * @note This creates a Version 0 message.
 2258  *
 2259  * @return Returns the number of bytes written.
 2260  */
 2261 static int32_t
 2262 sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint16_t mq_id)
 2263 {
 2264         sli4_req_common_destroy_mq_t    *mq = NULL;
 2265         uint32_t        sli_config_off = 0;
 2266 
 2267         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2268                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2269                                 /* Payload length must accommodate both request and response */
 2270                                 max(sizeof(sli4_req_common_destroy_mq_t),
 2271                                         sizeof(sli4_res_hdr_t)),
 2272                                 NULL);
 2273         }
 2274         mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + sli_config_off);
 2275 
 2276         mq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_MQ;
 2277         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2278         mq->hdr.request_length = sizeof(sli4_req_common_destroy_mq_t) -
 2279                                         sizeof(sli4_req_hdr_t);
 2280 
 2281         mq->mq_id = mq_id;
 2282 
 2283         return(sli_config_off + sizeof(sli4_req_common_destroy_mq_t));
 2284 }
 2285 
 2286 /**
 2287  * @ingroup sli
 2288  * @brief Write a COMMON_NOP command
 2289  *
 2290  * @param sli4 SLI context.
 2291  * @param buf Destination buffer for the command.
 2292  * @param size Buffer size, in bytes.
 2293  * @param context NOP context value (passed to response, except on FC/FCoE).
 2294  *
 2295  * @return Returns the number of bytes written.
 2296  */
 2297 int32_t
 2298 sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t context)
 2299 {
 2300         sli4_req_common_nop_t *nop = NULL;
 2301         uint32_t        sli_config_off = 0;
 2302 
 2303         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2304                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2305                                 /* Payload length must accommodate both request and response */
 2306                                 max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)),
 2307                                 NULL);
 2308         }
 2309 
 2310         nop = (sli4_req_common_nop_t *)((uint8_t *)buf + sli_config_off);
 2311 
 2312         nop->hdr.opcode = SLI4_OPC_COMMON_NOP;
 2313         nop->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2314         nop->hdr.request_length = 8;
 2315 
 2316         ocs_memcpy(&nop->context, &context, sizeof(context));
 2317 
 2318         return(sli_config_off + sizeof(sli4_req_common_nop_t));
 2319 }
 2320 
 2321 /**
 2322  * @ingroup sli
 2323  * @brief Write a COMMON_GET_RESOURCE_EXTENT_INFO command.
 2324  *
 2325  * @param sli4 SLI context.
 2326  * @param buf Destination buffer for the command.
 2327  * @param size Buffer size, in bytes.
 2328  * @param rtype Resource type (for example, XRI, VFI, VPI, and RPI).
 2329  *
 2330  * @return Returns the number of bytes written.
 2331  */
 2332 int32_t
 2333 sli_cmd_common_get_resource_extent_info(sli4_t *sli4, void *buf, size_t size, uint16_t rtype)
 2334 {
 2335         sli4_req_common_get_resource_extent_info_t *extent = NULL;
 2336         uint32_t        sli_config_off = 0;
 2337 
 2338         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2339                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2340                                 sizeof(sli4_req_common_get_resource_extent_info_t),
 2341                                 NULL);
 2342         }
 2343 
 2344         extent = (sli4_req_common_get_resource_extent_info_t *)((uint8_t *)buf + sli_config_off);
 2345 
 2346         extent->hdr.opcode = SLI4_OPC_COMMON_GET_RESOURCE_EXTENT_INFO;
 2347         extent->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2348         extent->hdr.request_length = 4;
 2349 
 2350         extent->resource_type = rtype;
 2351 
 2352         return(sli_config_off + sizeof(sli4_req_common_get_resource_extent_info_t));
 2353 }
 2354 
 2355 /**
 2356  * @ingroup sli
 2357  * @brief Write a COMMON_GET_SLI4_PARAMETERS command.
 2358  *
 2359  * @param sli4 SLI context.
 2360  * @param buf Destination buffer for the command.
 2361  * @param size Buffer size, in bytes.
 2362  *
 2363  * @return Returns the number of bytes written.
 2364  */
 2365 int32_t
 2366 sli_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
 2367 {
 2368         sli4_req_hdr_t  *hdr = NULL;
 2369         uint32_t        sli_config_off = 0;
 2370 
 2371         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2372                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2373                                 sizeof(sli4_res_common_get_sli4_parameters_t),
 2374                                 NULL);
 2375         }
 2376 
 2377         hdr = (sli4_req_hdr_t *)((uint8_t *)buf + sli_config_off);
 2378 
 2379         hdr->opcode = SLI4_OPC_COMMON_GET_SLI4_PARAMETERS;
 2380         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2381         hdr->request_length = 0x50;
 2382 
 2383         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2384 }
 2385 
 2386 /**
 2387  * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
 2388  *
 2389  * @param sli4 SLI context pointer.
 2390  * @param buf Virtual pointer to destination buffer.
 2391  * @param size Buffer size in bytes.
 2392  *
 2393  * @return Returns the number of bytes written
 2394  */
 2395 static int32_t
 2396 sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
 2397 {
 2398         sli4_req_common_query_fw_config_t   *fw_config;
 2399         uint32_t        sli_config_off = 0;
 2400         uint32_t payload_size;
 2401 
 2402         /* Payload length must accommodate both request and response */
 2403         payload_size = max(sizeof(sli4_req_common_query_fw_config_t),
 2404                            sizeof(sli4_res_common_query_fw_config_t));
 2405 
 2406         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2407                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2408                                 payload_size,
 2409                                 NULL);
 2410         }
 2411 
 2412         fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + sli_config_off);
 2413         fw_config->hdr.opcode         = SLI4_OPC_COMMON_QUERY_FW_CONFIG;
 2414         fw_config->hdr.subsystem      = SLI4_SUBSYSTEM_COMMON;
 2415         fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2416         return sli_config_off + sizeof(sli4_req_common_query_fw_config_t);
 2417 }
 2418 
 2419 /**
 2420  * @brief Write a COMMON_GET_PORT_NAME command to the provided buffer.
 2421  *
 2422  * @param sli4 SLI context pointer.
 2423  * @param buf Virtual pointer to destination buffer.
 2424  * @param size Buffer size in bytes.
 2425  *
 2426  * @note Function supports both version 0 and 1 forms of this command via
 2427  * the IF_TYPE.
 2428  *
 2429  * @return Returns the number of bytes written.
 2430  */
 2431 static int32_t
 2432 sli_cmd_common_get_port_name(sli4_t *sli4, void *buf, size_t size)
 2433 {
 2434         sli4_req_common_get_port_name_t *port_name;
 2435         uint32_t        sli_config_off = 0;
 2436         uint32_t        payload_size;
 2437         uint8_t         version = 0;
 2438         uint8_t         pt = 0;
 2439 
 2440         /* Select command version according to IF_TYPE */
 2441         switch (sli4->if_type) {
 2442         case SLI4_IF_TYPE_BE3_SKH_PF:
 2443         case SLI4_IF_TYPE_BE3_SKH_VF:
 2444                 version = 0;
 2445                 break;
 2446         case SLI4_IF_TYPE_LANCER_FC_ETH:
 2447         case SLI4_IF_TYPE_LANCER_RDMA:
 2448                 version = 1;
 2449                 break;
 2450         default:
 2451                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", sli4->if_type);
 2452                 return 0;
 2453         }
 2454 
 2455         /* Payload length must accommodate both request and response */
 2456         payload_size = max(sizeof(sli4_req_common_get_port_name_t),
 2457                            sizeof(sli4_res_common_get_port_name_t));
 2458 
 2459         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2460                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2461                                 payload_size,
 2462                                 NULL);
 2463 
 2464                 pt = 1;
 2465         }
 2466 
 2467         port_name = (sli4_req_common_get_port_name_t *)((uint8_t *)buf + sli_config_off);
 2468 
 2469         port_name->hdr.opcode           = SLI4_OPC_COMMON_GET_PORT_NAME;
 2470         port_name->hdr.subsystem        = SLI4_SUBSYSTEM_COMMON;
 2471         port_name->hdr.request_length   = sizeof(sli4_req_hdr_t) + (version * sizeof(uint32_t));
 2472         port_name->hdr.version          = version;
 2473 
 2474         /* Set the port type value (ethernet=0, FC=1) for V1 commands */
 2475         if (version == 1) {
 2476                 port_name->pt = pt;
 2477         }
 2478 
 2479         return sli_config_off + port_name->hdr.request_length;
 2480 }
 2481 
 2482 /**
 2483  * @ingroup sli
 2484  * @brief Write a COMMON_WRITE_OBJECT command.
 2485  *
 2486  * @param sli4 SLI context.
 2487  * @param buf Destination buffer for the command.
 2488  * @param size Buffer size, in bytes.
 2489  * @param noc True if the object should be written but not committed to flash.
 2490  * @param eof True if this is the last write for this object.
 2491  * @param desired_write_length Number of bytes of data to write to the object.
 2492  * @param offset Offset, in bytes, from the start of the object.
 2493  * @param object_name Name of the object to write.
 2494  * @param dma DMA structure from which the data will be copied.
 2495  *
 2496  * @return Returns the number of bytes written.
 2497  */
 2498 int32_t
 2499 sli_cmd_common_write_object(sli4_t *sli4, void *buf, size_t size,
 2500                 uint16_t noc, uint16_t eof, uint32_t desired_write_length,
 2501                 uint32_t offset,
 2502                 char *object_name,
 2503                 ocs_dma_t *dma)
 2504 {
 2505         sli4_req_common_write_object_t *wr_obj = NULL;
 2506         uint32_t        sli_config_off = 0;
 2507         sli4_bde_t *host_buffer;
 2508 
 2509         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2510                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2511                                 sizeof (sli4_req_common_write_object_t) + sizeof (sli4_bde_t),
 2512                                 NULL);
 2513         }
 2514 
 2515         wr_obj = (sli4_req_common_write_object_t *)((uint8_t *)buf + sli_config_off);
 2516 
 2517         wr_obj->hdr.opcode = SLI4_OPC_COMMON_WRITE_OBJECT;
 2518         wr_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2519         wr_obj->hdr.request_length = sizeof(*wr_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
 2520         wr_obj->hdr.timeout = 0;
 2521         wr_obj->hdr.version = 0;
 2522 
 2523         wr_obj->noc = noc;
 2524         wr_obj->eof = eof;
 2525         wr_obj->desired_write_length = desired_write_length;
 2526         wr_obj->write_offset = offset;
 2527         ocs_strncpy(wr_obj->object_name, object_name, sizeof(wr_obj->object_name));
 2528         wr_obj->host_buffer_descriptor_count = 1;
 2529 
 2530         host_buffer = (sli4_bde_t *)wr_obj->host_buffer_descriptor;
 2531 
 2532         /* Setup to transfer xfer_size bytes to device */
 2533         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
 2534         host_buffer->buffer_length = desired_write_length;
 2535         host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
 2536         host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 2537 
 2538         return(sli_config_off + sizeof(sli4_req_common_write_object_t) + sizeof (sli4_bde_t));
 2539 }
 2540 
 2541 /**
 2542  * @ingroup sli
 2543  * @brief Write a COMMON_DELETE_OBJECT command.
 2544  *
 2545  * @param sli4 SLI context.
 2546  * @param buf Destination buffer for the command.
 2547  * @param size Buffer size, in bytes.
 2548  * @param object_name Name of the object to write.
 2549  *
 2550  * @return Returns the number of bytes written.
 2551  */
 2552 int32_t
 2553 sli_cmd_common_delete_object(sli4_t *sli4, void *buf, size_t size,
 2554                 char *object_name)
 2555 {
 2556         sli4_req_common_delete_object_t *del_obj = NULL;
 2557         uint32_t        sli_config_off = 0;
 2558 
 2559         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2560                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2561                                 sizeof (sli4_req_common_delete_object_t),
 2562                                 NULL);
 2563         }
 2564 
 2565         del_obj = (sli4_req_common_delete_object_t *)((uint8_t *)buf + sli_config_off);
 2566 
 2567         del_obj->hdr.opcode = SLI4_OPC_COMMON_DELETE_OBJECT;
 2568         del_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2569         del_obj->hdr.request_length = sizeof(*del_obj);
 2570         del_obj->hdr.timeout = 0;
 2571         del_obj->hdr.version = 0;
 2572 
 2573         ocs_strncpy(del_obj->object_name, object_name, sizeof(del_obj->object_name));
 2574         return(sli_config_off + sizeof(sli4_req_common_delete_object_t));
 2575 }
 2576 
 2577 /**
 2578  * @ingroup sli
 2579  * @brief Write a COMMON_READ_OBJECT command.
 2580  *
 2581  * @param sli4 SLI context.
 2582  * @param buf Destination buffer for the command.
 2583  * @param size Buffer size, in bytes.
 2584  * @param desired_read_length Number of bytes of data to read from the object.
 2585  * @param offset Offset, in bytes, from the start of the object.
 2586  * @param object_name Name of the object to read.
 2587  * @param dma DMA structure from which the data will be copied.
 2588  *
 2589  * @return Returns the number of bytes written.
 2590  */
 2591 int32_t
 2592 sli_cmd_common_read_object(sli4_t *sli4, void *buf, size_t size,
 2593                 uint32_t desired_read_length,
 2594                 uint32_t offset,
 2595                 char *object_name,
 2596                 ocs_dma_t *dma)
 2597 {
 2598         sli4_req_common_read_object_t *rd_obj = NULL;
 2599         uint32_t        sli_config_off = 0;
 2600         sli4_bde_t *host_buffer;
 2601 
 2602         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2603                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2604                                 sizeof (sli4_req_common_read_object_t) + sizeof (sli4_bde_t),
 2605                                 NULL);
 2606         }
 2607 
 2608         rd_obj = (sli4_req_common_read_object_t *)((uint8_t *)buf + sli_config_off);
 2609 
 2610         rd_obj->hdr.opcode = SLI4_OPC_COMMON_READ_OBJECT;
 2611         rd_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2612         rd_obj->hdr.request_length = sizeof(*rd_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
 2613         rd_obj->hdr.timeout = 0;
 2614         rd_obj->hdr.version = 0;
 2615 
 2616         rd_obj->desired_read_length = desired_read_length;
 2617         rd_obj->read_offset = offset;
 2618         ocs_strncpy(rd_obj->object_name, object_name, sizeof(rd_obj->object_name));
 2619         rd_obj->host_buffer_descriptor_count = 1;
 2620 
 2621         host_buffer = (sli4_bde_t *)rd_obj->host_buffer_descriptor;
 2622 
 2623         /* Setup to transfer xfer_size bytes to device */
 2624         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
 2625         host_buffer->buffer_length = desired_read_length;
 2626         if (dma != NULL) {
 2627                 host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
 2628                 host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 2629         } else {
 2630                 host_buffer->u.data.buffer_address_low = 0;
 2631                 host_buffer->u.data.buffer_address_high = 0;
 2632         }
 2633 
 2634         return(sli_config_off + sizeof(sli4_req_common_read_object_t) + sizeof (sli4_bde_t));
 2635 }
 2636 
 2637 /**
 2638  * @ingroup sli
 2639  * @brief Write a DMTF_EXEC_CLP_CMD command.
 2640  *
 2641  * @param sli4 SLI context.
 2642  * @param buf Destination buffer for the command.
 2643  * @param size Buffer size, in bytes.
 2644  * @param cmd DMA structure that describes the buffer for the command.
 2645  * @param resp DMA structure that describes the buffer for the response.
 2646  *
 2647  * @return Returns the number of bytes written.
 2648  */
 2649 int32_t
 2650 sli_cmd_dmtf_exec_clp_cmd(sli4_t *sli4, void *buf, size_t size,
 2651                 ocs_dma_t *cmd,
 2652                 ocs_dma_t *resp)
 2653 {
 2654         sli4_req_dmtf_exec_clp_cmd_t *clp_cmd = NULL;
 2655         uint32_t        sli_config_off = 0;
 2656 
 2657         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2658                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2659                                 sizeof (sli4_req_dmtf_exec_clp_cmd_t),
 2660                                 NULL);
 2661         }
 2662 
 2663         clp_cmd = (sli4_req_dmtf_exec_clp_cmd_t*)((uint8_t *)buf + sli_config_off);
 2664 
 2665         clp_cmd->hdr.opcode = SLI4_OPC_DMTF_EXEC_CLP_CMD;
 2666         clp_cmd->hdr.subsystem = SLI4_SUBSYSTEM_DMTF;
 2667         clp_cmd->hdr.request_length = sizeof(sli4_req_dmtf_exec_clp_cmd_t) -
 2668                                         sizeof(sli4_req_hdr_t);
 2669         clp_cmd->hdr.timeout = 0;
 2670         clp_cmd->hdr.version = 0;
 2671         clp_cmd->cmd_buf_length = cmd->size;
 2672         clp_cmd->cmd_buf_addr_low = ocs_addr32_lo(cmd->phys);
 2673         clp_cmd->cmd_buf_addr_high = ocs_addr32_hi(cmd->phys);
 2674         clp_cmd->resp_buf_length = resp->size;
 2675         clp_cmd->resp_buf_addr_low = ocs_addr32_lo(resp->phys);
 2676         clp_cmd->resp_buf_addr_high = ocs_addr32_hi(resp->phys);
 2677 
 2678         return(sli_config_off + sizeof(sli4_req_dmtf_exec_clp_cmd_t));
 2679 }
 2680 
 2681 /**
 2682  * @ingroup sli
 2683  * @brief Write a COMMON_SET_DUMP_LOCATION command.
 2684  *
 2685  * @param sli4 SLI context.
 2686  * @param buf Destination buffer for the command.
 2687  * @param size Buffer size, in bytes.
 2688  * @param query Zero to set dump location, non-zero to query dump size
 2689  * @param is_buffer_list Set to one if the buffer is a set of buffer descriptors or
 2690  *                       set to 0 if the buffer is a contiguous dump area.
 2691  * @param buffer DMA structure to which the dump will be copied.
 2692  *
 2693  * @return Returns the number of bytes written.
 2694  */
 2695 int32_t
 2696 sli_cmd_common_set_dump_location(sli4_t *sli4, void *buf, size_t size,
 2697                                  uint8_t query, uint8_t is_buffer_list,
 2698                                  ocs_dma_t *buffer, uint8_t fdb)
 2699 {
 2700         sli4_req_common_set_dump_location_t *set_dump_loc = NULL;
 2701         uint32_t        sli_config_off = 0;
 2702 
 2703         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2704                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2705                                 sizeof (sli4_req_common_set_dump_location_t),
 2706                                 NULL);
 2707         }
 2708 
 2709         set_dump_loc = (sli4_req_common_set_dump_location_t *)((uint8_t *)buf + sli_config_off);
 2710 
 2711         set_dump_loc->hdr.opcode = SLI4_OPC_COMMON_SET_DUMP_LOCATION;
 2712         set_dump_loc->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2713         set_dump_loc->hdr.request_length = sizeof(sli4_req_common_set_dump_location_t) - sizeof(sli4_req_hdr_t);
 2714         set_dump_loc->hdr.timeout = 0;
 2715         set_dump_loc->hdr.version = 0;
 2716 
 2717         set_dump_loc->blp = is_buffer_list;
 2718         set_dump_loc->qry = query;
 2719         set_dump_loc->fdb = fdb;
 2720 
 2721         if (buffer) {
 2722                 set_dump_loc->buf_addr_low = ocs_addr32_lo(buffer->phys);
 2723                 set_dump_loc->buf_addr_high = ocs_addr32_hi(buffer->phys);
 2724                 set_dump_loc->buffer_length = buffer->len;
 2725         } else {
 2726                 set_dump_loc->buf_addr_low = 0;
 2727                 set_dump_loc->buf_addr_high = 0;
 2728                 set_dump_loc->buffer_length = 0;
 2729         }
 2730 
 2731         return(sli_config_off + sizeof(sli4_req_common_set_dump_location_t));
 2732 }
 2733 
 2734 /**
 2735  * @ingroup sli
 2736  * @brief Write a COMMON_SET_FEATURES command.
 2737  *
 2738  * @param sli4 SLI context.
 2739  * @param buf Destination buffer for the command.
 2740  * @param size Buffer size, in bytes.
 2741  * @param feature Feature to set.
 2742  * @param param_len Length of the parameter (must be a multiple of 4 bytes).
 2743  * @param parameter Pointer to the parameter value.
 2744  *
 2745  * @return Returns the number of bytes written.
 2746  */
 2747 int32_t
 2748 sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size,
 2749                             uint32_t feature,
 2750                             uint32_t param_len,
 2751                             void* parameter)
 2752 {
 2753         sli4_req_common_set_features_t *cmd = NULL;
 2754         uint32_t        sli_config_off = 0;
 2755 
 2756         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2757                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2758                                 sizeof (sli4_req_common_set_features_t),
 2759                                 NULL);
 2760         }
 2761 
 2762         cmd = (sli4_req_common_set_features_t *)((uint8_t *)buf + sli_config_off);
 2763 
 2764         cmd->hdr.opcode = SLI4_OPC_COMMON_SET_FEATURES;
 2765         cmd->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2766         cmd->hdr.request_length = sizeof(sli4_req_common_set_features_t) - sizeof(sli4_req_hdr_t);
 2767         cmd->hdr.timeout = 0;
 2768         cmd->hdr.version = 0;
 2769 
 2770         cmd->feature = feature;
 2771         cmd->param_len = param_len;
 2772         ocs_memcpy(cmd->params, parameter, param_len);
 2773 
 2774         return(sli_config_off + sizeof(sli4_req_common_set_features_t));
 2775 }
 2776 
 2777 /**
 2778  * @ingroup sli
 2779  * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
 2780  *
 2781  * @param sli4 SLI context.
 2782  * @param buf Destination buffer for the command.
 2783  * @param size Buffer size in bytes.
 2784  * @param dma DMA capable memory used to retrieve profile.
 2785  *
 2786  * @return Returns the number of bytes written.
 2787  */
 2788 int32_t
 2789 sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2790 {
 2791         sli4_req_common_get_profile_config_t *req = NULL;
 2792         uint32_t        sli_config_off = 0;
 2793         uint32_t        payload_size;
 2794 
 2795         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2796                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2797                                 sizeof (sli4_req_common_get_profile_config_t),
 2798                                 dma);
 2799         }
 2800 
 2801         if (dma != NULL) {
 2802                 req = dma->virt;
 2803                 ocs_memset(req, 0, dma->size);
 2804                 payload_size = dma->size;
 2805         } else {
 2806                 req = (sli4_req_common_get_profile_config_t *)((uint8_t *)buf + sli_config_off);
 2807                 payload_size = sizeof(sli4_req_common_get_profile_config_t);
 2808         }
 2809 
 2810         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_CONFIG;
 2811         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2812         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2813         req->hdr.version = 1;
 2814 
 2815         return(sli_config_off + sizeof(sli4_req_common_get_profile_config_t));
 2816 }
 2817 
 2818 /**
 2819  * @ingroup sli
 2820  * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
 2821  *
 2822  * @param sli4 SLI context.
 2823  * @param buf Destination buffer for the command.
 2824  * @param size Buffer size, in bytes.
 2825  * @param dma DMA capable memory containing profile.
 2826  * @param profile_id Profile ID to configure.
 2827  * @param descriptor_count Number of descriptors in DMA buffer.
 2828  * @param isap Implicit Set Active Profile value to use.
 2829  *
 2830  * @return Returns the number of bytes written.
 2831  */
 2832 int32_t
 2833 sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 2834                 uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
 2835 {
 2836         sli4_req_common_set_profile_config_t *req = NULL;
 2837         uint32_t cmd_off = 0;
 2838         uint32_t payload_size;
 2839 
 2840         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2841                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2842                                                     sizeof (sli4_req_common_set_profile_config_t),
 2843                                                     dma);
 2844         }
 2845 
 2846         if (dma != NULL) {
 2847                 req = dma->virt;
 2848                 ocs_memset(req, 0, dma->size);
 2849                 payload_size = dma->size;
 2850         } else {
 2851                 req = (sli4_req_common_set_profile_config_t *)((uint8_t *)buf + cmd_off);
 2852                 payload_size = sizeof(sli4_req_common_set_profile_config_t);
 2853         }
 2854 
 2855         req->hdr.opcode = SLI4_OPC_COMMON_SET_PROFILE_CONFIG;
 2856         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2857         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2858         req->hdr.version = 1;
 2859         req->profile_id = profile_id;
 2860         req->desc_count = descriptor_count;
 2861         req->isap = isap;
 2862 
 2863         return(cmd_off + sizeof(sli4_req_common_set_profile_config_t));
 2864 }
 2865 
 2866 /**
 2867  * @ingroup sli
 2868  * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command.
 2869  *
 2870  * @param sli4 SLI context.
 2871  * @param buf Destination buffer for the command.
 2872  * @param size Buffer size in bytes.
 2873  * @param start_profile_index First profile index to return.
 2874  * @param dma Buffer into which the list will be written.
 2875  *
 2876  * @return Returns the number of bytes written.
 2877  */
 2878 int32_t
 2879 sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size,
 2880                                    uint32_t start_profile_index, ocs_dma_t *dma)
 2881 {
 2882         sli4_req_common_get_profile_list_t *req = NULL;
 2883         uint32_t cmd_off = 0;
 2884         uint32_t payload_size;
 2885 
 2886         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2887                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2888                                              sizeof (sli4_req_common_get_profile_list_t),
 2889                                              dma);
 2890         }
 2891 
 2892         if (dma != NULL) {
 2893                 req = dma->virt;
 2894                 ocs_memset(req, 0, dma->size);
 2895                 payload_size = dma->size;
 2896         } else {
 2897                 req = (sli4_req_common_get_profile_list_t *)((uint8_t *)buf + cmd_off);
 2898                 payload_size = sizeof(sli4_req_common_get_profile_list_t);
 2899         }
 2900 
 2901         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_LIST;
 2902         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2903         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2904         req->hdr.version = 0;
 2905 
 2906         req->start_profile_index = start_profile_index;
 2907 
 2908         return(cmd_off + sizeof(sli4_req_common_get_profile_list_t));
 2909 }
 2910 
 2911 /**
 2912  * @ingroup sli
 2913  * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
 2914  *
 2915  * @param sli4 SLI context.
 2916  * @param buf Destination buffer for the command.
 2917  * @param size Buffer size in bytes.
 2918  *
 2919  * @return Returns the number of bytes written.
 2920  */
 2921 int32_t
 2922 sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size)
 2923 {
 2924         sli4_req_common_get_active_profile_t *req = NULL;
 2925         uint32_t cmd_off = 0;
 2926         uint32_t payload_size;
 2927 
 2928         /* Payload length must accommodate both request and response */
 2929         payload_size = max(sizeof(sli4_req_common_get_active_profile_t),
 2930                            sizeof(sli4_res_common_get_active_profile_t));
 2931 
 2932         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2933                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2934                                 payload_size,
 2935                                 NULL);
 2936         }
 2937 
 2938         req = (sli4_req_common_get_active_profile_t *)
 2939                 ((uint8_t*)buf + cmd_off);
 2940 
 2941         req->hdr.opcode = SLI4_OPC_COMMON_GET_ACTIVE_PROFILE;
 2942         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2943         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2944         req->hdr.version = 0;
 2945 
 2946         return(cmd_off + sizeof(sli4_req_common_get_active_profile_t));
 2947 }
 2948 
 2949 /**
 2950  * @ingroup sli
 2951  * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
 2952  *
 2953  * @param sli4 SLI context.
 2954  * @param buf Destination buffer for the command.
 2955  * @param size Buffer size in bytes.
 2956  * @param fd If non-zero, set profile to factory default.
 2957  * @param active_profile_id ID of new active profile.
 2958  *
 2959  * @return Returns the number of bytes written.
 2960  */
 2961 int32_t
 2962 sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size,
 2963                                   uint32_t fd, uint32_t active_profile_id)
 2964 {
 2965         sli4_req_common_set_active_profile_t *req = NULL;
 2966         uint32_t cmd_off = 0;
 2967         uint32_t payload_size;
 2968 
 2969         /* Payload length must accommodate both request and response */
 2970         payload_size = max(sizeof(sli4_req_common_set_active_profile_t),
 2971                            sizeof(sli4_res_common_set_active_profile_t));
 2972 
 2973         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2974                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2975                                 payload_size,
 2976                                 NULL);
 2977         }
 2978 
 2979         req = (sli4_req_common_set_active_profile_t *)
 2980                 ((uint8_t*)buf + cmd_off);
 2981 
 2982         req->hdr.opcode = SLI4_OPC_COMMON_SET_ACTIVE_PROFILE;
 2983         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2984         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2985         req->hdr.version = 0;
 2986         req->fd = fd;
 2987         req->active_profile_id = active_profile_id;
 2988 
 2989         return(cmd_off + sizeof(sli4_req_common_set_active_profile_t));
 2990 }
 2991 
 2992 /**
 2993  * @ingroup sli
 2994  * @brief Write a COMMON_GET_RECONFIG_LINK_INFO command.
 2995  *
 2996  * @param sli4 SLI context.
 2997  * @param buf Destination buffer for the command.
 2998  * @param size Buffer size in bytes.
 2999  * @param dma Buffer to store the supported link configuration modes from the physical device.
 3000  *
 3001  * @return Returns the number of bytes written.
 3002  */
 3003 int32_t
 3004 sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 3005 {
 3006         sli4_req_common_get_reconfig_link_info_t *req = NULL;
 3007         uint32_t cmd_off = 0;
 3008         uint32_t payload_size;
 3009 
 3010         /* Payload length must accommodate both request and response */
 3011         payload_size = max(sizeof(sli4_req_common_get_reconfig_link_info_t),
 3012                            sizeof(sli4_res_common_get_reconfig_link_info_t));
 3013 
 3014         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3015                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3016                                 payload_size,
 3017                                 dma);
 3018         }
 3019 
 3020         if (dma != NULL) {
 3021                 req = dma->virt;
 3022                 ocs_memset(req, 0, dma->size);
 3023                 payload_size = dma->size;
 3024         } else {
 3025                 req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off);
 3026                 payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t);
 3027         }
 3028 
 3029         req->hdr.opcode = SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO;
 3030         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3031         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3032         req->hdr.version = 0;
 3033 
 3034         return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t));
 3035 }
 3036 
 3037 /**
 3038  * @ingroup sli
 3039  * @brief Write a COMMON_SET_RECONFIG_LINK_ID command.
 3040  *
 3041  * @param sli4 SLI context.
 3042  * @param buf destination buffer for the command.
 3043  * @param size buffer size in bytes.
 3044  * @param fd If non-zero, set link config to factory default.
 3045  * @param active_link_config_id ID of new active profile.
 3046  * @param dma Buffer to assign the link configuration mode that is to become active from the physical device.
 3047  *
 3048  * @return Returns the number of bytes written.
 3049  */
 3050 int32_t
 3051 sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 3052                                   uint32_t fd, uint32_t active_link_config_id)
 3053 {
 3054         sli4_req_common_set_reconfig_link_id_t *req = NULL;
 3055         uint32_t cmd_off = 0;
 3056         uint32_t payload_size;
 3057 
 3058         /* Payload length must accommodate both request and response */
 3059         payload_size = max(sizeof(sli4_req_common_set_reconfig_link_id_t),
 3060                            sizeof(sli4_res_common_set_reconfig_link_id_t));
 3061 
 3062         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3063                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3064                                 payload_size,
 3065                                 NULL);
 3066         }
 3067 
 3068                 if (dma != NULL) {
 3069                 req = dma->virt;
 3070                 ocs_memset(req, 0, dma->size);
 3071                 payload_size = dma->size;
 3072         } else {
 3073                 req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off);
 3074                 payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t);
 3075         }
 3076 
 3077         req->hdr.opcode = SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID;
 3078         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3079         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3080         req->hdr.version = 0;
 3081         req->fd = fd;
 3082         req->next_link_config_id = active_link_config_id;
 3083 
 3084         return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t));
 3085 }
 3086 
 3087 /**
 3088  * @ingroup sli
 3089  * @brief Check the mailbox/queue completion entry.
 3090  *
 3091  * @param buf Pointer to the MCQE.
 3092  *
 3093  * @return Returns 0 on success, or a non-zero value on failure.
 3094  */
 3095 int32_t
 3096 sli_cqe_mq(void *buf)
 3097 {
 3098         sli4_mcqe_t     *mcqe = buf;
 3099 
 3100         /*
 3101          * Firmware can split mbx completions into two MCQEs: first with only
 3102          * the "consumed" bit set and a second with the "complete" bit set.
 3103          * Thus, ignore MCQE unless "complete" is set.
 3104          */
 3105         if (!mcqe->cmp) {
 3106                 return -2;
 3107         }
 3108 
 3109         if (mcqe->completion_status) {
 3110                 ocs_log_debug(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
 3111                                 mcqe->completion_status,
 3112                                 mcqe->extended_status,
 3113                                 mcqe->con,
 3114                                 mcqe->cmp,
 3115                                 mcqe->ae,
 3116                                 mcqe->val);
 3117         }
 3118 
 3119         return mcqe->completion_status;
 3120 }
 3121 
 3122 /**
 3123  * @ingroup sli
 3124  * @brief Check the asynchronous event completion entry.
 3125  *
 3126  * @param sli4 SLI context.
 3127  * @param buf Pointer to the ACQE.
 3128  *
 3129  * @return Returns 0 on success, or a non-zero value on failure.
 3130  */
 3131 int32_t
 3132 sli_cqe_async(sli4_t *sli4, void *buf)
 3133 {
 3134         sli4_acqe_t     *acqe = buf;
 3135         int32_t         rc = -1;
 3136 
 3137         if (!sli4 || !buf) {
 3138                 ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf);
 3139                 return -1;
 3140         }
 3141 
 3142         switch (acqe->event_code) {
 3143         case SLI4_ACQE_EVENT_CODE_LINK_STATE:
 3144                 rc = sli_fc_process_link_state(sli4, buf);
 3145                 break;
 3146         case SLI4_ACQE_EVENT_CODE_FCOE_FIP:
 3147                 rc = sli_fc_process_fcoe(sli4, buf);
 3148                 break;
 3149         case SLI4_ACQE_EVENT_CODE_GRP_5:
 3150                 /*TODO*/ocs_log_debug(sli4->os, "ACQE GRP5\n");
 3151                 break;
 3152         case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT:
 3153         ocs_log_debug(sli4->os,"ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n",
 3154                 acqe->event_type, acqe->event_data[0], acqe->event_data[1]);
 3155 #if defined(OCS_INCLUDE_DEBUG)
 3156                 ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "acq", acqe, sizeof(*acqe));
 3157 #endif
 3158                 break;
 3159         case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT:
 3160                 rc = sli_fc_process_link_attention(sli4, buf);
 3161                 break;
 3162         default:
 3163                 /*TODO*/ocs_log_test(sli4->os, "ACQE unknown=%#x\n", acqe->event_code);
 3164         }
 3165 
 3166         return rc;
 3167 }
 3168 
 3169 /**
 3170  * @brief Check the SLI_CONFIG response.
 3171  *
 3172  * @par Description
 3173  * Function checks the SLI_CONFIG response and the payload status.
 3174  *
 3175  * @param buf Pointer to SLI_CONFIG response.
 3176  *
 3177  * @return Returns 0 on success, or a non-zero value on failure.
 3178  */
 3179 static int32_t
 3180 sli_res_sli_config(void *buf)
 3181 {
 3182         sli4_cmd_sli_config_t   *sli_config = buf;
 3183 
 3184         if (!buf || (SLI4_MBOX_COMMAND_SLI_CONFIG != sli_config->hdr.command)) {
 3185                 ocs_log_err(NULL, "bad parameter buf=%p cmd=%#x\n", buf,
 3186                                 buf ? sli_config->hdr.command : -1);
 3187                 return -1;
 3188         }
 3189 
 3190         if (sli_config->hdr.status) {
 3191                 return sli_config->hdr.status;
 3192         }
 3193 
 3194         if (sli_config->emb) {
 3195                 return sli_config->payload.embed[4];
 3196         } else {
 3197                 ocs_log_test(NULL, "external buffers not supported\n");
 3198                 return -1;
 3199         }
 3200 }
 3201 
 3202 /**
 3203  * @brief Issue a COMMON_FUNCTION_RESET command.
 3204  *
 3205  * @param sli4 SLI context.
 3206  *
 3207  * @return Returns 0 on success, or a non-zero value on failure.
 3208  */
 3209 static int32_t
 3210 sli_common_function_reset(sli4_t *sli4)
 3211 {
 3212 
 3213         if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3214                 if (sli_bmbx_command(sli4)) {
 3215                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COM_FUNC_RESET)\n");
 3216                         return -1;
 3217                 }
 3218                 if (sli_res_sli_config(sli4->bmbx.virt)) {
 3219                         ocs_log_err(sli4->os, "bad status COM_FUNC_RESET\n");
 3220                         return -1;
 3221                 }
 3222         } else {
 3223                 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3224                 return -1;
 3225         }
 3226 
 3227         return 0;
 3228 }
 3229 
 3230 /**
 3231  * @brief check to see if the FW is ready.
 3232  *
 3233  * @par Description
 3234  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
 3235  *
 3236  * @param sli4 SLI context.
 3237  * @param timeout_ms Time, in milliseconds, to wait for the port to be ready
 3238  *  before failing.
 3239  *
 3240  * @return Returns TRUE for ready, or FALSE otherwise.
 3241  */
 3242 static int32_t
 3243 sli_wait_for_fw_ready(sli4_t *sli4, uint32_t timeout_ms)
 3244 {
 3245         uint32_t        iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000);
 3246         uint32_t        ready = FALSE;
 3247 
 3248         do {
 3249                 iter--;
 3250                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
 3251                 if (sli_fw_ready(sli4) == 1) {
 3252                         ready = TRUE;
 3253                 }
 3254         } while (!ready && (iter > 0));
 3255 
 3256         return ready;
 3257 }
 3258 
 3259 /**
 3260  * @brief Initialize the firmware.
 3261  *
 3262  * @par Description
 3263  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
 3264  *
 3265  * @param sli4 SLI context.
 3266  *
 3267  * @return Returns 0 on success, or a non-zero value on failure.
 3268  */
 3269 static int32_t
 3270 sli_fw_init(sli4_t *sli4)
 3271 {
 3272         uint32_t ready;
 3273         uint32_t endian;
 3274 
 3275         /*
 3276          * Is firmware ready for operation?
 3277          */
 3278         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 3279         if (!ready) {
 3280                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
 3281                 return -1;
 3282         }
 3283 
 3284         /*
 3285          * Reset port to a known state
 3286          */
 3287         switch (sli4->if_type) {
 3288         case SLI4_IF_TYPE_BE3_SKH_PF:
 3289         case SLI4_IF_TYPE_BE3_SKH_VF:
 3290                 /* No SLIPORT_CONTROL register so use command sequence instead */
 3291                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
 3292                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
 3293                         return -1;
 3294                 }
 3295 
 3296                 if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3297                         if (sli_bmbx_command(sli4)) {
 3298                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_INIT)\n");
 3299                                 return -1;
 3300                         }
 3301                 } else {
 3302                         ocs_log_crit(sli4->os, "bad FW_INIT write\n");
 3303                         return -1;
 3304                 }
 3305 
 3306                 if (sli_common_function_reset(sli4)) {
 3307                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3308                         return -1;
 3309                 }
 3310                 break;
 3311         case SLI4_IF_TYPE_LANCER_FC_ETH:
 3312 #if BYTE_ORDER == LITTLE_ENDIAN
 3313                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
 3314 #else
 3315                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
 3316 #endif
 3317 
 3318                 if (sli_sliport_control(sli4, endian))
 3319                         return -1;
 3320                 break;
 3321         default:
 3322                 ocs_log_test(sli4->os, "if_type %d not supported\n", sli4->if_type);
 3323                 return -1;
 3324         }
 3325 
 3326         return 0;
 3327 }
 3328 
 3329 /**
 3330  * @brief Terminate the firmware.
 3331  *
 3332  * @param sli4 SLI context.
 3333  *
 3334  * @return Returns 0 on success, or a non-zero value on failure.
 3335  */
 3336 static int32_t
 3337 sli_fw_term(sli4_t *sli4)
 3338 {
 3339         uint32_t endian;
 3340 
 3341         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF ||
 3342             sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF) {
 3343                 /* No SLIPORT_CONTROL register so use command sequence instead */
 3344                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
 3345                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
 3346                         return -1;
 3347                 }
 3348 
 3349                 if (sli_common_function_reset(sli4)) {
 3350                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3351                         return -1;
 3352                 }
 3353 
 3354                 if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3355                         if (sli_bmbx_command(sli4)) {
 3356                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_DEINIT)\n");
 3357                                 return -1;
 3358                         }
 3359                 } else {
 3360                         ocs_log_test(sli4->os, "bad FW_DEINIT write\n");
 3361                         return -1;
 3362                 }
 3363         } else {
 3364 #if BYTE_ORDER == LITTLE_ENDIAN
 3365                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
 3366 #else
 3367                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
 3368 #endif
 3369                 /* type 2 etc. use SLIPORT_CONTROL to initialize port */
 3370                 sli_sliport_control(sli4, endian);
 3371         }
 3372         return 0;
 3373 }
 3374 
 3375 /**
 3376  * @brief Write the doorbell register associated with the queue object.
 3377  *
 3378  * @param sli4 SLI context.
 3379  * @param q Queue object.
 3380  *
 3381  * @return Returns 0 on success, or a non-zero value on failure.
 3382  */
 3383 static int32_t
 3384 sli_queue_doorbell(sli4_t *sli4, sli4_queue_t *q)
 3385 {
 3386         uint32_t        val = 0;
 3387 
 3388         switch (q->type) {
 3389         case SLI_QTYPE_EQ:
 3390                 val = sli_eq_doorbell(q->n_posted, q->id, FALSE);
 3391                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3392                 break;
 3393         case SLI_QTYPE_CQ:
 3394                 val = sli_cq_doorbell(q->n_posted, q->id, FALSE);
 3395                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3396                 break;
 3397         case SLI_QTYPE_MQ:
 3398                 val = SLI4_MQ_DOORBELL(q->n_posted, q->id);
 3399                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3400                 break;
 3401         case SLI_QTYPE_RQ:
 3402         {
 3403                 uint32_t        n_posted = q->n_posted;
 3404                 /*
 3405                  * FC/FCoE has different rules for Receive Queues. The host
 3406                  * should only update the doorbell of the RQ-pair containing
 3407                  * the headers since the header / payload RQs are treated
 3408                  * as a matched unit.
 3409                  */
 3410                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3411                         /*
 3412                          * In RQ-pair, an RQ either contains the FC header
 3413                          * (i.e. is_hdr == TRUE) or the payload.
 3414                          *
 3415                          * Don't ring doorbell for payload RQ
 3416                          */
 3417                         if (!q->u.flag.is_hdr) {
 3418                                 break;
 3419                         }
 3420                         /*
 3421                          * Some RQ cannot be incremented one entry at a time. Instead,
 3422                          * the driver collects a number of entries and updates the
 3423                          * RQ in batches.
 3424                          */
 3425                         if (q->u.flag.rq_batch) {
 3426                                 if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) {
 3427                                         break;
 3428                                 }
 3429                                 n_posted = SLI4_QUEUE_RQ_BATCH;
 3430                         }
 3431                 }
 3432 
 3433                 val = SLI4_RQ_DOORBELL(n_posted, q->id);
 3434                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3435                 break;
 3436         }
 3437         case SLI_QTYPE_WQ:
 3438                 val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id);
 3439                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3440                 break;
 3441         default:
 3442                 ocs_log_test(sli4->os, "bad queue type %d\n", q->type);
 3443                 return -1;
 3444         }
 3445 
 3446         return 0;
 3447 }
 3448 
 3449 static int32_t
 3450 sli_request_features(sli4_t *sli4, sli4_features_t *features, uint8_t query)
 3451 {
 3452 
 3453         if (sli_cmd_request_features(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
 3454                                 *features, query)) {
 3455                 sli4_cmd_request_features_t *req_features = sli4->bmbx.virt;
 3456 
 3457                 if (sli_bmbx_command(sli4)) {
 3458                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (REQUEST_FEATURES)\n");
 3459                         return -1;
 3460                 }
 3461                 if (req_features->hdr.status) {
 3462                         ocs_log_err(sli4->os, "REQUEST_FEATURES bad status %#x\n",
 3463                                         req_features->hdr.status);
 3464                         return -1;
 3465                 }
 3466                 features->dword = req_features->response.dword;
 3467         } else {
 3468                 ocs_log_err(sli4->os, "bad REQUEST_FEATURES write\n");
 3469                 return -1;
 3470         }
 3471 
 3472         return 0;
 3473 }
 3474 
 3475 /**
 3476  * @brief Calculate max queue entries.
 3477  *
 3478  * @param sli4 SLI context.
 3479  *
 3480  * @return Returns 0 on success, or a non-zero value on failure.
 3481  */
 3482 void
 3483 sli_calc_max_qentries(sli4_t *sli4)
 3484 {
 3485         sli4_qtype_e q;
 3486         uint32_t alloc_size, qentries, qentry_size;
 3487 
 3488         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
 3489                 sli4->config.max_qentries[q] = sli_convert_mask_to_count(sli4->config.count_method[q],
 3490                                                                          sli4->config.count_mask[q]);
 3491         }
 3492 
 3493         /* single, continguous DMA allocations will be called for each queue
 3494          * of size (max_qentries * queue entry size); since these can be large,
 3495          * check against the OS max DMA allocation size
 3496          */
 3497         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
 3498                 qentries = sli4->config.max_qentries[q];
 3499                 qentry_size = sli_get_queue_entry_size(sli4, q);
 3500                 alloc_size = qentries * qentry_size;
 3501                 if (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
 3502                         while (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
 3503                                 /* cut the qentries in hwf until alloc_size <= max DMA alloc size */
 3504                                 qentries >>= 1;
 3505                                 alloc_size = qentries * qentry_size;
 3506                         }
 3507                         ocs_log_debug(sli4->os, "[%s]: max_qentries from %d to %d (max dma %d)\n",
 3508                                 SLI_QNAME[q], sli4->config.max_qentries[q],
 3509                                 qentries, ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE));
 3510                         sli4->config.max_qentries[q] = qentries;
 3511                 }
 3512         }
 3513 }
 3514 
 3515 /**
 3516  * @brief Issue a FW_CONFIG mailbox command and store the results.
 3517  *
 3518  * @param sli4 SLI context.
 3519  *
 3520  * @return Returns 0 on success, or a non-zero value on failure.
 3521  */
 3522 static int32_t
 3523 sli_query_fw_config(sli4_t *sli4)
 3524 {
 3525         /*
 3526          * Read the device configuration
 3527          *
 3528          * Note: Only ulp0 fields contain values
 3529          */
 3530         if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3531                 sli4_res_common_query_fw_config_t   *fw_config =
 3532                         (sli4_res_common_query_fw_config_t *)
 3533                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
 3534 
 3535                 if (sli_bmbx_command(sli4)) {
 3536                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (QUERY_FW_CONFIG)\n");
 3537                         return -1;
 3538                 }
 3539                 if (fw_config->hdr.status) {
 3540                         ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n",
 3541                                 fw_config->hdr.status);
 3542                         return -1;
 3543                 }
 3544 
 3545                 sli4->physical_port = fw_config->physical_port;
 3546                 sli4->config.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1);
 3547                 sli4->config.is_ulp_fc[0] = ((fw_config->ulp0_mode &
 3548                                               (SLI4_ULP_MODE_FCOE_INI |
 3549                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
 3550                 sli4->config.is_ulp_fc[1] = ((fw_config->ulp1_mode &
 3551                                               (SLI4_ULP_MODE_FCOE_INI |
 3552                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
 3553 
 3554                 if (sli4->config.dual_ulp_capable) {
 3555                         /*
 3556                          * Lancer will not support this, so we use the values
 3557                          * from the READ_CONFIG.
 3558                          */
 3559                         if (sli4->config.is_ulp_fc[0] &&
 3560                             sli4->config.is_ulp_fc[1]) {
 3561                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total;
 3562                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total;
 3563                         } else if (sli4->config.is_ulp_fc[0]) {
 3564                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total;
 3565                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total;
 3566                         } else {
 3567                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total;
 3568                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total;
 3569                         }
 3570                 }
 3571         } else {
 3572                 ocs_log_err(sli4->os, "bad QUERY_FW_CONFIG write\n");
 3573                 return -1;
 3574         }
 3575         return 0;
 3576 }
 3577 
 3578 static int32_t
 3579 sli_get_config(sli4_t *sli4)
 3580 {
 3581         ocs_dma_t       get_cntl_addl_data;
 3582 
 3583         /*
 3584          * Read the device configuration
 3585          */
 3586         if (sli_cmd_read_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3587                 sli4_res_read_config_t  *read_config = sli4->bmbx.virt;
 3588                 uint32_t        i;
 3589                 uint32_t        total;
 3590 
 3591                 if (sli_bmbx_command(sli4)) {
 3592                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
 3593                         return -1;
 3594                 }
 3595                 if (read_config->hdr.status) {
 3596                         ocs_log_err(sli4->os, "READ_CONFIG bad status %#x\n",
 3597                                         read_config->hdr.status);
 3598                         return -1;
 3599                 }
 3600 
 3601                 sli4->config.has_extents = read_config->ext;
 3602                 if (FALSE == sli4->config.has_extents) {
 3603                         uint32_t        i = 0;
 3604                         uint32_t        *base = sli4->config.extent[0].base;
 3605 
 3606                         if (!base) {
 3607                                 if (NULL == (base = ocs_malloc(sli4->os, SLI_RSRC_MAX * sizeof(uint32_t),
 3608                                                                 OCS_M_ZERO | OCS_M_NOWAIT))) {
 3609                                         ocs_log_err(sli4->os, "memory allocation failed for sli4_resource_t\n");
 3610                                         return -1;
 3611                                 }
 3612                         }
 3613 
 3614                         for (i = 0; i < SLI_RSRC_MAX; i++) {
 3615                                 sli4->config.extent[i].number = 1;
 3616                                 sli4->config.extent[i].n_alloc = 0;
 3617                                 sli4->config.extent[i].base = &base[i];
 3618                         }
 3619 
 3620                         sli4->config.extent[SLI_RSRC_FCOE_VFI].base[0] = read_config->vfi_base;
 3621                         sli4->config.extent[SLI_RSRC_FCOE_VFI].size = read_config->vfi_count;
 3622 
 3623                         sli4->config.extent[SLI_RSRC_FCOE_VPI].base[0] = read_config->vpi_base;
 3624                         sli4->config.extent[SLI_RSRC_FCOE_VPI].size = read_config->vpi_count;
 3625 
 3626                         sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0] = read_config->rpi_base;
 3627                         sli4->config.extent[SLI_RSRC_FCOE_RPI].size = read_config->rpi_count;
 3628 
 3629                         sli4->config.extent[SLI_RSRC_FCOE_XRI].base[0] = read_config->xri_base;
 3630                         sli4->config.extent[SLI_RSRC_FCOE_XRI].size = read_config->xri_count;
 3631 
 3632                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].base[0] = 0;
 3633                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].size = read_config->fcfi_count;
 3634                 } else {
 3635                         /* TODO extents*/
 3636                         ;
 3637                 }
 3638 
 3639                 for (i = 0; i < SLI_RSRC_MAX; i++) {
 3640                         total = sli4->config.extent[i].number * sli4->config.extent[i].size;
 3641                         sli4->config.extent[i].use_map = ocs_bitmap_alloc(total);
 3642                         if (NULL == sli4->config.extent[i].use_map) {
 3643                                 ocs_log_err(sli4->os, "bitmap memory allocation failed "
 3644                                                 "resource %d\n", i);
 3645                                 return -1;
 3646                         }
 3647                         sli4->config.extent[i].map_size = total;
 3648                 }
 3649 
 3650                 sli4->config.topology = read_config->topology;
 3651                 switch (sli4->config.topology) {
 3652                 case SLI4_READ_CFG_TOPO_FCOE:
 3653                         ocs_log_debug(sli4->os, "FCoE\n");
 3654                         break;
 3655                 case SLI4_READ_CFG_TOPO_FC:
 3656                         ocs_log_debug(sli4->os, "FC (unknown)\n");
 3657                         break;
 3658                 case SLI4_READ_CFG_TOPO_FC_DA:
 3659                         ocs_log_debug(sli4->os, "FC (direct attach)\n");
 3660                         break;
 3661                 case SLI4_READ_CFG_TOPO_FC_AL:
 3662                         ocs_log_debug(sli4->os, "FC (arbitrated loop)\n");
 3663                         break;
 3664                 default:
 3665                         ocs_log_test(sli4->os, "bad topology %#x\n", sli4->config.topology);
 3666                 }
 3667 
 3668                 sli4->config.e_d_tov = read_config->e_d_tov;
 3669                 sli4->config.r_a_tov = read_config->r_a_tov;
 3670 
 3671                 sli4->config.link_module_type = read_config->lmt;
 3672 
 3673                 sli4->config.max_qcount[SLI_QTYPE_EQ] = read_config->eq_count;
 3674                 sli4->config.max_qcount[SLI_QTYPE_CQ] = read_config->cq_count;
 3675                 sli4->config.max_qcount[SLI_QTYPE_WQ] = read_config->wq_count;
 3676                 sli4->config.max_qcount[SLI_QTYPE_RQ] = read_config->rq_count;
 3677 
 3678                 /*
 3679                  * READ_CONFIG doesn't give the max number of MQ. Applications
 3680                  * will typically want 1, but we may need another at some future
 3681                  * date. Dummy up a "max" MQ count here.
 3682                  */
 3683                 sli4->config.max_qcount[SLI_QTYPE_MQ] = SLI_USER_MQ_COUNT;
 3684         } else {
 3685                 ocs_log_err(sli4->os, "bad READ_CONFIG write\n");
 3686                 return -1;
 3687         }
 3688 
 3689         if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3690                 sli4_res_common_get_sli4_parameters_t   *parms = (sli4_res_common_get_sli4_parameters_t *)
 3691                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
 3692 
 3693                 if (sli_bmbx_command(sli4)) {
 3694                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_SLI4_PARAMETERS)\n");
 3695                         return -1;
 3696                 } else if (parms->hdr.status) {
 3697                         ocs_log_err(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x att'l %#x\n",
 3698                                         parms->hdr.status, parms->hdr.additional_status);
 3699                         return -1;
 3700                 }
 3701 
 3702                 sli4->config.auto_reg = parms->areg;
 3703                 sli4->config.auto_xfer_rdy = parms->agxf;
 3704                 sli4->config.hdr_template_req = parms->hdrr;
 3705                 sli4->config.t10_dif_inline_capable = parms->timm;
 3706                 sli4->config.t10_dif_separate_capable = parms->tsmm;
 3707 
 3708                 sli4->config.mq_create_version = parms->mqv;
 3709                 sli4->config.cq_create_version = parms->cqv;
 3710                 sli4->config.rq_min_buf_size = parms->min_rq_buffer_size;
 3711                 sli4->config.rq_max_buf_size = parms->max_rq_buffer_size;
 3712 
 3713                 sli4->config.qpage_count[SLI_QTYPE_EQ] = parms->eq_page_cnt;
 3714                 sli4->config.qpage_count[SLI_QTYPE_CQ] = parms->cq_page_cnt;
 3715                 sli4->config.qpage_count[SLI_QTYPE_MQ] = parms->mq_page_cnt;
 3716                 sli4->config.qpage_count[SLI_QTYPE_WQ] = parms->wq_page_cnt;
 3717                 sli4->config.qpage_count[SLI_QTYPE_RQ] = parms->rq_page_cnt;
 3718 
 3719                 /* save count methods and masks for each queue type */
 3720                 sli4->config.count_mask[SLI_QTYPE_EQ] = parms->eqe_count_mask;
 3721                 sli4->config.count_method[SLI_QTYPE_EQ] = parms->eqe_count_method;
 3722                 sli4->config.count_mask[SLI_QTYPE_CQ] = parms->cqe_count_mask;
 3723                 sli4->config.count_method[SLI_QTYPE_CQ] = parms->cqe_count_method;
 3724                 sli4->config.count_mask[SLI_QTYPE_MQ] = parms->mqe_count_mask;
 3725                 sli4->config.count_method[SLI_QTYPE_MQ] = parms->mqe_count_method;
 3726                 sli4->config.count_mask[SLI_QTYPE_WQ] = parms->wqe_count_mask;
 3727                 sli4->config.count_method[SLI_QTYPE_WQ] = parms->wqe_count_method;
 3728                 sli4->config.count_mask[SLI_QTYPE_RQ] = parms->rqe_count_mask;
 3729                 sli4->config.count_method[SLI_QTYPE_RQ] = parms->rqe_count_method;
 3730 
 3731                 /* now calculate max queue entries */
 3732                 sli_calc_max_qentries(sli4);
 3733 
 3734                 sli4->config.max_sgl_pages = parms->sgl_page_cnt;       /* max # of pages */
 3735                 sli4->config.sgl_page_sizes = parms->sgl_page_sizes;    /* bit map of available sizes */
 3736                 /* ignore HLM here. Use value from REQUEST_FEATURES */
 3737                 
 3738                 sli4->config.sge_supported_length = parms->sge_supported_length;
 3739                 if (sli4->config.sge_supported_length > OCS_MAX_SGE_SIZE)
 3740                         sli4->config.sge_supported_length = OCS_MAX_SGE_SIZE;
 3741 
 3742                 sli4->config.sgl_pre_registration_required = parms->sglr;
 3743                 /* default to using pre-registered SGL's */
 3744                 sli4->config.sgl_pre_registered = TRUE;
 3745 
 3746                 sli4->config.perf_hint = parms->phon;
 3747                 sli4->config.perf_wq_id_association = parms->phwq;
 3748 
 3749                 sli4->config.rq_batch = parms->rq_db_window;
 3750 
 3751                 /* save the fields for skyhawk SGL chaining */
 3752                 sli4->config.sgl_chaining_params.chaining_capable =
 3753                         (parms->sglc == 1);
 3754                 sli4->config.sgl_chaining_params.frag_num_field_offset =
 3755                         parms->frag_num_field_offset;
 3756                 sli4->config.sgl_chaining_params.frag_num_field_mask =
 3757                         (1ull << parms->frag_num_field_size) - 1;
 3758                 sli4->config.sgl_chaining_params.sgl_index_field_offset =
 3759                         parms->sgl_index_field_offset;
 3760                 sli4->config.sgl_chaining_params.sgl_index_field_mask =
 3761                         (1ull << parms->sgl_index_field_size) - 1;
 3762                 sli4->config.sgl_chaining_params.chain_sge_initial_value_lo =
 3763                         parms->chain_sge_initial_value_lo;
 3764                 sli4->config.sgl_chaining_params.chain_sge_initial_value_hi =
 3765                         parms->chain_sge_initial_value_hi;
 3766 
 3767                 /* Use the highest available WQE size. */
 3768                 if (parms->wqe_sizes & SLI4_128BYTE_WQE_SUPPORT) {
 3769                         sli4->config.wqe_size = SLI4_WQE_EXT_BYTES;
 3770                 } else {
 3771                         sli4->config.wqe_size = SLI4_WQE_BYTES;
 3772                 }
 3773         }
 3774 
 3775         if (sli_query_fw_config(sli4)) {
 3776                 ocs_log_err(sli4->os, "Error sending QUERY_FW_CONFIG\n");
 3777                 return -1;
 3778         }
 3779 
 3780         sli4->config.port_number = 0;
 3781 
 3782         /*
 3783          * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily
 3784          * uses VPD DMA buffer as the response won't fit in the embedded
 3785          * buffer.
 3786          */
 3787         if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
 3788                 sli4_res_common_get_cntl_attributes_t *attr = sli4->vpd.data.virt;
 3789 
 3790                 if (sli_bmbx_command(sli4)) {
 3791                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n");
 3792                         return -1;
 3793                 } else if (attr->hdr.status) {
 3794                         ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x att'l %#x\n",
 3795                                         attr->hdr.status, attr->hdr.additional_status);
 3796                         return -1;
 3797                 }
 3798 
 3799                 sli4->config.port_number = attr->port_number;
 3800 
 3801                 ocs_memcpy(sli4->config.bios_version_string, attr->bios_version_string,
 3802                                 sizeof(sli4->config.bios_version_string));
 3803         } else {
 3804                 ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
 3805                 return -1;
 3806         }
 3807 
 3808         if (ocs_dma_alloc(sli4->os, &get_cntl_addl_data, sizeof(sli4_res_common_get_cntl_addl_attributes_t),
 3809                           OCS_MIN_DMA_ALIGNMENT)) {
 3810                 ocs_log_err(sli4->os, "Failed to allocate memory for GET_CNTL_ADDL_ATTR data\n");
 3811         } else {
 3812                 if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
 3813                                                             &get_cntl_addl_data)) {
 3814                         sli4_res_common_get_cntl_addl_attributes_t *attr = get_cntl_addl_data.virt;
 3815 
 3816                         if (sli_bmbx_command(sli4)) {
 3817                                 ocs_log_crit(sli4->os,
 3818                                              "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n");
 3819                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3820                                 return -1;
 3821                         }
 3822                         if (attr->hdr.status) {
 3823                                 ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n",
 3824                                             attr->hdr.status);
 3825                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3826                                 return -1;
 3827                         }
 3828 
 3829                         ocs_memcpy(sli4->config.ipl_name, attr->ipl_file_name, sizeof(sli4->config.ipl_name));
 3830 
 3831                         ocs_log_debug(sli4->os, "IPL:%s \n", (char*)sli4->config.ipl_name);
 3832                 } else {
 3833                         ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n");
 3834                         ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3835                         return -1;
 3836                 }
 3837 
 3838                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3839         }
 3840 
 3841         if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3842                 sli4_res_common_get_port_name_t *port_name = (sli4_res_common_get_port_name_t *)(((uint8_t *)sli4->bmbx.virt) +
 3843                         offsetof(sli4_cmd_sli_config_t, payload.embed));
 3844 
 3845                 if (sli_bmbx_command(sli4)) {
 3846                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_PORT_NAME)\n");
 3847                         return -1;
 3848                 }
 3849 
 3850                 sli4->config.port_name[0] = port_name->port_name[sli4->config.port_number];
 3851         }
 3852         sli4->config.port_name[1] = '\0';
 3853 
 3854         if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
 3855                 sli4_cmd_read_rev_t     *read_rev = sli4->bmbx.virt;
 3856 
 3857                 if (sli_bmbx_command(sli4)) {
 3858                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_REV)\n");
 3859                         return -1;
 3860                 }
 3861                 if (read_rev->hdr.status) {
 3862                         ocs_log_err(sli4->os, "READ_REV bad status %#x\n",
 3863                                         read_rev->hdr.status);
 3864                         return -1;
 3865                 }
 3866 
 3867                 sli4->config.fw_rev[0] = read_rev->first_fw_id;
 3868                 ocs_memcpy(sli4->config.fw_name[0],read_rev->first_fw_name, sizeof(sli4->config.fw_name[0]));
 3869 
 3870                 sli4->config.fw_rev[1] = read_rev->second_fw_id;
 3871                 ocs_memcpy(sli4->config.fw_name[1],read_rev->second_fw_name, sizeof(sli4->config.fw_name[1]));
 3872 
 3873                 sli4->config.hw_rev[0] = read_rev->first_hw_revision;
 3874                 sli4->config.hw_rev[1] = read_rev->second_hw_revision;
 3875                 sli4->config.hw_rev[2] = read_rev->third_hw_revision;
 3876 
 3877                 ocs_log_debug(sli4->os, "FW1:%s (%08x) / FW2:%s (%08x)\n",
 3878                                 read_rev->first_fw_name, read_rev->first_fw_id,
 3879                                 read_rev->second_fw_name, read_rev->second_fw_id);
 3880 
 3881                 ocs_log_debug(sli4->os, "HW1: %08x / HW2: %08x\n", read_rev->first_hw_revision,
 3882                                 read_rev->second_hw_revision);
 3883 
 3884                 /* Check that all VPD data was returned */
 3885                 if (read_rev->returned_vpd_length != read_rev->actual_vpd_length) {
 3886                         ocs_log_test(sli4->os, "VPD length: available=%d returned=%d actual=%d\n",
 3887                                         read_rev->available_length,
 3888                                         read_rev->returned_vpd_length,
 3889                                         read_rev->actual_vpd_length);
 3890                 }
 3891                 sli4->vpd.length = read_rev->returned_vpd_length;
 3892         } else {
 3893                 ocs_log_err(sli4->os, "bad READ_REV write\n");
 3894                 return -1;
 3895         }
 3896 
 3897         if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3898                 sli4_cmd_read_nvparms_t *read_nvparms = sli4->bmbx.virt;
 3899 
 3900                 if (sli_bmbx_command(sli4)) {
 3901                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n");
 3902                         return -1;
 3903                 }
 3904                 if (read_nvparms->hdr.status) {
 3905                         ocs_log_err(sli4->os, "READ_NVPARMS bad status %#x\n",
 3906                                         read_nvparms->hdr.status);
 3907                         return -1;
 3908                 }
 3909 
 3910                 ocs_memcpy(sli4->config.wwpn, read_nvparms->wwpn, sizeof(sli4->config.wwpn));
 3911                 ocs_memcpy(sli4->config.wwnn, read_nvparms->wwnn, sizeof(sli4->config.wwnn));
 3912 
 3913                 ocs_log_debug(sli4->os, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 3914                                 sli4->config.wwpn[0],
 3915                                 sli4->config.wwpn[1],
 3916                                 sli4->config.wwpn[2],
 3917                                 sli4->config.wwpn[3],
 3918                                 sli4->config.wwpn[4],
 3919                                 sli4->config.wwpn[5],
 3920                                 sli4->config.wwpn[6],
 3921                                 sli4->config.wwpn[7]);
 3922                 ocs_log_debug(sli4->os, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 3923                                 sli4->config.wwnn[0],
 3924                                 sli4->config.wwnn[1],
 3925                                 sli4->config.wwnn[2],
 3926                                 sli4->config.wwnn[3],
 3927                                 sli4->config.wwnn[4],
 3928                                 sli4->config.wwnn[5],
 3929                                 sli4->config.wwnn[6],
 3930                                 sli4->config.wwnn[7]);
 3931         } else {
 3932                 ocs_log_err(sli4->os, "bad READ_NVPARMS write\n");
 3933                 return -1;
 3934         }
 3935 
 3936         return 0;
 3937 }
 3938 
 3939 /****************************************************************************
 3940  * Public functions
 3941  */
 3942 
 3943 /**
 3944  * @ingroup sli
 3945  * @brief Set up the SLI context.
 3946  *
 3947  * @param sli4 SLI context.
 3948  * @param os Device abstraction.
 3949  * @param port_type Protocol type of port (for example, FC and NIC).
 3950  *
 3951  * @return Returns 0 on success, or a non-zero value on failure.
 3952  */
 3953 int32_t
 3954 sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
 3955 {
 3956         uint32_t sli_intf = UINT32_MAX;
 3957         uint32_t pci_class_rev = 0;
 3958         uint32_t rev_id = 0;
 3959         uint32_t family = 0;
 3960         uint32_t i;
 3961         sli4_asic_entry_t *asic;
 3962 
 3963         ocs_memset(sli4, 0, sizeof(sli4_t));
 3964 
 3965         sli4->os = os;
 3966         sli4->port_type = port_type;
 3967 
 3968         /*
 3969          * Read the SLI_INTF register to discover the register layout
 3970          * and other capability information
 3971          */
 3972         sli_intf = ocs_config_read32(os, SLI4_INTF_REG);
 3973 
 3974         if (sli_intf_valid_check(sli_intf)) {
 3975                 ocs_log_err(os, "SLI_INTF is not valid\n");
 3976                 return -1;
 3977         }
 3978 
 3979         /* driver only support SLI-4 */
 3980         sli4->sli_rev = sli_intf_sli_revision(sli_intf);
 3981         if (4 != sli4->sli_rev) {
 3982                 ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n",
 3983                                 sli_intf);
 3984                 return -1;
 3985         }
 3986 
 3987         sli4->sli_family = sli_intf_sli_family(sli_intf);
 3988 
 3989         sli4->if_type = sli_intf_if_type(sli_intf);
 3990 
 3991         if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) {
 3992                 ocs_log_debug(os, "status=%#x error1=%#x error2=%#x\n",
 3993                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
 3994                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
 3995                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
 3996         }
 3997 
 3998         /*
 3999          * set the ASIC type and revision
 4000          */
 4001         pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION);
 4002         rev_id = sli_pci_rev_id(pci_class_rev);
 4003         family = sli4->sli_family;
 4004         if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) {
 4005                 uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
 4006                 family = sli_asic_gen(asic_id);
 4007         }
 4008 
 4009         for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) {
 4010                 if ((rev_id == asic->rev_id) && (family == asic->family)) {
 4011                         sli4->asic_type = asic->type;
 4012                         sli4->asic_rev = asic->rev;
 4013                         break;
 4014                 }
 4015         }
 4016         /* Fail if no matching asic type/rev was found */
 4017         if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) {
 4018                 ocs_log_err(os, "no matching asic family/rev found: %02x/%02x\n", family, rev_id);
 4019                 return -1;
 4020         }
 4021 
 4022         /*
 4023          * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
 4024          * entry, a CQ with a single 16 byte entry, and no event queue.
 4025          * Alignment must be 16 bytes as the low order address bits in the
 4026          * address register are also control / status.
 4027          */
 4028         if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE +
 4029                                 sizeof(sli4_mcqe_t), 16)) {
 4030                 ocs_log_err(os, "bootstrap mailbox allocation failed\n");
 4031                 return -1;
 4032         }
 4033 
 4034         if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
 4035                 ocs_log_err(os, "bad alignment for bootstrap mailbox\n");
 4036                 return -1;
 4037         }
 4038 
 4039         ocs_log_debug(os, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt,
 4040                 ocs_addr32_hi(sli4->bmbx.phys),
 4041                 ocs_addr32_lo(sli4->bmbx.phys),
 4042                 sli4->bmbx.size);
 4043 
 4044         /* TODO 4096 is arbitrary. What should this value actually be? */
 4045         if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) {
 4046                 /* Note that failure isn't fatal in this specific case */
 4047                 sli4->vpd.data.size = 0;
 4048                 ocs_log_test(os, "VPD buffer allocation failed\n");
 4049         }
 4050 
 4051         if (sli_fw_init(sli4)) {
 4052                 ocs_log_err(sli4->os, "FW initialization failed\n");
 4053                 return -1;
 4054         }
 4055 
 4056         /*
 4057          * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true
 4058          * in addition to any other desired features
 4059          */
 4060         sli4->config.features.flag.iaab = TRUE;
 4061         sli4->config.features.flag.npiv = TRUE;
 4062         sli4->config.features.flag.dif = TRUE;
 4063         sli4->config.features.flag.vf = TRUE;
 4064         sli4->config.features.flag.fcpc = TRUE;
 4065         sli4->config.features.flag.iaar = TRUE;
 4066         sli4->config.features.flag.hlm = TRUE;
 4067         sli4->config.features.flag.perfh = TRUE;
 4068         sli4->config.features.flag.rxseq = TRUE;
 4069         sli4->config.features.flag.rxri = TRUE;
 4070         sli4->config.features.flag.mrqp = TRUE;
 4071 
 4072         /* use performance hints if available */
 4073         if (sli4->config.perf_hint) {
 4074                 sli4->config.features.flag.perfh = TRUE;
 4075         }
 4076 
 4077         if (sli_request_features(sli4, &sli4->config.features, TRUE)) {
 4078                 return -1;
 4079         }
 4080 
 4081         if (sli_get_config(sli4)) {
 4082                 return -1;
 4083         }
 4084 
 4085         return 0;
 4086 }
 4087 
 4088 int32_t
 4089 sli_init(sli4_t *sli4)
 4090 {
 4091 
 4092         if (sli4->config.has_extents) {
 4093                 /* TODO COMMON_ALLOC_RESOURCE_EXTENTS */;
 4094                 ocs_log_test(sli4->os, "XXX need to implement extent allocation\n");
 4095                 return -1;
 4096         }
 4097 
 4098         sli4->config.features.flag.hlm = sli4->config.high_login_mode;
 4099         sli4->config.features.flag.rxseq = FALSE;
 4100         sli4->config.features.flag.rxri  = FALSE;
 4101 
 4102         if (sli_request_features(sli4, &sli4->config.features, FALSE)) {
 4103                 return -1;
 4104         }
 4105 
 4106         return 0;
 4107 }
 4108 
 4109 int32_t
 4110 sli_reset(sli4_t *sli4)
 4111 {
 4112         uint32_t        i;
 4113 
 4114         if (sli_fw_init(sli4)) {
 4115                 ocs_log_crit(sli4->os, "FW initialization failed\n");
 4116                 return -1;
 4117         }
 4118 
 4119         if (sli4->config.extent[0].base) {
 4120                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
 4121                 sli4->config.extent[0].base = NULL;
 4122         }
 4123 
 4124         for (i = 0; i < SLI_RSRC_MAX; i++) {
 4125                 if (sli4->config.extent[i].use_map) {
 4126                         ocs_bitmap_free(sli4->config.extent[i].use_map);
 4127                         sli4->config.extent[i].use_map = NULL;
 4128                 }
 4129                 sli4->config.extent[i].base = NULL;
 4130         }
 4131 
 4132         if (sli_get_config(sli4)) {
 4133                 return -1;
 4134         }
 4135 
 4136         return 0;
 4137 }
 4138 
 4139 /**
 4140  * @ingroup sli
 4141  * @brief Issue a Firmware Reset.
 4142  *
 4143  * @par Description
 4144  * Issues a Firmware Reset to the chip.  This reset affects the entire chip,
 4145  * so all PCI function on the same PCI bus and device are affected.
 4146  * @n @n This type of reset can be used to activate newly downloaded firmware.
 4147  * @n @n The driver should be considered to be in an unknown state after this
 4148  * reset and should be reloaded.
 4149  *
 4150  * @param sli4 SLI context.
 4151  *
 4152  * @return Returns 0 on success, or -1 otherwise.
 4153  */
 4154 
 4155 int32_t
 4156 sli_fw_reset(sli4_t *sli4)
 4157 {
 4158         uint32_t val;
 4159         uint32_t ready;
 4160 
 4161         /*
 4162          * Firmware must be ready before issuing the reset.
 4163          */
 4164         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 4165         if (!ready) {
 4166                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
 4167                 return -1;
 4168         }
 4169         switch(sli4->if_type) {
 4170         case SLI4_IF_TYPE_BE3_SKH_PF:
 4171                 /* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */
 4172                 val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR);
 4173                 val |= SLI4_PCI_SOFT_RESET_MASK;
 4174                 ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val);
 4175                 break;
 4176         case SLI4_IF_TYPE_LANCER_FC_ETH:
 4177                 /* Lancer uses PHYDEV_CONTROL */
 4178 
 4179                 val = SLI4_PHYDEV_CONTROL_FRST;
 4180                 sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, val);
 4181                 break;
 4182         default:
 4183                 ocs_log_test(sli4->os, "Unexpected iftype %d\n", sli4->if_type);
 4184                 return -1;
 4185                 break;
 4186         }
 4187 
 4188         /* wait for the FW to become ready after the reset */
 4189         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 4190         if (!ready) {
 4191                 ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n");
 4192                 return -1;
 4193         }
 4194         return 0;
 4195 }
 4196 
 4197 /**
 4198  * @ingroup sli
 4199  * @brief Tear down a SLI context.
 4200  *
 4201  * @param sli4 SLI context.
 4202  *
 4203  * @return Returns 0 on success, or non-zero otherwise.
 4204  */
 4205 int32_t
 4206 sli_teardown(sli4_t *sli4)
 4207 {
 4208         uint32_t i;
 4209 
 4210         if (sli4->config.extent[0].base) {
 4211                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
 4212                 sli4->config.extent[0].base = NULL;
 4213         }
 4214 
 4215         for (i = 0; i < SLI_RSRC_MAX; i++) {
 4216                 if (sli4->config.has_extents) {
 4217                         /* TODO COMMON_DEALLOC_RESOURCE_EXTENTS */;
 4218                 }
 4219 
 4220                 sli4->config.extent[i].base = NULL;
 4221 
 4222                 ocs_bitmap_free(sli4->config.extent[i].use_map);
 4223                 sli4->config.extent[i].use_map = NULL;
 4224         }
 4225 
 4226         if (sli_fw_term(sli4)) {
 4227                 ocs_log_err(sli4->os, "FW deinitialization failed\n");
 4228         }
 4229 
 4230         ocs_dma_free(sli4->os, &sli4->vpd.data);
 4231         ocs_dma_free(sli4->os, &sli4->bmbx);
 4232 
 4233         return 0;
 4234 }
 4235 
 4236 /**
 4237  * @ingroup sli
 4238  * @brief Register a callback for the given event.
 4239  *
 4240  * @param sli4 SLI context.
 4241  * @param which Event of interest.
 4242  * @param func Function to call when the event occurs.
 4243  * @param arg Argument passed to the callback function.
 4244  *
 4245  * @return Returns 0 on success, or non-zero otherwise.
 4246  */
 4247 int32_t
 4248 sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
 4249 {
 4250 
 4251         if (!sli4 || !func || (which >= SLI4_CB_MAX)) {
 4252                 ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n",
 4253                             sli4, which, func);
 4254                 return -1;
 4255         }
 4256 
 4257         switch (which) {
 4258         case SLI4_CB_LINK:
 4259                 sli4->link = func;
 4260                 sli4->link_arg = arg;
 4261                 break;
 4262         case SLI4_CB_FIP:
 4263                 sli4->fip = func;
 4264                 sli4->fip_arg = arg;
 4265                 break;
 4266         default:
 4267                 ocs_log_test(sli4->os, "unknown callback %#x\n", which);
 4268                 return -1;
 4269         }
 4270 
 4271         return 0;
 4272 }
 4273 
 4274 /**
 4275  * @ingroup sli
 4276  * @brief Initialize a queue object.
 4277  *
 4278  * @par Description
 4279  * This initializes the sli4_queue_t object members, including the underlying
 4280  * DMA memory.
 4281  *
 4282  * @param sli4 SLI context.
 4283  * @param q Pointer to queue object.
 4284  * @param qtype Type of queue to create.
 4285  * @param size Size of each entry.
 4286  * @param n_entries Number of entries to allocate.
 4287  * @param align Starting memory address alignment.
 4288  *
 4289  * @note Checks if using the existing DMA memory (if any) is possible. If not,
 4290  * it frees the existing memory and re-allocates.
 4291  *
 4292  * @return Returns 0 on success, or non-zero otherwise.
 4293  */
 4294 int32_t
 4295 __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype,
 4296                 size_t size, uint32_t n_entries, uint32_t align)
 4297 {
 4298 
 4299         if ((q->dma.virt == NULL) || (size != q->size) || (n_entries != q->length)) {
 4300                 if (q->dma.size) {
 4301                         ocs_dma_free(sli4->os, &q->dma);
 4302                 }
 4303 
 4304                 ocs_memset(q, 0, sizeof(sli4_queue_t));
 4305 
 4306                 if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) {
 4307                         ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
 4308                         return -1;
 4309                 }
 4310 
 4311                 ocs_memset(q->dma.virt, 0, size * n_entries);
 4312 
 4313                 ocs_lock_init(sli4->os, &q->lock, "%s lock[%d:%p]", 
 4314                         SLI_QNAME[qtype], ocs_instance(sli4->os), &q->lock);
 4315 
 4316                 q->type = qtype;
 4317                 q->size = size;
 4318                 q->length = n_entries;
 4319 
 4320                 /* Limit to hwf the queue size per interrupt */
 4321                 q->proc_limit = n_entries / 2;
 4322 
 4323                 switch(q->type) {
 4324                 case SLI_QTYPE_EQ:
 4325                         q->posted_limit = q->length / 2;
 4326                         break;
 4327                 default:
 4328                         if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) ||
 4329                             (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) {
 4330                                 /* For Skyhawk, ring the doorbell more often */
 4331                                 q->posted_limit = 8;
 4332                         } else {
 4333                                 q->posted_limit = 64;
 4334                         }
 4335                         break;
 4336                 }
 4337         }
 4338 
 4339         return 0;
 4340 }
 4341 
 4342 /**
 4343  * @ingroup sli
 4344  * @brief Issue the command to create a queue.
 4345  *
 4346  * @param sli4 SLI context.
 4347  * @param q Pointer to queue object.
 4348  *
 4349  * @return Returns 0 on success, or non-zero otherwise.
 4350  */
 4351 int32_t
 4352 __sli_create_queue(sli4_t *sli4, sli4_queue_t *q)
 4353 {
 4354         sli4_res_common_create_queue_t *res_q = NULL;
 4355 
 4356         if (sli_bmbx_command(sli4)){
 4357                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n",
 4358                                 SLI_QNAME[q->type]);
 4359                 ocs_dma_free(sli4->os, &q->dma);
 4360                 return -1;
 4361         }
 4362         if (sli_res_sli_config(sli4->bmbx.virt)) {
 4363                 ocs_log_err(sli4->os, "bad status create %s\n", SLI_QNAME[q->type]);
 4364                 ocs_dma_free(sli4->os, &q->dma);
 4365                 return -1;
 4366         }
 4367         res_q = (void *)((uint8_t *)sli4->bmbx.virt +
 4368                         offsetof(sli4_cmd_sli_config_t, payload));
 4369 
 4370         if (res_q->hdr.status) {
 4371                 ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n",
 4372                                 SLI_QNAME[q->type],
 4373                                 res_q->hdr.status, res_q->hdr.additional_status);
 4374                 ocs_dma_free(sli4->os, &q->dma);
 4375                 return -1;
 4376         } else {
 4377                 q->id = res_q->q_id;
 4378                 q->doorbell_offset = res_q->db_offset;
 4379                 q->doorbell_rset = res_q->db_rs;
 4380 
 4381                 switch (q->type) {
 4382                 case SLI_QTYPE_EQ:
 4383                         /* No doorbell information in response for EQs */
 4384                         q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
 4385                         q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
 4386                         break;
 4387                 case SLI_QTYPE_CQ:
 4388                         /* No doorbell information in response for CQs */
 4389                         q->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
 4390                         q->doorbell_rset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
 4391                         break;
 4392                 case SLI_QTYPE_MQ:
 4393                         /* No doorbell information in response for MQs */
 4394                         q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off;
 4395                         q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset;
 4396                         break;
 4397                 case SLI_QTYPE_RQ:
 4398                         /* set the doorbell for non-skyhawks */
 4399                         if (!sli4->config.dual_ulp_capable) {
 4400                                 q->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
 4401                                 q->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
 4402                         }
 4403                         break;
 4404                 case SLI_QTYPE_WQ:
 4405                         /* set the doorbell for non-skyhawks */
 4406                         if (!sli4->config.dual_ulp_capable) {
 4407                                 q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off;
 4408                                 q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset;
 4409                         }
 4410                         break;
 4411                 default:
 4412                         break;
 4413                 }
 4414         }
 4415 
 4416         return 0;
 4417 }
 4418 
 4419 /**
 4420  * @ingroup sli
 4421  * @brief Get queue entry size.
 4422  *
 4423  * Get queue entry size given queue type.
 4424  *
 4425  * @param sli4 SLI context
 4426  * @param qtype Type for which the entry size is returned.
 4427  *
 4428  * @return Returns > 0 on success (queue entry size), or a negative value on failure.
 4429  */
 4430 int32_t
 4431 sli_get_queue_entry_size(sli4_t *sli4, uint32_t qtype)
 4432 {
 4433         uint32_t        size = 0;
 4434 
 4435         if (!sli4) {
 4436                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
 4437                 return -1;
 4438         }
 4439 
 4440         switch (qtype) {
 4441         case SLI_QTYPE_EQ:
 4442                 size = sizeof(uint32_t);
 4443                 break;
 4444         case SLI_QTYPE_CQ:
 4445                 size = 16;
 4446                 break;
 4447         case SLI_QTYPE_MQ:
 4448                 size = 256;
 4449                 break;
 4450         case SLI_QTYPE_WQ:
 4451                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4452                         size = sli4->config.wqe_size;
 4453                 } else {
 4454                         /* TODO */
 4455                         ocs_log_test(sli4->os, "unsupported queue entry size\n");
 4456                         return -1;
 4457                 }
 4458                 break;
 4459         case SLI_QTYPE_RQ:
 4460                 size = SLI4_FCOE_RQE_SIZE;
 4461                 break;
 4462         default:
 4463                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
 4464                 return -1;
 4465         }
 4466         return size;
 4467 }
 4468 
 4469 /**
 4470  * @ingroup sli
 4471  * @brief Modify the delay timer for all the EQs
 4472  *
 4473  * @param sli4 SLI context.
 4474  * @param eq Array of EQs.
 4475  * @param num_eq Count of EQs.
 4476  * @param shift Phase shift for staggering interrupts.
 4477  * @param delay_mult Delay multiplier for limiting interrupt frequency.
 4478  *
 4479  * @return Returns 0 on success, or -1 otherwise.
 4480  */
 4481 int32_t
 4482 sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
 4483 {
 4484 
 4485         sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult);
 4486 
 4487         if (sli_bmbx_command(sli4)) {
 4488                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
 4489                 return -1;
 4490         }
 4491         if (sli_res_sli_config(sli4->bmbx.virt)) {
 4492                 ocs_log_err(sli4->os, "bad status MODIFY EQ DELAY\n");
 4493                 return -1;
 4494         }
 4495 
 4496         return 0;
 4497 }
 4498 
 4499 /**
 4500  * @ingroup sli
 4501  * @brief Allocate a queue.
 4502  *
 4503  * @par Description
 4504  * Allocates DMA memory and configures the requested queue type.
 4505  *
 4506  * @param sli4 SLI context.
 4507  * @param qtype Type of queue to create.
 4508  * @param q Pointer to the queue object.
 4509  * @param n_entries Number of entries to allocate.
 4510  * @param assoc Associated queue (that is, the EQ for a CQ, the CQ for a MQ, and so on).
 4511  * @param ulp The ULP to bind, which is only used for WQ and RQs
 4512  *
 4513  * @return Returns 0 on success, or -1 otherwise.
 4514  */
 4515 int32_t
 4516 sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries,
 4517                 sli4_queue_t *assoc, uint16_t ulp)
 4518 {
 4519         int32_t         size;
 4520         uint32_t        align = 0;
 4521         sli4_create_q_fn_t create = NULL;
 4522 
 4523         if (!sli4 || !q) {
 4524                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
 4525                 return -1;
 4526         }
 4527 
 4528         /* get queue size */
 4529         size = sli_get_queue_entry_size(sli4, qtype);
 4530         if (size < 0)
 4531                 return -1;
 4532         align = SLI_PAGE_SIZE;
 4533 
 4534         switch (qtype) {
 4535         case SLI_QTYPE_EQ:
 4536                 create = sli_cmd_common_create_eq;
 4537                 break;
 4538         case SLI_QTYPE_CQ:
 4539                 create = sli_cmd_common_create_cq;
 4540                 break;
 4541         case SLI_QTYPE_MQ:
 4542                 /* Validate the number of entries */
 4543                 switch (n_entries) {
 4544                 case 16:
 4545                 case 32:
 4546                 case 64:
 4547                 case 128:
 4548                         break;
 4549                 default:
 4550                         ocs_log_test(sli4->os, "illegal n_entries value %d for MQ\n", n_entries);
 4551                         return -1;
 4552                 }
 4553                 assoc->u.flag.is_mq = TRUE;
 4554                 create = sli_cmd_common_create_mq_ext;
 4555                 break;
 4556         case SLI_QTYPE_WQ:
 4557                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4558                         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
 4559                                 create = sli_cmd_fcoe_wq_create;
 4560                         } else {
 4561                                 create = sli_cmd_fcoe_wq_create_v1;
 4562                         }
 4563                 } else {
 4564                         /* TODO */
 4565                         ocs_log_test(sli4->os, "unsupported WQ create\n");
 4566                         return -1;
 4567                 }
 4568                 break;
 4569         default:
 4570                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
 4571                 return -1;
 4572         }
 4573 
 4574         if (__sli_queue_init(sli4, q, qtype, size, n_entries, align)) {
 4575                 ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
 4576                 return -1;
 4577         }
 4578 
 4579         if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, assoc ? assoc->id : 0, ulp)) {
 4580                 if (__sli_create_queue(sli4, q)) {
 4581                         ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]);
 4582                         return -1;
 4583                 }
 4584                 q->ulp = ulp;
 4585         } else {
 4586                 ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]);
 4587                 return -1;
 4588         }
 4589 
 4590         return 0;
 4591 }
 4592 
 4593 /**
 4594  * @ingroup sli
 4595  * @brief Allocate a c queue set.
 4596  *
 4597  * @param sli4 SLI context.
 4598  * @param num_cqs to create
 4599  * @param qs Pointers to the queue objects.
 4600  * @param n_entries Number of entries to allocate per CQ.
 4601  * @param eqs Associated event queues
 4602  *
 4603  * @return Returns 0 on success, or -1 otherwise.
 4604  */
 4605 int32_t
 4606 sli_cq_alloc_set(sli4_t *sli4, sli4_queue_t *qs[], uint32_t num_cqs,
 4607                  uint32_t n_entries, sli4_queue_t *eqs[])
 4608 {
 4609         uint32_t i, offset = 0,  page_bytes = 0, payload_size, cmd_size = 0;
 4610         uint32_t p = 0, page_size = 0, n_cqe = 0, num_pages_cq;
 4611         uintptr_t addr;
 4612         ocs_dma_t dma;
 4613         sli4_req_common_create_cq_set_v0_t  *req = NULL;
 4614         sli4_res_common_create_queue_set_t *res = NULL;
 4615 
 4616         if (!sli4) {
 4617                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
 4618                 return -1;
 4619         }
 4620 
 4621         memset(&dma, 0, sizeof(dma));
 4622 
 4623         /* Align the queue DMA memory */
 4624         for (i = 0; i < num_cqs; i++) {
 4625                 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_CQ, SLI4_CQE_BYTES,
 4626                         n_entries, SLI_PAGE_SIZE)) {
 4627                         ocs_log_err(sli4->os, "Queue init failed.\n");
 4628                         goto error;
 4629                 }
 4630         }
 4631 
 4632         n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES;
 4633         switch (n_cqe) {
 4634         case 256:
 4635         case 512:
 4636         case 1024:
 4637         case 2048:
 4638                 page_size = 1;
 4639                 break;
 4640         case 4096:
 4641                 page_size = 2;
 4642                 break;
 4643         default:
 4644                 return -1;
 4645         }
 4646 
 4647         page_bytes = page_size * SLI_PAGE_SIZE;
 4648         num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes);
 4649         cmd_size = sizeof(sli4_req_common_create_cq_set_v0_t) + (8 * num_pages_cq * num_cqs);
 4650         payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_set_t));
 4651 
 4652         if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
 4653                 ocs_log_err(sli4->os, "DMA allocation failed\n");
 4654                 goto error;
 4655         }
 4656         ocs_memset(dma.virt, 0, payload_size);
 4657 
 4658         if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 
 4659                         payload_size, &dma) == -1) {
 4660                 goto error;
 4661         }
 4662 
 4663         /* Fill the request structure */
 4664 
 4665         req = (sli4_req_common_create_cq_set_v0_t *)((uint8_t *)dma.virt);
 4666         req->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ_SET;
 4667         req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 4668         req->hdr.version = 0;
 4669         req->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 4670         req->page_size = page_size;
 4671 
 4672         req->num_pages = num_pages_cq;
 4673         switch (req->num_pages) {
 4674         case 1:
 4675                 req->cqecnt = SLI4_CQ_CNT_256;
 4676                 break;
 4677         case 2:
 4678                 req->cqecnt = SLI4_CQ_CNT_512;
 4679                 break;
 4680         case 4:
 4681                 req->cqecnt = SLI4_CQ_CNT_1024;
 4682                 break;
 4683         case 8:
 4684                 req->cqecnt = SLI4_CQ_CNT_LARGE;
 4685                 req->cqe_count = n_cqe;
 4686                 break;
 4687         default:
 4688                 ocs_log_test(sli4->os, "num_pages %d not valid\n", req->num_pages);
 4689                 goto error;
 4690         }
 4691 
 4692         req->evt = TRUE;
 4693         req->valid = TRUE;
 4694         req->arm = FALSE;
 4695         req->num_cq_req = num_cqs;
 4696 
 4697         /* Fill page addresses of all the CQs. */
 4698         for (i = 0; i < num_cqs; i++) {
 4699                 req->eq_id[i] = eqs[i]->id;
 4700                 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += page_bytes) {
 4701                         req->page_physical_address[offset].low = ocs_addr32_lo(addr);
 4702                         req->page_physical_address[offset].high = ocs_addr32_hi(addr);
 4703                         offset++;
 4704                 }
 4705         }
 4706 
 4707         if (sli_bmbx_command(sli4)) {
 4708                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail CQSet\n");
 4709                 goto error;
 4710         }
 4711 
 4712         res = (void *)((uint8_t *)dma.virt);
 4713         if (res->hdr.status) {
 4714                 ocs_log_err(sli4->os, "bad create CQSet status=%#x addl=%#x\n",
 4715                         res->hdr.status, res->hdr.additional_status);
 4716                 goto error;
 4717         } else {
 4718                 /* Check if we got all requested CQs. */
 4719                 if (res->num_q_allocated != num_cqs) {
 4720                         ocs_log_crit(sli4->os, "Requested count CQs doesnt match.\n");
 4721                         goto error;
 4722                 }
 4723 
 4724                 /* Fill the resp cq ids. */
 4725                 for (i = 0; i < num_cqs; i++) {
 4726                         qs[i]->id = res->q_id + i;
 4727                         qs[i]->doorbell_offset = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].off;
 4728                         qs[i]->doorbell_rset   = regmap[SLI4_REG_EQCQ_DOORBELL][sli4->if_type].rset;
 4729                 }
 4730         }
 4731 
 4732         ocs_dma_free(sli4->os, &dma);
 4733 
 4734         return 0;
 4735 
 4736 error:
 4737         for (i = 0; i < num_cqs; i++) {
 4738                 if (qs[i]->dma.size) {
 4739                         ocs_dma_free(sli4->os, &qs[i]->dma);
 4740                 }
 4741         }
 4742 
 4743         if (dma.size) {
 4744                 ocs_dma_free(sli4->os, &dma);
 4745         }
 4746 
 4747         return -1;
 4748 }
 4749 
 4750 /**
 4751  * @ingroup sli
 4752  * @brief Free a queue.
 4753  *
 4754  * @par Description
 4755  * Frees DMA memory and de-registers the requested queue.
 4756  *
 4757  * @param sli4 SLI context.
 4758  * @param q Pointer to the queue object.
 4759  * @param destroy_queues Non-zero if the mailbox commands should be sent to destroy the queues.
 4760  * @param free_memory Non-zero if the DMA memory associated with the queue should be freed.
 4761  *
 4762  * @return Returns 0 on success, or -1 otherwise.
 4763  */
 4764 int32_t
 4765 sli_queue_free(sli4_t *sli4, sli4_queue_t *q, uint32_t destroy_queues, uint32_t free_memory)
 4766 {
 4767         sli4_destroy_q_fn_t destroy = NULL;
 4768         int32_t         rc = -1;
 4769 
 4770         if (!sli4 || !q) {
 4771                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
 4772                 return -1;
 4773         }
 4774 
 4775         if (destroy_queues) {
 4776                 switch (q->type) {
 4777                 case SLI_QTYPE_EQ:
 4778                         destroy = sli_cmd_common_destroy_eq;
 4779                         break;
 4780                 case SLI_QTYPE_CQ:
 4781                         destroy = sli_cmd_common_destroy_cq;
 4782                         break;
 4783                 case SLI_QTYPE_MQ:
 4784                         destroy = sli_cmd_common_destroy_mq;
 4785                         break;
 4786                 case SLI_QTYPE_WQ:
 4787                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4788                                 destroy = sli_cmd_fcoe_wq_destroy;
 4789                         } else {
 4790                                 /* TODO */
 4791                                 ocs_log_test(sli4->os, "unsupported WQ destroy\n");
 4792                                 return -1;
 4793                         }
 4794                         break;
 4795                 case SLI_QTYPE_RQ:
 4796                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4797                                 destroy = sli_cmd_fcoe_rq_destroy;
 4798                         } else {
 4799                                 /* TODO */
 4800                                 ocs_log_test(sli4->os, "unsupported RQ destroy\n");
 4801                                 return -1;
 4802                         }
 4803                         break;
 4804                 default:
 4805                         ocs_log_test(sli4->os, "bad queue type %d\n",
 4806                                         q->type);
 4807                         return -1;
 4808                 }
 4809 
 4810                 /*
 4811                  * Destroying queues makes BE3 sad (version 0 interface type). Rely
 4812                  * on COMMON_FUNCTION_RESET to free host allocated queue resources
 4813                  * inside the SLI Port.
 4814                  */
 4815                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 4816                         destroy = NULL;
 4817                 }
 4818 
 4819                 /* Destroy the queue if the operation is defined */
 4820                 if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, q->id)) {
 4821                         sli4_res_hdr_t  *res = NULL;
 4822 
 4823                         if (sli_bmbx_command(sli4)){
 4824                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n",
 4825                                                 SLI_QNAME[q->type]);
 4826                         } else if (sli_res_sli_config(sli4->bmbx.virt)) {
 4827                                 ocs_log_err(sli4->os, "bad status destroy %s\n", SLI_QNAME[q->type]);
 4828                         } else {
 4829                                 res = (void *)((uint8_t *)sli4->bmbx.virt +
 4830                                                 offsetof(sli4_cmd_sli_config_t, payload));
 4831 
 4832                                 if (res->status) {
 4833                                         ocs_log_err(sli4->os, "bad destroy %s status=%#x addl=%#x\n",
 4834                                                         SLI_QNAME[q->type],
 4835                                                         res->status, res->additional_status);
 4836                                 } else {
 4837                                         rc = 0;
 4838                                 }
 4839                         }
 4840                 }
 4841         }
 4842 
 4843         if (free_memory) {
 4844                 ocs_lock_free(&q->lock);
 4845 
 4846                 if (ocs_dma_free(sli4->os, &q->dma)) {
 4847                         ocs_log_err(sli4->os, "%s queue ID %d free failed\n",
 4848                                     SLI_QNAME[q->type], q->id);
 4849                         rc = -1;
 4850                 }
 4851         }
 4852 
 4853         return rc;
 4854 }
 4855 
 4856 int32_t
 4857 sli_queue_reset(sli4_t *sli4, sli4_queue_t *q)
 4858 {
 4859 
 4860         ocs_lock(&q->lock);
 4861 
 4862         q->index = 0;
 4863         q->n_posted = 0;
 4864 
 4865         if (SLI_QTYPE_MQ == q->type) {
 4866                 q->u.r_idx = 0;
 4867         }
 4868 
 4869         if (q->dma.virt != NULL) {
 4870                 ocs_memset(q->dma.virt, 0, (q->size * (uint64_t)q->length));
 4871         }
 4872 
 4873         ocs_unlock(&q->lock);
 4874 
 4875         return 0;
 4876 }
 4877 
 4878 /**
 4879  * @ingroup sli
 4880  * @brief Check if the given queue is empty.
 4881  *
 4882  * @par Description
 4883  * If the valid bit of the current entry is unset, the queue is empty.
 4884  *
 4885  * @param sli4 SLI context.
 4886  * @param q Pointer to the queue object.
 4887  *
 4888  * @return Returns TRUE if empty, or FALSE otherwise.
 4889  */
 4890 int32_t
 4891 sli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q)
 4892 {
 4893         int32_t         rc = TRUE;
 4894         uint8_t         *qe = q->dma.virt;
 4895 
 4896         ocs_lock(&q->lock);
 4897 
 4898         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
 4899 
 4900         qe += q->index * q->size;
 4901 
 4902         rc = !sli_queue_entry_is_valid(q, qe, FALSE);
 4903 
 4904         ocs_unlock(&q->lock);
 4905 
 4906         return rc;
 4907 }
 4908 
 4909 /**
 4910  * @ingroup sli
 4911  * @brief Arm an EQ.
 4912  *
 4913  * @param sli4 SLI context.
 4914  * @param q Pointer to queue object.
 4915  * @param arm If TRUE, arm the EQ.
 4916  *
 4917  * @return Returns 0 on success, or non-zero otherwise.
 4918  */
 4919 int32_t
 4920 sli_queue_eq_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
 4921 {
 4922         uint32_t        val = 0;
 4923 
 4924         ocs_lock(&q->lock);
 4925                 val = sli_eq_doorbell(q->n_posted, q->id, arm);
 4926                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 4927                 q->n_posted = 0;
 4928         ocs_unlock(&q->lock);
 4929 
 4930         return 0;
 4931 }
 4932 
 4933 /**
 4934  * @ingroup sli
 4935  * @brief Arm a queue.
 4936  *
 4937  * @param sli4 SLI context.
 4938  * @param q Pointer to queue object.
 4939  * @param arm If TRUE, arm the queue.
 4940  *
 4941  * @return Returns 0 on success, or non-zero otherwise.
 4942  */
 4943 int32_t
 4944 sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
 4945 {
 4946         uint32_t        val = 0;
 4947 
 4948         ocs_lock(&q->lock);
 4949 
 4950         switch (q->type) {
 4951         case SLI_QTYPE_EQ:
 4952                 val = sli_eq_doorbell(q->n_posted, q->id, arm);
 4953                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 4954                 q->n_posted = 0;
 4955                 break;
 4956         case SLI_QTYPE_CQ:
 4957                 val = sli_cq_doorbell(q->n_posted, q->id, arm);
 4958                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 4959                 q->n_posted = 0;
 4960                 break;
 4961         default:
 4962                 ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n",
 4963                              SLI_QNAME[q->type]);
 4964         }
 4965 
 4966         ocs_unlock(&q->lock);
 4967 
 4968         return 0;
 4969 }
 4970 
 4971 /**
 4972  * @ingroup sli
 4973  * @brief Write an entry to the queue object.
 4974  *
 4975  * Note: Assumes the q->lock will be locked and released by the caller.
 4976  *
 4977  * @param sli4 SLI context.
 4978  * @param q Pointer to the queue object.
 4979  * @param entry Pointer to the entry contents.
 4980  *
 4981  * @return Returns queue index on success, or negative error value otherwise.
 4982  */
 4983 int32_t
 4984 _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 4985 {
 4986         int32_t         rc = 0;
 4987         uint8_t         *qe = q->dma.virt;
 4988         uint32_t        qindex;
 4989 
 4990         qindex = q->index;
 4991         qe += q->index * q->size;
 4992 
 4993         if (entry) {
 4994                 if ((SLI_QTYPE_WQ == q->type) && sli4->config.perf_wq_id_association) {
 4995                         sli_set_wq_id_association(entry, q->id);
 4996                 }
 4997 #if defined(OCS_INCLUDE_DEBUG)
 4998                 switch (q->type) {
 4999                 case SLI_QTYPE_WQ: {
 5000                         ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, "wqe", entry, q->size);
 5001                         break;
 5002                 }
 5003                 case SLI_QTYPE_MQ:
 5004                         /* Note: we don't really need to dump the whole 
 5005                          * 256 bytes, just do 64 */
 5006                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mqe outbound", entry, 64);
 5007                         break;
 5008 
 5009                 default:
 5010                         break;
 5011                 }
 5012 #endif
 5013                 ocs_memcpy(qe, entry, q->size);
 5014                 q->n_posted = 1;
 5015         }
 5016 
 5017         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5018 
 5019         rc = sli_queue_doorbell(sli4, q);
 5020 
 5021         q->index = (q->index + q->n_posted) & (q->length - 1);
 5022         q->n_posted = 0;
 5023 
 5024         if (rc < 0) {
 5025                 /* failure */
 5026                 return rc;
 5027         } else if (rc > 0) {
 5028                 /* failure, but we need to return a negative value on failure */
 5029                 return -rc;
 5030         } else {
 5031                 return qindex;
 5032         }
 5033 }
 5034 
 5035 /**
 5036  * @ingroup sli
 5037  * @brief Write an entry to the queue object.
 5038  *
 5039  * Note: Assumes the q->lock will be locked and released by the caller.
 5040  *
 5041  * @param sli4 SLI context.
 5042  * @param q Pointer to the queue object.
 5043  * @param entry Pointer to the entry contents.
 5044  *
 5045  * @return Returns queue index on success, or negative error value otherwise.
 5046  */
 5047 int32_t
 5048 sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 5049 {
 5050         int32_t rc;
 5051 
 5052         ocs_lock(&q->lock);
 5053                 rc = _sli_queue_write(sli4, q, entry);
 5054         ocs_unlock(&q->lock);
 5055 
 5056         return rc;
 5057 }
 5058 
 5059 /**
 5060  * @brief Check if the current queue entry is valid.
 5061  *
 5062  * @param q Pointer to the queue object.
 5063  * @param qe Pointer to the queue entry.
 5064  * @param clear Boolean to clear valid bit.
 5065  *
 5066  * @return Returns TRUE if the entry is valid, or FALSE otherwise.
 5067  */
 5068 static uint8_t
 5069 sli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear)
 5070 {
 5071         uint8_t         valid = FALSE;
 5072 
 5073         switch (q->type) {
 5074         case SLI_QTYPE_EQ:
 5075                 valid = ((sli4_eqe_t *)qe)->vld;
 5076                 if (valid && clear) {
 5077                         ((sli4_eqe_t *)qe)->vld = 0;
 5078                 }
 5079                 break;
 5080         case SLI_QTYPE_CQ:
 5081                 /*
 5082                  * For both MCQE and WCQE/RCQE, the valid bit
 5083                  * is bit 31 of dword 3 (0 based)
 5084                  */
 5085                 valid = (qe[15] & 0x80) != 0;
 5086                 if (valid & clear) {
 5087                         qe[15] &= ~0x80;
 5088                 }
 5089                 break;
 5090         case SLI_QTYPE_MQ:
 5091                 valid = q->index != q->u.r_idx;
 5092                 break;
 5093         case SLI_QTYPE_RQ:
 5094                 valid = TRUE;
 5095                 clear = FALSE;
 5096                 break;
 5097         default:
 5098                 ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type);
 5099         }
 5100 
 5101         if (clear) {
 5102                 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5103         }
 5104 
 5105         return valid;
 5106 }
 5107 
 5108 /**
 5109  * @ingroup sli
 5110  * @brief Read an entry from the queue object.
 5111  *
 5112  * @param sli4 SLI context.
 5113  * @param q Pointer to the queue object.
 5114  * @param entry Destination pointer for the queue entry contents.
 5115  *
 5116  * @return Returns 0 on success, or non-zero otherwise.
 5117  */
 5118 int32_t
 5119 sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 5120 {
 5121         int32_t         rc = 0;
 5122         uint8_t         *qe = q->dma.virt;
 5123         uint32_t        *qindex = NULL;
 5124 
 5125         if (SLI_QTYPE_MQ == q->type) {
 5126                 qindex = &q->u.r_idx;
 5127         } else {
 5128                 qindex = &q->index;
 5129         }
 5130 
 5131         ocs_lock(&q->lock);
 5132 
 5133         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
 5134 
 5135         qe += *qindex * q->size;
 5136 
 5137         if (!sli_queue_entry_is_valid(q, qe, TRUE)) {
 5138                 ocs_unlock(&q->lock);
 5139                 return -1;
 5140         }
 5141 
 5142         if (entry) {
 5143                 ocs_memcpy(entry, qe, q->size);
 5144 #if defined(OCS_INCLUDE_DEBUG)
 5145                 switch(q->type) {
 5146                 case SLI_QTYPE_CQ:
 5147                         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "cq", entry, q->size);
 5148                         break;
 5149                 case SLI_QTYPE_MQ:
 5150                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mq Compl", entry, 64);
 5151                         break;
 5152                 case SLI_QTYPE_EQ:
 5153                         ocs_dump32(OCS_DEBUG_ENABLE_EQ_DUMP, sli4->os, "eq Compl", entry, q->size);
 5154                         break;
 5155                 default:
 5156                         break;
 5157                 }
 5158 #endif
 5159         }
 5160 
 5161         switch (q->type) {
 5162                 case SLI_QTYPE_EQ:
 5163                 case SLI_QTYPE_CQ:
 5164                 case SLI_QTYPE_MQ:
 5165                         *qindex = (*qindex + 1) & (q->length - 1);
 5166                         if (SLI_QTYPE_MQ != q->type) {
 5167                                 q->n_posted++;
 5168                         }
 5169                         break;
 5170                 default:
 5171                         /* reads don't update the index */
 5172                         break;
 5173         }
 5174 
 5175         ocs_unlock(&q->lock);
 5176 
 5177         return rc;
 5178 }
 5179 
 5180 int32_t
 5181 sli_queue_index(sli4_t *sli4, sli4_queue_t *q)
 5182 {
 5183 
 5184         if (q) {
 5185                 return q->index;
 5186         } else {
 5187                 return -1;
 5188         }
 5189 }
 5190 
 5191 int32_t
 5192 sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
 5193 {
 5194         int32_t rc;
 5195 
 5196         ocs_lock(&q->lock);
 5197                 rc = _sli_queue_poke(sli4, q, index, entry);
 5198         ocs_unlock(&q->lock);
 5199 
 5200         return rc;
 5201 }
 5202 
 5203 int32_t
 5204 _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
 5205 {
 5206         int32_t         rc = 0;
 5207         uint8_t         *qe = q->dma.virt;
 5208 
 5209         if (index >= q->length) {
 5210                 return -1;
 5211         }
 5212 
 5213         qe += index * q->size;
 5214 
 5215         if (entry) {
 5216                 ocs_memcpy(qe, entry, q->size);
 5217         }
 5218 
 5219         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5220 
 5221         return rc;
 5222 }
 5223 
 5224 /**
 5225  * @ingroup sli
 5226  * @brief Allocate SLI Port resources.
 5227  *
 5228  * @par Description
 5229  * Allocate port-related resources, such as VFI, RPI, XRI, and so on.
 5230  * Resources are modeled using extents, regardless of whether the underlying
 5231  * device implements resource extents. If the device does not implement
 5232  * extents, the SLI layer models this as a single (albeit large) extent.
 5233  *
 5234  * @param sli4 SLI context.
 5235  * @param rtype Resource type (for example, RPI or XRI)
 5236  * @param rid Allocated resource ID.
 5237  * @param index Index into the bitmap.
 5238  *
 5239  * @return Returns 0 on success, or a non-zero value on failure.
 5240  */
 5241 int32_t
 5242 sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
 5243 {
 5244         int32_t         rc = 0;
 5245         uint32_t        size;
 5246         uint32_t        extent_idx;
 5247         uint32_t        item_idx;
 5248         int             status;
 5249 
 5250         *rid = UINT32_MAX;
 5251         *index = UINT32_MAX;
 5252 
 5253         switch (rtype) {
 5254         case SLI_RSRC_FCOE_VFI:
 5255         case SLI_RSRC_FCOE_VPI:
 5256         case SLI_RSRC_FCOE_RPI:
 5257         case SLI_RSRC_FCOE_XRI:
 5258                 status = ocs_bitmap_find(sli4->config.extent[rtype].use_map,
 5259                                 sli4->config.extent[rtype].map_size);
 5260                 if (status < 0) {
 5261                         ocs_log_err(sli4->os, "out of resource %d (alloc=%d)\n",
 5262                                         rtype, sli4->config.extent[rtype].n_alloc);
 5263                         rc = -1;
 5264                         break;
 5265                 } else {
 5266                         *index = status;
 5267                 }
 5268 
 5269                 size = sli4->config.extent[rtype].size;
 5270 
 5271                 extent_idx = *index / size;
 5272                 item_idx   = *index % size;
 5273 
 5274                 *rid = sli4->config.extent[rtype].base[extent_idx] + item_idx;
 5275 
 5276                 sli4->config.extent[rtype].n_alloc++;
 5277                 break;
 5278         default:
 5279                 rc = -1;
 5280         }
 5281 
 5282         return rc;
 5283 }
 5284 
 5285 /**
 5286  * @ingroup sli
 5287  * @brief Free the SLI Port resources.
 5288  *
 5289  * @par Description
 5290  * Free port-related resources, such as VFI, RPI, XRI, and so. See discussion of
 5291  * "extent" usage in sli_resource_alloc.
 5292  *
 5293  * @param sli4 SLI context.
 5294  * @param rtype Resource type (for example, RPI or XRI).
 5295  * @param rid Allocated resource ID.
 5296  *
 5297  * @return Returns 0 on success, or a non-zero value on failure.
 5298  */
 5299 int32_t
 5300 sli_resource_free(sli4_t *sli4, sli4_resource_e rtype, uint32_t rid)
 5301 {
 5302         int32_t         rc = -1;
 5303         uint32_t        x;
 5304         uint32_t        size, *base;
 5305 
 5306         switch (rtype) {
 5307         case SLI_RSRC_FCOE_VFI:
 5308         case SLI_RSRC_FCOE_VPI:
 5309         case SLI_RSRC_FCOE_RPI:
 5310         case SLI_RSRC_FCOE_XRI:
 5311                 /*
 5312                  * Figure out which extent contains the resource ID. I.e. find
 5313                  * the extent such that
 5314                  *   extent->base <= resource ID < extent->base + extent->size
 5315                  */
 5316                 base = sli4->config.extent[rtype].base;
 5317                 size = sli4->config.extent[rtype].size;
 5318 
 5319                 /*
 5320                  * In the case of FW reset, this may be cleared but the force_free path will
 5321                  * still attempt to free the resource. Prevent a NULL pointer access.
 5322                  */
 5323                 if (base != NULL) {
 5324                         for (x = 0; x < sli4->config.extent[rtype].number; x++) {
 5325                                 if ((rid >= base[x]) && (rid < (base[x] + size))) {
 5326                                         rid -= base[x];
 5327                                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map,
 5328                                                          (x * size) + rid);
 5329                                         rc = 0;
 5330                                         break;
 5331                                 }
 5332                         }
 5333                 }
 5334                 break;
 5335         default:
 5336                 ;
 5337         }
 5338 
 5339         return rc;
 5340 }
 5341 
 5342 int32_t
 5343 sli_resource_reset(sli4_t *sli4, sli4_resource_e rtype)
 5344 {
 5345         int32_t         rc = -1;
 5346         uint32_t        i;
 5347 
 5348         switch (rtype) {
 5349         case SLI_RSRC_FCOE_VFI:
 5350         case SLI_RSRC_FCOE_VPI:
 5351         case SLI_RSRC_FCOE_RPI:
 5352         case SLI_RSRC_FCOE_XRI:
 5353                 for (i = 0; i < sli4->config.extent[rtype].map_size; i++) {
 5354                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map, i);
 5355                 }
 5356                 rc = 0;
 5357                 break;
 5358         default:
 5359                 ;
 5360         }
 5361 
 5362         return rc;
 5363 }
 5364 
 5365 /**
 5366  * @ingroup sli
 5367  * @brief Parse an EQ entry to retrieve the CQ_ID for this event.
 5368  *
 5369  * @param sli4 SLI context.
 5370  * @param buf Pointer to the EQ entry.
 5371  * @param cq_id CQ_ID for this entry (only valid on success).
 5372  *
 5373  * @return
 5374  * - 0 if success.
 5375  * - < 0 if error.
 5376  * - > 0 if firmware detects EQ overflow.
 5377  */
 5378 int32_t
 5379 sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
 5380 {
 5381         sli4_eqe_t      *eqe = (void *)buf;
 5382         int32_t         rc = 0;
 5383 
 5384         if (!sli4 || !buf || !cq_id) {
 5385                 ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n",
 5386                                 sli4, buf, cq_id);
 5387                 return -1;
 5388         }
 5389 
 5390         switch (eqe->major_code) {
 5391         case SLI4_MAJOR_CODE_STANDARD:
 5392                 *cq_id = eqe->resource_id;
 5393                 break;
 5394         case SLI4_MAJOR_CODE_SENTINEL:
 5395                 ocs_log_debug(sli4->os, "sentinel EQE\n");
 5396                 rc = 1;
 5397                 break;
 5398         default:
 5399                 ocs_log_test(sli4->os, "Unsupported EQE: major %x minor %x\n",
 5400                                 eqe->major_code, eqe->minor_code);
 5401                 rc = -1;
 5402         }
 5403 
 5404         return rc;
 5405 }
 5406 
 5407 /**
 5408  * @ingroup sli
 5409  * @brief Parse a CQ entry to retrieve the event type and the associated queue.
 5410  *
 5411  * @param sli4 SLI context.
 5412  * @param cq CQ to process.
 5413  * @param cqe Pointer to the CQ entry.
 5414  * @param etype CQ event type.
 5415  * @param q_id Queue ID associated with this completion message
 5416  * (that is, MQ_ID, RQ_ID, and so on).
 5417  *
 5418  * @return
 5419  * - 0 if call completed correctly and CQE status is SUCCESS.
 5420  * - -1 if call failed (no CQE status).
 5421  * - Other value if call completed correctly and return value is a CQE status value.
 5422  */
 5423 int32_t
 5424 sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
 5425                 uint16_t *q_id)
 5426 {
 5427         int32_t rc = 0;
 5428 
 5429         if (!sli4 || !cq || !cqe || !etype) {
 5430                 ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n",
 5431                             sli4, cq, cqe, etype, q_id);
 5432                 return -1;
 5433         }
 5434 
 5435         if (cq->u.flag.is_mq) {
 5436                 sli4_mcqe_t     *mcqe = (void *)cqe;
 5437 
 5438                 if (mcqe->ae) {
 5439                         *etype = SLI_QENTRY_ASYNC;
 5440                 } else {
 5441                         *etype = SLI_QENTRY_MQ;
 5442                         rc = sli_cqe_mq(mcqe);
 5443                 }
 5444                 *q_id = -1;
 5445         } else if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5446                 rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id);
 5447         } else {
 5448                 ocs_log_test(sli4->os, "implement CQE parsing type = %#x\n",
 5449                              sli4->port_type);
 5450                 rc = -1;
 5451         }
 5452 
 5453         return rc;
 5454 }
 5455 
 5456 /**
 5457  * @ingroup sli
 5458  * @brief Cause chip to enter an unrecoverable error state.
 5459  *
 5460  * @par Description
 5461  * Cause chip to enter an unrecoverable error state. This is
 5462  * used when detecting unexpected FW behavior so FW can be
 5463  * hwted from the driver as soon as error is detected.
 5464  *
 5465  * @param sli4 SLI context.
 5466  * @param dump Generate dump as part of reset.
 5467  *
 5468  * @return Returns 0 if call completed correctly, or -1 if call failed (unsupported chip).
 5469  */
 5470 int32_t sli_raise_ue(sli4_t *sli4, uint8_t dump)
 5471 {
 5472 #define FDD 2
 5473         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5474                 switch(sli_get_asic_type(sli4)) {
 5475                 case SLI4_ASIC_TYPE_BE3: {
 5476                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR1, 0xffffffff);
 5477                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR2, 0);
 5478                         break;
 5479                 }
 5480                 case SLI4_ASIC_TYPE_SKYHAWK: {
 5481                         uint32_t value;
 5482                         value = ocs_config_read32(sli4->os, SLI4_SW_UE_REG);
 5483                         ocs_config_write32(sli4->os, SLI4_SW_UE_REG, (value | (1U << 24)));
 5484                         break;
 5485                 }
 5486                 default:
 5487                         ocs_log_test(sli4->os, "invalid asic type %d\n", sli_get_asic_type(sli4));
 5488                         return -1;
 5489                 }
 5490         } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) {       
 5491                 if (dump == FDD) {
 5492                         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, SLI4_SLIPORT_CONTROL_FDD | SLI4_SLIPORT_CONTROL_IP);
 5493                 } else {
 5494                         uint32_t value = SLI4_PHYDEV_CONTROL_FRST;
 5495                         if (dump == 1) {
 5496                                 value |= SLI4_PHYDEV_CONTROL_DD;
 5497                         }
 5498                         sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, value);
 5499                 }
 5500         } else {
 5501                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
 5502                 return -1;
 5503         }
 5504         return 0;
 5505 }
 5506 
 5507 /**
 5508  * @ingroup sli
 5509  * @brief Read the SLIPORT_STATUS register to to check if a dump is present.
 5510  *
 5511  * @param sli4 SLI context.
 5512  *
 5513  * @return  Returns 1 if the chip is ready, or 0 if the chip is not ready, 2 if fdp is present.
 5514  */
 5515 int32_t sli_dump_is_ready(sli4_t *sli4)
 5516 {
 5517         int32_t rc = 0;
 5518         uint32_t port_val;
 5519         uint32_t bmbx_val;
 5520         uint32_t uerr_lo;
 5521         uint32_t uerr_hi;
 5522         uint32_t uerr_mask_lo;
 5523         uint32_t uerr_mask_hi;
 5524 
 5525         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5526                 /* for iftype=0, dump ready when UE is encountered */
 5527                 uerr_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
 5528                 uerr_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
 5529                 uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
 5530                 uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
 5531                 if ((uerr_lo & ~uerr_mask_lo) || (uerr_hi & ~uerr_mask_hi)) {
 5532                         rc = 1;
 5533                 }
 5534 
 5535         } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) {
 5536                 /*
 5537                  * Ensure that the port is ready AND the mailbox is
 5538                  * ready before signaling that the dump is ready to go.
 5539                  */
 5540                 port_val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5541                 bmbx_val = sli_reg_read(sli4, SLI4_REG_BMBX);
 5542 
 5543                 if ((bmbx_val & SLI4_BMBX_RDY) &&
 5544                     SLI4_PORT_STATUS_READY(port_val)) { 
 5545                         if(SLI4_PORT_STATUS_DUMP_PRESENT(port_val)) {
 5546                                 rc = 1;
 5547                         }else if( SLI4_PORT_STATUS_FDP_PRESENT(port_val)) {
 5548                                 rc = 2;
 5549                         }
 5550                 }
 5551         } else {
 5552                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
 5553                 return -1;
 5554         }
 5555         return rc;
 5556 }
 5557 
 5558 /**
 5559  * @ingroup sli
 5560  * @brief Read the SLIPORT_STATUS register to check if a dump is present.
 5561  *
 5562  * @param sli4 SLI context.
 5563  *
 5564  * @return
 5565  * - 0 if call completed correctly and no dump is present.
 5566  * - 1 if call completed and dump is present.
 5567  * - -1 if call failed (unsupported chip).
 5568  */
 5569 int32_t sli_dump_is_present(sli4_t *sli4)
 5570 {
 5571         uint32_t val;
 5572         uint32_t ready;
 5573 
 5574         if (SLI4_IF_TYPE_LANCER_FC_ETH != sli_get_if_type(sli4)) {
 5575                 ocs_log_test(sli4->os, "Function only supported for I/F type 2");
 5576                 return -1;
 5577         }
 5578 
 5579         /* If the chip is not ready, then there cannot be a dump */
 5580         ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US);
 5581         if (!ready) {
 5582                 return 0;
 5583         }
 5584 
 5585         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5586         if (UINT32_MAX == val) {
 5587                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
 5588                 return -1;
 5589         } else {
 5590                 return ((val & SLI4_PORT_STATUS_DIP) ? 1 : 0);
 5591         }
 5592 }
 5593 
 5594 /**
 5595  * @ingroup sli
 5596  * @brief Read the SLIPORT_STATUS register to check if the reset required is set.
 5597  *
 5598  * @param sli4 SLI context.
 5599  *
 5600  * @return
 5601  * - 0 if call completed correctly and reset is not required.
 5602  * - 1 if call completed and reset is required.
 5603  * - -1 if call failed.
 5604  */
 5605 int32_t sli_reset_required(sli4_t *sli4)
 5606 {
 5607         uint32_t val;
 5608 
 5609         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5610                 ocs_log_test(sli4->os, "reset required N/A for iftype 0\n");
 5611                 return 0;
 5612         }
 5613 
 5614         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5615         if (UINT32_MAX == val) {
 5616                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
 5617                 return -1;
 5618         } else {
 5619                 return ((val & SLI4_PORT_STATUS_RN) ? 1 : 0);
 5620         }
 5621 }
 5622 
 5623 /**
 5624  * @ingroup sli
 5625  * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if
 5626  * the port status indicates that a FW error has occurred.
 5627  *
 5628  * @param sli4 SLI context.
 5629  *
 5630  * @return
 5631  * - 0 if call completed correctly and no FW error occurred.
 5632  * - > 0 which indicates that a FW error has occurred.
 5633  * - -1 if call failed.
 5634  */
 5635 int32_t sli_fw_error_status(sli4_t *sli4)
 5636 {
 5637         uint32_t sliport_semaphore;
 5638         int32_t rc = 0;
 5639 
 5640         sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
 5641         if (UINT32_MAX == sliport_semaphore) {
 5642                 ocs_log_err(sli4->os, "error reading SLIPORT_SEMAPHORE register\n");
 5643                 return 1;
 5644         }
 5645         rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0);
 5646 
 5647         if (rc == 0) {
 5648                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
 5649                     (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) {
 5650                         uint32_t uerr_mask_lo, uerr_mask_hi;
 5651                         uint32_t uerr_status_lo, uerr_status_hi;
 5652 
 5653                         uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
 5654                         uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
 5655                         uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
 5656                         uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
 5657                         if ((uerr_mask_lo & uerr_status_lo) != 0 ||
 5658                             (uerr_mask_hi & uerr_status_hi) != 0) {
 5659                                 rc = 1;
 5660                         }
 5661                 } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type)) {
 5662                         uint32_t sliport_status;
 5663 
 5664                         sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5665                         rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0);
 5666                 }
 5667         }
 5668         return rc;
 5669 }
 5670 
 5671 /**
 5672  * @ingroup sli
 5673  * @brief Determine if the chip FW is in a ready state
 5674  *
 5675  * @param sli4 SLI context.
 5676  *
 5677  * @return
 5678  * - 0 if call completed correctly and FW is not ready.
 5679  * - 1 if call completed correctly and FW is ready.
 5680  * - -1 if call failed.
 5681  */
 5682 int32_t
 5683 sli_fw_ready(sli4_t *sli4)
 5684 {
 5685         uint32_t val;
 5686         int32_t rc = -1;
 5687 
 5688         /*
 5689          * Is firmware ready for operation? Check needed depends on IF_TYPE
 5690          */
 5691         if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
 5692             SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type) {
 5693                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
 5694                 rc = ((SLI4_PORT_SEMAPHORE_STATUS_POST_READY ==
 5695                        SLI4_PORT_SEMAPHORE_PORT(val)) &&
 5696                       (!SLI4_PORT_SEMAPHORE_IN_ERR(val)) ? 1 : 0);
 5697         } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) {
 5698                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5699                 rc = (SLI4_PORT_STATUS_READY(val) ? 1 : 0);
 5700         }
 5701         return rc;
 5702 }
 5703 
 5704 /**
 5705  * @ingroup sli
 5706  * @brief Determine if the link can be configured
 5707  *
 5708  * @param sli4 SLI context.
 5709  *
 5710  * @return
 5711  * - 0 if link is not configurable.
 5712  * - 1 if link is configurable.
 5713  */
 5714 int32_t sli_link_is_configurable(sli4_t *sli)
 5715 {
 5716         int32_t rc = 0;
 5717         /*
 5718          * Link config works on: Skyhawk and Lancer
 5719          * Link config does not work on: LancerG6
 5720          */
 5721 
 5722         switch (sli_get_asic_type(sli)) {
 5723         case SLI4_ASIC_TYPE_SKYHAWK:
 5724         case SLI4_ASIC_TYPE_LANCER:
 5725         case SLI4_ASIC_TYPE_CORSAIR:
 5726                 rc = 1;
 5727                 break;
 5728         case SLI4_ASIC_TYPE_LANCERG6:
 5729         case SLI4_ASIC_TYPE_BE3:
 5730         default:
 5731                 rc = 0;
 5732                 break;
 5733         }
 5734 
 5735         return rc;
 5736 
 5737 }
 5738 
 5739 /* vim: set noexpandtab textwidth=120: */
 5740 
 5741 /**
 5742  * @ingroup sli_fc
 5743  * @brief Write an FCOE_WQ_CREATE command.
 5744  *
 5745  * @param sli4 SLI context.
 5746  * @param buf Destination buffer for the command.
 5747  * @param size Buffer size, in bytes.
 5748  * @param qmem DMA memory for the queue.
 5749  * @param cq_id Associated CQ_ID.
 5750  * @param ulp The ULP to bind
 5751  *
 5752  * @note This creates a Version 0 message.
 5753  *
 5754  * @return Returns the number of bytes written.
 5755  */
 5756 int32_t
 5757 sli_cmd_fcoe_wq_create(sli4_t *sli4, void *buf, size_t size,
 5758                        ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp)
 5759 {
 5760         sli4_req_fcoe_wq_create_t       *wq = NULL;
 5761         uint32_t        sli_config_off = 0;
 5762         uint32_t        p;
 5763         uintptr_t       addr;
 5764 
 5765         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5766                 uint32_t payload_size;
 5767 
 5768                 /* Payload length must accommodate both request and response */
 5769                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_t),
 5770                                 sizeof(sli4_res_common_create_queue_t));
 5771 
 5772                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 5773                                 NULL);
 5774         }
 5775         wq = (sli4_req_fcoe_wq_create_t *)((uint8_t *)buf + sli_config_off);
 5776 
 5777         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
 5778         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 5779         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_t) -
 5780                                         sizeof(sli4_req_hdr_t);
 5781         /* valid values for number of pages: 1-4 (sec 4.5.1) */
 5782         wq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 5783         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V0_MAX_PAGES)) {
 5784                 return 0;
 5785         }
 5786 
 5787         wq->cq_id = cq_id;
 5788 
 5789         if (sli4->config.dual_ulp_capable) {
 5790                 wq->dua = 1;
 5791                 wq->bqu = 1;
 5792                 wq->ulp = ulp;
 5793         }
 5794 
 5795         for (p = 0, addr = qmem->phys;
 5796                         p < wq->num_pages;
 5797                         p++, addr += SLI_PAGE_SIZE) {
 5798                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 5799                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
 5800         }
 5801 
 5802         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_t));
 5803 }
 5804 
 5805 /**
 5806  * @ingroup sli_fc
 5807  * @brief Write an FCOE_WQ_CREATE_V1 command.
 5808  *
 5809  * @param sli4 SLI context.
 5810  * @param buf Destination buffer for the command.
 5811  * @param size Buffer size, in bytes.
 5812  * @param qmem DMA memory for the queue.
 5813  * @param cq_id Associated CQ_ID.
 5814  * @param ignored This parameter carries the ULP for WQ (ignored for V1)
 5815 
 5816  *
 5817  * @return Returns the number of bytes written.
 5818  */
 5819 int32_t
 5820 sli_cmd_fcoe_wq_create_v1(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
 5821                           uint16_t cq_id, uint16_t ignored)
 5822 {
 5823         sli4_req_fcoe_wq_create_v1_t    *wq = NULL;
 5824         uint32_t        sli_config_off = 0;
 5825         uint32_t        p;
 5826         uintptr_t       addr;
 5827         uint32_t        page_size = 0;
 5828         uint32_t        page_bytes = 0;
 5829         uint32_t        n_wqe = 0;
 5830 
 5831         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5832                 uint32_t payload_size;
 5833 
 5834                 /* Payload length must accommodate both request and response */
 5835                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_v1_t),
 5836                                 sizeof(sli4_res_common_create_queue_t));
 5837 
 5838                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 5839                                 NULL);
 5840         }
 5841         wq = (sli4_req_fcoe_wq_create_v1_t *)((uint8_t *)buf + sli_config_off);
 5842 
 5843         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
 5844         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 5845         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_v1_t) -
 5846                                         sizeof(sli4_req_hdr_t);
 5847         wq->hdr.version = 1;
 5848 
 5849         n_wqe = qmem->size / sli4->config.wqe_size;
 5850 
 5851         /* This heuristic to determine the page size is simplistic 
 5852          * but could be made more sophisticated
 5853          */
 5854         switch (qmem->size) {
 5855         case 4096:
 5856         case 8192:
 5857         case 16384:
 5858         case 32768:
 5859                 page_size = 1;
 5860                 break;
 5861         case 65536:
 5862                 page_size = 2;
 5863                 break;
 5864         case 131072:
 5865                 page_size = 4;
 5866                 break;
 5867         case 262144:
 5868                 page_size = 8;
 5869                 break;
 5870         case 524288:
 5871                 page_size = 10;
 5872                 break;
 5873         default:
 5874                 return 0;
 5875         }
 5876         page_bytes = page_size * SLI_PAGE_SIZE;
 5877 
 5878         /* valid values for number of pages: 1-8 */
 5879         wq->num_pages = sli_page_count(qmem->size, page_bytes);
 5880         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V1_MAX_PAGES)) {
 5881                 return 0;
 5882         }
 5883 
 5884         wq->cq_id = cq_id;
 5885 
 5886         wq->page_size = page_size;
 5887 
 5888         if (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) {
 5889                 wq->wqe_size = SLI4_WQE_EXT_SIZE;
 5890         } else {
 5891                 wq->wqe_size = SLI4_WQE_SIZE;
 5892         }
 5893 
 5894         wq->wqe_count = n_wqe;
 5895 
 5896         for (p = 0, addr = qmem->phys;
 5897                         p < wq->num_pages;
 5898                         p++, addr += page_bytes) {
 5899                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 5900                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
 5901         }
 5902 
 5903         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_v1_t));
 5904 }
 5905 
 5906 /**
 5907  * @ingroup sli_fc
 5908  * @brief Write an FCOE_WQ_DESTROY command.
 5909  *
 5910  * @param sli4 SLI context.
 5911  * @param buf Destination buffer for the command.
 5912  * @param size Buffer size, in bytes.
 5913  * @param wq_id WQ_ID.
 5914  *
 5915  * @return Returns the number of bytes written.
 5916  */
 5917 int32_t
 5918 sli_cmd_fcoe_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t wq_id)
 5919 {
 5920         sli4_req_fcoe_wq_destroy_t      *wq = NULL;
 5921         uint32_t        sli_config_off = 0;
 5922 
 5923         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5924                 uint32_t payload_size;
 5925 
 5926                 /* Payload length must accommodate both request and response */
 5927                 payload_size = max(sizeof(sli4_req_fcoe_wq_destroy_t),
 5928                                 sizeof(sli4_res_hdr_t));
 5929 
 5930                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 5931                                 NULL);
 5932         }
 5933         wq = (sli4_req_fcoe_wq_destroy_t *)((uint8_t *)buf + sli_config_off);
 5934 
 5935         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_DESTROY;
 5936         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 5937         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_destroy_t) -
 5938                                         sizeof(sli4_req_hdr_t);
 5939 
 5940         wq->wq_id = wq_id;
 5941 
 5942         return(sli_config_off + sizeof(sli4_req_fcoe_wq_destroy_t));
 5943 }
 5944 
 5945 /**
 5946  * @ingroup sli_fc
 5947  * @brief Write an FCOE_POST_SGL_PAGES command.
 5948  *
 5949  * @param sli4 SLI context.
 5950  * @param buf Destination buffer for the command.
 5951  * @param size Buffer size, in bytes.
 5952  * @param xri starting XRI
 5953  * @param xri_count XRI
 5954  * @param page0 First SGL memory page.
 5955  * @param page1 Second SGL memory page (optional).
 5956  * @param dma DMA buffer for non-embedded mailbox command (options)
 5957  *
 5958  * if non-embedded mbx command is used, dma buffer must be at least (32 + xri_count*16) in length
 5959  *
 5960  * @return Returns the number of bytes written.
 5961  */
 5962 int32_t
 5963 sli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size,
 5964                 uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma)
 5965 {
 5966         sli4_req_fcoe_post_sgl_pages_t  *post = NULL;
 5967         uint32_t        sli_config_off = 0;
 5968         uint32_t        i;
 5969 
 5970         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5971                 uint32_t payload_size;
 5972 
 5973                 /* Payload length must accommodate both request and response */
 5974                 payload_size = max(sizeof(sli4_req_fcoe_post_sgl_pages_t),
 5975                                 sizeof(sli4_res_hdr_t));
 5976 
 5977                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 5978                                 dma);
 5979         }
 5980         if (dma) {
 5981                 post = dma->virt;
 5982                 ocs_memset(post, 0, dma->size);
 5983         } else {
 5984                 post = (sli4_req_fcoe_post_sgl_pages_t *)((uint8_t *)buf + sli_config_off);
 5985         }
 5986 
 5987         post->hdr.opcode = SLI4_OPC_FCOE_POST_SGL_PAGES;
 5988         post->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 5989         /* payload size calculation
 5990          *   4 = xri_start + xri_count
 5991          *   xri_count = # of XRI's registered
 5992          *   sizeof(uint64_t) = physical address size
 5993          *   2 = # of physical addresses per page set
 5994          */
 5995         post->hdr.request_length = 4 + (xri_count * (sizeof(uint64_t) * 2));
 5996 
 5997         post->xri_start = xri;
 5998         post->xri_count = xri_count;
 5999 
 6000         for (i = 0; i < xri_count; i++) {
 6001                 post->page_set[i].page0_low  = ocs_addr32_lo(page0[i]->phys);
 6002                 post->page_set[i].page0_high = ocs_addr32_hi(page0[i]->phys);
 6003         }
 6004 
 6005         if (page1) {
 6006                 for (i = 0; i < xri_count; i++) {
 6007                         post->page_set[i].page1_low  = ocs_addr32_lo(page1[i]->phys);
 6008                         post->page_set[i].page1_high = ocs_addr32_hi(page1[i]->phys);
 6009                 }
 6010         }
 6011 
 6012         return dma ? sli_config_off : (sli_config_off + sizeof(sli4_req_fcoe_post_sgl_pages_t));
 6013 }
 6014 
 6015 /**
 6016  * @ingroup sli_fc
 6017  * @brief Write an FCOE_RQ_CREATE command.
 6018  *
 6019  * @param sli4 SLI context.
 6020  * @param buf Destination buffer for the command.
 6021  * @param size Buffer size, in bytes.
 6022  * @param qmem DMA memory for the queue.
 6023  * @param cq_id Associated CQ_ID.
 6024  * @param ulp This parameter carries the ULP for the RQ
 6025  * @param buffer_size Buffer size pointed to by each RQE.
 6026  *
 6027  * @note This creates a Version 0 message.
 6028  *
 6029  * @return Returns the number of bytes written.
 6030  */
 6031 int32_t
 6032 sli_cmd_fcoe_rq_create(sli4_t *sli4, void *buf, size_t size,
 6033                 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, uint16_t buffer_size)
 6034 {
 6035         sli4_req_fcoe_rq_create_t       *rq = NULL;
 6036         uint32_t        sli_config_off = 0;
 6037         uint32_t        p;
 6038         uintptr_t       addr;
 6039 
 6040         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6041                 uint32_t payload_size;
 6042 
 6043                 /* Payload length must accommodate both request and response */
 6044                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_t),
 6045                                 sizeof(sli4_res_common_create_queue_t));
 6046 
 6047                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6048                                 NULL);
 6049         }
 6050         rq = (sli4_req_fcoe_rq_create_t *)((uint8_t *)buf + sli_config_off);
 6051 
 6052         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
 6053         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6054         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_t) -
 6055                                         sizeof(sli4_req_hdr_t);
 6056         /* valid values for number of pages: 1-8 (sec 4.5.6) */
 6057         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 6058         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V0_MAX_PAGES)) {
 6059                 ocs_log_test(sli4->os, "num_pages %d not valid\n", rq->num_pages);
 6060                 return 0;
 6061         }
 6062 
 6063         /*
 6064          * RQE count is the log base 2 of the total number of entries
 6065          */
 6066         rq->rqe_count = ocs_lg2(qmem->size / SLI4_FCOE_RQE_SIZE);
 6067 
 6068         if ((buffer_size < SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE) ||
 6069                         (buffer_size > SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE)) {
 6070                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
 6071                                 buffer_size,
 6072                                 SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE,
 6073                                 SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE);
 6074                 return -1;
 6075         }
 6076         rq->buffer_size = buffer_size;
 6077 
 6078         rq->cq_id = cq_id;
 6079 
 6080         if (sli4->config.dual_ulp_capable) {
 6081                 rq->dua = 1;
 6082                 rq->bqu = 1;
 6083                 rq->ulp = ulp;
 6084         }
 6085 
 6086         for (p = 0, addr = qmem->phys;
 6087                         p < rq->num_pages;
 6088                         p++, addr += SLI_PAGE_SIZE) {
 6089                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 6090                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
 6091         }
 6092 
 6093         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_t));
 6094 }
 6095 
 6096 /**
 6097  * @ingroup sli_fc
 6098  * @brief Write an FCOE_RQ_CREATE_V1 command.
 6099  *
 6100  * @param sli4 SLI context.
 6101  * @param buf Destination buffer for the command.
 6102  * @param size Buffer size, in bytes.
 6103  * @param qmem DMA memory for the queue.
 6104  * @param cq_id Associated CQ_ID.
 6105  * @param ulp This parameter carries the ULP for RQ (ignored for V1)
 6106  * @param buffer_size Buffer size pointed to by each RQE.
 6107  *
 6108  * @note This creates a Version 0 message
 6109  *
 6110  * @return Returns the number of bytes written.
 6111  */
 6112 int32_t
 6113 sli_cmd_fcoe_rq_create_v1(sli4_t *sli4, void *buf, size_t size,
 6114                           ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp,
 6115                           uint16_t buffer_size)
 6116 {
 6117         sli4_req_fcoe_rq_create_v1_t    *rq = NULL;
 6118         uint32_t        sli_config_off = 0;
 6119         uint32_t        p;
 6120         uintptr_t       addr;
 6121 
 6122         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6123                 uint32_t payload_size;
 6124 
 6125                 /* Payload length must accommodate both request and response */
 6126                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_v1_t),
 6127                                 sizeof(sli4_res_common_create_queue_t));
 6128 
 6129                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6130                                 NULL);
 6131         }
 6132         rq = (sli4_req_fcoe_rq_create_v1_t *)((uint8_t *)buf + sli_config_off);
 6133 
 6134         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
 6135         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6136         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v1_t) -
 6137                                         sizeof(sli4_req_hdr_t);
 6138         rq->hdr.version = 1;
 6139 
 6140         /* Disable "no buffer warnings" to avoid Lancer bug */
 6141         rq->dnb = TRUE;
 6142 
 6143         /* valid values for number of pages: 1-8 (sec 4.5.6) */
 6144         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 6145         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES)) {
 6146                 ocs_log_test(sli4->os, "num_pages %d not valid, max %d\n",
 6147                 rq->num_pages, SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES);
 6148                 return 0;
 6149         }
 6150 
 6151         /*
 6152          * RQE count is the total number of entries (note not lg2(# entries))
 6153          */
 6154         rq->rqe_count = qmem->size / SLI4_FCOE_RQE_SIZE;
 6155 
 6156         rq->rqe_size = SLI4_FCOE_RQE_SIZE_8;
 6157 
 6158         rq->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096;
 6159 
 6160         if ((buffer_size < sli4->config.rq_min_buf_size) ||
 6161             (buffer_size > sli4->config.rq_max_buf_size)) {
 6162                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
 6163                                 buffer_size,
 6164                                 sli4->config.rq_min_buf_size,
 6165                                 sli4->config.rq_max_buf_size);
 6166                 return -1;
 6167         }
 6168         rq->buffer_size = buffer_size;
 6169 
 6170         rq->cq_id = cq_id;
 6171 
 6172         for (p = 0, addr = qmem->phys;
 6173                         p < rq->num_pages;
 6174                         p++, addr += SLI_PAGE_SIZE) {
 6175                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 6176                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
 6177         }
 6178 
 6179         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_v1_t));
 6180 }
 6181 
 6182 /**
 6183  * @ingroup sli_fc
 6184  * @brief Write an FCOE_RQ_DESTROY command.
 6185  *
 6186  * @param sli4 SLI context.
 6187  * @param buf Destination buffer for the command.
 6188  * @param size Buffer size, in bytes.
 6189  * @param rq_id RQ_ID.
 6190  *
 6191  * @return Returns the number of bytes written.
 6192  */
 6193 int32_t
 6194 sli_cmd_fcoe_rq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t rq_id)
 6195 {
 6196         sli4_req_fcoe_rq_destroy_t      *rq = NULL;
 6197         uint32_t        sli_config_off = 0;
 6198 
 6199         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6200                 uint32_t payload_size;
 6201 
 6202                 /* Payload length must accommodate both request and response */
 6203                 payload_size = max(sizeof(sli4_req_fcoe_rq_destroy_t),
 6204                                 sizeof(sli4_res_hdr_t));
 6205 
 6206                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6207                                 NULL);
 6208         }
 6209         rq = (sli4_req_fcoe_rq_destroy_t *)((uint8_t *)buf + sli_config_off);
 6210 
 6211         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_DESTROY;
 6212         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6213         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_destroy_t) -
 6214                                         sizeof(sli4_req_hdr_t);
 6215 
 6216         rq->rq_id = rq_id;
 6217 
 6218         return(sli_config_off + sizeof(sli4_req_fcoe_rq_destroy_t));
 6219 }
 6220 
 6221 /**
 6222  * @ingroup sli_fc
 6223  * @brief Write an FCOE_READ_FCF_TABLE command.
 6224  *
 6225  * @note
 6226  * The response of this command exceeds the size of an embedded
 6227  * command and requires an external buffer with DMA capability to hold the results.
 6228  * The caller should allocate the ocs_dma_t structure / memory.
 6229  *
 6230  * @param sli4 SLI context.
 6231  * @param buf Destination buffer for the command.
 6232  * @param size Buffer size, in bytes.
 6233  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
 6234  * @param index FCF table index to retrieve.
 6235  *
 6236  * @return Returns the number of bytes written.
 6237  */
 6238 int32_t
 6239 sli_cmd_fcoe_read_fcf_table(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, uint16_t index)
 6240 {
 6241         sli4_req_fcoe_read_fcf_table_t *read_fcf = NULL;
 6242 
 6243         if (SLI4_PORT_TYPE_FC != sli4->port_type) {
 6244                 ocs_log_test(sli4->os, "FCOE_READ_FCF_TABLE only supported on FC\n");
 6245                 return -1;
 6246         }
 6247 
 6248         read_fcf = dma->virt;
 6249 
 6250         ocs_memset(read_fcf, 0, sizeof(sli4_req_fcoe_read_fcf_table_t));
 6251 
 6252         read_fcf->hdr.opcode = SLI4_OPC_FCOE_READ_FCF_TABLE;
 6253         read_fcf->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6254         read_fcf->hdr.request_length = dma->size -
 6255                 sizeof(sli4_req_fcoe_read_fcf_table_t);
 6256         read_fcf->fcf_index = index;
 6257 
 6258         return sli_cmd_sli_config(sli4, buf, size, 0, dma);
 6259 }
 6260 
 6261 /**
 6262  * @ingroup sli_fc
 6263  * @brief Write an FCOE_POST_HDR_TEMPLATES command.
 6264  *
 6265  * @param sli4 SLI context.
 6266  * @param buf Destination buffer for the command.
 6267  * @param size Buffer size, in bytes.
 6268  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
 6269  * @param rpi Starting RPI index for the header templates.
 6270  * @param payload_dma Pointer to DMA memory used to hold larger descriptor counts.
 6271  *
 6272  * @return Returns the number of bytes written.
 6273  */
 6274 int32_t
 6275 sli_cmd_fcoe_post_hdr_templates(sli4_t *sli4, void *buf, size_t size,
 6276                 ocs_dma_t *dma, uint16_t rpi, ocs_dma_t *payload_dma)
 6277 {
 6278         sli4_req_fcoe_post_hdr_templates_t *template = NULL;
 6279         uint32_t        sli_config_off = 0;
 6280         uintptr_t       phys = 0;
 6281         uint32_t        i = 0;
 6282         uint32_t        page_count;
 6283         uint32_t        payload_size;
 6284 
 6285         page_count = sli_page_count(dma->size, SLI_PAGE_SIZE);
 6286 
 6287         payload_size = sizeof(sli4_req_fcoe_post_hdr_templates_t) +
 6288                                 page_count * sizeof(sli4_physical_page_descriptor_t);
 6289 
 6290         if (page_count > 16) {
 6291                 /* We can't fit more than 16 descriptors into an embedded mailbox
 6292                    command, it has to be non-embedded */
 6293                 if (ocs_dma_alloc(sli4->os, payload_dma, payload_size, 4)) {
 6294                         ocs_log_err(sli4->os, "mailbox payload memory allocation fail\n");
 6295                         return 0;
 6296                 }
 6297                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, payload_dma);
 6298                 template = (sli4_req_fcoe_post_hdr_templates_t *)payload_dma->virt;
 6299         } else {
 6300                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, NULL);
 6301                 template = (sli4_req_fcoe_post_hdr_templates_t *)((uint8_t *)buf + sli_config_off);
 6302         }
 6303 
 6304         if (UINT16_MAX == rpi) {
 6305                 rpi = sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0];
 6306         }
 6307 
 6308         template->hdr.opcode = SLI4_OPC_FCOE_POST_HDR_TEMPLATES;
 6309         template->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6310         template->hdr.request_length = sizeof(sli4_req_fcoe_post_hdr_templates_t) -
 6311                                         sizeof(sli4_req_hdr_t);
 6312 
 6313         template->rpi_offset = rpi;
 6314         template->page_count = page_count;
 6315         phys = dma->phys;
 6316         for (i = 0; i < template->page_count; i++) {
 6317                 template->page_descriptor[i].low  = ocs_addr32_lo(phys);
 6318                 template->page_descriptor[i].high = ocs_addr32_hi(phys);
 6319 
 6320                 phys += SLI_PAGE_SIZE;
 6321         }
 6322 
 6323         return(sli_config_off + payload_size);
 6324 }
 6325 
 6326 int32_t
 6327 sli_cmd_fcoe_rediscover_fcf(sli4_t *sli4, void *buf, size_t size, uint16_t index)
 6328 {
 6329         sli4_req_fcoe_rediscover_fcf_t *redisc = NULL;
 6330         uint32_t        sli_config_off = 0;
 6331 
 6332         sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 6333                         sizeof(sli4_req_fcoe_rediscover_fcf_t),
 6334                         NULL);
 6335 
 6336         redisc = (sli4_req_fcoe_rediscover_fcf_t *)((uint8_t *)buf + sli_config_off);
 6337 
 6338         redisc->hdr.opcode = SLI4_OPC_FCOE_REDISCOVER_FCF;
 6339         redisc->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6340         redisc->hdr.request_length = sizeof(sli4_req_fcoe_rediscover_fcf_t) -
 6341                                         sizeof(sli4_req_hdr_t);
 6342 
 6343         if (index == UINT16_MAX) {
 6344                 redisc->fcf_count = 0;
 6345         } else {
 6346                 redisc->fcf_count = 1;
 6347                 redisc->fcf_index[0] = index;
 6348         }
 6349 
 6350         return(sli_config_off + sizeof(sli4_req_fcoe_rediscover_fcf_t));
 6351 }
 6352 
 6353 /**
 6354  * @ingroup sli_fc
 6355  * @brief Write an ABORT_WQE work queue entry.
 6356  *
 6357  * @param sli4 SLI context.
 6358  * @param buf Destination buffer for the WQE.
 6359  * @param size Buffer size, in bytes.
 6360  * @param type Abort type, such as XRI, abort tag, and request tag.
 6361  * @param send_abts Boolean to cause the hardware to automatically generate an ABTS.
 6362  * @param ids ID of IOs to abort.
 6363  * @param mask Mask applied to the ID values to abort.
 6364  * @param tag Tag value associated with this abort.
 6365  * @param cq_id The id of the completion queue where the WQE response is sent.
 6366  * @param dnrx When set to 1, this field indicates that the SLI Port must not return the associated XRI to the SLI
 6367  *             Port's optimized write XRI pool.
 6368  *
 6369  * @return Returns 0 on success, or a non-zero value on failure.
 6370  */
 6371 int32_t
 6372 sli_abort_wqe(sli4_t *sli4, void *buf, size_t size, sli4_abort_type_e type, uint32_t send_abts,
 6373               uint32_t ids, uint32_t mask, uint16_t tag, uint16_t cq_id)
 6374 {
 6375         sli4_abort_wqe_t        *abort = buf;
 6376 
 6377         ocs_memset(buf, 0, size);
 6378 
 6379         switch (type) {
 6380         case SLI_ABORT_XRI:
 6381                 abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG;
 6382                 if (mask) {
 6383                         ocs_log_warn(sli4->os, "warning non-zero mask %#x when aborting XRI %#x\n", mask, ids);
 6384                         mask = 0;
 6385                 }
 6386                 break;
 6387         case SLI_ABORT_ABORT_ID:
 6388                 abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG;
 6389                 break;
 6390         case SLI_ABORT_REQUEST_ID:
 6391                 abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG;
 6392                 break;
 6393         default:
 6394                 ocs_log_test(sli4->os, "unsupported type %#x\n", type);
 6395                 return -1;
 6396         }
 6397 
 6398         abort->ia = send_abts ? 0 : 1;
 6399 
 6400         /* Suppress ABTS retries */
 6401         abort->ir = 1;
 6402 
 6403         abort->t_mask = mask;
 6404         abort->t_tag  = ids;
 6405         abort->command = SLI4_WQE_ABORT;
 6406         abort->request_tag = tag;
 6407         abort->qosd = TRUE;
 6408         abort->cq_id = cq_id;
 6409         abort->cmd_type = SLI4_CMD_ABORT_WQE;
 6410 
 6411         return 0;
 6412 }
 6413 
 6414 /**
 6415  * @ingroup sli_fc
 6416  * @brief Write an ELS_REQUEST64_WQE work queue entry.
 6417  *
 6418  * @param sli4 SLI context.
 6419  * @param buf Destination buffer for the WQE.
 6420  * @param size Buffer size, in bytes.
 6421  * @param sgl DMA memory for the ELS request.
 6422  * @param req_type ELS request type.
 6423  * @param req_len Length of ELS request in bytes.
 6424  * @param max_rsp_len Max length of ELS response in bytes.
 6425  * @param timeout Time, in seconds, before an IO times out. Zero means 2 * R_A_TOV.
 6426  * @param xri XRI for this exchange.
 6427  * @param tag IO tag value.
 6428  * @param cq_id The id of the completion queue where the WQE response is sent.
 6429  * @param rnode Destination of ELS request (that is, the remote node).
 6430  *
 6431  * @return Returns 0 on success, or a non-zero value on failure.
 6432  */
 6433 int32_t
 6434 sli_els_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint8_t req_type,
 6435                       uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
 6436                       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode)
 6437 {
 6438         sli4_els_request64_wqe_t        *els = buf;
 6439         sli4_sge_t      *sge = sgl->virt;
 6440         uint8_t         is_fabric = FALSE;
 6441 
 6442         ocs_memset(buf, 0, size);
 6443 
 6444         if (sli4->config.sgl_pre_registered) {
 6445                 els->xbl = FALSE;
 6446 
 6447                 els->dbde = TRUE;
 6448                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
 6449 
 6450                 els->els_request_payload.buffer_length = req_len;
 6451                 els->els_request_payload.u.data.buffer_address_low  = sge[0].buffer_address_low;
 6452                 els->els_request_payload.u.data.buffer_address_high = sge[0].buffer_address_high;
 6453         } else {
 6454                 els->xbl = TRUE;
 6455 
 6456                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BLP;
 6457 
 6458                 els->els_request_payload.buffer_length = 2 * sizeof(sli4_sge_t);
 6459                 els->els_request_payload.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 6460                 els->els_request_payload.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 6461         }
 6462 
 6463         els->els_request_payload_length = req_len;
 6464         els->max_response_payload_length = max_rsp_len;
 6465 
 6466         els->xri_tag = xri;
 6467         els->timer = timeout;
 6468         els->class = SLI4_ELS_REQUEST64_CLASS_3;
 6469 
 6470         els->command = SLI4_WQE_ELS_REQUEST64;
 6471 
 6472         els->request_tag = tag;
 6473 
 6474         if (rnode->node_group) {
 6475                 els->hlm = TRUE;
 6476                 els->remote_id = rnode->fc_id & 0x00ffffff;
 6477         }
 6478 
 6479         els->iod = SLI4_ELS_REQUEST64_DIR_READ;
 6480 
 6481         els->qosd = TRUE;
 6482 
 6483         /* figure out the ELS_ID value from the request buffer */
 6484 
 6485         switch (req_type) {
 6486         case FC_ELS_CMD_LOGO:
 6487                 els->els_id = SLI4_ELS_REQUEST64_LOGO;
 6488                 if (rnode->attached) {
 6489                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6490                         els->context_tag = rnode->indicator;
 6491                 } else {
 6492                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6493                         els->context_tag = rnode->sport->indicator;
 6494                 }
 6495                 if (FC_ADDR_FABRIC == rnode->fc_id) {
 6496                         is_fabric = TRUE;
 6497                 }
 6498                 break;
 6499         case FC_ELS_CMD_FDISC:
 6500                 if (FC_ADDR_FABRIC == rnode->fc_id) {
 6501                         is_fabric = TRUE;
 6502                 }
 6503                 if (0 == rnode->sport->fc_id) {
 6504                         els->els_id = SLI4_ELS_REQUEST64_FDISC;
 6505                         is_fabric = TRUE;
 6506                 } else {
 6507                         els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6508                 }
 6509                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6510                 els->context_tag = rnode->sport->indicator;
 6511                 els->sp = TRUE;
 6512                 break;
 6513         case FC_ELS_CMD_FLOGI:
 6514                 els->els_id = SLI4_ELS_REQUEST64_FLOGIN;
 6515                 is_fabric = TRUE;
 6516                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 6517                         if (!rnode->sport->domain) {
 6518                                 ocs_log_test(sli4->os, "invalid domain handle\n");
 6519                                 return -1;
 6520                         }
 6521                         /*
 6522                          * IF_TYPE 0 skips INIT_VFI/INIT_VPI and therefore must use the
 6523                          * FCFI here
 6524                          */
 6525                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_FCFI;
 6526                         els->context_tag = rnode->sport->domain->fcf_indicator;
 6527                         els->sp = TRUE;
 6528                 } else {
 6529                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6530                         els->context_tag = rnode->sport->indicator;
 6531 
 6532                         /*
 6533                          * Set SP here ... we haven't done a REG_VPI yet
 6534                          * TODO: need to maybe not set this when we have
 6535                          *       completed VFI/VPI registrations ...
 6536                          *
 6537                          * Use the FC_ID of the SPORT if it has been allocated, otherwise
 6538                          * use an S_ID of zero.
 6539                          */
 6540                         els->sp = TRUE;
 6541                         if (rnode->sport->fc_id != UINT32_MAX) {
 6542                                 els->sid = rnode->sport->fc_id;
 6543                         }
 6544                 }
 6545                 break;
 6546         case FC_ELS_CMD_PLOGI:
 6547                 els->els_id = SLI4_ELS_REQUEST64_PLOGI;
 6548                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6549                 els->context_tag = rnode->sport->indicator;
 6550                 break;
 6551         case FC_ELS_CMD_SCR:
 6552                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6553                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6554                 els->context_tag = rnode->sport->indicator;
 6555                 break;
 6556         default:
 6557                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6558                 if (rnode->attached) {
 6559                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6560                         els->context_tag = rnode->indicator;
 6561                 } else {
 6562                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6563                         els->context_tag = rnode->sport->indicator;
 6564                 }
 6565                 break;
 6566         }
 6567 
 6568         if (is_fabric) {
 6569                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_FABRIC;
 6570         } else {
 6571                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_NON_FABRIC;
 6572         }
 6573 
 6574         els->cq_id = cq_id;
 6575 
 6576         if (SLI4_ELS_REQUEST64_CONTEXT_RPI != els->ct) {
 6577                 els->remote_id = rnode->fc_id;
 6578         }
 6579         if (SLI4_ELS_REQUEST64_CONTEXT_VPI == els->ct) {
 6580                 els->temporary_rpi = rnode->indicator;
 6581         }
 6582 
 6583         return 0;
 6584 }
 6585 
 6586 /**
 6587  * @ingroup sli_fc
 6588  * @brief Write an FCP_ICMND64_WQE work queue entry.
 6589  *
 6590  * @param sli4 SLI context.
 6591  * @param buf Destination buffer for the WQE.
 6592  * @param size Buffer size, in bytes.
 6593  * @param sgl DMA memory for the scatter gather list.
 6594  * @param xri XRI for this exchange.
 6595  * @param tag IO tag value.
 6596  * @param cq_id The id of the completion queue where the WQE response is sent.
 6597  * @param rpi remote node indicator (RPI)
 6598  * @param rnode Destination request (that is, the remote node).
 6599  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
 6600  *
 660