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         {       0x1,    0x0d,   SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_A1}, 
   95         {       0x10,   0x0d,   SLI4_ASIC_TYPE_LANCERG7,SLI4_ASIC_REV_B0}, 
   96         {       0x00,   0x05,   SLI4_ASIC_TYPE_CORSAIR, SLI4_ASIC_REV_A0},
   97 };
   98 
   99 /*
  100  * @brief Convert queue type enum (SLI_QTYPE_*) into a string.
  101  */
  102 const char *SLI_QNAME[] = {
  103         "Event Queue",
  104         "Completion Queue",
  105         "Mailbox Queue",
  106         "Work Queue",
  107         "Receive Queue",
  108         "Undefined"
  109 };
  110 
  111 /**
  112  * @brief Define the mapping of registers to their BAR and offset.
  113  *
  114  * @par Description
  115  * Although SLI-4 specification defines a common set of registers, their locations
  116  * (both BAR and offset) depend on the interface type. This array maps a register
  117  * enum to an array of BAR/offset pairs indexed by the interface type. For
  118  * example, to access the bootstrap mailbox register on an interface type 0
  119  * device, code can refer to the offset using regmap[SLI4_REG_BMBX][0].offset.
  120  *
  121  * @b Note: A value of UINT32_MAX for either the register set (rset) or offset (off)
  122  * indicates an invalid mapping.
  123  */
  124 const sli4_reg_t regmap[SLI4_REG_MAX][SLI4_MAX_IF_TYPES] = {
  125         /* SLI4_REG_BMBX */
  126         {
  127                 { 2, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG }, { 0, SLI4_BMBX_REG },
  128                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX } , { 0, SLI4_BMBX_REG },
  129         },
  130         /* SLI4_REG_EQCQ_DOORBELL */
  131         {
  132                 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  133                 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  134                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  135                 { 1, SLI4_IF6_EQ_DOORBELL_REG }
  136         },
  137         // SLI4_REG_CQ_DOORBELL
  138         {
  139                 { 2, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  140                 { 0, SLI4_EQCQ_DOORBELL_REG }, { 0, SLI4_EQCQ_DOORBELL_REG },
  141                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  142                 { 1, SLI4_IF6_CQ_DOORBELL_REG }
  143         },
  144         /* SLI4_REG_FCOE_RQ_DOORBELL */
  145         {
  146                 { 2, SLI4_RQ_DOORBELL_REG }, { 0, SLI4_RQ_DOORBELL_REG },
  147                 { 0, SLI4_RQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
  148                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  149                 { 1, SLI4_IF6_RQ_DOORBELL_REG }
  150         },
  151         /* SLI4_REG_IO_WQ_DOORBELL */
  152         {
  153                 { 2, SLI4_IO_WQ_DOORBELL_REG }, { 0, SLI4_IO_WQ_DOORBELL_REG },
  154                 { 0, SLI4_IO_WQ_DOORBELL_REG }, { UINT32_MAX, UINT32_MAX },
  155                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  156                 { 1, SLI4_IF6_WQ_DOORBELL_REG }
  157         },
  158         /* SLI4_REG_MQ_DOORBELL */
  159         {
  160                 { 2, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
  161                 { 0, SLI4_MQ_DOORBELL_REG }, { 0, SLI4_MQ_DOORBELL_REG },
  162                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  163                 { 1, SLI4_IF6_MQ_DOORBELL_REG }
  164         },
  165         /* SLI4_REG_PHYSDEV_CONTROL */
  166         {
  167                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  168                 { 0, SLI4_PHSDEV_CONTROL_REG_236 }, { 0, SLI4_PHSDEV_CONTROL_REG_236 },
  169                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  170                 { 0, SLI4_PHSDEV_CONTROL_REG_236 }
  171         },
  172         /* SLI4_REG_SLIPORT_CONTROL */
  173         {
  174                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  175                 { 0, SLI4_SLIPORT_CONTROL_REG }, { UINT32_MAX, UINT32_MAX },
  176                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  177                 { 0, SLI4_SLIPORT_CONTROL_REG },
  178         },
  179         /* SLI4_REG_SLIPORT_ERROR1 */
  180         {
  181                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  182                 { 0, SLI4_SLIPORT_ERROR1 }, { UINT32_MAX, UINT32_MAX },
  183                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  184                 { 0, SLI4_SLIPORT_ERROR1 },
  185         },
  186         /* SLI4_REG_SLIPORT_ERROR2 */
  187         {
  188                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  189                 { 0, SLI4_SLIPORT_ERROR2 }, { UINT32_MAX, UINT32_MAX },
  190                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  191                 { 0, SLI4_SLIPORT_ERROR2 },
  192         },
  193         /* SLI4_REG_SLIPORT_SEMAPHORE */
  194         {
  195                 { 1, SLI4_PORT_SEMAPHORE_REG_0 },  { 0, SLI4_PORT_SEMAPHORE_REG_1 },
  196                 { 0, SLI4_PORT_SEMAPHORE_REG_236 }, { 0, SLI4_PORT_SEMAPHORE_REG_236 },
  197                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX }, 
  198                 { 0, SLI4_PORT_SEMAPHORE_REG_236 },
  199         },
  200         /* SLI4_REG_SLIPORT_STATUS */
  201         {
  202                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  203                 { 0, SLI4_PORT_STATUS_REG_236 }, { 0, SLI4_PORT_STATUS_REG_236 },
  204                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  205                 { 0, SLI4_PORT_STATUS_REG_236 },
  206         },
  207         /* SLI4_REG_UERR_MASK_HI */
  208         {
  209                 { 0, SLI4_UERR_MASK_HIGH_REG }, { UINT32_MAX, UINT32_MAX },
  210                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  211                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  212                 { UINT32_MAX, UINT32_MAX }
  213         },
  214         /* SLI4_REG_UERR_MASK_LO */
  215         {
  216                 { 0, SLI4_UERR_MASK_LOW_REG }, { UINT32_MAX, UINT32_MAX },
  217                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  218                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  219                 { UINT32_MAX, UINT32_MAX }
  220         },
  221         /* SLI4_REG_UERR_STATUS_HI */
  222         {
  223                 { 0, SLI4_UERR_STATUS_HIGH_REG }, { UINT32_MAX, UINT32_MAX },
  224                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  225                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  226                 { UINT32_MAX, UINT32_MAX }
  227         },
  228         /* SLI4_REG_UERR_STATUS_LO */
  229         {
  230                 { 0, SLI4_UERR_STATUS_LOW_REG }, { UINT32_MAX, UINT32_MAX },
  231                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  232                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  233                 { UINT32_MAX, UINT32_MAX }
  234         },
  235         /* SLI4_REG_SW_UE_CSR1 */
  236         {
  237                 { 1, SLI4_SW_UE_CSR1}, { UINT32_MAX, UINT32_MAX },
  238                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  239                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  240                 { UINT32_MAX, UINT32_MAX }
  241         },
  242         /* SLI4_REG_SW_UE_CSR2 */
  243         {
  244                 { 1, SLI4_SW_UE_CSR2}, { UINT32_MAX, UINT32_MAX },
  245                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  246                 { UINT32_MAX, UINT32_MAX }, { UINT32_MAX, UINT32_MAX },
  247                 { UINT32_MAX, UINT32_MAX }
  248         },
  249 };
  250 
  251 /**
  252  * @brief Read the given SLI register.
  253  *
  254  * @param sli Pointer to the SLI context.
  255  * @param reg Register name enum.
  256  *
  257  * @return Returns the register value.
  258  */
  259 uint32_t
  260 sli_reg_read(sli4_t *sli, sli4_regname_e reg)
  261 {
  262         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
  263 
  264         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
  265                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
  266                 return UINT32_MAX;
  267         }
  268 
  269         return ocs_reg_read32(sli->os, r->rset, r->off);
  270 }
  271 
  272 /**
  273  * @brief Write the value to the given SLI register.
  274  *
  275  * @param sli Pointer to the SLI context.
  276  * @param reg Register name enum.
  277  * @param val Value to write.
  278  *
  279  * @return None.
  280  */
  281 void
  282 sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
  283 {
  284         const sli4_reg_t        *r = &(regmap[reg][sli->if_type]);
  285 
  286         if ((UINT32_MAX == r->rset) || (UINT32_MAX == r->off)) {
  287                 ocs_log_err(sli->os, "regname %d not defined for if_type %d\n", reg, sli->if_type);
  288                 return;
  289         }
  290 
  291         ocs_reg_write32(sli->os, r->rset, r->off, val);
  292 }
  293 
  294 /**
  295  * @brief Check if the SLI_INTF register is valid.
  296  *
  297  * @param val 32-bit SLI_INTF register value.
  298  *
  299  * @return Returns 0 on success, or a non-zero value on failure.
  300  */
  301 static uint8_t
  302 sli_intf_valid_check(uint32_t val)
  303 {
  304         return ((val >> SLI4_INTF_VALID_SHIFT) & SLI4_INTF_VALID_MASK) != SLI4_INTF_VALID;
  305 }
  306 
  307 /**
  308  * @brief Retrieve the SLI revision level.
  309  *
  310  * @param val 32-bit SLI_INTF register value.
  311  *
  312  * @return Returns the SLI revision level.
  313  */
  314 static uint8_t
  315 sli_intf_sli_revision(uint32_t val)
  316 {
  317         return ((val >> SLI4_INTF_SLI_REVISION_SHIFT) & SLI4_INTF_SLI_REVISION_MASK);
  318 }
  319 
  320 static uint8_t
  321 sli_intf_sli_family(uint32_t val)
  322 {
  323         return ((val >> SLI4_INTF_SLI_FAMILY_SHIFT) & SLI4_INTF_SLI_FAMILY_MASK);
  324 }
  325 
  326 /**
  327  * @brief Retrieve the SLI interface type.
  328  *
  329  * @param val 32-bit SLI_INTF register value.
  330  *
  331  * @return Returns the SLI interface type.
  332  */
  333 static uint8_t
  334 sli_intf_if_type(uint32_t val)
  335 {
  336         return ((val >> SLI4_INTF_IF_TYPE_SHIFT) & SLI4_INTF_IF_TYPE_MASK);
  337 }
  338 
  339 /**
  340  * @brief Retrieve PCI revision ID.
  341  *
  342  * @param val 32-bit PCI CLASS_REVISION register value.
  343  *
  344  * @return Returns the PCI revision ID.
  345  */
  346 static uint8_t
  347 sli_pci_rev_id(uint32_t val)
  348 {
  349         return ((val >> SLI4_PCI_REV_ID_SHIFT) & SLI4_PCI_REV_ID_MASK);
  350 }
  351 
  352 /**
  353  * @brief retrieve SLI ASIC generation
  354  *
  355  * @param val 32-bit SLI_ASIC_ID register value
  356  *
  357  * @return SLI ASIC generation
  358  */
  359 static uint8_t
  360 sli_asic_gen(uint32_t val)
  361 {
  362         return ((val >> SLI4_ASIC_GEN_SHIFT) & SLI4_ASIC_GEN_MASK);
  363 }
  364 
  365 /**
  366  * @brief Wait for the bootstrap mailbox to report "ready".
  367  *
  368  * @param sli4 SLI context pointer.
  369  * @param msec Number of milliseconds to wait.
  370  *
  371  * @return Returns 0 if BMBX is ready, or non-zero otherwise (i.e. time out occurred).
  372  */
  373 static int32_t
  374 sli_bmbx_wait(sli4_t *sli4, uint32_t msec)
  375 {
  376         uint32_t        val = 0;
  377 
  378         do {
  379                 ocs_udelay(SLI4_BMBX_DELAY_US);
  380                 val = sli_reg_read(sli4, SLI4_REG_BMBX);
  381                 msec--;
  382         } while(msec && !(val & SLI4_BMBX_RDY));
  383 
  384         return(!(val & SLI4_BMBX_RDY));
  385 }
  386 
  387 /**
  388  * @brief Write bootstrap mailbox.
  389  *
  390  * @param sli4 SLI context pointer.
  391  *
  392  * @return Returns 0 if command succeeded, or non-zero otherwise.
  393  */
  394 static int32_t
  395 sli_bmbx_write(sli4_t *sli4)
  396 {
  397         uint32_t        val = 0;
  398 
  399         /* write buffer location to bootstrap mailbox register */
  400         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_PREWRITE);
  401         val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys);
  402         sli_reg_write(sli4, SLI4_REG_BMBX, val);
  403 
  404         if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
  405                 ocs_log_crit(sli4->os, "BMBX WRITE_HI failed\n");
  406                 return -1;
  407         }
  408         val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys);
  409         sli_reg_write(sli4, SLI4_REG_BMBX, val);
  410 
  411         /* wait for SLI Port to set ready bit */
  412         return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC/*XXX*/);
  413 }
  414 
  415 #if defined(OCS_INCLUDE_DEBUG)
  416 /**
  417  * @ingroup sli
  418  * @brief Dump BMBX mailbox command.
  419  *
  420  * @par Description
  421  * Convenience function for dumping BMBX mailbox commands. Takes
  422  * into account which mailbox command is given since SLI_CONFIG
  423  * commands are special.
  424  *
  425  * @b Note: This function takes advantage of
  426  * the one-command-at-a-time nature of the BMBX to be able to
  427  * display non-embedded SLI_CONFIG commands. This will not work
  428  * for mailbox commands on the MQ. Luckily, all current non-emb
  429  * mailbox commands go through the BMBX.
  430  *
  431  * @param sli4 SLI context pointer.
  432  * @param mbx Pointer to mailbox command to dump.
  433  * @param prefix Prefix for dump label.
  434  *
  435  * @return None.
  436  */
  437 static void
  438 sli_dump_bmbx_command(sli4_t *sli4, void *mbx, const char *prefix)
  439 {
  440         uint32_t size = 0;
  441         char label[64];
  442         uint32_t i;
  443         /* Mailbox diagnostic logging */
  444         sli4_mbox_command_header_t *hdr = (sli4_mbox_command_header_t *)mbx;
  445 
  446         if (!ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)) {
  447                 return;
  448         }
  449 
  450         if (hdr->command == SLI4_MBOX_COMMAND_SLI_CONFIG) {
  451                 sli4_cmd_sli_config_t *sli_config = (sli4_cmd_sli_config_t *)hdr;
  452                 sli4_req_hdr_t  *sli_config_hdr;
  453                 if (sli_config->emb) {
  454                         ocs_snprintf(label, sizeof(label), "%s (emb)", prefix);
  455 
  456                         /*  if embedded, dump entire command */
  457                         sli_config_hdr = (sli4_req_hdr_t *)sli_config->payload.embed;
  458                         size = sizeof(*sli_config) - sizeof(sli_config->payload) +
  459                                 sli_config_hdr->request_length + (4*sizeof(uint32_t));
  460                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  461                                    (uint8_t *)sli4->bmbx.virt, size);
  462                 } else {
  463                         sli4_sli_config_pmd_t *pmd;
  464                         ocs_snprintf(label, sizeof(label), "%s (non-emb hdr)", prefix);
  465 
  466                         /* if non-embedded, break up into two parts: SLI_CONFIG hdr
  467                            and the payload(s) */
  468                         size = sizeof(*sli_config) - sizeof(sli_config->payload) + (12 * sli_config->pmd_count);
  469                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  470                                    (uint8_t *)sli4->bmbx.virt, size);
  471 
  472                         /* as sanity check, make sure first PMD matches what was saved */
  473                         pmd = &sli_config->payload.mem;
  474                         if ((pmd->address_high == ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys)) &&
  475                             (pmd->address_low == ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys))) {
  476                                 for (i = 0; i < sli_config->pmd_count; i++, pmd++) {
  477                                         sli_config_hdr = sli4->bmbx_non_emb_pmd->virt;
  478                                         ocs_snprintf(label, sizeof(label), "%s (non-emb pay[%d])",
  479                                                      prefix, i);
  480                                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, label,
  481                                                    (uint8_t *)sli4->bmbx_non_emb_pmd->virt,
  482                                                    sli_config_hdr->request_length + (4*sizeof(uint32_t)));
  483                                 }
  484                         } else {
  485                                 ocs_log_debug(sli4->os, "pmd addr does not match pmd:%x %x (%x %x)\n",
  486                                         pmd->address_high, pmd->address_low,
  487                                         ocs_addr32_hi(sli4->bmbx_non_emb_pmd->phys),
  488                                         ocs_addr32_lo(sli4->bmbx_non_emb_pmd->phys));
  489                         }
  490                 }
  491         } else {
  492                 /* not an SLI_CONFIG command, just display first 64 bytes, like we do
  493                    for MQEs */
  494                 size = 64;
  495                 ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, prefix,
  496                            (uint8_t *)mbx, size);
  497         }
  498 }
  499 #endif
  500 
  501 /**
  502  * @ingroup sli
  503  * @brief Submit a command to the bootstrap mailbox and check the status.
  504  *
  505  * @param sli4 SLI context pointer.
  506  *
  507  * @return Returns 0 on success, or a non-zero value on failure.
  508  */
  509 int32_t
  510 sli_bmbx_command(sli4_t *sli4)
  511 {
  512         void *cqe = (uint8_t *)sli4->bmbx.virt + SLI4_BMBX_SIZE;
  513 
  514 #if defined(OCS_INCLUDE_DEBUG)
  515         sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmd");
  516 #endif
  517 
  518         if (sli_fw_error_status(sli4) > 0) {
  519                 ocs_log_crit(sli4->os, "Chip is in an error state - Mailbox "
  520                         "command rejected status=%#x error1=%#x error2=%#x\n",
  521                         sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
  522                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
  523                         sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
  524                 return -1;
  525         }
  526 
  527         if (sli_bmbx_write(sli4)) {
  528                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail phys=%p reg=%#x\n",
  529                         (void*)sli4->bmbx.phys,
  530                         sli_reg_read(sli4, SLI4_REG_BMBX));
  531                 return -1;
  532         }
  533 
  534         /* check completion queue entry status */
  535         ocs_dma_sync(&sli4->bmbx, OCS_DMASYNC_POSTREAD);
  536         if (((sli4_mcqe_t *)cqe)->val) {
  537 #if defined(OCS_INCLUDE_DEBUG)
  538                 sli_dump_bmbx_command(sli4, sli4->bmbx.virt, "bmbx cmpl");
  539         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "bmbx cqe", cqe, sizeof(sli4_mcqe_t));
  540 #endif
  541                 return sli_cqe_mq(cqe);
  542         } else {
  543                 ocs_log_err(sli4->os, "invalid or wrong type\n");
  544                 return -1;
  545         }
  546 }
  547 
  548 /****************************************************************************
  549  * Messages
  550  */
  551 
  552 /**
  553  * @ingroup sli
  554  * @brief Write a CONFIG_LINK command to the provided buffer.
  555  *
  556  * @param sli4 SLI context pointer.
  557  * @param buf Virtual pointer to the destination buffer.
  558  * @param size Buffer size, in bytes.
  559  *
  560  * @return Returns the number of bytes written.
  561  */
  562 int32_t
  563 sli_cmd_config_link(sli4_t *sli4, void *buf, size_t size)
  564 {
  565         sli4_cmd_config_link_t  *config_link = buf;
  566 
  567         ocs_memset(buf, 0, size);
  568 
  569         config_link->hdr.command = SLI4_MBOX_COMMAND_CONFIG_LINK;
  570 
  571         /* Port interprets zero in a field as "use default value" */
  572 
  573         return sizeof(sli4_cmd_config_link_t);
  574 }
  575 
  576 /**
  577  * @ingroup sli
  578  * @brief Write a DOWN_LINK command to the provided buffer.
  579  *
  580  * @param sli4 SLI context pointer.
  581  * @param buf Virtual pointer to the destination buffer.
  582  * @param size Buffer size, in bytes.
  583  *
  584  * @return Returns the number of bytes written.
  585  */
  586 int32_t
  587 sli_cmd_down_link(sli4_t *sli4, void *buf, size_t size)
  588 {
  589         sli4_mbox_command_header_t      *hdr = buf;
  590 
  591         ocs_memset(buf, 0, size);
  592 
  593         hdr->command = SLI4_MBOX_COMMAND_DOWN_LINK;
  594 
  595         /* Port interprets zero in a field as "use default value" */
  596 
  597         return sizeof(sli4_mbox_command_header_t);
  598 }
  599 
  600 /**
  601  * @ingroup sli
  602  * @brief Write a DUMP Type 4 command to the provided buffer.
  603  *
  604  * @param sli4 SLI context pointer.
  605  * @param buf Virtual pointer to the destination buffer.
  606  * @param size Buffer size, in bytes.
  607  * @param wki The well known item ID.
  608  *
  609  * @return Returns the number of bytes written.
  610  */
  611 int32_t
  612 sli_cmd_dump_type4(sli4_t *sli4, void *buf, size_t size, uint16_t wki)
  613 {
  614         sli4_cmd_dump4_t        *cmd = buf;
  615 
  616         ocs_memset(buf, 0, size);
  617 
  618         cmd->hdr.command = SLI4_MBOX_COMMAND_DUMP;
  619         cmd->type = 4;
  620         cmd->wki_selection = wki;
  621         return sizeof(sli4_cmd_dump4_t);
  622 }
  623 
  624 /**
  625  * @ingroup sli
  626  * @brief Write a COMMON_READ_TRANSCEIVER_DATA command.
  627  *
  628  * @param sli4 SLI context.
  629  * @param buf Destination buffer for the command.
  630  * @param size Buffer size, in bytes.
  631  * @param page_num The page of SFP data to retrieve (0xa0 or 0xa2).
  632  * @param dma DMA structure from which the data will be copied.
  633  *
  634  * @note This creates a Version 0 message.
  635  *
  636  * @return Returns the number of bytes written.
  637  */
  638 int32_t
  639 sli_cmd_common_read_transceiver_data(sli4_t *sli4, void *buf, size_t size, uint32_t page_num,
  640                                      ocs_dma_t *dma)
  641 {
  642         sli4_req_common_read_transceiver_data_t *req = NULL;
  643         uint32_t        sli_config_off = 0;
  644         uint32_t        payload_size;
  645 
  646         if (dma == NULL) {
  647                 /* Payload length must accommodate both request and response */
  648                 payload_size = max(sizeof(sli4_req_common_read_transceiver_data_t),
  649                                    sizeof(sli4_res_common_read_transceiver_data_t));
  650         } else {
  651                 payload_size = dma->size;
  652         }
  653 
  654         if (sli4->port_type == SLI4_PORT_TYPE_FC) {
  655                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, dma);
  656         }
  657 
  658         if (dma == NULL) {
  659                 req = (sli4_req_common_read_transceiver_data_t *)((uint8_t *)buf + sli_config_off);
  660         } else {
  661                 req = (sli4_req_common_read_transceiver_data_t *)dma->virt;
  662                 ocs_memset(req, 0, dma->size);
  663         }
  664 
  665         req->hdr.opcode = SLI4_OPC_COMMON_READ_TRANSCEIVER_DATA;
  666         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
  667         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
  668 
  669         req->page_number = page_num;
  670         req->port = sli4->physical_port;
  671 
  672         return(sli_config_off + sizeof(sli4_req_common_read_transceiver_data_t));
  673 }
  674 
  675 /**
  676  * @ingroup sli
  677  * @brief Write a READ_LINK_STAT 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  * @param req_ext_counters If TRUE, then the extended counters will be requested.
  683  * @param clear_overflow_flags If TRUE, then overflow flags will be cleared.
  684  * @param clear_all_counters If TRUE, the counters will be cleared.
  685  *
  686  * @return Returns the number of bytes written.
  687  */
  688 int32_t
  689 sli_cmd_read_link_stats(sli4_t *sli4, void *buf, size_t size,
  690                         uint8_t req_ext_counters,
  691                         uint8_t clear_overflow_flags,
  692                         uint8_t clear_all_counters)
  693 {
  694         sli4_cmd_read_link_stats_t      *cmd = buf;
  695 
  696         ocs_memset(buf, 0, size);
  697 
  698         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_LNK_STAT;
  699         cmd->rec = req_ext_counters;
  700         cmd->clrc = clear_all_counters;
  701         cmd->clof = clear_overflow_flags;
  702         return sizeof(sli4_cmd_read_link_stats_t);
  703 }
  704 
  705 /**
  706  * @ingroup sli
  707  * @brief Write a READ_STATUS command to the provided buffer.
  708  *
  709  * @param sli4 SLI context pointer.
  710  * @param buf Virtual pointer to the destination buffer.
  711  * @param size Buffer size, in bytes.
  712  * @param clear_counters If TRUE, the counters will be cleared.
  713  *
  714  * @return Returns the number of bytes written.
  715  */
  716 int32_t
  717 sli_cmd_read_status(sli4_t *sli4, void *buf, size_t size,
  718                         uint8_t clear_counters)
  719 {
  720         sli4_cmd_read_status_t  *cmd = buf;
  721 
  722         ocs_memset(buf, 0, size);
  723 
  724         cmd->hdr.command = SLI4_MBOX_COMMAND_READ_STATUS;
  725         cmd->cc = clear_counters;
  726         return sizeof(sli4_cmd_read_status_t);
  727 }
  728 
  729 /**
  730  * @brief Write a FW_DEINITIALIZE command to the provided buffer.
  731  *
  732  * @param sli4 SLI context pointer.
  733  * @param buf Virtual pointer to the destination buffer.
  734  * @param size Buffer size, in bytes.
  735  *
  736  * @return Returns the number of bytes written.
  737  */
  738 static int32_t
  739 sli_cmd_fw_deinitialize(sli4_t *sli4, void *buf, size_t size)
  740 {
  741 
  742         ocs_memset(buf, 0, size);
  743         ocs_memcpy(buf, sli4_fw_deinitialize, sizeof(sli4_fw_deinitialize));
  744 
  745         return sizeof(sli4_fw_deinitialize);
  746 }
  747 
  748 /**
  749  * @brief Write a FW_INITIALIZE command to the provided buffer.
  750  *
  751  * @param sli4 SLI context pointer.
  752  * @param buf Virtual pointer to the destination buffer.
  753  * @param size Buffer size, in bytes.
  754  *
  755  * @return Returns the number of bytes written.
  756  */
  757 static int32_t
  758 sli_cmd_fw_initialize(sli4_t *sli4, void *buf, size_t size)
  759 {
  760 
  761         ocs_memset(buf, 0, size);
  762         ocs_memcpy(buf, sli4_fw_initialize, sizeof(sli4_fw_initialize));
  763 
  764         return sizeof(sli4_fw_initialize);
  765 }
  766 
  767 /**
  768  * @ingroup sli
  769  * @brief update INIT_LINK flags with the sli config topology.
  770  *
  771  * @param sli4 SLI context pointer.
  772  * @param init_link Pointer to the init link command
  773  *
  774  * @return Returns 0 on success, -1 on failure
  775  */
  776 static int32_t
  777 sli4_set_link_flags_config_topo(sli4_t *sli4, sli4_cmd_init_link_t *init_link)
  778 {
  779 
  780         switch (sli4->config.topology) {
  781         case SLI4_READ_CFG_TOPO_FC:
  782                 // Attempt P2P but failover to FC-AL
  783                 init_link->link_flags.enable_topology_failover = TRUE;
  784                 init_link->link_flags.topology = SLI4_INIT_LINK_F_P2P_FAIL_OVER;
  785                 break;
  786         case SLI4_READ_CFG_TOPO_FC_AL:
  787                 init_link->link_flags.topology = SLI4_INIT_LINK_F_FCAL_ONLY;
  788                 return (!sli_fcal_is_speed_supported(init_link->link_speed_selection_code));
  789 
  790         case SLI4_READ_CFG_TOPO_FC_DA:
  791                 init_link->link_flags.topology = FC_TOPOLOGY_P2P;
  792                 break;
  793         default:
  794                 ocs_log_err(sli4->os, "unsupported topology %#x\n", sli4->config.topology);
  795                 return -1;
  796         }
  797 
  798         return 0;
  799 }
  800 
  801 /**
  802  * @ingroup sli
  803  * @brief update INIT_LINK flags with the persistent topology.
  804  * PT stores value in compatible form, directly assign to link_flags
  805  *
  806  * @param sli4 SLI context pointer.
  807  * @param init_link Pointer to the init link command
  808  *
  809  * @return Returns 0 on success, -1 on failure
  810  */
  811 static int32_t
  812 sli4_set_link_flags_persistent_topo(sli4_t *sli4, sli4_cmd_init_link_t *init_link)
  813 {
  814         if ((sli4->config.pt == SLI4_INIT_LINK_F_FCAL_ONLY) &&
  815             (!sli_fcal_is_speed_supported(init_link->link_speed_selection_code)))
  816                 return -1;
  817 
  818         init_link->link_flags.enable_topology_failover = sli4->config.tf;
  819         init_link->link_flags.topology = sli4->config.pt;
  820 
  821         return 0;
  822 }
  823 
  824 /**
  825  * @ingroup sli
  826  * @brief Write an INIT_LINK command to the provided buffer.
  827  *
  828  * @param sli4 SLI context pointer.
  829  * @param buf Virtual pointer to the destination buffer.
  830  * @param size Buffer size, in bytes.
  831  * @param speed Link speed.
  832  * @param reset_alpa For native FC, this is the selective reset AL_PA
  833  *
  834  * @return Returns the number of bytes written.
  835  */
  836 int32_t
  837 sli_cmd_init_link(sli4_t *sli4, void *buf, size_t size, uint32_t speed, uint8_t reset_alpa)
  838 {
  839         sli4_cmd_init_link_t    *init_link = buf;
  840         int32_t rc = 0;
  841 
  842         ocs_memset(buf, 0, size);
  843 
  844         init_link->hdr.command = SLI4_MBOX_COMMAND_INIT_LINK;
  845 
  846         /* Most fields only have meaning for FC links */
  847         if (sli4->config.topology != SLI4_READ_CFG_TOPO_FCOE) {
  848                 init_link->selective_reset_al_pa = reset_alpa;
  849                 init_link->link_flags.loopback = FALSE;
  850 
  851                 init_link->link_speed_selection_code = speed;
  852                 switch (speed) {
  853                 case FC_LINK_SPEED_1G:
  854                 case FC_LINK_SPEED_2G:
  855                 case FC_LINK_SPEED_4G:
  856                 case FC_LINK_SPEED_8G:
  857                 case FC_LINK_SPEED_16G:
  858                 case FC_LINK_SPEED_32G:
  859                         init_link->link_flags.fixed_speed = TRUE;
  860                         break;
  861                 case FC_LINK_SPEED_10G:
  862                         ocs_log_test(sli4->os, "unsupported FC speed %d\n", speed);
  863                         return 0;
  864                 }
  865 
  866                 init_link->link_flags.unfair = FALSE;
  867                 init_link->link_flags.skip_lirp_lilp = FALSE;
  868                 init_link->link_flags.gen_loop_validity_check = FALSE;
  869                 init_link->link_flags.skip_lisa = FALSE;
  870                 init_link->link_flags.select_hightest_al_pa = FALSE;
  871 
  872                 //update topology in the link flags for link bring up
  873                 ocs_log_info(sli4->os, "bring up link with topology: %d, PTV: %d, TF: %d, PT: %d \n",
  874                              sli4->config.topology, sli4->config.ptv, sli4->config.tf, sli4->config.pt);
  875                 if (sli4->config.ptv)
  876                         rc = sli4_set_link_flags_persistent_topo(sli4, init_link);
  877                 else
  878                         rc = sli4_set_link_flags_config_topo(sli4, init_link);
  879 
  880         }
  881 
  882         return rc ? 0 : sizeof(sli4_cmd_init_link_t);
  883 }
  884 
  885 /**
  886  * @ingroup sli
  887  * @brief Write an INIT_VFI command to the provided buffer.
  888  *
  889  * @param sli4 SLI context pointer.
  890  * @param buf Virtual pointer to the destination buffer.
  891  * @param size Buffer size, in bytes.
  892  * @param vfi VFI
  893  * @param fcfi FCFI
  894  * @param vpi VPI (Set to -1 if unused.)
  895  *
  896  * @return Returns the number of bytes written.
  897  */
  898 int32_t
  899 sli_cmd_init_vfi(sli4_t *sli4, void *buf, size_t size, uint16_t vfi,
  900                 uint16_t fcfi, uint16_t vpi)
  901 {
  902         sli4_cmd_init_vfi_t     *init_vfi = buf;
  903 
  904         ocs_memset(buf, 0, size);
  905 
  906         init_vfi->hdr.command = SLI4_MBOX_COMMAND_INIT_VFI;
  907 
  908         init_vfi->vfi = vfi;
  909         init_vfi->fcfi = fcfi;
  910 
  911         /*
  912          * If the VPI is valid, initialize it at the same time as
  913          * the VFI
  914          */
  915         if (0xffff != vpi) {
  916                 init_vfi->vp  = TRUE;
  917                 init_vfi->vpi = vpi;
  918         }
  919 
  920         return sizeof(sli4_cmd_init_vfi_t);
  921 }
  922 
  923 /**
  924  * @ingroup sli
  925  * @brief Write an INIT_VPI command to the provided buffer.
  926  *
  927  * @param sli4 SLI context pointer.
  928  * @param buf Virtual pointer to the destination buffer.
  929  * @param size Buffer size, in bytes.
  930  * @param vpi VPI allocated.
  931  * @param vfi VFI associated with this VPI.
  932  *
  933  * @return Returns the number of bytes written.
  934  */
  935 int32_t
  936 sli_cmd_init_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t vpi, uint16_t vfi)
  937 {
  938         sli4_cmd_init_vpi_t     *init_vpi = buf;
  939 
  940         ocs_memset(buf, 0, size);
  941 
  942         init_vpi->hdr.command = SLI4_MBOX_COMMAND_INIT_VPI;
  943         init_vpi->vpi = vpi;
  944         init_vpi->vfi = vfi;
  945 
  946         return sizeof(sli4_cmd_init_vpi_t);
  947 }
  948 
  949 /**
  950  * @ingroup sli
  951  * @brief Write a POST_XRI command to the provided buffer.
  952  *
  953  * @param sli4 SLI context pointer.
  954  * @param buf Virtual pointer to the destination buffer.
  955  * @param size Buffer size, in bytes.
  956  * @param xri_base Starting XRI value for range of XRI given to SLI Port.
  957  * @param xri_count Number of XRIs provided to the SLI Port.
  958  *
  959  * @return Returns the number of bytes written.
  960  */
  961 int32_t
  962 sli_cmd_post_xri(sli4_t *sli4, void *buf, size_t size,  uint16_t xri_base, uint16_t xri_count)
  963 {
  964         sli4_cmd_post_xri_t     *post_xri = buf;
  965 
  966         ocs_memset(buf, 0, size);
  967 
  968         post_xri->hdr.command = SLI4_MBOX_COMMAND_POST_XRI;
  969         post_xri->xri_base = xri_base;
  970         post_xri->xri_count = xri_count;
  971 
  972         if (sli4->config.auto_xfer_rdy == 0) {
  973                 post_xri->enx = TRUE;
  974                 post_xri->val = TRUE;
  975         }
  976 
  977         return sizeof(sli4_cmd_post_xri_t);
  978 }
  979 
  980 /**
  981  * @ingroup sli
  982  * @brief Write a RELEASE_XRI command to the provided buffer.
  983  *
  984  * @param sli4 SLI context pointer.
  985  * @param buf Virtual pointer to the destination buffer.
  986  * @param size Buffer size, in bytes.
  987  * @param num_xri The number of XRIs to be released.
  988  *
  989  * @return Returns the number of bytes written.
  990  */
  991 int32_t
  992 sli_cmd_release_xri(sli4_t *sli4, void *buf, size_t size,  uint8_t num_xri)
  993 {
  994         sli4_cmd_release_xri_t  *release_xri = buf;
  995 
  996         ocs_memset(buf, 0, size);
  997 
  998         release_xri->hdr.command = SLI4_MBOX_COMMAND_RELEASE_XRI;
  999         release_xri->xri_count = num_xri;
 1000 
 1001         return sizeof(sli4_cmd_release_xri_t);
 1002 }
 1003 
 1004 /**
 1005  * @brief Write a READ_CONFIG command to the provided buffer.
 1006  *
 1007  * @param sli4 SLI context pointer.
 1008  * @param buf Virtual pointer to the destination buffer.
 1009  * @param size Buffer size, in bytes
 1010  *
 1011  * @return Returns the number of bytes written.
 1012  */
 1013 static int32_t
 1014 sli_cmd_read_config(sli4_t *sli4, void *buf, size_t size)
 1015 {
 1016         sli4_cmd_read_config_t  *read_config = buf;
 1017 
 1018         ocs_memset(buf, 0, size);
 1019 
 1020         read_config->hdr.command = SLI4_MBOX_COMMAND_READ_CONFIG;
 1021 
 1022         return sizeof(sli4_cmd_read_config_t);
 1023 }
 1024 
 1025 /**
 1026  * @brief Write a READ_NVPARMS command to the provided buffer.
 1027  *
 1028  * @param sli4 SLI context pointer.
 1029  * @param buf Virtual pointer to the destination buffer.
 1030  * @param size Buffer size, in bytes.
 1031  *
 1032  * @return Returns the number of bytes written.
 1033  */
 1034 int32_t
 1035 sli_cmd_read_nvparms(sli4_t *sli4, void *buf, size_t size)
 1036 {
 1037         sli4_cmd_read_nvparms_t *read_nvparms = buf;
 1038 
 1039         ocs_memset(buf, 0, size);
 1040 
 1041         read_nvparms->hdr.command = SLI4_MBOX_COMMAND_READ_NVPARMS;
 1042 
 1043         return sizeof(sli4_cmd_read_nvparms_t);
 1044 }
 1045 
 1046 /**
 1047  * @brief Write a WRITE_NVPARMS command to the provided buffer.
 1048  *
 1049  * @param sli4 SLI context pointer.
 1050  * @param buf Virtual pointer to the destination buffer.
 1051  * @param size Buffer size, in bytes.
 1052  * @param wwpn WWPN to write - pointer to array of 8 uint8_t.
 1053  * @param wwnn WWNN to write - pointer to array of 8 uint8_t.
 1054  * @param hard_alpa Hard ALPA to write.
 1055  * @param preferred_d_id  Preferred D_ID to write.
 1056  *
 1057  * @return Returns the number of bytes written.
 1058  */
 1059 int32_t
 1060 sli_cmd_write_nvparms(sli4_t *sli4, void *buf, size_t size, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
 1061                 uint32_t preferred_d_id)
 1062 {
 1063         sli4_cmd_write_nvparms_t        *write_nvparms = buf;
 1064 
 1065         ocs_memset(buf, 0, size);
 1066 
 1067         write_nvparms->hdr.command = SLI4_MBOX_COMMAND_WRITE_NVPARMS;
 1068         ocs_memcpy(write_nvparms->wwpn, wwpn, 8);
 1069         ocs_memcpy(write_nvparms->wwnn, wwnn, 8);
 1070         write_nvparms->hard_alpa = hard_alpa;
 1071         write_nvparms->preferred_d_id = preferred_d_id;
 1072 
 1073         return sizeof(sli4_cmd_write_nvparms_t);
 1074 }
 1075 
 1076 /**
 1077  * @brief Write a READ_REV command to the provided buffer.
 1078  *
 1079  * @param sli4 SLI context pointer.
 1080  * @param buf Virtual pointer to the destination buffer.
 1081  * @param size Buffer size, in bytes.
 1082  * @param vpd Pointer to the buffer.
 1083  *
 1084  * @return Returns the number of bytes written.
 1085  */
 1086 static int32_t
 1087 sli_cmd_read_rev(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *vpd)
 1088 {
 1089         sli4_cmd_read_rev_t     *read_rev = buf;
 1090 
 1091         ocs_memset(buf, 0, size);
 1092 
 1093         read_rev->hdr.command = SLI4_MBOX_COMMAND_READ_REV;
 1094 
 1095         if (vpd && vpd->size) {
 1096                 read_rev->vpd = TRUE;
 1097 
 1098                 read_rev->available_length = vpd->size;
 1099 
 1100                 read_rev->physical_address_low  = ocs_addr32_lo(vpd->phys);
 1101                 read_rev->physical_address_high = ocs_addr32_hi(vpd->phys);
 1102         }
 1103 
 1104         return sizeof(sli4_cmd_read_rev_t);
 1105 }
 1106 
 1107 /**
 1108  * @ingroup sli
 1109  * @brief Write a READ_SPARM64 command to the provided buffer.
 1110  *
 1111  * @param sli4 SLI context pointer.
 1112  * @param buf Virtual pointer to the destination buffer.
 1113  * @param size Buffer size, in bytes.
 1114  * @param dma DMA buffer for the service parameters.
 1115  * @param vpi VPI used to determine the WWN.
 1116  *
 1117  * @return Returns the number of bytes written.
 1118  */
 1119 int32_t
 1120 sli_cmd_read_sparm64(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 1121                 uint16_t vpi)
 1122 {
 1123         sli4_cmd_read_sparm64_t *read_sparm64 = buf;
 1124 
 1125         ocs_memset(buf, 0, size);
 1126 
 1127         if (SLI4_READ_SPARM64_VPI_SPECIAL == vpi) {
 1128                 ocs_log_test(sli4->os, "special VPI not supported!!!\n");
 1129                 return -1;
 1130         }
 1131 
 1132         if (!dma || !dma->phys) {
 1133                 ocs_log_test(sli4->os, "bad DMA buffer\n");
 1134                 return -1;
 1135         }
 1136 
 1137         read_sparm64->hdr.command = SLI4_MBOX_COMMAND_READ_SPARM64;
 1138 
 1139         read_sparm64->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
 1140         read_sparm64->bde_64.buffer_length = dma->size;
 1141         read_sparm64->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1142         read_sparm64->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1143 
 1144         read_sparm64->vpi = vpi;
 1145 
 1146         return sizeof(sli4_cmd_read_sparm64_t);
 1147 }
 1148 
 1149 /**
 1150  * @ingroup sli
 1151  * @brief Write a READ_TOPOLOGY command to the provided buffer.
 1152  *
 1153  * @param sli4 SLI context pointer.
 1154  * @param buf Virtual pointer to the destination buffer.
 1155  * @param size Buffer size, in bytes.
 1156  * @param dma DMA buffer for loop map (optional).
 1157  *
 1158  * @return Returns the number of bytes written.
 1159  */
 1160 int32_t
 1161 sli_cmd_read_topology(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 1162 {
 1163         sli4_cmd_read_topology_t *read_topo = buf;
 1164 
 1165         ocs_memset(buf, 0, size);
 1166 
 1167         read_topo->hdr.command = SLI4_MBOX_COMMAND_READ_TOPOLOGY;
 1168 
 1169         if (dma && dma->size) {
 1170                 if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) {
 1171                         ocs_log_test(sli4->os, "loop map buffer too small %jd\n",
 1172                                         dma->size);
 1173                         return 0;
 1174                 }
 1175 
 1176                 ocs_memset(dma->virt, 0, dma->size);
 1177 
 1178                 read_topo->bde_loop_map.bde_type = SLI4_BDE_TYPE_BDE_64;
 1179                 read_topo->bde_loop_map.buffer_length = dma->size;
 1180                 read_topo->bde_loop_map.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1181                 read_topo->bde_loop_map.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1182         }
 1183 
 1184         return sizeof(sli4_cmd_read_topology_t);
 1185 }
 1186 
 1187 /**
 1188  * @ingroup sli
 1189  * @brief Write a REG_FCFI command to the provided buffer.
 1190  *
 1191  * @param sli4 SLI context pointer.
 1192  * @param buf Virtual pointer to the destination buffer.
 1193  * @param size Buffer size, in bytes.
 1194  * @param index FCF index returned by READ_FCF_TABLE.
 1195  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
 1196  * @param vlan_id VLAN ID tag.
 1197  *
 1198  * @return Returns the number of bytes written.
 1199  */
 1200 int32_t
 1201 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)
 1202 {
 1203         sli4_cmd_reg_fcfi_t     *reg_fcfi = buf;
 1204         uint32_t                i;
 1205 
 1206         ocs_memset(buf, 0, size);
 1207 
 1208         reg_fcfi->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI;
 1209 
 1210         reg_fcfi->fcf_index = index;
 1211 
 1212         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
 1213                 switch(i) {
 1214                 case 0: reg_fcfi->rq_id_0 = rq_cfg[0].rq_id; break;
 1215                 case 1: reg_fcfi->rq_id_1 = rq_cfg[1].rq_id; break;
 1216                 case 2: reg_fcfi->rq_id_2 = rq_cfg[2].rq_id; break;
 1217                 case 3: reg_fcfi->rq_id_3 = rq_cfg[3].rq_id; break;
 1218                 }
 1219                 reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
 1220                 reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
 1221                 reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
 1222                 reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match;
 1223         }
 1224 
 1225         if (vlan_id) {
 1226                 reg_fcfi->vv = TRUE;
 1227                 reg_fcfi->vlan_tag = vlan_id;
 1228         }
 1229 
 1230         return sizeof(sli4_cmd_reg_fcfi_t);
 1231 }
 1232 
 1233 /**
 1234  * @brief Write REG_FCFI_MRQ to provided command buffer
 1235  *
 1236  * @param sli4 SLI context pointer.
 1237  * @param buf Virtual pointer to the destination buffer.
 1238  * @param size Buffer size, in bytes.
 1239  * @param fcf_index FCF index returned by READ_FCF_TABLE.
 1240  * @param vlan_id VLAN ID tag.
 1241  * @param rr_quant Round robin quanta if RQ selection policy is 2
 1242  * @param rq_selection_policy RQ selection policy
 1243  * @param num_rqs Array of count of RQs per filter
 1244  * @param rq_ids Array of RQ ids per filter
 1245  * @param rq_cfg RQ_ID/R_CTL/TYPE routing information
 1246  *
 1247  * @return returns 0 for success, a negative error code value for failure.
 1248  */
 1249 int32_t
 1250 sli_cmd_reg_fcfi_mrq(sli4_t *sli4, void *buf, size_t size, uint8_t mode,
 1251                      uint16_t fcf_index, uint16_t vlan_id, uint8_t rq_selection_policy,
 1252                      uint8_t mrq_bit_mask, uint16_t num_mrqs,
 1253                      sli4_cmd_rq_cfg_t rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG])
 1254 {
 1255         sli4_cmd_reg_fcfi_mrq_t *reg_fcfi_mrq = buf;
 1256         uint32_t i;
 1257 
 1258         ocs_memset(buf, 0, size);
 1259 
 1260         reg_fcfi_mrq->hdr.command = SLI4_MBOX_COMMAND_REG_FCFI_MRQ;
 1261         if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) {
 1262                 reg_fcfi_mrq->fcf_index = fcf_index;
 1263                 if (vlan_id) {
 1264                         reg_fcfi_mrq->vv = TRUE;
 1265                         reg_fcfi_mrq->vlan_tag = vlan_id;
 1266                 }
 1267                 goto done;
 1268         }
 1269 
 1270         reg_fcfi_mrq->mode = mode;
 1271         for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) {
 1272                 reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask;
 1273                 reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match;
 1274                 reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask;
 1275                 reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match;
 1276 
 1277                 switch(i) {
 1278                 case 3: reg_fcfi_mrq->rq_id_3 = rq_cfg[i].rq_id; break;
 1279                 case 2: reg_fcfi_mrq->rq_id_2 = rq_cfg[i].rq_id; break;
 1280                 case 1: reg_fcfi_mrq->rq_id_1 = rq_cfg[i].rq_id; break;
 1281                 case 0: reg_fcfi_mrq->rq_id_0 = rq_cfg[i].rq_id; break;
 1282                 }
 1283         }
 1284 
 1285         reg_fcfi_mrq->rq_selection_policy = rq_selection_policy;
 1286         reg_fcfi_mrq->mrq_filter_bitmask = mrq_bit_mask;
 1287         reg_fcfi_mrq->num_mrq_pairs = num_mrqs;
 1288 done:
 1289         return sizeof(sli4_cmd_reg_fcfi_mrq_t);
 1290 }
 1291 
 1292 /**
 1293  * @ingroup sli
 1294  * @brief Write a REG_RPI command to the provided buffer.
 1295  *
 1296  * @param sli4 SLI context pointer.
 1297  * @param buf Virtual pointer to the destination buffer.
 1298  * @param size Buffer size, in bytes.
 1299  * @param nport_id Remote F/N_Port_ID.
 1300  * @param rpi Previously-allocated Remote Port Indicator.
 1301  * @param vpi Previously-allocated Virtual Port Indicator.
 1302  * @param dma DMA buffer that contains the remote port's service parameters.
 1303  * @param update Boolean indicating an update to an existing RPI (TRUE)
 1304  * or a new registration (FALSE).
 1305  *
 1306  * @return Returns the number of bytes written.
 1307  */
 1308 int32_t
 1309 sli_cmd_reg_rpi(sli4_t *sli4, void *buf, size_t size, uint32_t nport_id, uint16_t rpi, 
 1310                         uint16_t vpi, ocs_dma_t *dma, uint8_t update,  uint8_t enable_t10_pi)
 1311 {
 1312         sli4_cmd_reg_rpi_t *reg_rpi = buf;
 1313 
 1314         ocs_memset(buf, 0, size);
 1315 
 1316         reg_rpi->hdr.command = SLI4_MBOX_COMMAND_REG_RPI;
 1317 
 1318         reg_rpi->rpi = rpi;
 1319         reg_rpi->remote_n_port_id = nport_id;
 1320         reg_rpi->upd = update;
 1321         reg_rpi->etow = enable_t10_pi;
 1322 
 1323         reg_rpi->bde_64.bde_type = SLI4_BDE_TYPE_BDE_64;
 1324         reg_rpi->bde_64.buffer_length = SLI4_REG_RPI_BUF_LEN;
 1325         reg_rpi->bde_64.u.data.buffer_address_low  = ocs_addr32_lo(dma->phys);
 1326         reg_rpi->bde_64.u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 1327 
 1328         reg_rpi->vpi = vpi;
 1329 
 1330         return sizeof(sli4_cmd_reg_rpi_t);
 1331 }
 1332 
 1333 /**
 1334  * @ingroup sli
 1335  * @brief Write a REG_VFI command to the provided buffer.
 1336  *
 1337  * @param sli4 SLI context pointer.
 1338  * @param buf Virtual pointer to the destination buffer.
 1339  * @param size Buffer size, in bytes.
 1340  * @param domain Pointer to the domain object.
 1341  *
 1342  * @return Returns the number of bytes written.
 1343  */
 1344 int32_t
 1345 sli_cmd_reg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain)
 1346 {
 1347         sli4_cmd_reg_vfi_t      *reg_vfi = buf;
 1348 
 1349         if (!sli4 || !buf || !domain) {
 1350                 return 0;
 1351         }
 1352 
 1353         ocs_memset(buf, 0, size);
 1354 
 1355         reg_vfi->hdr.command = SLI4_MBOX_COMMAND_REG_VFI;
 1356 
 1357         reg_vfi->vfi = domain->indicator;
 1358 
 1359         reg_vfi->fcfi = domain->fcf_indicator;
 1360 
 1361         /* TODO contents of domain->dma only valid if topo == FABRIC */
 1362         reg_vfi->sparm.bde_type = SLI4_BDE_TYPE_BDE_64;
 1363         reg_vfi->sparm.buffer_length = 0x70;
 1364         reg_vfi->sparm.u.data.buffer_address_low  = ocs_addr32_lo(domain->dma.phys);
 1365         reg_vfi->sparm.u.data.buffer_address_high = ocs_addr32_hi(domain->dma.phys);
 1366 
 1367         reg_vfi->e_d_tov = sli4->config.e_d_tov;
 1368         reg_vfi->r_a_tov = sli4->config.r_a_tov;
 1369 
 1370         reg_vfi->vp = TRUE;
 1371         reg_vfi->vpi = domain->sport->indicator;
 1372         ocs_memcpy(reg_vfi->wwpn, &domain->sport->sli_wwpn, sizeof(reg_vfi->wwpn));
 1373         reg_vfi->local_n_port_id = domain->sport->fc_id;
 1374 
 1375         return sizeof(sli4_cmd_reg_vfi_t);
 1376 }
 1377 
 1378 /**
 1379  * @ingroup sli
 1380  * @brief Write a REG_VPI command to the provided buffer.
 1381  *
 1382  * @param sli4 SLI context pointer.
 1383  * @param buf Virtual pointer to the destination buffer.
 1384  * @param size Buffer size, in bytes.
 1385  * @param sport Point to SLI Port object.
 1386  * @param update Boolean indicating whether to update the existing VPI (true)
 1387  * or create a new VPI (false).
 1388  *
 1389  * @return Returns the number of bytes written.
 1390  */
 1391 int32_t
 1392 sli_cmd_reg_vpi(sli4_t *sli4, void *buf, size_t size, ocs_sli_port_t *sport, uint8_t update)
 1393 {
 1394         sli4_cmd_reg_vpi_t      *reg_vpi = buf;
 1395 
 1396         if (!sli4 || !buf || !sport) {
 1397                 return 0;
 1398         }
 1399 
 1400         ocs_memset(buf, 0, size);
 1401 
 1402         reg_vpi->hdr.command = SLI4_MBOX_COMMAND_REG_VPI;
 1403 
 1404         reg_vpi->local_n_port_id = sport->fc_id;
 1405         reg_vpi->upd = update != 0;
 1406         ocs_memcpy(reg_vpi->wwpn, &sport->sli_wwpn, sizeof(reg_vpi->wwpn));
 1407         reg_vpi->vpi = sport->indicator;
 1408         reg_vpi->vfi = sport->domain->indicator;
 1409 
 1410         return sizeof(sli4_cmd_reg_vpi_t);
 1411 }
 1412 
 1413 /**
 1414  * @brief Write a REQUEST_FEATURES command to the provided buffer.
 1415  *
 1416  * @param sli4 SLI context pointer.
 1417  * @param buf Virtual pointer to the destination buffer.
 1418  * @param size Buffer size, in bytes.
 1419  * @param mask Features to request.
 1420  * @param query Use feature query mode (does not change FW).
 1421  *
 1422  * @return Returns the number of bytes written.
 1423  */
 1424 static int32_t
 1425 sli_cmd_request_features(sli4_t *sli4, void *buf, size_t size, sli4_features_t mask, uint8_t query)
 1426 {
 1427         sli4_cmd_request_features_t *features = buf;
 1428 
 1429         ocs_memset(buf, 0, size);
 1430 
 1431         features->hdr.command = SLI4_MBOX_COMMAND_REQUEST_FEATURES;
 1432 
 1433         if (query) {
 1434                 features->qry = TRUE;
 1435         }
 1436         features->command.dword = mask.dword;
 1437 
 1438         return sizeof(sli4_cmd_request_features_t);
 1439 }
 1440 
 1441 /**
 1442  * @ingroup sli
 1443  * @brief Write a SLI_CONFIG command to the provided buffer.
 1444  *
 1445  * @param sli4 SLI context pointer.
 1446  * @param buf Virtual pointer to the destination buffer.
 1447  * @param size Buffer size, in bytes.
 1448  * @param length Length in bytes of attached command.
 1449  * @param dma DMA buffer for non-embedded commands.
 1450  *
 1451  * @return Returns the number of bytes written.
 1452  */
 1453 int32_t
 1454 sli_cmd_sli_config(sli4_t *sli4, void *buf, size_t size, uint32_t length, ocs_dma_t *dma)
 1455 {
 1456         sli4_cmd_sli_config_t   *sli_config = NULL;
 1457 
 1458         if ((length > sizeof(sli_config->payload.embed)) && (dma == NULL)) {
 1459                 ocs_log_test(sli4->os, "length(%d) > payload(%ld)\n",
 1460                                 length, sizeof(sli_config->payload.embed));
 1461                 return -1;
 1462         }
 1463 
 1464         sli_config = buf;
 1465 
 1466         ocs_memset(buf, 0, size);
 1467 
 1468         sli_config->hdr.command = SLI4_MBOX_COMMAND_SLI_CONFIG;
 1469         if (NULL == dma) {
 1470                 sli_config->emb = TRUE;
 1471                 sli_config->payload_length = length;
 1472         } else {
 1473                 sli_config->emb = FALSE;
 1474 
 1475                 sli_config->pmd_count = 1;
 1476 
 1477                 sli_config->payload.mem.address_low = ocs_addr32_lo(dma->phys);
 1478                 sli_config->payload.mem.address_high = ocs_addr32_hi(dma->phys);
 1479                 sli_config->payload.mem.length = dma->size;
 1480                 sli_config->payload_length = dma->size;
 1481 #if defined(OCS_INCLUDE_DEBUG)
 1482                 /* save pointer to DMA for BMBX dumping purposes */
 1483                 sli4->bmbx_non_emb_pmd = dma;
 1484 #endif
 1485         }
 1486 
 1487         return offsetof(sli4_cmd_sli_config_t, payload.embed);
 1488 }
 1489 
 1490 /**
 1491  * @brief Initialize SLI Port control register.
 1492  *
 1493  * @param sli4 SLI context pointer.
 1494  * @param endian Endian value to write.
 1495  *
 1496  * @return Returns 0 on success, or a negative error code value on failure.
 1497  */
 1498 
 1499 static int32_t
 1500 sli_sliport_control(sli4_t *sli4, uint32_t endian)
 1501 {
 1502         uint32_t iter;
 1503         int32_t rc;
 1504 
 1505         rc = -1;
 1506 
 1507         /* Initialize port, endian */
 1508         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, endian | SLI4_SLIPORT_CONTROL_IP);
 1509 
 1510         for (iter = 0; iter < 3000; iter ++) {
 1511                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
 1512                 if (sli_fw_ready(sli4) == 1) {
 1513                         rc = 0;
 1514                         break;
 1515                 }
 1516         }
 1517 
 1518         if (rc != 0) {
 1519                 ocs_log_crit(sli4->os, "port failed to become ready after initialization\n");
 1520         }
 1521 
 1522         return rc;
 1523 }
 1524 
 1525 /**
 1526  * @ingroup sli
 1527  * @brief Write a UNREG_FCFI command to the provided buffer.
 1528  *
 1529  * @param sli4 SLI context pointer.
 1530  * @param buf Virtual pointer to the destination buffer.
 1531  * @param size Buffer size, in bytes.
 1532  * @param indicator Indicator value.
 1533  *
 1534  * @return Returns the number of bytes written.
 1535  */
 1536 int32_t
 1537 sli_cmd_unreg_fcfi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator)
 1538 {
 1539         sli4_cmd_unreg_fcfi_t   *unreg_fcfi = buf;
 1540 
 1541         if (!sli4 || !buf) {
 1542                 return 0;
 1543         }
 1544 
 1545         ocs_memset(buf, 0, size);
 1546 
 1547         unreg_fcfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_FCFI;
 1548 
 1549         unreg_fcfi->fcfi = indicator;
 1550 
 1551         return sizeof(sli4_cmd_unreg_fcfi_t);
 1552 }
 1553 
 1554 /**
 1555  * @ingroup sli
 1556  * @brief Write an UNREG_RPI command to the provided buffer.
 1557  *
 1558  * @param sli4 SLI context pointer.
 1559  * @param buf Virtual pointer to the destination buffer.
 1560  * @param size Buffer size, in bytes.
 1561  * @param indicator Indicator value.
 1562  * @param which Type of unregister, such as node, port, domain, or FCF.
 1563  * @param fc_id FC address.
 1564  *
 1565  * @return Returns the number of bytes written.
 1566  */
 1567 int32_t
 1568 sli_cmd_unreg_rpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, sli4_resource_e which,
 1569                 uint32_t fc_id)
 1570 {
 1571         sli4_cmd_unreg_rpi_t    *unreg_rpi = buf;
 1572         uint8_t         index_indicator = 0;
 1573 
 1574         if (!sli4 || !buf) {
 1575                 return 0;
 1576         }
 1577 
 1578         ocs_memset(buf, 0, size);
 1579 
 1580         unreg_rpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_RPI;
 1581 
 1582         switch (which) {
 1583         case SLI_RSRC_FCOE_RPI:
 1584                 index_indicator = SLI4_UNREG_RPI_II_RPI;
 1585                 if (fc_id != UINT32_MAX) {
 1586                         unreg_rpi->dp = TRUE;
 1587                         unreg_rpi->destination_n_port_id = fc_id & 0x00ffffff;
 1588                 }
 1589                 break;
 1590         case SLI_RSRC_FCOE_VPI:
 1591                 index_indicator = SLI4_UNREG_RPI_II_VPI;
 1592                 break;
 1593         case SLI_RSRC_FCOE_VFI:
 1594                 index_indicator = SLI4_UNREG_RPI_II_VFI;
 1595                 break;
 1596         case SLI_RSRC_FCOE_FCFI:
 1597                 index_indicator = SLI4_UNREG_RPI_II_FCFI;
 1598                 break;
 1599         default:
 1600                 ocs_log_test(sli4->os, "unknown type %#x\n", which);
 1601                 return 0;
 1602         }
 1603 
 1604         unreg_rpi->ii = index_indicator;
 1605         unreg_rpi->index = indicator;
 1606 
 1607         return sizeof(sli4_cmd_unreg_rpi_t);
 1608 }
 1609 
 1610 /**
 1611  * @ingroup sli
 1612  * @brief Write an UNREG_VFI command to the provided buffer.
 1613  *
 1614  * @param sli4 SLI context pointer.
 1615  * @param buf Virtual pointer to the destination buffer.
 1616  * @param size Buffer size, in bytes.
 1617  * @param domain Pointer to the domain object
 1618  * @param which Type of unregister, such as domain, FCFI, or everything.
 1619  *
 1620  * @return Returns the number of bytes written.
 1621  */
 1622 int32_t
 1623 sli_cmd_unreg_vfi(sli4_t *sli4, void *buf, size_t size, ocs_domain_t *domain, uint32_t which)
 1624 {
 1625         sli4_cmd_unreg_vfi_t    *unreg_vfi = buf;
 1626 
 1627         if (!sli4 || !buf || !domain) {
 1628                 return 0;
 1629         }
 1630 
 1631         ocs_memset(buf, 0, size);
 1632 
 1633         unreg_vfi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VFI;
 1634         switch (which) {
 1635         case SLI4_UNREG_TYPE_DOMAIN:
 1636                 unreg_vfi->index = domain->indicator;
 1637                 break;
 1638         case SLI4_UNREG_TYPE_FCF:
 1639                 unreg_vfi->index = domain->fcf_indicator;
 1640                 break;
 1641         case SLI4_UNREG_TYPE_ALL:
 1642                 unreg_vfi->index = UINT16_MAX;
 1643                 break;
 1644         default:
 1645                 return 0;
 1646         }
 1647 
 1648         if (SLI4_UNREG_TYPE_DOMAIN != which) {
 1649                 unreg_vfi->ii = SLI4_UNREG_VFI_II_FCFI;
 1650         }
 1651 
 1652         return sizeof(sli4_cmd_unreg_vfi_t);
 1653 }
 1654 
 1655 /**
 1656  * @ingroup sli
 1657  * @brief Write an UNREG_VPI command to the provided buffer.
 1658  *
 1659  * @param sli4 SLI context pointer.
 1660  * @param buf Virtual pointer to the destination buffer.
 1661  * @param size Buffer size, in bytes.
 1662  * @param indicator Indicator value.
 1663  * @param which Type of unregister: port, domain, FCFI, everything
 1664  *
 1665  * @return Returns the number of bytes written.
 1666  */
 1667 int32_t
 1668 sli_cmd_unreg_vpi(sli4_t *sli4, void *buf, size_t size, uint16_t indicator, uint32_t which)
 1669 {
 1670         sli4_cmd_unreg_vpi_t    *unreg_vpi = buf;
 1671 
 1672         if (!sli4 || !buf) {
 1673                 return 0;
 1674         }
 1675 
 1676         ocs_memset(buf, 0, size);
 1677 
 1678         unreg_vpi->hdr.command = SLI4_MBOX_COMMAND_UNREG_VPI;
 1679         unreg_vpi->index = indicator;
 1680         switch (which) {
 1681         case SLI4_UNREG_TYPE_PORT:
 1682                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VPI;
 1683                 break;
 1684         case SLI4_UNREG_TYPE_DOMAIN:
 1685                 unreg_vpi->ii = SLI4_UNREG_VPI_II_VFI;
 1686                 break;
 1687         case SLI4_UNREG_TYPE_FCF:
 1688                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
 1689                 break;
 1690         case SLI4_UNREG_TYPE_ALL:
 1691                 unreg_vpi->index = UINT16_MAX;  /* override indicator */
 1692                 unreg_vpi->ii = SLI4_UNREG_VPI_II_FCFI;
 1693                 break;
 1694         default:
 1695                 return 0;
 1696         }
 1697 
 1698         return sizeof(sli4_cmd_unreg_vpi_t);
 1699 }
 1700 
 1701 /**
 1702  * @ingroup sli
 1703  * @brief Write an CONFIG_AUTO_XFER_RDY command to the provided buffer.
 1704  *
 1705  * @param sli4 SLI context pointer.
 1706  * @param buf Virtual pointer to the destination buffer.
 1707  * @param size Buffer size, in bytes.
 1708  * @param max_burst_len if the write FCP_DL is less than this size,
 1709  * then the SLI port will generate the auto XFER_RDY.
 1710  *
 1711  * @return Returns the number of bytes written.
 1712  */
 1713 int32_t
 1714 sli_cmd_config_auto_xfer_rdy(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len)
 1715 {
 1716         sli4_cmd_config_auto_xfer_rdy_t *req = buf;
 1717 
 1718         if (!sli4 || !buf) {
 1719                 return 0;
 1720         }
 1721 
 1722         ocs_memset(buf, 0, size);
 1723 
 1724         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY;
 1725         req->max_burst_len = max_burst_len;
 1726 
 1727         return sizeof(sli4_cmd_config_auto_xfer_rdy_t);
 1728 }
 1729 
 1730 /**
 1731  * @ingroup sli
 1732  * @brief Write an CONFIG_AUTO_XFER_RDY_HP command to the provided buffer.
 1733  *
 1734  * @param sli4 SLI context pointer.
 1735  * @param buf Virtual pointer to the destination buffer.
 1736  * @param size Buffer size, in bytes.
 1737  * @param max_burst_len if the write FCP_DL is less than this size,
 1738  * @param esoc enable start offset computation,
 1739  * @param block_size block size,
 1740  * then the SLI port will generate the auto XFER_RDY.
 1741  *
 1742  * @return Returns the number of bytes written.
 1743  */
 1744 int32_t
 1745 sli_cmd_config_auto_xfer_rdy_hp(sli4_t *sli4, void *buf, size_t size, uint32_t max_burst_len,
 1746                                                 uint32_t esoc, uint32_t block_size )
 1747 {
 1748         sli4_cmd_config_auto_xfer_rdy_hp_t      *req = buf;
 1749 
 1750         if (!sli4 || !buf) {
 1751                 return 0;
 1752         }
 1753 
 1754         ocs_memset(buf, 0, size);
 1755 
 1756         req->hdr.command = SLI4_MBOX_COMMAND_CONFIG_AUTO_XFER_RDY_HP;
 1757         req->max_burst_len = max_burst_len;
 1758         req->esoc = esoc;
 1759         req->block_size = block_size;
 1760         return sizeof(sli4_cmd_config_auto_xfer_rdy_hp_t);
 1761 }
 1762 
 1763 /**
 1764  * @brief Write a COMMON_FUNCTION_RESET command.
 1765  *
 1766  * @param sli4 SLI context.
 1767  * @param buf Destination buffer for the command.
 1768  * @param size Buffer size, in bytes.
 1769  *
 1770  * @return Returns the number of bytes written.
 1771  */
 1772 static int32_t
 1773 sli_cmd_common_function_reset(sli4_t *sli4, void *buf, size_t size)
 1774 {
 1775         sli4_req_common_function_reset_t *reset = NULL;
 1776         uint32_t        sli_config_off = 0;
 1777 
 1778         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1779                 uint32_t payload_size;
 1780 
 1781                 /* Payload length must accommodate both request and response */
 1782                 payload_size = max(sizeof(sli4_req_common_function_reset_t),
 1783                                 sizeof(sli4_res_common_function_reset_t));
 1784 
 1785                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 1786                                 NULL);
 1787         }
 1788         reset = (sli4_req_common_function_reset_t *)((uint8_t *)buf + sli_config_off);
 1789 
 1790         reset->hdr.opcode = SLI4_OPC_COMMON_FUNCTION_RESET;
 1791         reset->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1792 
 1793         return(sli_config_off + sizeof(sli4_req_common_function_reset_t));
 1794 }
 1795 
 1796 /**
 1797  * @brief Write a COMMON_CREATE_CQ command.
 1798  *
 1799  * @param sli4 SLI context.
 1800  * @param buf Destination buffer for the command.
 1801  * @param size Buffer size, in bytes.
 1802  * @param qmem DMA memory for the queue.
 1803  * @param eq_id Associated EQ_ID
 1804  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
 1805  *
 1806  * @note This creates a Version 0 message.
 1807  *
 1808  * @return Returns the number of bytes written.
 1809  */
 1810 static int32_t
 1811 sli_cmd_common_create_cq(sli4_t *sli4, void *buf, size_t size,
 1812                 ocs_dma_t *qmem, uint16_t eq_id, uint16_t ignored)
 1813 {
 1814         sli4_req_common_create_cq_v0_t  *cqv0 = NULL;
 1815         sli4_req_common_create_cq_v2_t  *cqv2 = NULL;
 1816         uint32_t        sli_config_off = 0;
 1817         uint32_t        p;
 1818         uintptr_t       addr;
 1819         uint32_t        if_type = sli4->if_type;
 1820         uint32_t        page_bytes = 0;
 1821         uint32_t        num_pages = 0;
 1822         uint32_t        cmd_size = 0;
 1823         uint32_t        page_size = 0;
 1824         uint32_t        n_cqe = 0;
 1825 
 1826         /* First calculate number of pages and the mailbox cmd length */
 1827         switch (if_type)
 1828         {
 1829         case SLI4_IF_TYPE_BE3_SKH_PF:
 1830                 page_bytes = SLI_PAGE_SIZE;
 1831                 num_pages = sli_page_count(qmem->size, page_bytes);
 1832                 cmd_size = sizeof(sli4_req_common_create_cq_v0_t) + (8 * num_pages);
 1833                 break;
 1834         case SLI4_IF_TYPE_LANCER_FC_ETH:
 1835         case SLI4_IF_TYPE_LANCER_G7:
 1836                 n_cqe = qmem->size / SLI4_CQE_BYTES;
 1837                 switch (n_cqe) {
 1838                 case 256:
 1839                 case 512:
 1840                 case 1024:
 1841                 case 2048:
 1842                         page_size = 1;
 1843                         break;
 1844                 case 4096:
 1845                         page_size = 2;
 1846                         break;
 1847                 default:
 1848                         return 0;
 1849                 }
 1850                 page_bytes = page_size * SLI_PAGE_SIZE;
 1851                 num_pages = sli_page_count(qmem->size, page_bytes);
 1852                 cmd_size = sizeof(sli4_req_common_create_cq_v2_t) + (8 * num_pages);
 1853                 break;
 1854         default:
 1855                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", if_type);
 1856                 return -1;
 1857         }
 1858 
 1859         /* now that we have the mailbox command size, we can set SLI_CONFIG fields */
 1860         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1861                 uint32_t payload_size;
 1862 
 1863                 /* Payload length must accommodate both request and response */
 1864                 payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_t));
 1865 
 1866                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 1867                                 NULL);
 1868         }
 1869 
 1870         switch (if_type)
 1871         {
 1872         case SLI4_IF_TYPE_BE3_SKH_PF:
 1873                 cqv0 = (sli4_req_common_create_cq_v0_t *)((uint8_t *)buf + sli_config_off);
 1874                 cqv0->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
 1875                 cqv0->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1876                 cqv0->hdr.version = 0;
 1877                 cqv0->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 1878 
 1879                 /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
 1880                 cqv0->num_pages = num_pages;
 1881                 switch (cqv0->num_pages) {
 1882                 case 1:
 1883                         cqv0->cqecnt = SLI4_CQ_CNT_256;
 1884                         break;
 1885                 case 2:
 1886                         cqv0->cqecnt = SLI4_CQ_CNT_512;
 1887                         break;
 1888                 case 4:
 1889                         cqv0->cqecnt = SLI4_CQ_CNT_1024;
 1890                         break;
 1891                 default:
 1892                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv0->num_pages);
 1893                         return -1;
 1894                 }
 1895                 cqv0->evt = TRUE;
 1896                 cqv0->valid = TRUE;
 1897                 /* TODO cq->nodelay = ???; */
 1898                 /* TODO cq->clswm = ???; */
 1899                 cqv0->arm = FALSE;
 1900                 cqv0->eq_id = eq_id;
 1901 
 1902                 for (p = 0, addr = qmem->phys;
 1903                                 p < cqv0->num_pages;
 1904                                 p++, addr += page_bytes) {
 1905                         cqv0->page_physical_address[p].low = ocs_addr32_lo(addr);
 1906                         cqv0->page_physical_address[p].high = ocs_addr32_hi(addr);
 1907                 }
 1908 
 1909                 break;
 1910         case SLI4_IF_TYPE_LANCER_FC_ETH:
 1911         case SLI4_IF_TYPE_LANCER_G7:
 1912         {
 1913                 cqv2 = (sli4_req_common_create_cq_v2_t *)((uint8_t *)buf + sli_config_off);
 1914                 cqv2->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ;
 1915                 cqv2->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1916                 cqv2->hdr.version = 2;
 1917                 cqv2->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 1918 
 1919                 if (if_type == SLI4_IF_TYPE_LANCER_G7)
 1920                         cqv2->autovalid = TRUE;
 1921 
 1922                 cqv2->page_size = page_size;
 1923 
 1924                 /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.3) */
 1925                 cqv2->num_pages = num_pages;
 1926                 if (!cqv2->num_pages || (cqv2->num_pages > SLI4_COMMON_CREATE_CQ_V2_MAX_PAGES)) {
 1927                         return 0;
 1928                 }
 1929 
 1930                 switch (cqv2->num_pages) {
 1931                 case 1:
 1932                         cqv2->cqecnt = SLI4_CQ_CNT_256;
 1933                         break;
 1934                 case 2:
 1935                         cqv2->cqecnt = SLI4_CQ_CNT_512;
 1936                         break;
 1937                 case 4:
 1938                         cqv2->cqecnt = SLI4_CQ_CNT_1024;
 1939                         break;
 1940                 case 8:
 1941                         cqv2->cqecnt = SLI4_CQ_CNT_LARGE;
 1942                         cqv2->cqe_count = n_cqe;
 1943                         break;
 1944                 default:
 1945                         ocs_log_test(sli4->os, "num_pages %d not valid\n", cqv2->num_pages);
 1946                         return -1;
 1947                 }
 1948 
 1949                 cqv2->evt = TRUE;
 1950                 cqv2->valid = TRUE;
 1951                 /* TODO cq->nodelay = ???; */
 1952                 /* TODO cq->clswm = ???; */
 1953                 cqv2->arm = FALSE;
 1954                 cqv2->eq_id = eq_id;
 1955 
 1956                 for (p = 0, addr = qmem->phys;
 1957                                 p < cqv2->num_pages;
 1958                                 p++, addr += page_bytes) {
 1959                         cqv2->page_physical_address[p].low = ocs_addr32_lo(addr);
 1960                         cqv2->page_physical_address[p].high = ocs_addr32_hi(addr);
 1961                 }
 1962         }
 1963                 break;
 1964         }       
 1965 
 1966         return (sli_config_off + cmd_size);
 1967 }
 1968 
 1969 /**
 1970  * @brief Write a COMMON_DESTROY_CQ command.
 1971  *
 1972  * @param sli4 SLI context.
 1973  * @param buf Destination buffer for the command.
 1974  * @param size Buffer size, in bytes.
 1975  * @param cq_id CQ ID
 1976  *
 1977  * @note This creates a Version 0 message.
 1978  *
 1979  * @return Returns the number of bytes written.
 1980  */
 1981 static int32_t
 1982 sli_cmd_common_destroy_cq(sli4_t *sli4, void *buf, size_t size, uint16_t cq_id)
 1983 {
 1984         sli4_req_common_destroy_cq_t    *cq = NULL;
 1985         uint32_t        sli_config_off = 0;
 1986 
 1987         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 1988                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 1989                                 /* Payload length must accommodate both request and response */
 1990                                 max(sizeof(sli4_req_common_destroy_cq_t),
 1991                                         sizeof(sli4_res_hdr_t)),
 1992                                 NULL);
 1993         }
 1994         cq = (sli4_req_common_destroy_cq_t *)((uint8_t *)buf + sli_config_off);
 1995 
 1996         cq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_CQ;
 1997         cq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 1998         cq->hdr.request_length = sizeof(sli4_req_common_destroy_cq_t) -
 1999                                         sizeof(sli4_req_hdr_t);
 2000         cq->cq_id = cq_id;
 2001 
 2002         return(sli_config_off + sizeof(sli4_req_common_destroy_cq_t));
 2003 }
 2004 
 2005 /**
 2006  * @brief Write a COMMON_MODIFY_EQ_DELAY command.
 2007  *
 2008  * @param sli4 SLI context.
 2009  * @param buf Destination buffer for the command.
 2010  * @param size Buffer size, in bytes.
 2011  * @param q Queue object array.
 2012  * @param num_q Queue object array count.
 2013  * @param shift Phase shift for staggering interrupts.
 2014  * @param delay_mult Delay multiplier for limiting interrupt frequency.
 2015  *
 2016  * @return Returns the number of bytes written.
 2017  */
 2018 static int32_t
 2019 sli_cmd_common_modify_eq_delay(sli4_t *sli4, void *buf, size_t size, sli4_queue_t *q, int num_q, uint32_t shift,
 2020                                 uint32_t delay_mult)
 2021 {
 2022         sli4_req_common_modify_eq_delay_t *modify_delay = NULL;
 2023         uint32_t        sli_config_off = 0;
 2024         int i;
 2025 
 2026         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2027                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2028                                 /* Payload length must accommodate both request and response */
 2029                                 max(sizeof(sli4_req_common_modify_eq_delay_t), sizeof(sli4_res_hdr_t)),
 2030                                 NULL);
 2031         }
 2032 
 2033         modify_delay = (sli4_req_common_modify_eq_delay_t *)((uint8_t *)buf + sli_config_off);
 2034 
 2035         modify_delay->hdr.opcode = SLI4_OPC_COMMON_MODIFY_EQ_DELAY;
 2036         modify_delay->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2037         modify_delay->hdr.request_length = sizeof(sli4_req_common_modify_eq_delay_t) -
 2038                                         sizeof(sli4_req_hdr_t);
 2039 
 2040         modify_delay->num_eq = num_q;
 2041 
 2042         for (i = 0; i<num_q; i++) {
 2043                 modify_delay->eq_delay_record[i].eq_id = q[i].id;
 2044                 modify_delay->eq_delay_record[i].phase = shift;
 2045                 modify_delay->eq_delay_record[i].delay_multiplier = delay_mult;
 2046         }
 2047 
 2048         return(sli_config_off + sizeof(sli4_req_common_modify_eq_delay_t));
 2049 }
 2050 
 2051 /**
 2052  * @brief Write a COMMON_CREATE_EQ command.
 2053  *
 2054  * @param sli4 SLI context.
 2055  * @param buf Destination buffer for the command.
 2056  * @param size Buffer size, in bytes.
 2057  * @param qmem DMA memory for the queue.
 2058  * @param ignored1 Ignored (used for consistency among queue creation functions).
 2059  * @param ignored2 Ignored (used for consistency among queue creation functions).
 2060  *
 2061  * @note Other queue creation routines use the last parameter to pass in
 2062  * the associated Q_ID and ULP. EQ doesn't have an associated queue or ULP,
 2063  * so these parameters are ignored
 2064  *
 2065  * @note This creates a Version 0 message
 2066  *
 2067  * @return Returns the number of bytes written.
 2068  */
 2069 static int32_t
 2070 sli_cmd_common_create_eq(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
 2071                 uint16_t ignored1, uint16_t ignored2)
 2072 {
 2073         sli4_req_common_create_eq_t     *eq = NULL;
 2074         uint32_t        sli_config_off = 0;
 2075         uint32_t        p;
 2076         uintptr_t       addr;
 2077 
 2078         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2079                 uint32_t payload_size;
 2080 
 2081                 /* Payload length must accommodate both request and response */
 2082                 payload_size = max(sizeof(sli4_req_common_create_eq_t),
 2083                                 sizeof(sli4_res_common_create_queue_t));
 2084 
 2085                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 2086                                 NULL);
 2087         }
 2088         eq = (sli4_req_common_create_eq_t *)((uint8_t *)buf + sli_config_off);
 2089 
 2090         eq->hdr.opcode = SLI4_OPC_COMMON_CREATE_EQ;
 2091         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2092         eq->hdr.request_length = sizeof(sli4_req_common_create_eq_t) -
 2093                                         sizeof(sli4_req_hdr_t);
 2094         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) {
 2095                 eq->hdr.version = 2;
 2096                 eq->autovalid = TRUE;
 2097         }
 2098         /* valid values for number of pages: 1, 2, 4 (sec 4.4.3) */
 2099         eq->num_pages = qmem->size / SLI_PAGE_SIZE;
 2100         switch (eq->num_pages) {
 2101         case 1:
 2102                 eq->eqesz = SLI4_EQE_SIZE_4;
 2103                 eq->count = SLI4_EQ_CNT_1024;
 2104                 break;
 2105         case 2:
 2106                 eq->eqesz = SLI4_EQE_SIZE_4;
 2107                 eq->count = SLI4_EQ_CNT_2048;
 2108                 break;
 2109         case 4:
 2110                 eq->eqesz = SLI4_EQE_SIZE_4;
 2111                 eq->count = SLI4_EQ_CNT_4096;
 2112                 break;
 2113         default:
 2114                 ocs_log_test(sli4->os, "num_pages %d not valid\n", eq->num_pages);
 2115                 return -1;
 2116         }
 2117         eq->valid = TRUE;
 2118         eq->arm = FALSE;
 2119         eq->delay_multiplier = 32;
 2120 
 2121         for (p = 0, addr = qmem->phys;
 2122                         p < eq->num_pages;
 2123                         p++, addr += SLI_PAGE_SIZE) {
 2124                 eq->page_address[p].low = ocs_addr32_lo(addr);
 2125                 eq->page_address[p].high = ocs_addr32_hi(addr);
 2126         }
 2127 
 2128         return(sli_config_off + sizeof(sli4_req_common_create_eq_t));
 2129 }
 2130 
 2131 /**
 2132  * @brief Write a COMMON_DESTROY_EQ command.
 2133  *
 2134  * @param sli4 SLI context.
 2135  * @param buf Destination buffer for the command.
 2136  * @param size Buffer size, in bytes.
 2137  * @param eq_id Queue ID to destroy.
 2138  *
 2139  * @note Other queue creation routines use the last parameter to pass in
 2140  * the associated Q_ID. EQ doesn't have an associated queue so this
 2141  * parameter is ignored.
 2142  *
 2143  * @note This creates a Version 0 message.
 2144  *
 2145  * @return Returns the number of bytes written.
 2146  */
 2147 static int32_t
 2148 sli_cmd_common_destroy_eq(sli4_t *sli4, void *buf, size_t size, uint16_t eq_id)
 2149 {
 2150         sli4_req_common_destroy_eq_t    *eq = NULL;
 2151         uint32_t        sli_config_off = 0;
 2152 
 2153         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2154                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2155                                 /* Payload length must accommodate both request and response */
 2156                                 max(sizeof(sli4_req_common_destroy_eq_t),
 2157                                         sizeof(sli4_res_hdr_t)),
 2158                                 NULL);
 2159         }
 2160         eq = (sli4_req_common_destroy_eq_t *)((uint8_t *)buf + sli_config_off);
 2161 
 2162         eq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_EQ;
 2163         eq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2164         eq->hdr.request_length = sizeof(sli4_req_common_destroy_eq_t) -
 2165                                         sizeof(sli4_req_hdr_t);
 2166 
 2167         eq->eq_id = eq_id;
 2168 
 2169         return(sli_config_off + sizeof(sli4_req_common_destroy_eq_t));
 2170 }
 2171 
 2172 /**
 2173  * @brief Write a LOWLEVEL_SET_WATCHDOG command.
 2174  *
 2175  * @param sli4 SLI context.
 2176  * @param buf Destination buffer for the command.
 2177  * @param size Buffer size, in bytes.
 2178  * @param timeout watchdog timer timeout in seconds
 2179  *
 2180  * @return void
 2181  */
 2182 void
 2183 sli4_cmd_lowlevel_set_watchdog(sli4_t *sli4, void *buf, size_t size, uint16_t timeout)
 2184 {
 2185 
 2186         sli4_req_lowlevel_set_watchdog_t *req = NULL;
 2187         uint32_t        sli_config_off = 0;
 2188 
 2189         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2190                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2191                                 /* Payload length must accommodate both request and response */
 2192                                 max(sizeof(sli4_req_lowlevel_set_watchdog_t),
 2193                                         sizeof(sli4_res_lowlevel_set_watchdog_t)),
 2194                                 NULL);
 2195         }
 2196         req = (sli4_req_lowlevel_set_watchdog_t *)((uint8_t *)buf + sli_config_off);
 2197 
 2198         req->hdr.opcode = SLI4_OPC_LOWLEVEL_SET_WATCHDOG;
 2199         req->hdr.subsystem = SLI4_SUBSYSTEM_LOWLEVEL;
 2200         req->hdr.request_length = sizeof(sli4_req_lowlevel_set_watchdog_t) - sizeof(sli4_req_hdr_t);
 2201         req->watchdog_timeout = timeout;
 2202 
 2203         return;
 2204 }
 2205 
 2206 static int32_t
 2207 sli_cmd_common_get_cntl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2208 {
 2209         sli4_req_hdr_t *hdr = NULL;
 2210         uint32_t        sli_config_off = 0;
 2211 
 2212         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2213                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2214                                 sizeof(sli4_req_hdr_t),
 2215                                 dma);
 2216         }
 2217 
 2218         if (dma == NULL) {
 2219                 return 0;
 2220         }
 2221 
 2222         ocs_memset(dma->virt, 0, dma->size);
 2223 
 2224         hdr = dma->virt;
 2225 
 2226         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ATTRIBUTES;
 2227         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2228         hdr->request_length = dma->size;
 2229 
 2230         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2231 }
 2232 
 2233 /**
 2234  * @brief Write a COMMON_GET_CNTL_ADDL_ATTRIBUTES command.
 2235  *
 2236  * @param sli4 SLI context.
 2237  * @param buf Destination buffer for the command.
 2238  * @param size Buffer size, in bytes.
 2239  * @param dma DMA structure from which the data will be copied.
 2240  *
 2241  * @note This creates a Version 0 message.
 2242  *
 2243  * @return Returns the number of bytes written.
 2244  */
 2245 static int32_t
 2246 sli_cmd_common_get_cntl_addl_attributes(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2247 {
 2248         sli4_req_hdr_t *hdr = NULL;
 2249         uint32_t        sli_config_off = 0;
 2250 
 2251         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2252                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, sizeof(sli4_req_hdr_t), dma);
 2253         }
 2254 
 2255         if (dma == NULL) {
 2256                 return 0;
 2257         }
 2258 
 2259         ocs_memset(dma->virt, 0, dma->size);
 2260 
 2261         hdr = dma->virt;
 2262 
 2263         hdr->opcode = SLI4_OPC_COMMON_GET_CNTL_ADDL_ATTRIBUTES;
 2264         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2265         hdr->request_length = dma->size;
 2266 
 2267         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2268 }
 2269 
 2270 /**
 2271  * @brief Write a COMMON_CREATE_MQ_EXT command.
 2272  *
 2273  * @param sli4 SLI context.
 2274  * @param buf Destination buffer for the command.
 2275  * @param size Buffer size, in bytes.
 2276  * @param qmem DMA memory for the queue.
 2277  * @param cq_id Associated CQ_ID.
 2278  * @param ignored This parameter carries the ULP which is only used for WQ and RQs
 2279  *
 2280  * @note This creates a Version 0 message.
 2281  *
 2282  * @return Returns the number of bytes written.
 2283  */
 2284 static int32_t
 2285 sli_cmd_common_create_mq_ext(sli4_t *sli4, void *buf, size_t size,
 2286                              ocs_dma_t *qmem, uint16_t cq_id, uint16_t ignored)
 2287 {
 2288         sli4_req_common_create_mq_ext_t *mq = NULL;
 2289         uint32_t        sli_config_off = 0;
 2290         uint32_t        p;
 2291         uintptr_t       addr;
 2292 
 2293         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2294                 uint32_t payload_size;
 2295 
 2296                 /* Payload length must accommodate both request and response */
 2297                 payload_size = max(sizeof(sli4_req_common_create_mq_ext_t),
 2298                                 sizeof(sli4_res_common_create_queue_t));
 2299 
 2300                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 2301                                 NULL);
 2302         }
 2303         mq = (sli4_req_common_create_mq_ext_t *)((uint8_t *)buf + sli_config_off);
 2304 
 2305         mq->hdr.opcode = SLI4_OPC_COMMON_CREATE_MQ_EXT;
 2306         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2307         mq->hdr.request_length = sizeof(sli4_req_common_create_mq_ext_t) -
 2308                                         sizeof(sli4_req_hdr_t);
 2309         /* valid values for number of pages: 1, 2, 4, 8 (sec 4.4.12) */
 2310         mq->num_pages = qmem->size / SLI_PAGE_SIZE;
 2311         switch (mq->num_pages) {
 2312         case 1:
 2313                 mq->ring_size = SLI4_MQE_SIZE_16;
 2314                 break;
 2315         case 2:
 2316                 mq->ring_size = SLI4_MQE_SIZE_32;
 2317                 break;
 2318         case 4:
 2319                 mq->ring_size = SLI4_MQE_SIZE_64;
 2320                 break;
 2321         case 8:
 2322                 mq->ring_size = SLI4_MQE_SIZE_128;
 2323                 break;
 2324         default:
 2325                 ocs_log_test(sli4->os, "num_pages %d not valid\n", mq->num_pages);
 2326                 return -1;
 2327         }
 2328 
 2329         /* TODO break this down by sli4->config.topology */
 2330         mq->async_event_bitmap = SLI4_ASYNC_EVT_FC_FCOE;
 2331 
 2332         if (sli4->config.mq_create_version) {
 2333                 mq->cq_id_v1 = cq_id;
 2334                 mq->hdr.version = 1;
 2335         }
 2336         else {
 2337                 mq->cq_id_v0 = cq_id;
 2338         }
 2339         mq->val = TRUE;
 2340 
 2341         for (p = 0, addr = qmem->phys;
 2342                         p < mq->num_pages;
 2343                         p++, addr += SLI_PAGE_SIZE) {
 2344                 mq->page_physical_address[p].low = ocs_addr32_lo(addr);
 2345                 mq->page_physical_address[p].high = ocs_addr32_hi(addr);
 2346         }
 2347 
 2348         return(sli_config_off + sizeof(sli4_req_common_create_mq_ext_t));
 2349 }
 2350 
 2351 /**
 2352  * @brief Write a COMMON_DESTROY_MQ command.
 2353  *
 2354  * @param sli4 SLI context.
 2355  * @param buf Destination buffer for the command.
 2356  * @param size Buffer size, in bytes.
 2357  * @param mq_id MQ ID
 2358  *
 2359  * @note This creates a Version 0 message.
 2360  *
 2361  * @return Returns the number of bytes written.
 2362  */
 2363 static int32_t
 2364 sli_cmd_common_destroy_mq(sli4_t *sli4, void *buf, size_t size, uint16_t mq_id)
 2365 {
 2366         sli4_req_common_destroy_mq_t    *mq = NULL;
 2367         uint32_t        sli_config_off = 0;
 2368 
 2369         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2370                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2371                                 /* Payload length must accommodate both request and response */
 2372                                 max(sizeof(sli4_req_common_destroy_mq_t),
 2373                                         sizeof(sli4_res_hdr_t)),
 2374                                 NULL);
 2375         }
 2376         mq = (sli4_req_common_destroy_mq_t *)((uint8_t *)buf + sli_config_off);
 2377 
 2378         mq->hdr.opcode = SLI4_OPC_COMMON_DESTROY_MQ;
 2379         mq->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2380         mq->hdr.request_length = sizeof(sli4_req_common_destroy_mq_t) -
 2381                                         sizeof(sli4_req_hdr_t);
 2382 
 2383         mq->mq_id = mq_id;
 2384 
 2385         return(sli_config_off + sizeof(sli4_req_common_destroy_mq_t));
 2386 }
 2387 
 2388 /**
 2389  * @ingroup sli
 2390  * @brief Write a COMMON_NOP command
 2391  *
 2392  * @param sli4 SLI context.
 2393  * @param buf Destination buffer for the command.
 2394  * @param size Buffer size, in bytes.
 2395  * @param context NOP context value (passed to response, except on FC/FCoE).
 2396  *
 2397  * @return Returns the number of bytes written.
 2398  */
 2399 int32_t
 2400 sli_cmd_common_nop(sli4_t *sli4, void *buf, size_t size, uint64_t context)
 2401 {
 2402         sli4_req_common_nop_t *nop = NULL;
 2403         uint32_t        sli_config_off = 0;
 2404 
 2405         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2406                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2407                                 /* Payload length must accommodate both request and response */
 2408                                 max(sizeof(sli4_req_common_nop_t), sizeof(sli4_res_common_nop_t)),
 2409                                 NULL);
 2410         }
 2411 
 2412         nop = (sli4_req_common_nop_t *)((uint8_t *)buf + sli_config_off);
 2413 
 2414         nop->hdr.opcode = SLI4_OPC_COMMON_NOP;
 2415         nop->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2416         nop->hdr.request_length = 8;
 2417 
 2418         ocs_memcpy(&nop->context, &context, sizeof(context));
 2419 
 2420         return(sli_config_off + sizeof(sli4_req_common_nop_t));
 2421 }
 2422 
 2423 /**
 2424  * @ingroup sli
 2425  * @brief Write a COMMON_GET_RESOURCE_EXTENT_INFO command.
 2426  *
 2427  * @param sli4 SLI context.
 2428  * @param buf Destination buffer for the command.
 2429  * @param size Buffer size, in bytes.
 2430  * @param rtype Resource type (for example, XRI, VFI, VPI, and RPI).
 2431  *
 2432  * @return Returns the number of bytes written.
 2433  */
 2434 int32_t
 2435 sli_cmd_common_get_resource_extent_info(sli4_t *sli4, void *buf, size_t size, uint16_t rtype)
 2436 {
 2437         sli4_req_common_get_resource_extent_info_t *extent = NULL;
 2438         uint32_t        sli_config_off = 0;
 2439 
 2440         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2441                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2442                                 sizeof(sli4_req_common_get_resource_extent_info_t),
 2443                                 NULL);
 2444         }
 2445 
 2446         extent = (sli4_req_common_get_resource_extent_info_t *)((uint8_t *)buf + sli_config_off);
 2447 
 2448         extent->hdr.opcode = SLI4_OPC_COMMON_GET_RESOURCE_EXTENT_INFO;
 2449         extent->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2450         extent->hdr.request_length = 4;
 2451 
 2452         extent->resource_type = rtype;
 2453 
 2454         return(sli_config_off + sizeof(sli4_req_common_get_resource_extent_info_t));
 2455 }
 2456 
 2457 /**
 2458  * @ingroup sli
 2459  * @brief Write a COMMON_GET_SLI4_PARAMETERS command.
 2460  *
 2461  * @param sli4 SLI context.
 2462  * @param buf Destination buffer for the command.
 2463  * @param size Buffer size, in bytes.
 2464  *
 2465  * @return Returns the number of bytes written.
 2466  */
 2467 int32_t
 2468 sli_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
 2469 {
 2470         sli4_req_hdr_t  *hdr = NULL;
 2471         uint32_t        sli_config_off = 0;
 2472 
 2473         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2474                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2475                                 sizeof(sli4_res_common_get_sli4_parameters_t),
 2476                                 NULL);
 2477         }
 2478 
 2479         hdr = (sli4_req_hdr_t *)((uint8_t *)buf + sli_config_off);
 2480 
 2481         hdr->opcode = SLI4_OPC_COMMON_GET_SLI4_PARAMETERS;
 2482         hdr->subsystem = SLI4_SUBSYSTEM_COMMON;
 2483         hdr->request_length = 0x50;
 2484 
 2485         return(sli_config_off + sizeof(sli4_req_hdr_t));
 2486 }
 2487 
 2488 /**
 2489  * @brief Write a COMMON_QUERY_FW_CONFIG command to the provided buffer.
 2490  *
 2491  * @param sli4 SLI context pointer.
 2492  * @param buf Virtual pointer to destination buffer.
 2493  * @param size Buffer size in bytes.
 2494  *
 2495  * @return Returns the number of bytes written
 2496  */
 2497 static int32_t
 2498 sli_cmd_common_query_fw_config(sli4_t *sli4, void *buf, size_t size)
 2499 {
 2500         sli4_req_common_query_fw_config_t   *fw_config;
 2501         uint32_t        sli_config_off = 0;
 2502         uint32_t payload_size;
 2503 
 2504         /* Payload length must accommodate both request and response */
 2505         payload_size = max(sizeof(sli4_req_common_query_fw_config_t),
 2506                            sizeof(sli4_res_common_query_fw_config_t));
 2507 
 2508         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2509                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2510                                 payload_size,
 2511                                 NULL);
 2512         }
 2513 
 2514         fw_config = (sli4_req_common_query_fw_config_t*)((uint8_t*)buf + sli_config_off);
 2515         fw_config->hdr.opcode         = SLI4_OPC_COMMON_QUERY_FW_CONFIG;
 2516         fw_config->hdr.subsystem      = SLI4_SUBSYSTEM_COMMON;
 2517         fw_config->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2518         return sli_config_off + sizeof(sli4_req_common_query_fw_config_t);
 2519 }
 2520 
 2521 /**
 2522  * @brief Write a COMMON_GET_PORT_NAME command to the provided buffer.
 2523  *
 2524  * @param sli4 SLI context pointer.
 2525  * @param buf Virtual pointer to destination buffer.
 2526  * @param size Buffer size in bytes.
 2527  *
 2528  * @note Function supports both version 0 and 1 forms of this command via
 2529  * the IF_TYPE.
 2530  *
 2531  * @return Returns the number of bytes written.
 2532  */
 2533 static int32_t
 2534 sli_cmd_common_get_port_name(sli4_t *sli4, void *buf, size_t size)
 2535 {
 2536         sli4_req_common_get_port_name_t *port_name;
 2537         uint32_t        sli_config_off = 0;
 2538         uint32_t        payload_size;
 2539         uint8_t         version = 0;
 2540         uint8_t         pt = 0;
 2541 
 2542         /* Select command version according to IF_TYPE */
 2543         switch (sli4->if_type) {
 2544         case SLI4_IF_TYPE_BE3_SKH_PF:
 2545         case SLI4_IF_TYPE_BE3_SKH_VF:
 2546                 version = 0;
 2547                 break;
 2548         case SLI4_IF_TYPE_LANCER_FC_ETH:
 2549         case SLI4_IF_TYPE_LANCER_RDMA:
 2550         case SLI4_IF_TYPE_LANCER_G7:
 2551                 version = 1;
 2552                 break;
 2553         default:
 2554                 ocs_log_test(sli4->os, "unsupported IF_TYPE %d\n", sli4->if_type);
 2555                 return 0;
 2556         }
 2557 
 2558         /* Payload length must accommodate both request and response */
 2559         payload_size = max(sizeof(sli4_req_common_get_port_name_t),
 2560                            sizeof(sli4_res_common_get_port_name_t));
 2561 
 2562         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2563                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2564                                 payload_size,
 2565                                 NULL);
 2566 
 2567                 pt = 1;
 2568         }
 2569 
 2570         port_name = (sli4_req_common_get_port_name_t *)((uint8_t *)buf + sli_config_off);
 2571 
 2572         port_name->hdr.opcode           = SLI4_OPC_COMMON_GET_PORT_NAME;
 2573         port_name->hdr.subsystem        = SLI4_SUBSYSTEM_COMMON;
 2574         port_name->hdr.request_length   = sizeof(sli4_req_hdr_t) + (version * sizeof(uint32_t));
 2575         port_name->hdr.version          = version;
 2576 
 2577         /* Set the port type value (ethernet=0, FC=1) for V1 commands */
 2578         if (version == 1) {
 2579                 port_name->pt = pt;
 2580         }
 2581 
 2582         return sli_config_off + port_name->hdr.request_length;
 2583 }
 2584 
 2585 /**
 2586  * @ingroup sli
 2587  * @brief Write a COMMON_WRITE_OBJECT command.
 2588  *
 2589  * @param sli4 SLI context.
 2590  * @param buf Destination buffer for the command.
 2591  * @param size Buffer size, in bytes.
 2592  * @param noc True if the object should be written but not committed to flash.
 2593  * @param eof True if this is the last write for this object.
 2594  * @param desired_write_length Number of bytes of data to write to the object.
 2595  * @param offset Offset, in bytes, from the start of the object.
 2596  * @param object_name Name of the object to write.
 2597  * @param dma DMA structure from which the data will be copied.
 2598  *
 2599  * @return Returns the number of bytes written.
 2600  */
 2601 int32_t
 2602 sli_cmd_common_write_object(sli4_t *sli4, void *buf, size_t size,
 2603                 uint16_t noc, uint16_t eof, uint32_t desired_write_length,
 2604                 uint32_t offset,
 2605                 char *object_name,
 2606                 ocs_dma_t *dma)
 2607 {
 2608         sli4_req_common_write_object_t *wr_obj = NULL;
 2609         uint32_t        sli_config_off = 0;
 2610         sli4_bde_t *host_buffer;
 2611 
 2612         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2613                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2614                                 sizeof (sli4_req_common_write_object_t) + sizeof (sli4_bde_t),
 2615                                 NULL);
 2616         }
 2617 
 2618         wr_obj = (sli4_req_common_write_object_t *)((uint8_t *)buf + sli_config_off);
 2619 
 2620         wr_obj->hdr.opcode = SLI4_OPC_COMMON_WRITE_OBJECT;
 2621         wr_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2622         wr_obj->hdr.request_length = sizeof(*wr_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
 2623         wr_obj->hdr.timeout = 0;
 2624         wr_obj->hdr.version = 0;
 2625 
 2626         wr_obj->noc = noc;
 2627         wr_obj->eof = eof;
 2628         wr_obj->desired_write_length = desired_write_length;
 2629         wr_obj->write_offset = offset;
 2630         ocs_strncpy(wr_obj->object_name, object_name, sizeof(wr_obj->object_name));
 2631         wr_obj->host_buffer_descriptor_count = 1;
 2632 
 2633         host_buffer = (sli4_bde_t *)wr_obj->host_buffer_descriptor;
 2634 
 2635         /* Setup to transfer xfer_size bytes to device */
 2636         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
 2637         host_buffer->buffer_length = desired_write_length;
 2638         host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
 2639         host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 2640 
 2641         return(sli_config_off + sizeof(sli4_req_common_write_object_t) + sizeof (sli4_bde_t));
 2642 }
 2643 
 2644 /**
 2645  * @ingroup sli
 2646  * @brief Write a COMMON_DELETE_OBJECT command.
 2647  *
 2648  * @param sli4 SLI context.
 2649  * @param buf Destination buffer for the command.
 2650  * @param size Buffer size, in bytes.
 2651  * @param object_name Name of the object to write.
 2652  *
 2653  * @return Returns the number of bytes written.
 2654  */
 2655 int32_t
 2656 sli_cmd_common_delete_object(sli4_t *sli4, void *buf, size_t size,
 2657                 char *object_name)
 2658 {
 2659         sli4_req_common_delete_object_t *del_obj = NULL;
 2660         uint32_t        sli_config_off = 0;
 2661 
 2662         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2663                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2664                                 sizeof (sli4_req_common_delete_object_t),
 2665                                 NULL);
 2666         }
 2667 
 2668         del_obj = (sli4_req_common_delete_object_t *)((uint8_t *)buf + sli_config_off);
 2669 
 2670         del_obj->hdr.opcode = SLI4_OPC_COMMON_DELETE_OBJECT;
 2671         del_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2672         del_obj->hdr.request_length = sizeof(*del_obj);
 2673         del_obj->hdr.timeout = 0;
 2674         del_obj->hdr.version = 0;
 2675 
 2676         ocs_strncpy(del_obj->object_name, object_name, sizeof(del_obj->object_name));
 2677         return(sli_config_off + sizeof(sli4_req_common_delete_object_t));
 2678 }
 2679 
 2680 /**
 2681  * @ingroup sli
 2682  * @brief Write a COMMON_READ_OBJECT command.
 2683  *
 2684  * @param sli4 SLI context.
 2685  * @param buf Destination buffer for the command.
 2686  * @param size Buffer size, in bytes.
 2687  * @param desired_read_length Number of bytes of data to read from the object.
 2688  * @param offset Offset, in bytes, from the start of the object.
 2689  * @param object_name Name of the object to read.
 2690  * @param dma DMA structure from which the data will be copied.
 2691  *
 2692  * @return Returns the number of bytes written.
 2693  */
 2694 int32_t
 2695 sli_cmd_common_read_object(sli4_t *sli4, void *buf, size_t size,
 2696                 uint32_t desired_read_length,
 2697                 uint32_t offset,
 2698                 char *object_name,
 2699                 ocs_dma_t *dma)
 2700 {
 2701         sli4_req_common_read_object_t *rd_obj = NULL;
 2702         uint32_t        sli_config_off = 0;
 2703         sli4_bde_t *host_buffer;
 2704 
 2705         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2706                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2707                                 sizeof (sli4_req_common_read_object_t) + sizeof (sli4_bde_t),
 2708                                 NULL);
 2709         }
 2710 
 2711         rd_obj = (sli4_req_common_read_object_t *)((uint8_t *)buf + sli_config_off);
 2712 
 2713         rd_obj->hdr.opcode = SLI4_OPC_COMMON_READ_OBJECT;
 2714         rd_obj->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2715         rd_obj->hdr.request_length = sizeof(*rd_obj) - 4*sizeof(uint32_t) + sizeof(sli4_bde_t);
 2716         rd_obj->hdr.timeout = 0;
 2717         rd_obj->hdr.version = 0;
 2718 
 2719         rd_obj->desired_read_length = desired_read_length;
 2720         rd_obj->read_offset = offset;
 2721         ocs_strncpy(rd_obj->object_name, object_name, sizeof(rd_obj->object_name));
 2722         rd_obj->host_buffer_descriptor_count = 1;
 2723 
 2724         host_buffer = (sli4_bde_t *)rd_obj->host_buffer_descriptor;
 2725 
 2726         /* Setup to transfer xfer_size bytes to device */
 2727         host_buffer->bde_type = SLI4_BDE_TYPE_BDE_64;
 2728         host_buffer->buffer_length = desired_read_length;
 2729         if (dma != NULL) {
 2730                 host_buffer->u.data.buffer_address_low = ocs_addr32_lo(dma->phys);
 2731                 host_buffer->u.data.buffer_address_high = ocs_addr32_hi(dma->phys);
 2732         } else {
 2733                 host_buffer->u.data.buffer_address_low = 0;
 2734                 host_buffer->u.data.buffer_address_high = 0;
 2735         }
 2736 
 2737         return(sli_config_off + sizeof(sli4_req_common_read_object_t) + sizeof (sli4_bde_t));
 2738 }
 2739 
 2740 /**
 2741  * @ingroup sli
 2742  * @brief Write a DMTF_EXEC_CLP_CMD command.
 2743  *
 2744  * @param sli4 SLI context.
 2745  * @param buf Destination buffer for the command.
 2746  * @param size Buffer size, in bytes.
 2747  * @param cmd DMA structure that describes the buffer for the command.
 2748  * @param resp DMA structure that describes the buffer for the response.
 2749  *
 2750  * @return Returns the number of bytes written.
 2751  */
 2752 int32_t
 2753 sli_cmd_dmtf_exec_clp_cmd(sli4_t *sli4, void *buf, size_t size,
 2754                 ocs_dma_t *cmd,
 2755                 ocs_dma_t *resp)
 2756 {
 2757         sli4_req_dmtf_exec_clp_cmd_t *clp_cmd = NULL;
 2758         uint32_t        sli_config_off = 0;
 2759 
 2760         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2761                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2762                                 sizeof (sli4_req_dmtf_exec_clp_cmd_t),
 2763                                 NULL);
 2764         }
 2765 
 2766         clp_cmd = (sli4_req_dmtf_exec_clp_cmd_t*)((uint8_t *)buf + sli_config_off);
 2767 
 2768         clp_cmd->hdr.opcode = SLI4_OPC_DMTF_EXEC_CLP_CMD;
 2769         clp_cmd->hdr.subsystem = SLI4_SUBSYSTEM_DMTF;
 2770         clp_cmd->hdr.request_length = sizeof(sli4_req_dmtf_exec_clp_cmd_t) -
 2771                                         sizeof(sli4_req_hdr_t);
 2772         clp_cmd->hdr.timeout = 0;
 2773         clp_cmd->hdr.version = 0;
 2774         clp_cmd->cmd_buf_length = cmd->size;
 2775         clp_cmd->cmd_buf_addr_low = ocs_addr32_lo(cmd->phys);
 2776         clp_cmd->cmd_buf_addr_high = ocs_addr32_hi(cmd->phys);
 2777         clp_cmd->resp_buf_length = resp->size;
 2778         clp_cmd->resp_buf_addr_low = ocs_addr32_lo(resp->phys);
 2779         clp_cmd->resp_buf_addr_high = ocs_addr32_hi(resp->phys);
 2780 
 2781         return(sli_config_off + sizeof(sli4_req_dmtf_exec_clp_cmd_t));
 2782 }
 2783 
 2784 /**
 2785  * @ingroup sli
 2786  * @brief Write a COMMON_SET_DUMP_LOCATION command.
 2787  *
 2788  * @param sli4 SLI context.
 2789  * @param buf Destination buffer for the command.
 2790  * @param size Buffer size, in bytes.
 2791  * @param query Zero to set dump location, non-zero to query dump size
 2792  * @param is_buffer_list Set to one if the buffer is a set of buffer descriptors or
 2793  *                       set to 0 if the buffer is a contiguous dump area.
 2794  * @param buffer DMA structure to which the dump will be copied.
 2795  *
 2796  * @return Returns the number of bytes written.
 2797  */
 2798 int32_t
 2799 sli_cmd_common_set_dump_location(sli4_t *sli4, void *buf, size_t size,
 2800                                  uint8_t query, uint8_t is_buffer_list,
 2801                                  ocs_dma_t *buffer, uint8_t fdb)
 2802 {
 2803         sli4_req_common_set_dump_location_t *set_dump_loc = NULL;
 2804         uint32_t        sli_config_off = 0;
 2805 
 2806         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2807                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2808                                 sizeof (sli4_req_common_set_dump_location_t),
 2809                                 NULL);
 2810         }
 2811 
 2812         set_dump_loc = (sli4_req_common_set_dump_location_t *)((uint8_t *)buf + sli_config_off);
 2813 
 2814         set_dump_loc->hdr.opcode = SLI4_OPC_COMMON_SET_DUMP_LOCATION;
 2815         set_dump_loc->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2816         set_dump_loc->hdr.request_length = sizeof(sli4_req_common_set_dump_location_t) - sizeof(sli4_req_hdr_t);
 2817         set_dump_loc->hdr.timeout = 0;
 2818         set_dump_loc->hdr.version = 0;
 2819 
 2820         set_dump_loc->blp = is_buffer_list;
 2821         set_dump_loc->qry = query;
 2822         set_dump_loc->fdb = fdb;
 2823 
 2824         if (buffer) {
 2825                 set_dump_loc->buf_addr_low = ocs_addr32_lo(buffer->phys);
 2826                 set_dump_loc->buf_addr_high = ocs_addr32_hi(buffer->phys);
 2827                 set_dump_loc->buffer_length = buffer->len;
 2828         } else {
 2829                 set_dump_loc->buf_addr_low = 0;
 2830                 set_dump_loc->buf_addr_high = 0;
 2831                 set_dump_loc->buffer_length = 0;
 2832         }
 2833 
 2834         return(sli_config_off + sizeof(sli4_req_common_set_dump_location_t));
 2835 }
 2836 
 2837 /**
 2838  * @ingroup sli
 2839  * @brief Write a COMMON_SET_FEATURES command.
 2840  *
 2841  * @param sli4 SLI context.
 2842  * @param buf Destination buffer for the command.
 2843  * @param size Buffer size, in bytes.
 2844  * @param feature Feature to set.
 2845  * @param param_len Length of the parameter (must be a multiple of 4 bytes).
 2846  * @param parameter Pointer to the parameter value.
 2847  *
 2848  * @return Returns the number of bytes written.
 2849  */
 2850 int32_t
 2851 sli_cmd_common_set_features(sli4_t *sli4, void *buf, size_t size,
 2852                             uint32_t feature,
 2853                             uint32_t param_len,
 2854                             void* parameter)
 2855 {
 2856         sli4_req_common_set_features_t *cmd = NULL;
 2857         uint32_t        sli_config_off = 0;
 2858 
 2859         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2860                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2861                                 sizeof (sli4_req_common_set_features_t),
 2862                                 NULL);
 2863         }
 2864 
 2865         cmd = (sli4_req_common_set_features_t *)((uint8_t *)buf + sli_config_off);
 2866 
 2867         cmd->hdr.opcode = SLI4_OPC_COMMON_SET_FEATURES;
 2868         cmd->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2869         cmd->hdr.request_length = sizeof(sli4_req_common_set_features_t) - sizeof(sli4_req_hdr_t);
 2870         cmd->hdr.timeout = 0;
 2871         cmd->hdr.version = 0;
 2872 
 2873         cmd->feature = feature;
 2874         cmd->param_len = param_len;
 2875         ocs_memcpy(cmd->params, parameter, param_len);
 2876 
 2877         return(sli_config_off + sizeof(sli4_req_common_set_features_t));
 2878 }
 2879 
 2880 /**
 2881  * @ingroup sli
 2882  * @brief Write a COMMON_COMMON_GET_PROFILE_CONFIG command.
 2883  *
 2884  * @param sli4 SLI context.
 2885  * @param buf Destination buffer for the command.
 2886  * @param size Buffer size in bytes.
 2887  * @param dma DMA capable memory used to retrieve profile.
 2888  *
 2889  * @return Returns the number of bytes written.
 2890  */
 2891 int32_t
 2892 sli_cmd_common_get_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 2893 {
 2894         sli4_req_common_get_profile_config_t *req = NULL;
 2895         uint32_t        sli_config_off = 0;
 2896         uint32_t        payload_size;
 2897 
 2898         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2899                 sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 2900                                 sizeof (sli4_req_common_get_profile_config_t),
 2901                                 dma);
 2902         }
 2903 
 2904         if (dma != NULL) {
 2905                 req = dma->virt;
 2906                 ocs_memset(req, 0, dma->size);
 2907                 payload_size = dma->size;
 2908         } else {
 2909                 req = (sli4_req_common_get_profile_config_t *)((uint8_t *)buf + sli_config_off);
 2910                 payload_size = sizeof(sli4_req_common_get_profile_config_t);
 2911         }
 2912 
 2913         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_CONFIG;
 2914         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2915         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2916         req->hdr.version = 1;
 2917 
 2918         return(sli_config_off + sizeof(sli4_req_common_get_profile_config_t));
 2919 }
 2920 
 2921 /**
 2922  * @ingroup sli
 2923  * @brief Write a COMMON_COMMON_SET_PROFILE_CONFIG command.
 2924  *
 2925  * @param sli4 SLI context.
 2926  * @param buf Destination buffer for the command.
 2927  * @param size Buffer size, in bytes.
 2928  * @param dma DMA capable memory containing profile.
 2929  * @param profile_id Profile ID to configure.
 2930  * @param descriptor_count Number of descriptors in DMA buffer.
 2931  * @param isap Implicit Set Active Profile value to use.
 2932  *
 2933  * @return Returns the number of bytes written.
 2934  */
 2935 int32_t
 2936 sli_cmd_common_set_profile_config(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 2937                 uint8_t profile_id, uint32_t descriptor_count, uint8_t isap)
 2938 {
 2939         sli4_req_common_set_profile_config_t *req = NULL;
 2940         uint32_t cmd_off = 0;
 2941         uint32_t payload_size;
 2942 
 2943         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2944                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2945                                                     sizeof (sli4_req_common_set_profile_config_t),
 2946                                                     dma);
 2947         }
 2948 
 2949         if (dma != NULL) {
 2950                 req = dma->virt;
 2951                 ocs_memset(req, 0, dma->size);
 2952                 payload_size = dma->size;
 2953         } else {
 2954                 req = (sli4_req_common_set_profile_config_t *)((uint8_t *)buf + cmd_off);
 2955                 payload_size = sizeof(sli4_req_common_set_profile_config_t);
 2956         }
 2957 
 2958         req->hdr.opcode = SLI4_OPC_COMMON_SET_PROFILE_CONFIG;
 2959         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 2960         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 2961         req->hdr.version = 1;
 2962         req->profile_id = profile_id;
 2963         req->desc_count = descriptor_count;
 2964         req->isap = isap;
 2965 
 2966         return(cmd_off + sizeof(sli4_req_common_set_profile_config_t));
 2967 }
 2968 
 2969 /**
 2970  * @ingroup sli
 2971  * @brief Write a COMMON_COMMON_GET_PROFILE_LIST command.
 2972  *
 2973  * @param sli4 SLI context.
 2974  * @param buf Destination buffer for the command.
 2975  * @param size Buffer size in bytes.
 2976  * @param start_profile_index First profile index to return.
 2977  * @param dma Buffer into which the list will be written.
 2978  *
 2979  * @return Returns the number of bytes written.
 2980  */
 2981 int32_t
 2982 sli_cmd_common_get_profile_list(sli4_t *sli4, void *buf, size_t size,
 2983                                    uint32_t start_profile_index, ocs_dma_t *dma)
 2984 {
 2985         sli4_req_common_get_profile_list_t *req = NULL;
 2986         uint32_t cmd_off = 0;
 2987         uint32_t payload_size;
 2988 
 2989         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 2990                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 2991                                              sizeof (sli4_req_common_get_profile_list_t),
 2992                                              dma);
 2993         }
 2994 
 2995         if (dma != NULL) {
 2996                 req = dma->virt;
 2997                 ocs_memset(req, 0, dma->size);
 2998                 payload_size = dma->size;
 2999         } else {
 3000                 req = (sli4_req_common_get_profile_list_t *)((uint8_t *)buf + cmd_off);
 3001                 payload_size = sizeof(sli4_req_common_get_profile_list_t);
 3002         }
 3003 
 3004         req->hdr.opcode = SLI4_OPC_COMMON_GET_PROFILE_LIST;
 3005         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3006         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3007         req->hdr.version = 0;
 3008 
 3009         req->start_profile_index = start_profile_index;
 3010 
 3011         return(cmd_off + sizeof(sli4_req_common_get_profile_list_t));
 3012 }
 3013 
 3014 /**
 3015  * @ingroup sli
 3016  * @brief Write a COMMON_COMMON_GET_ACTIVE_PROFILE command.
 3017  *
 3018  * @param sli4 SLI context.
 3019  * @param buf Destination buffer for the command.
 3020  * @param size Buffer size in bytes.
 3021  *
 3022  * @return Returns the number of bytes written.
 3023  */
 3024 int32_t
 3025 sli_cmd_common_get_active_profile(sli4_t *sli4, void *buf, size_t size)
 3026 {
 3027         sli4_req_common_get_active_profile_t *req = NULL;
 3028         uint32_t cmd_off = 0;
 3029         uint32_t payload_size;
 3030 
 3031         /* Payload length must accommodate both request and response */
 3032         payload_size = max(sizeof(sli4_req_common_get_active_profile_t),
 3033                            sizeof(sli4_res_common_get_active_profile_t));
 3034 
 3035         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3036                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3037                                 payload_size,
 3038                                 NULL);
 3039         }
 3040 
 3041         req = (sli4_req_common_get_active_profile_t *)
 3042                 ((uint8_t*)buf + cmd_off);
 3043 
 3044         req->hdr.opcode = SLI4_OPC_COMMON_GET_ACTIVE_PROFILE;
 3045         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3046         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3047         req->hdr.version = 0;
 3048 
 3049         return(cmd_off + sizeof(sli4_req_common_get_active_profile_t));
 3050 }
 3051 
 3052 /**
 3053  * @ingroup sli
 3054  * @brief Write a COMMON_COMMON_SET_ACTIVE_PROFILE command.
 3055  *
 3056  * @param sli4 SLI context.
 3057  * @param buf Destination buffer for the command.
 3058  * @param size Buffer size in bytes.
 3059  * @param fd If non-zero, set profile to factory default.
 3060  * @param active_profile_id ID of new active profile.
 3061  *
 3062  * @return Returns the number of bytes written.
 3063  */
 3064 int32_t
 3065 sli_cmd_common_set_active_profile(sli4_t *sli4, void *buf, size_t size,
 3066                                   uint32_t fd, uint32_t active_profile_id)
 3067 {
 3068         sli4_req_common_set_active_profile_t *req = NULL;
 3069         uint32_t cmd_off = 0;
 3070         uint32_t payload_size;
 3071 
 3072         /* Payload length must accommodate both request and response */
 3073         payload_size = max(sizeof(sli4_req_common_set_active_profile_t),
 3074                            sizeof(sli4_res_common_set_active_profile_t));
 3075 
 3076         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3077                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3078                                 payload_size,
 3079                                 NULL);
 3080         }
 3081 
 3082         req = (sli4_req_common_set_active_profile_t *)
 3083                 ((uint8_t*)buf + cmd_off);
 3084 
 3085         req->hdr.opcode = SLI4_OPC_COMMON_SET_ACTIVE_PROFILE;
 3086         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3087         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3088         req->hdr.version = 0;
 3089         req->fd = fd;
 3090         req->active_profile_id = active_profile_id;
 3091 
 3092         return(cmd_off + sizeof(sli4_req_common_set_active_profile_t));
 3093 }
 3094 
 3095 /**
 3096  * @ingroup sli
 3097  * @brief Write a COMMON_GET_RECONFIG_LINK_INFO command.
 3098  *
 3099  * @param sli4 SLI context.
 3100  * @param buf Destination buffer for the command.
 3101  * @param size Buffer size in bytes.
 3102  * @param dma Buffer to store the supported link configuration modes from the physical device.
 3103  *
 3104  * @return Returns the number of bytes written.
 3105  */
 3106 int32_t
 3107 sli_cmd_common_get_reconfig_link_info(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma)
 3108 {
 3109         sli4_req_common_get_reconfig_link_info_t *req = NULL;
 3110         uint32_t cmd_off = 0;
 3111         uint32_t payload_size;
 3112 
 3113         /* Payload length must accommodate both request and response */
 3114         payload_size = max(sizeof(sli4_req_common_get_reconfig_link_info_t),
 3115                            sizeof(sli4_res_common_get_reconfig_link_info_t));
 3116 
 3117         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3118                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3119                                 payload_size,
 3120                                 dma);
 3121         }
 3122 
 3123         if (dma != NULL) {
 3124                 req = dma->virt;
 3125                 ocs_memset(req, 0, dma->size);
 3126                 payload_size = dma->size;
 3127         } else {
 3128                 req = (sli4_req_common_get_reconfig_link_info_t *)((uint8_t *)buf + cmd_off);
 3129                 payload_size = sizeof(sli4_req_common_get_reconfig_link_info_t);
 3130         }
 3131 
 3132         req->hdr.opcode = SLI4_OPC_COMMON_GET_RECONFIG_LINK_INFO;
 3133         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3134         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3135         req->hdr.version = 0;
 3136 
 3137         return(cmd_off + sizeof(sli4_req_common_get_reconfig_link_info_t));
 3138 }
 3139 
 3140 /**
 3141  * @ingroup sli
 3142  * @brief Write a COMMON_SET_RECONFIG_LINK_ID command.
 3143  *
 3144  * @param sli4 SLI context.
 3145  * @param buf destination buffer for the command.
 3146  * @param size buffer size in bytes.
 3147  * @param fd If non-zero, set link config to factory default.
 3148  * @param active_link_config_id ID of new active profile.
 3149  * @param dma Buffer to assign the link configuration mode that is to become active from the physical device.
 3150  *
 3151  * @return Returns the number of bytes written.
 3152  */
 3153 int32_t
 3154 sli_cmd_common_set_reconfig_link_id(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma,
 3155                                   uint32_t fd, uint32_t active_link_config_id)
 3156 {
 3157         sli4_req_common_set_reconfig_link_id_t *req = NULL;
 3158         uint32_t cmd_off = 0;
 3159         uint32_t payload_size;
 3160 
 3161         /* Payload length must accommodate both request and response */
 3162         payload_size = max(sizeof(sli4_req_common_set_reconfig_link_id_t),
 3163                            sizeof(sli4_res_common_set_reconfig_link_id_t));
 3164 
 3165         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3166                 cmd_off = sli_cmd_sli_config(sli4, buf, size,
 3167                                 payload_size,
 3168                                 NULL);
 3169         }
 3170 
 3171                 if (dma != NULL) {
 3172                 req = dma->virt;
 3173                 ocs_memset(req, 0, dma->size);
 3174                 payload_size = dma->size;
 3175         } else {
 3176                 req = (sli4_req_common_set_reconfig_link_id_t *)((uint8_t *)buf + cmd_off);
 3177                 payload_size = sizeof(sli4_req_common_set_reconfig_link_id_t);
 3178         }
 3179 
 3180         req->hdr.opcode = SLI4_OPC_COMMON_SET_RECONFIG_LINK_ID;
 3181         req->hdr.subsystem = SLI4_SUBSYSTEM_COMMON;
 3182         req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
 3183         req->hdr.version = 0;
 3184         req->fd = fd;
 3185         req->next_link_config_id = active_link_config_id;
 3186 
 3187         return(cmd_off + sizeof(sli4_req_common_set_reconfig_link_id_t));
 3188 }
 3189 
 3190 /**
 3191  * @ingroup sli
 3192  * @brief Check the mailbox/queue completion entry.
 3193  *
 3194  * @param buf Pointer to the MCQE.
 3195  *
 3196  * @return Returns 0 on success, or a non-zero value on failure.
 3197  */
 3198 int32_t
 3199 sli_cqe_mq(void *buf)
 3200 {
 3201         sli4_mcqe_t     *mcqe = buf;
 3202 
 3203         /*
 3204          * Firmware can split mbx completions into two MCQEs: first with only
 3205          * the "consumed" bit set and a second with the "complete" bit set.
 3206          * Thus, ignore MCQE unless "complete" is set.
 3207          */
 3208         if (!mcqe->cmp) {
 3209                 return -2;
 3210         }
 3211 
 3212         if (mcqe->completion_status) {
 3213                 ocs_log_debug(NULL, "bad status (cmpl=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n",
 3214                                 mcqe->completion_status,
 3215                                 mcqe->extended_status,
 3216                                 mcqe->con,
 3217                                 mcqe->cmp,
 3218                                 mcqe->ae,
 3219                                 mcqe->val);
 3220         }
 3221 
 3222         return mcqe->completion_status;
 3223 }
 3224 
 3225 /**
 3226  * @ingroup sli
 3227  * @brief Check the asynchronous event completion entry.
 3228  *
 3229  * @param sli4 SLI context.
 3230  * @param buf Pointer to the ACQE.
 3231  *
 3232  * @return Returns 0 on success, or a non-zero value on failure.
 3233  */
 3234 int32_t
 3235 sli_cqe_async(sli4_t *sli4, void *buf)
 3236 {
 3237         sli4_acqe_t     *acqe = buf;
 3238         int32_t         rc = -1;
 3239 
 3240         if (!sli4 || !buf) {
 3241                 ocs_log_err(NULL, "bad parameter sli4=%p buf=%p\n", sli4, buf);
 3242                 return -1;
 3243         }
 3244 
 3245         switch (acqe->event_code) {
 3246         case SLI4_ACQE_EVENT_CODE_LINK_STATE:
 3247                 rc = sli_fc_process_link_state(sli4, buf);
 3248                 break;
 3249         case SLI4_ACQE_EVENT_CODE_FCOE_FIP:
 3250                 rc = sli_fc_process_fcoe(sli4, buf);
 3251                 break;
 3252         case SLI4_ACQE_EVENT_CODE_GRP_5:
 3253                 /*TODO*/ocs_log_debug(sli4->os, "ACQE GRP5\n");
 3254                 break;
 3255         case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT:
 3256         ocs_log_debug(sli4->os,"ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n",
 3257                 acqe->event_type, acqe->event_data[0], acqe->event_data[1]);
 3258 #if defined(OCS_INCLUDE_DEBUG)
 3259                 ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "acq", acqe, sizeof(*acqe));
 3260 #endif
 3261                 break;
 3262         case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT:
 3263                 rc = sli_fc_process_link_attention(sli4, buf);
 3264                 break;
 3265         default:
 3266                 /*TODO*/ocs_log_test(sli4->os, "ACQE unknown=%#x\n", acqe->event_code);
 3267         }
 3268 
 3269         return rc;
 3270 }
 3271 
 3272 /**
 3273  * @brief Check the SLI_CONFIG response.
 3274  *
 3275  * @par Description
 3276  * Function checks the SLI_CONFIG response and the payload status.
 3277  *
 3278  * @param buf Pointer to SLI_CONFIG response.
 3279  *
 3280  * @return Returns 0 on success, or a non-zero value on failure.
 3281  */
 3282 static int32_t
 3283 sli_res_sli_config(void *buf)
 3284 {
 3285         sli4_cmd_sli_config_t   *sli_config = buf;
 3286 
 3287         if (!buf || (SLI4_MBOX_COMMAND_SLI_CONFIG != sli_config->hdr.command)) {
 3288                 ocs_log_err(NULL, "bad parameter buf=%p cmd=%#x\n", buf,
 3289                                 buf ? sli_config->hdr.command : -1);
 3290                 return -1;
 3291         }
 3292 
 3293         if (sli_config->hdr.status) {
 3294                 return sli_config->hdr.status;
 3295         }
 3296 
 3297         if (sli_config->emb) {
 3298                 return sli_config->payload.embed[4];
 3299         } else {
 3300                 ocs_log_test(NULL, "external buffers not supported\n");
 3301                 return -1;
 3302         }
 3303 }
 3304 
 3305 /**
 3306  * @brief Issue a COMMON_FUNCTION_RESET command.
 3307  *
 3308  * @param sli4 SLI context.
 3309  *
 3310  * @return Returns 0 on success, or a non-zero value on failure.
 3311  */
 3312 static int32_t
 3313 sli_common_function_reset(sli4_t *sli4)
 3314 {
 3315 
 3316         if (sli_cmd_common_function_reset(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3317                 if (sli_bmbx_command(sli4)) {
 3318                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COM_FUNC_RESET)\n");
 3319                         return -1;
 3320                 }
 3321                 if (sli_res_sli_config(sli4->bmbx.virt)) {
 3322                         ocs_log_err(sli4->os, "bad status COM_FUNC_RESET\n");
 3323                         return -1;
 3324                 }
 3325         } else {
 3326                 ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3327                 return -1;
 3328         }
 3329 
 3330         return 0;
 3331 }
 3332 
 3333 /**
 3334  * @brief check to see if the FW is ready.
 3335  *
 3336  * @par Description
 3337  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
 3338  *
 3339  * @param sli4 SLI context.
 3340  * @param timeout_ms Time, in milliseconds, to wait for the port to be ready
 3341  *  before failing.
 3342  *
 3343  * @return Returns TRUE for ready, or FALSE otherwise.
 3344  */
 3345 static int32_t
 3346 sli_wait_for_fw_ready(sli4_t *sli4, uint32_t timeout_ms)
 3347 {
 3348         uint32_t        iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000);
 3349         uint32_t        ready = FALSE;
 3350 
 3351         do {
 3352                 iter--;
 3353                 ocs_udelay(SLI4_INIT_PORT_DELAY_US);
 3354                 if (sli_fw_ready(sli4) == 1) {
 3355                         ready = TRUE;
 3356                 }
 3357         } while (!ready && (iter > 0));
 3358 
 3359         return ready;
 3360 }
 3361 
 3362 /**
 3363  * @brief Initialize the firmware.
 3364  *
 3365  * @par Description
 3366  * Based on <i>SLI-4 Architecture Specification, Revision 4.x0-13 (2012).</i>.
 3367  *
 3368  * @param sli4 SLI context.
 3369  *
 3370  * @return Returns 0 on success, or a non-zero value on failure.
 3371  */
 3372 static int32_t
 3373 sli_fw_init(sli4_t *sli4)
 3374 {
 3375         uint32_t ready;
 3376         uint32_t endian;
 3377 
 3378         /*
 3379          * Is firmware ready for operation?
 3380          */
 3381         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 3382         if (!ready) {
 3383                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
 3384                 return -1;
 3385         }
 3386 
 3387         /*
 3388          * Reset port to a known state
 3389          */
 3390         switch (sli4->if_type) {
 3391         case SLI4_IF_TYPE_BE3_SKH_PF:
 3392         case SLI4_IF_TYPE_BE3_SKH_VF:
 3393                 /* No SLIPORT_CONTROL register so use command sequence instead */
 3394                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
 3395                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
 3396                         return -1;
 3397                 }
 3398 
 3399                 if (sli_cmd_fw_initialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3400                         if (sli_bmbx_command(sli4)) {
 3401                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_INIT)\n");
 3402                                 return -1;
 3403                         }
 3404                 } else {
 3405                         ocs_log_crit(sli4->os, "bad FW_INIT write\n");
 3406                         return -1;
 3407                 }
 3408 
 3409                 if (sli_common_function_reset(sli4)) {
 3410                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3411                         return -1;
 3412                 }
 3413                 break;
 3414         case SLI4_IF_TYPE_LANCER_FC_ETH:
 3415         case SLI4_IF_TYPE_LANCER_G7:
 3416 #if BYTE_ORDER == LITTLE_ENDIAN
 3417                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
 3418 #else
 3419                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
 3420 #endif
 3421 
 3422                 if (sli_sliport_control(sli4, endian))
 3423                         return -1;
 3424                 break;
 3425         default:
 3426                 ocs_log_test(sli4->os, "if_type %d not supported\n", sli4->if_type);
 3427                 return -1;
 3428         }
 3429 
 3430         return 0;
 3431 }
 3432 
 3433 /**
 3434  * @brief Terminate the firmware.
 3435  *
 3436  * @param sli4 SLI context.
 3437  *
 3438  * @return Returns 0 on success, or a non-zero value on failure.
 3439  */
 3440 static int32_t
 3441 sli_fw_term(sli4_t *sli4)
 3442 {
 3443         uint32_t endian;
 3444 
 3445         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF ||
 3446             sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF) {
 3447                 /* No SLIPORT_CONTROL register so use command sequence instead */
 3448                 if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) {
 3449                         ocs_log_crit(sli4->os, "bootstrap mailbox not ready\n");
 3450                         return -1;
 3451                 }
 3452 
 3453                 if (sli_common_function_reset(sli4)) {
 3454                         ocs_log_err(sli4->os, "bad COM_FUNC_RESET write\n");
 3455                         return -1;
 3456                 }
 3457 
 3458                 if (sli_cmd_fw_deinitialize(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3459                         if (sli_bmbx_command(sli4)) {
 3460                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (FW_DEINIT)\n");
 3461                                 return -1;
 3462                         }
 3463                 } else {
 3464                         ocs_log_test(sli4->os, "bad FW_DEINIT write\n");
 3465                         return -1;
 3466                 }
 3467         } else {
 3468 #if BYTE_ORDER == LITTLE_ENDIAN
 3469                 endian = SLI4_SLIPORT_CONTROL_LITTLE_ENDIAN;
 3470 #else
 3471                 endian = SLI4_SLIPORT_CONTROL_BIG_ENDIAN;
 3472 #endif
 3473                 /* type 2 etc. use SLIPORT_CONTROL to initialize port */
 3474                 sli_sliport_control(sli4, endian);
 3475         }
 3476         return 0;
 3477 }
 3478 
 3479 /**
 3480  * @brief Write the doorbell register associated with the queue object.
 3481  *
 3482  * @param sli4 SLI context.
 3483  * @param q Queue object.
 3484  *
 3485  * @return Returns 0 on success, or a non-zero value on failure.
 3486  */
 3487 static int32_t
 3488 sli_queue_doorbell(sli4_t *sli4, sli4_queue_t *q)
 3489 {
 3490         uint32_t        val = 0;
 3491 
 3492         switch (q->type) {
 3493         case SLI_QTYPE_EQ:
 3494                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 3495                         val = sli_iftype6_eq_doorbell(q->n_posted, q->id, FALSE);
 3496                 else
 3497                         val = sli_eq_doorbell(q->n_posted, q->id, FALSE);
 3498                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3499                 break;
 3500         case SLI_QTYPE_CQ:
 3501                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 3502                         val = sli_iftype6_cq_doorbell(q->n_posted, q->id, FALSE);
 3503                 else
 3504                         val = sli_cq_doorbell(q->n_posted, q->id, FALSE);
 3505                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3506                 break;
 3507         case SLI_QTYPE_MQ:
 3508                 val = SLI4_MQ_DOORBELL(q->n_posted, q->id);
 3509                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3510                 break;
 3511         case SLI_QTYPE_RQ:
 3512         {
 3513                 uint32_t        n_posted = q->n_posted;
 3514                 /*
 3515                  * FC/FCoE has different rules for Receive Queues. The host
 3516                  * should only update the doorbell of the RQ-pair containing
 3517                  * the headers since the header / payload RQs are treated
 3518                  * as a matched unit.
 3519                  */
 3520                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 3521                         /*
 3522                          * In RQ-pair, an RQ either contains the FC header
 3523                          * (i.e. is_hdr == TRUE) or the payload.
 3524                          *
 3525                          * Don't ring doorbell for payload RQ
 3526                          */
 3527                         if (!q->u.flag.is_hdr) {
 3528                                 break;
 3529                         }
 3530                         /*
 3531                          * Some RQ cannot be incremented one entry at a time. Instead,
 3532                          * the driver collects a number of entries and updates the
 3533                          * RQ in batches.
 3534                          */
 3535                         if (q->u.flag.rq_batch) {
 3536                                 if (((q->index + q->n_posted) % SLI4_QUEUE_RQ_BATCH)) {
 3537                                         break;
 3538                                 }
 3539                                 n_posted = SLI4_QUEUE_RQ_BATCH;
 3540                         }
 3541                 }
 3542 
 3543                 val = SLI4_RQ_DOORBELL(n_posted, q->id);
 3544                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3545                 break;
 3546         }
 3547         case SLI_QTYPE_WQ:
 3548                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7) {
 3549                         val = SLI4_WQ_DOORBELL(q->n_posted, 0, q->id);
 3550                 } else {
 3551                         /* For iftype = 2 and 3, q->index value is ignored */
 3552                         val = SLI4_WQ_DOORBELL(q->n_posted, q->index, q->id);
 3553                 }
 3554 
 3555                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 3556                 break;
 3557         default:
 3558                 ocs_log_test(sli4->os, "bad queue type %d\n", q->type);
 3559                 return -1;
 3560         }
 3561 
 3562         return 0;
 3563 }
 3564 
 3565 static int32_t
 3566 sli_request_features(sli4_t *sli4, sli4_features_t *features, uint8_t query)
 3567 {
 3568 
 3569         if (sli_cmd_request_features(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
 3570                                 *features, query)) {
 3571                 sli4_cmd_request_features_t *req_features = sli4->bmbx.virt;
 3572 
 3573                 if (sli_bmbx_command(sli4)) {
 3574                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (REQUEST_FEATURES)\n");
 3575                         return -1;
 3576                 }
 3577                 if (req_features->hdr.status) {
 3578                         ocs_log_err(sli4->os, "REQUEST_FEATURES bad status %#x\n",
 3579                                         req_features->hdr.status);
 3580                         return -1;
 3581                 }
 3582                 features->dword = req_features->response.dword;
 3583         } else {
 3584                 ocs_log_err(sli4->os, "bad REQUEST_FEATURES write\n");
 3585                 return -1;
 3586         }
 3587 
 3588         return 0;
 3589 }
 3590 
 3591 /**
 3592  * @brief Calculate max queue entries.
 3593  *
 3594  * @param sli4 SLI context.
 3595  *
 3596  * @return Returns 0 on success, or a non-zero value on failure.
 3597  */
 3598 void
 3599 sli_calc_max_qentries(sli4_t *sli4)
 3600 {
 3601         sli4_qtype_e q;
 3602         uint32_t alloc_size, qentries, qentry_size;
 3603 
 3604         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
 3605                 sli4->config.max_qentries[q] = sli_convert_mask_to_count(sli4->config.count_method[q],
 3606                                                                          sli4->config.count_mask[q]);
 3607         }
 3608 
 3609         /* single, continguous DMA allocations will be called for each queue
 3610          * of size (max_qentries * queue entry size); since these can be large,
 3611          * check against the OS max DMA allocation size
 3612          */
 3613         for (q = SLI_QTYPE_EQ; q < SLI_QTYPE_MAX; q++) {
 3614                 qentries = sli4->config.max_qentries[q];
 3615                 qentry_size = sli_get_queue_entry_size(sli4, q);
 3616                 alloc_size = qentries * qentry_size;
 3617                 if (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
 3618                         while (alloc_size > ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE)) {
 3619                                 /* cut the qentries in hwf until alloc_size <= max DMA alloc size */
 3620                                 qentries >>= 1;
 3621                                 alloc_size = qentries * qentry_size;
 3622                         }
 3623                         ocs_log_debug(sli4->os, "[%s]: max_qentries from %d to %d (max dma %d)\n",
 3624                                 SLI_QNAME[q], sli4->config.max_qentries[q],
 3625                                 qentries, ocs_max_dma_alloc(sli4->os, SLI_PAGE_SIZE));
 3626                         sli4->config.max_qentries[q] = qentries;
 3627                 }
 3628         }
 3629 }
 3630 
 3631 /**
 3632  * @brief Issue a FW_CONFIG mailbox command and store the results.
 3633  *
 3634  * @param sli4 SLI context.
 3635  *
 3636  * @return Returns 0 on success, or a non-zero value on failure.
 3637  */
 3638 static int32_t
 3639 sli_query_fw_config(sli4_t *sli4)
 3640 {
 3641         /*
 3642          * Read the device configuration
 3643          *
 3644          * Note: Only ulp0 fields contain values
 3645          */
 3646         if (sli_cmd_common_query_fw_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3647                 sli4_res_common_query_fw_config_t   *fw_config =
 3648                         (sli4_res_common_query_fw_config_t *)
 3649                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
 3650 
 3651                 if (sli_bmbx_command(sli4)) {
 3652                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (QUERY_FW_CONFIG)\n");
 3653                         return -1;
 3654                 }
 3655                 if (fw_config->hdr.status) {
 3656                         ocs_log_err(sli4->os, "COMMON_QUERY_FW_CONFIG bad status %#x\n",
 3657                                 fw_config->hdr.status);
 3658                         return -1;
 3659                 }
 3660 
 3661                 sli4->physical_port = fw_config->physical_port;
 3662                 sli4->config.dual_ulp_capable = ((fw_config->function_mode & SLI4_FUNCTION_MODE_DUA_MODE) == 0 ? 0 : 1);
 3663                 sli4->config.is_ulp_fc[0] = ((fw_config->ulp0_mode &
 3664                                               (SLI4_ULP_MODE_FCOE_INI |
 3665                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
 3666                 sli4->config.is_ulp_fc[1] = ((fw_config->ulp1_mode &
 3667                                               (SLI4_ULP_MODE_FCOE_INI |
 3668                                                SLI4_ULP_MODE_FCOE_TGT)) == 0 ? 0 : 1);
 3669 
 3670                 if (sli4->config.dual_ulp_capable) {
 3671                         /*
 3672                          * Lancer will not support this, so we use the values
 3673                          * from the READ_CONFIG.
 3674                          */
 3675                         if (sli4->config.is_ulp_fc[0] &&
 3676                             sli4->config.is_ulp_fc[1]) {
 3677                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total + fw_config->ulp1_toe_wq_total;
 3678                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total + fw_config->ulp1_toe_defrq_total;
 3679                         } else if (sli4->config.is_ulp_fc[0]) {
 3680                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp0_toe_wq_total;
 3681                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp0_toe_defrq_total;
 3682                         } else {
 3683                                 sli4->config.max_qcount[SLI_QTYPE_WQ] = fw_config->ulp1_toe_wq_total;
 3684                                 sli4->config.max_qcount[SLI_QTYPE_RQ] = fw_config->ulp1_toe_defrq_total;
 3685                         }
 3686                 }
 3687         } else {
 3688                 ocs_log_err(sli4->os, "bad QUERY_FW_CONFIG write\n");
 3689                 return -1;
 3690         }
 3691         return 0;
 3692 }
 3693 
 3694 static int32_t
 3695 sli_get_config(sli4_t *sli4)
 3696 {
 3697         ocs_dma_t       get_cntl_addl_data;
 3698 
 3699         /*
 3700          * Read the device configuration
 3701          */
 3702         if (sli_cmd_read_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3703                 sli4_res_read_config_t  *read_config = sli4->bmbx.virt;
 3704                 uint32_t        i;
 3705                 uint32_t        total;
 3706 
 3707                 if (sli_bmbx_command(sli4)) {
 3708                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_CONFIG)\n");
 3709                         return -1;
 3710                 }
 3711                 if (read_config->hdr.status) {
 3712                         ocs_log_err(sli4->os, "READ_CONFIG bad status %#x\n",
 3713                                         read_config->hdr.status);
 3714                         return -1;
 3715                 }
 3716 
 3717                 sli4->config.has_extents = read_config->ext;
 3718                 if (FALSE == sli4->config.has_extents) {
 3719                         uint32_t        i = 0;
 3720                         uint32_t        *base = sli4->config.extent[0].base;
 3721 
 3722                         if (!base) {
 3723                                 if (NULL == (base = ocs_malloc(sli4->os, SLI_RSRC_MAX * sizeof(uint32_t),
 3724                                                                 OCS_M_ZERO | OCS_M_NOWAIT))) {
 3725                                         ocs_log_err(sli4->os, "memory allocation failed for sli4_resource_t\n");
 3726                                         return -1;
 3727                                 }
 3728                         }
 3729 
 3730                         for (i = 0; i < SLI_RSRC_MAX; i++) {
 3731                                 sli4->config.extent[i].number = 1;
 3732                                 sli4->config.extent[i].n_alloc = 0;
 3733                                 sli4->config.extent[i].base = &base[i];
 3734                         }
 3735 
 3736                         sli4->config.extent[SLI_RSRC_FCOE_VFI].base[0] = read_config->vfi_base;
 3737                         sli4->config.extent[SLI_RSRC_FCOE_VFI].size = read_config->vfi_count;
 3738 
 3739                         sli4->config.extent[SLI_RSRC_FCOE_VPI].base[0] = read_config->vpi_base;
 3740                         sli4->config.extent[SLI_RSRC_FCOE_VPI].size = read_config->vpi_count;
 3741 
 3742                         sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0] = read_config->rpi_base;
 3743                         sli4->config.extent[SLI_RSRC_FCOE_RPI].size = read_config->rpi_count;
 3744 
 3745                         sli4->config.extent[SLI_RSRC_FCOE_XRI].base[0] = read_config->xri_base;
 3746                         sli4->config.extent[SLI_RSRC_FCOE_XRI].size = OCS_MIN(255,read_config->xri_count);
 3747 
 3748                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].base[0] = 0;
 3749                         sli4->config.extent[SLI_RSRC_FCOE_FCFI].size = read_config->fcfi_count;
 3750                 } else {
 3751                         /* TODO extents*/
 3752                         ;
 3753                 }
 3754 
 3755                 for (i = 0; i < SLI_RSRC_MAX; i++) {
 3756                         total = sli4->config.extent[i].number * sli4->config.extent[i].size;
 3757                         sli4->config.extent[i].use_map = ocs_bitmap_alloc(total);
 3758                         if (NULL == sli4->config.extent[i].use_map) {
 3759                                 ocs_log_err(sli4->os, "bitmap memory allocation failed "
 3760                                                 "resource %d\n", i);
 3761                                 return -1;
 3762                         }
 3763                         sli4->config.extent[i].map_size = total;
 3764                 }
 3765 
 3766                 sli4->config.topology = read_config->topology;
 3767                 sli4->config.ptv = read_config->ptv;
 3768                 if (sli4->config.ptv){
 3769                         sli4->config.tf = read_config->tf;
 3770                         sli4->config.pt = read_config->pt;
 3771                 }
 3772                 ocs_log_info(sli4->os, "Persistent Topology: PTV: %d, TF: %d, PT: %d \n",
 3773                              sli4->config.topology, sli4->config.ptv, sli4->config.tf, sli4->config.pt);
 3774 
 3775                 switch (sli4->config.topology) {
 3776                 case SLI4_READ_CFG_TOPO_FCOE:
 3777                         ocs_log_debug(sli4->os, "FCoE\n");
 3778                         break;
 3779                 case SLI4_READ_CFG_TOPO_FC:
 3780                         ocs_log_debug(sli4->os, "FC (unknown)\n");
 3781                         break;
 3782                 case SLI4_READ_CFG_TOPO_FC_DA:
 3783                         ocs_log_debug(sli4->os, "FC (direct attach)\n");
 3784                         break;
 3785                 case SLI4_READ_CFG_TOPO_FC_AL:
 3786                         ocs_log_debug(sli4->os, "FC (arbitrated loop)\n");
 3787                         break;
 3788                 default:
 3789                         ocs_log_test(sli4->os, "bad topology %#x\n", sli4->config.topology);
 3790                 }
 3791 
 3792                 sli4->config.e_d_tov = read_config->e_d_tov;
 3793                 sli4->config.r_a_tov = read_config->r_a_tov;
 3794 
 3795                 sli4->config.link_module_type = read_config->lmt;
 3796 
 3797                 sli4->config.max_qcount[SLI_QTYPE_EQ] = read_config->eq_count;
 3798                 sli4->config.max_qcount[SLI_QTYPE_CQ] = read_config->cq_count;
 3799                 sli4->config.max_qcount[SLI_QTYPE_WQ] = read_config->wq_count;
 3800                 sli4->config.max_qcount[SLI_QTYPE_RQ] = read_config->rq_count;
 3801 
 3802                 /*
 3803                  * READ_CONFIG doesn't give the max number of MQ. Applications
 3804                  * will typically want 1, but we may need another at some future
 3805                  * date. Dummy up a "max" MQ count here.
 3806                  */
 3807                 sli4->config.max_qcount[SLI_QTYPE_MQ] = SLI_USER_MQ_COUNT;
 3808         } else {
 3809                 ocs_log_err(sli4->os, "bad READ_CONFIG write\n");
 3810                 return -1;
 3811         }
 3812 
 3813         if (sli_cmd_common_get_sli4_parameters(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3814                 sli4_res_common_get_sli4_parameters_t   *parms = (sli4_res_common_get_sli4_parameters_t *)
 3815                         (((uint8_t *)sli4->bmbx.virt) + offsetof(sli4_cmd_sli_config_t, payload.embed));
 3816 
 3817                 if (sli_bmbx_command(sli4)) {
 3818                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_SLI4_PARAMETERS)\n");
 3819                         return -1;
 3820                 } else if (parms->hdr.status) {
 3821                         ocs_log_err(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x att'l %#x\n",
 3822                                         parms->hdr.status, parms->hdr.additional_status);
 3823                         return -1;
 3824                 }
 3825 
 3826                 sli4->config.auto_reg = parms->areg;
 3827                 sli4->config.auto_xfer_rdy = parms->agxf;
 3828                 sli4->config.hdr_template_req = parms->hdrr;
 3829                 sli4->config.t10_dif_inline_capable = parms->timm;
 3830                 sli4->config.t10_dif_separate_capable = parms->tsmm;
 3831 
 3832                 sli4->config.mq_create_version = parms->mqv;
 3833                 sli4->config.cq_create_version = parms->cqv;
 3834                 sli4->config.rq_min_buf_size = parms->min_rq_buffer_size;
 3835                 sli4->config.rq_max_buf_size = parms->max_rq_buffer_size;
 3836 
 3837                 sli4->config.qpage_count[SLI_QTYPE_EQ] = parms->eq_page_cnt;
 3838                 sli4->config.qpage_count[SLI_QTYPE_CQ] = parms->cq_page_cnt;
 3839                 sli4->config.qpage_count[SLI_QTYPE_MQ] = parms->mq_page_cnt;
 3840                 sli4->config.qpage_count[SLI_QTYPE_WQ] = parms->wq_page_cnt;
 3841                 sli4->config.qpage_count[SLI_QTYPE_RQ] = parms->rq_page_cnt;
 3842 
 3843                 /* save count methods and masks for each queue type */
 3844                 sli4->config.count_mask[SLI_QTYPE_EQ] = parms->eqe_count_mask;
 3845                 sli4->config.count_method[SLI_QTYPE_EQ] = parms->eqe_count_method;
 3846                 sli4->config.count_mask[SLI_QTYPE_CQ] = parms->cqe_count_mask;
 3847                 sli4->config.count_method[SLI_QTYPE_CQ] = parms->cqe_count_method;
 3848                 sli4->config.count_mask[SLI_QTYPE_MQ] = parms->mqe_count_mask;
 3849                 sli4->config.count_method[SLI_QTYPE_MQ] = parms->mqe_count_method;
 3850                 sli4->config.count_mask[SLI_QTYPE_WQ] = parms->wqe_count_mask;
 3851                 sli4->config.count_method[SLI_QTYPE_WQ] = parms->wqe_count_method;
 3852                 sli4->config.count_mask[SLI_QTYPE_RQ] = parms->rqe_count_mask;
 3853                 sli4->config.count_method[SLI_QTYPE_RQ] = parms->rqe_count_method;
 3854 
 3855                 /* now calculate max queue entries */
 3856                 sli_calc_max_qentries(sli4);
 3857 
 3858                 sli4->config.max_sgl_pages = parms->sgl_page_cnt;       /* max # of pages */
 3859                 sli4->config.sgl_page_sizes = parms->sgl_page_sizes;    /* bit map of available sizes */
 3860                 /* ignore HLM here. Use value from REQUEST_FEATURES */
 3861                 
 3862                 sli4->config.sge_supported_length = parms->sge_supported_length;
 3863                 if (sli4->config.sge_supported_length > OCS_MAX_SGE_SIZE)
 3864                         sli4->config.sge_supported_length = OCS_MAX_SGE_SIZE;
 3865 
 3866                 sli4->config.sgl_pre_registration_required = parms->sglr;
 3867                 /* default to using pre-registered SGL's */
 3868                 sli4->config.sgl_pre_registered = TRUE;
 3869 
 3870                 sli4->config.perf_hint = parms->phon;
 3871                 sli4->config.perf_wq_id_association = parms->phwq;
 3872 
 3873                 sli4->config.rq_batch = parms->rq_db_window;
 3874 
 3875                 /* save the fields for skyhawk SGL chaining */
 3876                 sli4->config.sgl_chaining_params.chaining_capable =
 3877                         (parms->sglc == 1);
 3878                 sli4->config.sgl_chaining_params.frag_num_field_offset =
 3879                         parms->frag_num_field_offset;
 3880                 sli4->config.sgl_chaining_params.frag_num_field_mask =
 3881                         (1ull << parms->frag_num_field_size) - 1;
 3882                 sli4->config.sgl_chaining_params.sgl_index_field_offset =
 3883                         parms->sgl_index_field_offset;
 3884                 sli4->config.sgl_chaining_params.sgl_index_field_mask =
 3885                         (1ull << parms->sgl_index_field_size) - 1;
 3886                 sli4->config.sgl_chaining_params.chain_sge_initial_value_lo =
 3887                         parms->chain_sge_initial_value_lo;
 3888                 sli4->config.sgl_chaining_params.chain_sge_initial_value_hi =
 3889                         parms->chain_sge_initial_value_hi;
 3890 
 3891                 /* Use the highest available WQE size. */
 3892                 if (parms->wqe_sizes & SLI4_128BYTE_WQE_SUPPORT) {
 3893                         sli4->config.wqe_size = SLI4_WQE_EXT_BYTES;
 3894                 } else {
 3895                         sli4->config.wqe_size = SLI4_WQE_BYTES;
 3896                 }
 3897         }
 3898 
 3899         if (sli_query_fw_config(sli4)) {
 3900                 ocs_log_err(sli4->os, "Error sending QUERY_FW_CONFIG\n");
 3901                 return -1;
 3902         }
 3903 
 3904         sli4->config.port_number = 0;
 3905 
 3906         /*
 3907          * Issue COMMON_GET_CNTL_ATTRIBUTES to get port_number. Temporarily
 3908          * uses VPD DMA buffer as the response won't fit in the embedded
 3909          * buffer.
 3910          */
 3911         if (sli_cmd_common_get_cntl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
 3912                 sli4_res_common_get_cntl_attributes_t *attr = sli4->vpd.data.virt;
 3913 
 3914                 if (sli_bmbx_command(sli4)) {
 3915                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_CNTL_ATTRIBUTES)\n");
 3916                         return -1;
 3917                 } else if (attr->hdr.status) {
 3918                         ocs_log_err(sli4->os, "COMMON_GET_CNTL_ATTRIBUTES bad status %#x att'l %#x\n",
 3919                                         attr->hdr.status, attr->hdr.additional_status);
 3920                         return -1;
 3921                 }
 3922 
 3923                 sli4->config.port_number = attr->port_number;
 3924 
 3925                 ocs_memcpy(sli4->config.bios_version_string, attr->bios_version_string,
 3926                                 sizeof(sli4->config.bios_version_string));
 3927         } else {
 3928                 ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ATTRIBUTES write\n");
 3929                 return -1;
 3930         }
 3931 
 3932         if (ocs_dma_alloc(sli4->os, &get_cntl_addl_data, sizeof(sli4_res_common_get_cntl_addl_attributes_t),
 3933                           OCS_MIN_DMA_ALIGNMENT)) {
 3934                 ocs_log_err(sli4->os, "Failed to allocate memory for GET_CNTL_ADDL_ATTR data\n");
 3935         } else {
 3936                 if (sli_cmd_common_get_cntl_addl_attributes(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
 3937                                                             &get_cntl_addl_data)) {
 3938                         sli4_res_common_get_cntl_addl_attributes_t *attr = get_cntl_addl_data.virt;
 3939 
 3940                         if (sli_bmbx_command(sli4)) {
 3941                                 ocs_log_crit(sli4->os,
 3942                                              "bootstrap mailbox write fail (COMMON_GET_CNTL_ADDL_ATTRIBUTES)\n");
 3943                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3944                                 return -1;
 3945                         }
 3946                         if (attr->hdr.status) {
 3947                                 ocs_log_err(sli4->os, "COMMON_GET_CNTL_ADDL_ATTRIBUTES bad status %#x\n",
 3948                                             attr->hdr.status);
 3949                                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3950                                 return -1;
 3951                         }
 3952 
 3953                         ocs_memcpy(sli4->config.ipl_name, attr->ipl_file_name, sizeof(sli4->config.ipl_name));
 3954 
 3955                         ocs_log_debug(sli4->os, "IPL:%s \n", (char*)sli4->config.ipl_name);
 3956                 } else {
 3957                         ocs_log_err(sli4->os, "bad COMMON_GET_CNTL_ADDL_ATTRIBUTES write\n");
 3958                         ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3959                         return -1;
 3960                 }
 3961 
 3962                 ocs_dma_free(sli4->os, &get_cntl_addl_data);
 3963         }
 3964 
 3965         if (sli_cmd_common_get_port_name(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 3966                 sli4_res_common_get_port_name_t *port_name = (sli4_res_common_get_port_name_t *)(((uint8_t *)sli4->bmbx.virt) +
 3967                         offsetof(sli4_cmd_sli_config_t, payload.embed));
 3968 
 3969                 if (sli_bmbx_command(sli4)) {
 3970                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (COMMON_GET_PORT_NAME)\n");
 3971                         return -1;
 3972                 }
 3973 
 3974                 sli4->config.port_name[0] = port_name->port_name[sli4->config.port_number];
 3975         }
 3976         sli4->config.port_name[1] = '\0';
 3977 
 3978         if (sli_cmd_read_rev(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &sli4->vpd.data)) {
 3979                 sli4_cmd_read_rev_t     *read_rev = sli4->bmbx.virt;
 3980 
 3981                 if (sli_bmbx_command(sli4)) {
 3982                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_REV)\n");
 3983                         return -1;
 3984                 }
 3985                 if (read_rev->hdr.status) {
 3986                         ocs_log_err(sli4->os, "READ_REV bad status %#x\n",
 3987                                         read_rev->hdr.status);
 3988                         return -1;
 3989                 }
 3990 
 3991                 sli4->config.fw_rev[0] = read_rev->first_fw_id;
 3992                 ocs_memcpy(sli4->config.fw_name[0],read_rev->first_fw_name, sizeof(sli4->config.fw_name[0]));
 3993 
 3994                 sli4->config.fw_rev[1] = read_rev->second_fw_id;
 3995                 ocs_memcpy(sli4->config.fw_name[1],read_rev->second_fw_name, sizeof(sli4->config.fw_name[1]));
 3996 
 3997                 sli4->config.hw_rev[0] = read_rev->first_hw_revision;
 3998                 sli4->config.hw_rev[1] = read_rev->second_hw_revision;
 3999                 sli4->config.hw_rev[2] = read_rev->third_hw_revision;
 4000 
 4001                 ocs_log_debug(sli4->os, "FW1:%s (%08x) / FW2:%s (%08x)\n",
 4002                                 read_rev->first_fw_name, read_rev->first_fw_id,
 4003                                 read_rev->second_fw_name, read_rev->second_fw_id);
 4004 
 4005                 ocs_log_debug(sli4->os, "HW1: %08x / HW2: %08x\n", read_rev->first_hw_revision,
 4006                                 read_rev->second_hw_revision);
 4007 
 4008                 /* Check that all VPD data was returned */
 4009                 if (read_rev->returned_vpd_length != read_rev->actual_vpd_length) {
 4010                         ocs_log_test(sli4->os, "VPD length: available=%d returned=%d actual=%d\n",
 4011                                         read_rev->available_length,
 4012                                         read_rev->returned_vpd_length,
 4013                                         read_rev->actual_vpd_length);
 4014                 }
 4015                 sli4->vpd.length = read_rev->returned_vpd_length;
 4016         } else {
 4017                 ocs_log_err(sli4->os, "bad READ_REV write\n");
 4018                 return -1;
 4019         }
 4020 
 4021         if (sli_cmd_read_nvparms(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE)) {
 4022                 sli4_cmd_read_nvparms_t *read_nvparms = sli4->bmbx.virt;
 4023 
 4024                 if (sli_bmbx_command(sli4)) {
 4025                         ocs_log_crit(sli4->os, "bootstrap mailbox write fail (READ_NVPARMS)\n");
 4026                         return -1;
 4027                 }
 4028                 if (read_nvparms->hdr.status) {
 4029                         ocs_log_err(sli4->os, "READ_NVPARMS bad status %#x\n",
 4030                                         read_nvparms->hdr.status);
 4031                         return -1;
 4032                 }
 4033 
 4034                 ocs_memcpy(sli4->config.wwpn, read_nvparms->wwpn, sizeof(sli4->config.wwpn));
 4035                 ocs_memcpy(sli4->config.wwnn, read_nvparms->wwnn, sizeof(sli4->config.wwnn));
 4036 
 4037                 ocs_log_debug(sli4->os, "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 4038                                 sli4->config.wwpn[0],
 4039                                 sli4->config.wwpn[1],
 4040                                 sli4->config.wwpn[2],
 4041                                 sli4->config.wwpn[3],
 4042                                 sli4->config.wwpn[4],
 4043                                 sli4->config.wwpn[5],
 4044                                 sli4->config.wwpn[6],
 4045                                 sli4->config.wwpn[7]);
 4046                 ocs_log_debug(sli4->os, "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 4047                                 sli4->config.wwnn[0],
 4048                                 sli4->config.wwnn[1],
 4049                                 sli4->config.wwnn[2],
 4050                                 sli4->config.wwnn[3],
 4051                                 sli4->config.wwnn[4],
 4052                                 sli4->config.wwnn[5],
 4053                                 sli4->config.wwnn[6],
 4054                                 sli4->config.wwnn[7]);
 4055         } else {
 4056                 ocs_log_err(sli4->os, "bad READ_NVPARMS write\n");
 4057                 return -1;
 4058         }
 4059 
 4060         return 0;
 4061 }
 4062 
 4063 /****************************************************************************
 4064  * Public functions
 4065  */
 4066 
 4067 /**
 4068  * @ingroup sli
 4069  * @brief Set up the SLI context.
 4070  *
 4071  * @param sli4 SLI context.
 4072  * @param os Device abstraction.
 4073  * @param port_type Protocol type of port (for example, FC and NIC).
 4074  *
 4075  * @return Returns 0 on success, or a non-zero value on failure.
 4076  */
 4077 int32_t
 4078 sli_setup(sli4_t *sli4, ocs_os_handle_t os, sli4_port_type_e port_type)
 4079 {
 4080         uint32_t sli_intf = UINT32_MAX;
 4081         uint32_t pci_class_rev = 0;
 4082         uint32_t rev_id = 0;
 4083         uint32_t family = 0;
 4084         uint32_t i;
 4085         sli4_asic_entry_t *asic;
 4086 
 4087         ocs_memset(sli4, 0, sizeof(sli4_t));
 4088 
 4089         sli4->os = os;
 4090         sli4->port_type = port_type;
 4091 
 4092         /*
 4093          * Read the SLI_INTF register to discover the register layout
 4094          * and other capability information
 4095          */
 4096         sli_intf = ocs_config_read32(os, SLI4_INTF_REG);
 4097 
 4098         if (sli_intf_valid_check(sli_intf)) {
 4099                 ocs_log_err(os, "SLI_INTF is not valid\n");
 4100                 return -1;
 4101         }
 4102 
 4103         /* driver only support SLI-4 */
 4104         sli4->sli_rev = sli_intf_sli_revision(sli_intf);
 4105         if (4 != sli4->sli_rev) {
 4106                 ocs_log_err(os, "Unsupported SLI revision (intf=%#x)\n",
 4107                                 sli_intf);
 4108                 return -1;
 4109         }
 4110 
 4111         sli4->sli_family = sli_intf_sli_family(sli_intf);
 4112 
 4113         sli4->if_type = sli_intf_if_type(sli_intf);
 4114 
 4115         if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type) ||
 4116            (SLI4_IF_TYPE_LANCER_G7 == sli4->if_type)) {
 4117                 ocs_log_debug(os, "status=%#x error1=%#x error2=%#x\n",
 4118                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS),
 4119                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR1),
 4120                                 sli_reg_read(sli4, SLI4_REG_SLIPORT_ERROR2));
 4121         }
 4122 
 4123         /*
 4124          * set the ASIC type and revision
 4125          */
 4126         pci_class_rev = ocs_config_read32(os, SLI4_PCI_CLASS_REVISION);
 4127         rev_id = sli_pci_rev_id(pci_class_rev);
 4128         family = sli4->sli_family;
 4129         if (family == SLI4_FAMILY_CHECK_ASIC_TYPE) {
 4130                 uint32_t asic_id = ocs_config_read32(os, SLI4_ASIC_ID_REG);
 4131                 family = sli_asic_gen(asic_id);
 4132         }
 4133 
 4134         for (i = 0, asic = sli4_asic_table; i < ARRAY_SIZE(sli4_asic_table); i++, asic++) {
 4135                 if ((rev_id == asic->rev_id) && (family == asic->family)) {
 4136                         sli4->asic_type = asic->type;
 4137                         sli4->asic_rev = asic->rev;
 4138                         break;
 4139                 }
 4140         }
 4141         /* Fail if no matching asic type/rev was found */
 4142         if( (sli4->asic_type == 0) || (sli4->asic_rev == 0)) {
 4143                 ocs_log_err(os, "no matching asic family/rev found: %02x/%02x\n", family, rev_id);
 4144                 return -1;
 4145         }
 4146 
 4147         /*
 4148          * The bootstrap mailbox is equivalent to a MQ with a single 256 byte
 4149          * entry, a CQ with a single 16 byte entry, and no event queue.
 4150          * Alignment must be 16 bytes as the low order address bits in the
 4151          * address register are also control / status.
 4152          */
 4153         if (ocs_dma_alloc(sli4->os, &sli4->bmbx, SLI4_BMBX_SIZE +
 4154                                 sizeof(sli4_mcqe_t), 16)) {
 4155                 ocs_log_err(os, "bootstrap mailbox allocation failed\n");
 4156                 return -1;
 4157         }
 4158 
 4159         if (sli4->bmbx.phys & SLI4_BMBX_MASK_LO) {
 4160                 ocs_log_err(os, "bad alignment for bootstrap mailbox\n");
 4161                 return -1;
 4162         }
 4163 
 4164         ocs_log_debug(os, "bmbx v=%p p=0x%x %08x s=%zd\n", sli4->bmbx.virt,
 4165                 ocs_addr32_hi(sli4->bmbx.phys),
 4166                 ocs_addr32_lo(sli4->bmbx.phys),
 4167                 sli4->bmbx.size);
 4168 
 4169         /* TODO 4096 is arbitrary. What should this value actually be? */
 4170         if (ocs_dma_alloc(sli4->os, &sli4->vpd.data, 4096/*TODO*/, 4096)) {
 4171                 /* Note that failure isn't fatal in this specific case */
 4172                 sli4->vpd.data.size = 0;
 4173                 ocs_log_test(os, "VPD buffer allocation failed\n");
 4174         }
 4175 
 4176         if (sli_fw_init(sli4)) {
 4177                 ocs_log_err(sli4->os, "FW initialization failed\n");
 4178                 return -1;
 4179         }
 4180 
 4181         /*
 4182          * Set one of fcpi(initiator), fcpt(target), fcpc(combined) to true
 4183          * in addition to any other desired features
 4184          */
 4185         sli4->config.features.flag.iaab = TRUE;
 4186         sli4->config.features.flag.npiv = TRUE;
 4187         sli4->config.features.flag.dif = TRUE;
 4188         sli4->config.features.flag.vf = TRUE;
 4189         sli4->config.features.flag.fcpc = TRUE;
 4190         sli4->config.features.flag.iaar = TRUE;
 4191         sli4->config.features.flag.hlm = TRUE;
 4192         sli4->config.features.flag.perfh = TRUE;
 4193         sli4->config.features.flag.rxseq = TRUE;
 4194         sli4->config.features.flag.rxri = TRUE;
 4195         sli4->config.features.flag.mrqp = TRUE;
 4196 
 4197         /* use performance hints if available */
 4198         if (sli4->config.perf_hint) {
 4199                 sli4->config.features.flag.perfh = TRUE;
 4200         }
 4201 
 4202         if (sli_request_features(sli4, &sli4->config.features, TRUE)) {
 4203                 return -1;
 4204         }
 4205 
 4206         if (sli_get_config(sli4)) {
 4207                 return -1;
 4208         }
 4209 
 4210         return 0;
 4211 }
 4212 
 4213 bool
 4214 sli_persist_topology_enabled(sli4_t *sli4)
 4215 {
 4216         return (sli4->config.ptv);
 4217 }
 4218 
 4219 int32_t
 4220 sli_init(sli4_t *sli4)
 4221 {
 4222 
 4223         if (sli4->config.has_extents) {
 4224                 /* TODO COMMON_ALLOC_RESOURCE_EXTENTS */;
 4225                 ocs_log_test(sli4->os, "XXX need to implement extent allocation\n");
 4226                 return -1;
 4227         }
 4228 
 4229         sli4->config.features.flag.hlm = sli4->config.high_login_mode;
 4230         sli4->config.features.flag.rxseq = FALSE;
 4231         sli4->config.features.flag.rxri  = FALSE;
 4232 
 4233         if (sli_request_features(sli4, &sli4->config.features, FALSE)) {
 4234                 return -1;
 4235         }
 4236 
 4237         return 0;
 4238 }
 4239 
 4240 int32_t
 4241 sli_reset(sli4_t *sli4)
 4242 {
 4243         uint32_t        i;
 4244 
 4245         if (sli_fw_init(sli4)) {
 4246                 ocs_log_crit(sli4->os, "FW initialization failed\n");
 4247                 return -1;
 4248         }
 4249 
 4250         if (sli4->config.extent[0].base) {
 4251                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
 4252                 sli4->config.extent[0].base = NULL;
 4253         }
 4254 
 4255         for (i = 0; i < SLI_RSRC_MAX; i++) {
 4256                 if (sli4->config.extent[i].use_map) {
 4257                         ocs_bitmap_free(sli4->config.extent[i].use_map);
 4258                         sli4->config.extent[i].use_map = NULL;
 4259                 }
 4260                 sli4->config.extent[i].base = NULL;
 4261         }
 4262 
 4263         if (sli_get_config(sli4)) {
 4264                 return -1;
 4265         }
 4266 
 4267         return 0;
 4268 }
 4269 
 4270 /**
 4271  * @ingroup sli
 4272  * @brief Issue a Firmware Reset.
 4273  *
 4274  * @par Description
 4275  * Issues a Firmware Reset to the chip.  This reset affects the entire chip,
 4276  * so all PCI function on the same PCI bus and device are affected.
 4277  * @n @n This type of reset can be used to activate newly downloaded firmware.
 4278  * @n @n The driver should be considered to be in an unknown state after this
 4279  * reset and should be reloaded.
 4280  *
 4281  * @param sli4 SLI context.
 4282  *
 4283  * @return Returns 0 on success, or -1 otherwise.
 4284  */
 4285 
 4286 int32_t
 4287 sli_fw_reset(sli4_t *sli4)
 4288 {
 4289         uint32_t val;
 4290         uint32_t ready;
 4291 
 4292         /*
 4293          * Firmware must be ready before issuing the reset.
 4294          */
 4295         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 4296         if (!ready) {
 4297                 ocs_log_crit(sli4->os, "FW status is NOT ready\n");
 4298                 return -1;
 4299         }
 4300         switch(sli4->if_type) {
 4301         case SLI4_IF_TYPE_BE3_SKH_PF:
 4302                 /* BE3 / Skyhawk use PCICFG_SOFT_RESET_CSR */
 4303                 val = ocs_config_read32(sli4->os, SLI4_PCI_SOFT_RESET_CSR);
 4304                 val |= SLI4_PCI_SOFT_RESET_MASK;
 4305                 ocs_config_write32(sli4->os, SLI4_PCI_SOFT_RESET_CSR, val);
 4306                 break;
 4307         case SLI4_IF_TYPE_LANCER_FC_ETH:
 4308                 /* Lancer uses PHYDEV_CONTROL */
 4309 
 4310                 val = SLI4_PHYDEV_CONTROL_FRST;
 4311                 sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, val);
 4312                 break;
 4313         default:
 4314                 ocs_log_test(sli4->os, "Unexpected iftype %d\n", sli4->if_type);
 4315                 return -1;
 4316                 break;
 4317         }
 4318 
 4319         /* wait for the FW to become ready after the reset */
 4320         ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
 4321         if (!ready) {
 4322                 ocs_log_crit(sli4->os, "Failed to become ready after firmware reset\n");
 4323                 return -1;
 4324         }
 4325         return 0;
 4326 }
 4327 
 4328 /**
 4329  * @ingroup sli
 4330  * @brief Tear down a SLI context.
 4331  *
 4332  * @param sli4 SLI context.
 4333  *
 4334  * @return Returns 0 on success, or non-zero otherwise.
 4335  */
 4336 int32_t
 4337 sli_teardown(sli4_t *sli4)
 4338 {
 4339         uint32_t i;
 4340 
 4341         if (sli4->config.extent[0].base) {
 4342                 ocs_free(sli4->os, sli4->config.extent[0].base, SLI_RSRC_MAX * sizeof(uint32_t));
 4343                 sli4->config.extent[0].base = NULL;
 4344         }
 4345 
 4346         for (i = 0; i < SLI_RSRC_MAX; i++) {
 4347                 if (sli4->config.has_extents) {
 4348                         /* TODO COMMON_DEALLOC_RESOURCE_EXTENTS */;
 4349                 }
 4350 
 4351                 sli4->config.extent[i].base = NULL;
 4352 
 4353                 ocs_bitmap_free(sli4->config.extent[i].use_map);
 4354                 sli4->config.extent[i].use_map = NULL;
 4355         }
 4356 
 4357         if (sli_fw_term(sli4)) {
 4358                 ocs_log_err(sli4->os, "FW deinitialization failed\n");
 4359         }
 4360 
 4361         ocs_dma_free(sli4->os, &sli4->vpd.data);
 4362         ocs_dma_free(sli4->os, &sli4->bmbx);
 4363 
 4364         return 0;
 4365 }
 4366 
 4367 /**
 4368  * @ingroup sli
 4369  * @brief Register a callback for the given event.
 4370  *
 4371  * @param sli4 SLI context.
 4372  * @param which Event of interest.
 4373  * @param func Function to call when the event occurs.
 4374  * @param arg Argument passed to the callback function.
 4375  *
 4376  * @return Returns 0 on success, or non-zero otherwise.
 4377  */
 4378 int32_t
 4379 sli_callback(sli4_t *sli4, sli4_callback_e which, void *func, void *arg)
 4380 {
 4381 
 4382         if (!sli4 || !func || (which >= SLI4_CB_MAX)) {
 4383                 ocs_log_err(NULL, "bad parameter sli4=%p which=%#x func=%p\n",
 4384                             sli4, which, func);
 4385                 return -1;
 4386         }
 4387 
 4388         switch (which) {
 4389         case SLI4_CB_LINK:
 4390                 sli4->link = func;
 4391                 sli4->link_arg = arg;
 4392                 break;
 4393         case SLI4_CB_FIP:
 4394                 sli4->fip = func;
 4395                 sli4->fip_arg = arg;
 4396                 break;
 4397         default:
 4398                 ocs_log_test(sli4->os, "unknown callback %#x\n", which);
 4399                 return -1;
 4400         }
 4401 
 4402         return 0;
 4403 }
 4404 
 4405 /**
 4406  * @ingroup sli
 4407  * @brief Initialize a queue object.
 4408  *
 4409  * @par Description
 4410  * This initializes the sli4_queue_t object members, including the underlying
 4411  * DMA memory.
 4412  *
 4413  * @param sli4 SLI context.
 4414  * @param q Pointer to queue object.
 4415  * @param qtype Type of queue to create.
 4416  * @param size Size of each entry.
 4417  * @param n_entries Number of entries to allocate.
 4418  * @param align Starting memory address alignment.
 4419  *
 4420  * @note Checks if using the existing DMA memory (if any) is possible. If not,
 4421  * it frees the existing memory and re-allocates.
 4422  *
 4423  * @return Returns 0 on success, or non-zero otherwise.
 4424  */
 4425 int32_t
 4426 __sli_queue_init(sli4_t *sli4, sli4_queue_t *q, uint32_t qtype,
 4427                 size_t size, uint32_t n_entries, uint32_t align)
 4428 {
 4429 
 4430         if ((q->dma.virt == NULL) || (size != q->size) || (n_entries != q->length)) {
 4431                 if (q->dma.size) {
 4432                         ocs_dma_free(sli4->os, &q->dma);
 4433                 }
 4434 
 4435                 ocs_memset(q, 0, sizeof(sli4_queue_t));
 4436 
 4437                 if (ocs_dma_alloc(sli4->os, &q->dma, size * n_entries, align)) {
 4438                         ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
 4439                         return -1;
 4440                 }
 4441 
 4442                 ocs_memset(q->dma.virt, 0, size * n_entries);
 4443 
 4444                 ocs_lock_init(sli4->os, &q->lock, "%s lock[%d:%p]", 
 4445                         SLI_QNAME[qtype], ocs_instance(sli4->os), &q->lock);
 4446 
 4447                 q->type = qtype;
 4448                 q->size = size;
 4449                 q->length = n_entries;
 4450 
 4451                 /* Limit to hwf the queue size per interrupt */
 4452                 q->proc_limit = n_entries / 2;
 4453 
 4454                 if ( (q->type == SLI_QTYPE_EQ) || (q->type == SLI_QTYPE_CQ) ) {
 4455                 /* For prism, phase will be flipped after a sweep through eq and cq */
 4456                         q->phase = 1;
 4457                 }
 4458 
 4459                 switch(q->type) {
 4460                 case SLI_QTYPE_EQ:
 4461                         q->posted_limit = q->length / 2;
 4462                         break;
 4463                 default:
 4464                         if ((sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) ||
 4465                             (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_VF)) {
 4466                                 /* For Skyhawk, ring the doorbell more often */
 4467                                 q->posted_limit = 8;
 4468                         } else {
 4469                                 q->posted_limit = 64;
 4470                         }
 4471                         break;
 4472                 }
 4473         }
 4474 
 4475         return 0;
 4476 }
 4477 
 4478 /**
 4479  * @ingroup sli
 4480  * @brief Issue the command to create a queue.
 4481  *
 4482  * @param sli4 SLI context.
 4483  * @param q Pointer to queue object.
 4484  *
 4485  * @return Returns 0 on success, or non-zero otherwise.
 4486  */
 4487 int32_t
 4488 __sli_create_queue(sli4_t *sli4, sli4_queue_t *q)
 4489 {
 4490         sli4_res_common_create_queue_t *res_q = NULL;
 4491 
 4492         if (sli_bmbx_command(sli4)){
 4493                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail %s\n",
 4494                                 SLI_QNAME[q->type]);
 4495                 ocs_dma_free(sli4->os, &q->dma);
 4496                 return -1;
 4497         }
 4498         if (sli_res_sli_config(sli4->bmbx.virt)) {
 4499                 ocs_log_err(sli4->os, "bad status create %s\n", SLI_QNAME[q->type]);
 4500                 ocs_dma_free(sli4->os, &q->dma);
 4501                 return -1;
 4502         }
 4503         res_q = (void *)((uint8_t *)sli4->bmbx.virt +
 4504                         offsetof(sli4_cmd_sli_config_t, payload));
 4505 
 4506         if (res_q->hdr.status) {
 4507                 ocs_log_err(sli4->os, "bad create %s status=%#x addl=%#x\n",
 4508                                 SLI_QNAME[q->type],
 4509                                 res_q->hdr.status, res_q->hdr.additional_status);
 4510                 ocs_dma_free(sli4->os, &q->dma);
 4511                 return -1;
 4512         } else {
 4513                 q->id = res_q->q_id;
 4514                 q->doorbell_offset = res_q->db_offset;
 4515                 q->doorbell_rset = res_q->db_rs;
 4516 
 4517                 switch (q->type) {
 4518                 case SLI_QTYPE_EQ:
 4519                         /* No doorbell information in response for EQs */
 4520                         q->doorbell_offset = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].off;
 4521                         q->doorbell_rset   = regmap[SLI4_REG_EQ_DOORBELL][sli4->if_type].rset;
 4522                         break;
 4523                 case SLI_QTYPE_CQ:
 4524                         /* No doorbell information in response for CQs */
 4525                         q->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off;
 4526                         q->doorbell_rset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset;
 4527                         break;
 4528                 case SLI_QTYPE_MQ:
 4529                         /* No doorbell information in response for MQs */
 4530                         q->doorbell_offset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].off;
 4531                         q->doorbell_rset = regmap[SLI4_REG_MQ_DOORBELL][sli4->if_type].rset;
 4532                         break;
 4533                 case SLI_QTYPE_RQ:
 4534                         /* set the doorbell for non-skyhawks */
 4535                         if (!sli4->config.dual_ulp_capable) {
 4536                                 q->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
 4537                                 q->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
 4538                         }
 4539                         break;
 4540                 case SLI_QTYPE_WQ:
 4541                         /* set the doorbell for non-skyhawks */
 4542                         if (!sli4->config.dual_ulp_capable) {
 4543                                 q->doorbell_offset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].off;
 4544                                 q->doorbell_rset = regmap[SLI4_REG_IO_WQ_DOORBELL][sli4->if_type].rset;
 4545                         }
 4546                         break;
 4547                 default:
 4548                         break;
 4549                 }
 4550         }
 4551 
 4552         return 0;
 4553 }
 4554 
 4555 /**
 4556  * @ingroup sli
 4557  * @brief Get queue entry size.
 4558  *
 4559  * Get queue entry size given queue type.
 4560  *
 4561  * @param sli4 SLI context
 4562  * @param qtype Type for which the entry size is returned.
 4563  *
 4564  * @return Returns > 0 on success (queue entry size), or a negative value on failure.
 4565  */
 4566 int32_t
 4567 sli_get_queue_entry_size(sli4_t *sli4, uint32_t qtype)
 4568 {
 4569         uint32_t        size = 0;
 4570 
 4571         if (!sli4) {
 4572                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
 4573                 return -1;
 4574         }
 4575 
 4576         switch (qtype) {
 4577         case SLI_QTYPE_EQ:
 4578                 size = sizeof(uint32_t);
 4579                 break;
 4580         case SLI_QTYPE_CQ:
 4581                 size = 16;
 4582                 break;
 4583         case SLI_QTYPE_MQ:
 4584                 size = 256;
 4585                 break;
 4586         case SLI_QTYPE_WQ:
 4587                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4588                         size = sli4->config.wqe_size;
 4589                 } else {
 4590                         /* TODO */
 4591                         ocs_log_test(sli4->os, "unsupported queue entry size\n");
 4592                         return -1;
 4593                 }
 4594                 break;
 4595         case SLI_QTYPE_RQ:
 4596                 size = SLI4_FCOE_RQE_SIZE;
 4597                 break;
 4598         default:
 4599                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
 4600                 return -1;
 4601         }
 4602         return size;
 4603 }
 4604 
 4605 /**
 4606  * @ingroup sli
 4607  * @brief Modify the delay timer for all the EQs
 4608  *
 4609  * @param sli4 SLI context.
 4610  * @param eq Array of EQs.
 4611  * @param num_eq Count of EQs.
 4612  * @param shift Phase shift for staggering interrupts.
 4613  * @param delay_mult Delay multiplier for limiting interrupt frequency.
 4614  *
 4615  * @return Returns 0 on success, or -1 otherwise.
 4616  */
 4617 int32_t
 4618 sli_eq_modify_delay(sli4_t *sli4, sli4_queue_t *eq, uint32_t num_eq, uint32_t shift, uint32_t delay_mult)
 4619 {
 4620 
 4621         sli_cmd_common_modify_eq_delay(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, eq, num_eq, shift, delay_mult);
 4622 
 4623         if (sli_bmbx_command(sli4)) {
 4624                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail (MODIFY EQ DELAY)\n");
 4625                 return -1;
 4626         }
 4627         if (sli_res_sli_config(sli4->bmbx.virt)) {
 4628                 ocs_log_err(sli4->os, "bad status MODIFY EQ DELAY\n");
 4629                 return -1;
 4630         }
 4631 
 4632         return 0;
 4633 }
 4634 
 4635 /**
 4636  * @ingroup sli
 4637  * @brief Allocate a queue.
 4638  *
 4639  * @par Description
 4640  * Allocates DMA memory and configures the requested queue type.
 4641  *
 4642  * @param sli4 SLI context.
 4643  * @param qtype Type of queue to create.
 4644  * @param q Pointer to the queue object.
 4645  * @param n_entries Number of entries to allocate.
 4646  * @param assoc Associated queue (that is, the EQ for a CQ, the CQ for a MQ, and so on).
 4647  * @param ulp The ULP to bind, which is only used for WQ and RQs
 4648  *
 4649  * @return Returns 0 on success, or -1 otherwise.
 4650  */
 4651 int32_t
 4652 sli_queue_alloc(sli4_t *sli4, uint32_t qtype, sli4_queue_t *q, uint32_t n_entries,
 4653                 sli4_queue_t *assoc, uint16_t ulp)
 4654 {
 4655         int32_t         size;
 4656         uint32_t        align = 0;
 4657         sli4_create_q_fn_t create = NULL;
 4658 
 4659         if (!sli4 || !q) {
 4660                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
 4661                 return -1;
 4662         }
 4663 
 4664         /* get queue size */
 4665         size = sli_get_queue_entry_size(sli4, qtype);
 4666         if (size < 0)
 4667                 return -1;
 4668         align = SLI_PAGE_SIZE;
 4669 
 4670         switch (qtype) {
 4671         case SLI_QTYPE_EQ:
 4672                 create = sli_cmd_common_create_eq;
 4673                 break;
 4674         case SLI_QTYPE_CQ:
 4675                 create = sli_cmd_common_create_cq;
 4676                 break;
 4677         case SLI_QTYPE_MQ:
 4678                 /* Validate the number of entries */
 4679                 switch (n_entries) {
 4680                 case 16:
 4681                 case 32:
 4682                 case 64:
 4683                 case 128:
 4684                         break;
 4685                 default:
 4686                         ocs_log_test(sli4->os, "illegal n_entries value %d for MQ\n", n_entries);
 4687                         return -1;
 4688                 }
 4689                 assoc->u.flag.is_mq = TRUE;
 4690                 create = sli_cmd_common_create_mq_ext;
 4691                 break;
 4692         case SLI_QTYPE_WQ:
 4693                 if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4694                         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
 4695                                 create = sli_cmd_fcoe_wq_create;
 4696                         } else {
 4697                                 create = sli_cmd_fcoe_wq_create_v1;
 4698                         }
 4699                 } else {
 4700                         /* TODO */
 4701                         ocs_log_test(sli4->os, "unsupported WQ create\n");
 4702                         return -1;
 4703                 }
 4704                 break;
 4705         default:
 4706                 ocs_log_test(sli4->os, "unknown queue type %d\n", qtype);
 4707                 return -1;
 4708         }
 4709 
 4710         if (__sli_queue_init(sli4, q, qtype, size, n_entries, align)) {
 4711                 ocs_log_err(sli4->os, "%s allocation failed\n", SLI_QNAME[qtype]);
 4712                 return -1;
 4713         }
 4714 
 4715         if (create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma, assoc ? assoc->id : 0, ulp)) {
 4716                 if (__sli_create_queue(sli4, q)) {
 4717                         ocs_log_err(sli4->os, "create %s failed\n", SLI_QNAME[qtype]);
 4718                         return -1;
 4719                 }
 4720                 q->ulp = ulp;
 4721         } else {
 4722                 ocs_log_err(sli4->os, "cannot create %s\n", SLI_QNAME[qtype]);
 4723                 return -1;
 4724         }
 4725 
 4726         return 0;
 4727 }
 4728 
 4729 /**
 4730  * @ingroup sli
 4731  * @brief Allocate a c queue set.
 4732  *
 4733  * @param sli4 SLI context.
 4734  * @param num_cqs to create
 4735  * @param qs Pointers to the queue objects.
 4736  * @param n_entries Number of entries to allocate per CQ.
 4737  * @param eqs Associated event queues
 4738  *
 4739  * @return Returns 0 on success, or -1 otherwise.
 4740  */
 4741 int32_t
 4742 sli_cq_alloc_set(sli4_t *sli4, sli4_queue_t *qs[], uint32_t num_cqs,
 4743                  uint32_t n_entries, sli4_queue_t *eqs[])
 4744 {
 4745         uint32_t i, offset = 0,  page_bytes = 0, payload_size, cmd_size = 0;
 4746         uint32_t p = 0, page_size = 0, n_cqe = 0, num_pages_cq;
 4747         uintptr_t addr;
 4748         ocs_dma_t dma;
 4749         sli4_req_common_create_cq_set_v0_t  *req = NULL;
 4750         sli4_res_common_create_queue_set_t *res = NULL;
 4751 
 4752         if (!sli4) {
 4753                 ocs_log_err(NULL, "bad parameter sli4=%p\n", sli4);
 4754                 return -1;
 4755         }
 4756 
 4757         memset(&dma, 0, sizeof(dma));
 4758 
 4759         /* Align the queue DMA memory */
 4760         for (i = 0; i < num_cqs; i++) {
 4761                 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_CQ, SLI4_CQE_BYTES,
 4762                         n_entries, SLI_PAGE_SIZE)) {
 4763                         ocs_log_err(sli4->os, "Queue init failed.\n");
 4764                         goto error;
 4765                 }
 4766         }
 4767 
 4768         n_cqe = qs[0]->dma.size / SLI4_CQE_BYTES;
 4769         switch (n_cqe) {
 4770         case 256:
 4771         case 512:
 4772         case 1024:
 4773         case 2048:
 4774                 page_size = 1;
 4775                 break;
 4776         case 4096:
 4777                 page_size = 2;
 4778                 break;
 4779         default:
 4780                 return -1;
 4781         }
 4782 
 4783         page_bytes = page_size * SLI_PAGE_SIZE;
 4784         num_pages_cq = sli_page_count(qs[0]->dma.size, page_bytes);
 4785         cmd_size = sizeof(sli4_req_common_create_cq_set_v0_t) + (8 * num_pages_cq * num_cqs);
 4786         payload_size = max((size_t)cmd_size, sizeof(sli4_res_common_create_queue_set_t));
 4787 
 4788         if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
 4789                 ocs_log_err(sli4->os, "DMA allocation failed\n");
 4790                 goto error;
 4791         }
 4792         ocs_memset(dma.virt, 0, payload_size);
 4793 
 4794         if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, 
 4795                         payload_size, &dma) == -1) {
 4796                 goto error;
 4797         }
 4798 
 4799         /* Fill the request structure */
 4800 
 4801         req = (sli4_req_common_create_cq_set_v0_t *)((uint8_t *)dma.virt);
 4802         req->hdr.opcode = SLI4_OPC_COMMON_CREATE_CQ_SET;
 4803         req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 4804         req->hdr.version = 0;
 4805         req->hdr.request_length = cmd_size - sizeof(sli4_req_hdr_t);
 4806         req->page_size = page_size;
 4807 
 4808         req->num_pages = num_pages_cq;
 4809         switch (req->num_pages) {
 4810         case 1:
 4811                 req->cqecnt = SLI4_CQ_CNT_256;
 4812                 break;
 4813         case 2:
 4814                 req->cqecnt = SLI4_CQ_CNT_512;
 4815                 break;
 4816         case 4:
 4817                 req->cqecnt = SLI4_CQ_CNT_1024;
 4818                 break;
 4819         case 8:
 4820                 req->cqecnt = SLI4_CQ_CNT_LARGE;
 4821                 req->cqe_count = n_cqe;
 4822                 break;
 4823         default:
 4824                 ocs_log_test(sli4->os, "num_pages %d not valid\n", req->num_pages);
 4825                 goto error;
 4826         }
 4827 
 4828         req->evt = TRUE;
 4829         req->valid = TRUE;
 4830         req->arm = FALSE;
 4831         req->num_cq_req = num_cqs;
 4832 
 4833         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 4834                 req->autovalid = TRUE;
 4835 
 4836         /* Fill page addresses of all the CQs. */
 4837         for (i = 0; i < num_cqs; i++) {
 4838                 req->eq_id[i] = eqs[i]->id;
 4839                 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += page_bytes) {
 4840                         req->page_physical_address[offset].low = ocs_addr32_lo(addr);
 4841                         req->page_physical_address[offset].high = ocs_addr32_hi(addr);
 4842                         offset++;
 4843                 }
 4844         }
 4845 
 4846         if (sli_bmbx_command(sli4)) {
 4847                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail CQSet\n");
 4848                 goto error;
 4849         }
 4850 
 4851         res = (void *)((uint8_t *)dma.virt);
 4852         if (res->hdr.status) {
 4853                 ocs_log_err(sli4->os, "bad create CQSet status=%#x addl=%#x\n",
 4854                         res->hdr.status, res->hdr.additional_status);
 4855                 goto error;
 4856         } else {
 4857                 /* Check if we got all requested CQs. */
 4858                 if (res->num_q_allocated != num_cqs) {
 4859                         ocs_log_crit(sli4->os, "Requested count CQs doesnt match.\n");
 4860                         goto error;
 4861                 }
 4862 
 4863                 /* Fill the resp cq ids. */
 4864                 for (i = 0; i < num_cqs; i++) {
 4865                         qs[i]->id = res->q_id + i;
 4866                         qs[i]->doorbell_offset = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].off;
 4867                         qs[i]->doorbell_rset   = regmap[SLI4_REG_CQ_DOORBELL][sli4->if_type].rset;
 4868                 }
 4869         }
 4870 
 4871         ocs_dma_free(sli4->os, &dma);
 4872 
 4873         return 0;
 4874 
 4875 error:
 4876         for (i = 0; i < num_cqs; i++) {
 4877                 if (qs[i]->dma.size) {
 4878                         ocs_dma_free(sli4->os, &qs[i]->dma);
 4879                 }
 4880         }
 4881 
 4882         if (dma.size) {
 4883                 ocs_dma_free(sli4->os, &dma);
 4884         }
 4885 
 4886         return -1;
 4887 }
 4888 
 4889 /**
 4890  * @ingroup sli
 4891  * @brief Free a queue.
 4892  *
 4893  * @par Description
 4894  * Frees DMA memory and de-registers the requested queue.
 4895  *
 4896  * @param sli4 SLI context.
 4897  * @param q Pointer to the queue object.
 4898  * @param destroy_queues Non-zero if the mailbox commands should be sent to destroy the queues.
 4899  * @param free_memory Non-zero if the DMA memory associated with the queue should be freed.
 4900  *
 4901  * @return Returns 0 on success, or -1 otherwise.
 4902  */
 4903 int32_t
 4904 sli_queue_free(sli4_t *sli4, sli4_queue_t *q, uint32_t destroy_queues, uint32_t free_memory)
 4905 {
 4906         sli4_destroy_q_fn_t destroy = NULL;
 4907         int32_t         rc = -1;
 4908 
 4909         if (!sli4 || !q) {
 4910                 ocs_log_err(NULL, "bad parameter sli4=%p q=%p\n", sli4, q);
 4911                 return -1;
 4912         }
 4913 
 4914         if (destroy_queues) {
 4915                 switch (q->type) {
 4916                 case SLI_QTYPE_EQ:
 4917                         destroy = sli_cmd_common_destroy_eq;
 4918                         break;
 4919                 case SLI_QTYPE_CQ:
 4920                         destroy = sli_cmd_common_destroy_cq;
 4921                         break;
 4922                 case SLI_QTYPE_MQ:
 4923                         destroy = sli_cmd_common_destroy_mq;
 4924                         break;
 4925                 case SLI_QTYPE_WQ:
 4926                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4927                                 destroy = sli_cmd_fcoe_wq_destroy;
 4928                         } else {
 4929                                 /* TODO */
 4930                                 ocs_log_test(sli4->os, "unsupported WQ destroy\n");
 4931                                 return -1;
 4932                         }
 4933                         break;
 4934                 case SLI_QTYPE_RQ:
 4935                         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 4936                                 destroy = sli_cmd_fcoe_rq_destroy;
 4937                         } else {
 4938                                 /* TODO */
 4939                                 ocs_log_test(sli4->os, "unsupported RQ destroy\n");
 4940                                 return -1;
 4941                         }
 4942                         break;
 4943                 default:
 4944                         ocs_log_test(sli4->os, "bad queue type %d\n",
 4945                                         q->type);
 4946                         return -1;
 4947                 }
 4948 
 4949                 /*
 4950                  * Destroying queues makes BE3 sad (version 0 interface type). Rely
 4951                  * on COMMON_FUNCTION_RESET to free host allocated queue resources
 4952                  * inside the SLI Port.
 4953                  */
 4954                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 4955                         destroy = NULL;
 4956                 }
 4957 
 4958                 /* Destroy the queue if the operation is defined */
 4959                 if (destroy && destroy(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, q->id)) {
 4960                         sli4_res_hdr_t  *res = NULL;
 4961 
 4962                         if (sli_bmbx_command(sli4)){
 4963                                 ocs_log_crit(sli4->os, "bootstrap mailbox write fail destroy %s\n",
 4964                                                 SLI_QNAME[q->type]);
 4965                         } else if (sli_res_sli_config(sli4->bmbx.virt)) {
 4966                                 ocs_log_err(sli4->os, "bad status destroy %s\n", SLI_QNAME[q->type]);
 4967                         } else {
 4968                                 res = (void *)((uint8_t *)sli4->bmbx.virt +
 4969                                                 offsetof(sli4_cmd_sli_config_t, payload));
 4970 
 4971                                 if (res->status) {
 4972                                         ocs_log_err(sli4->os, "bad destroy %s status=%#x addl=%#x\n",
 4973                                                         SLI_QNAME[q->type],
 4974                                                         res->status, res->additional_status);
 4975                                 } else {
 4976                                         rc = 0;
 4977                                 }
 4978                         }
 4979                 }
 4980         }
 4981 
 4982         if (free_memory) {
 4983                 ocs_lock_free(&q->lock);
 4984 
 4985                 if (ocs_dma_free(sli4->os, &q->dma)) {
 4986                         ocs_log_err(sli4->os, "%s queue ID %d free failed\n",
 4987                                     SLI_QNAME[q->type], q->id);
 4988                         rc = -1;
 4989                 }
 4990         }
 4991 
 4992         return rc;
 4993 }
 4994 
 4995 int32_t
 4996 sli_queue_reset(sli4_t *sli4, sli4_queue_t *q)
 4997 {
 4998 
 4999         ocs_lock(&q->lock);
 5000 
 5001         q->index = 0;
 5002         q->n_posted = 0;
 5003 
 5004         if (SLI_QTYPE_MQ == q->type) {
 5005                 q->u.r_idx = 0;
 5006         }
 5007 
 5008         if (q->dma.virt != NULL) {
 5009                 ocs_memset(q->dma.virt, 0, (q->size * (uint64_t)q->length));
 5010         }
 5011 
 5012         ocs_unlock(&q->lock);
 5013 
 5014         return 0;
 5015 }
 5016 
 5017 /**
 5018  * @ingroup sli
 5019  * @brief Check if the given queue is empty.
 5020  *
 5021  * @par Description
 5022  * If the valid bit of the current entry is unset, the queue is empty.
 5023  *
 5024  * @param sli4 SLI context.
 5025  * @param q Pointer to the queue object.
 5026  *
 5027  * @return Returns TRUE if empty, or FALSE otherwise.
 5028  */
 5029 int32_t
 5030 sli_queue_is_empty(sli4_t *sli4, sli4_queue_t *q)
 5031 {
 5032         int32_t         rc = TRUE;
 5033         uint8_t         *qe = q->dma.virt;
 5034 
 5035         ocs_lock(&q->lock);
 5036 
 5037         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
 5038 
 5039         qe += q->index * q->size;
 5040 
 5041         rc = !sli_queue_entry_is_valid(q, qe, FALSE);
 5042 
 5043         ocs_unlock(&q->lock);
 5044 
 5045         return rc;
 5046 }
 5047 
 5048 /**
 5049  * @ingroup sli
 5050  * @brief Arm an EQ.
 5051  *
 5052  * @param sli4 SLI context.
 5053  * @param q Pointer to queue object.
 5054  * @param arm If TRUE, arm the EQ.
 5055  *
 5056  * @return Returns 0 on success, or non-zero otherwise.
 5057  */
 5058 int32_t
 5059 sli_queue_eq_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
 5060 {
 5061         uint32_t        val = 0;
 5062 
 5063         ocs_lock(&q->lock);
 5064         if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 5065                 val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm);
 5066         else
 5067                 val = sli_eq_doorbell(q->n_posted, q->id, arm);
 5068 
 5069         ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 5070         q->n_posted = 0;
 5071         ocs_unlock(&q->lock);
 5072 
 5073         return 0;
 5074 }
 5075 
 5076 /**
 5077  * @ingroup sli
 5078  * @brief Arm a queue.
 5079  *
 5080  * @param sli4 SLI context.
 5081  * @param q Pointer to queue object.
 5082  * @param arm If TRUE, arm the queue.
 5083  *
 5084  * @return Returns 0 on success, or non-zero otherwise.
 5085  */
 5086 int32_t
 5087 sli_queue_arm(sli4_t *sli4, sli4_queue_t *q, uint8_t arm)
 5088 {
 5089         uint32_t        val = 0;
 5090 
 5091         ocs_lock(&q->lock);
 5092 
 5093         switch (q->type) {
 5094         case SLI_QTYPE_EQ:
 5095                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 5096                         val = sli_iftype6_eq_doorbell(q->n_posted, q->id, arm);
 5097                 else
 5098                         val = sli_eq_doorbell(q->n_posted, q->id, arm);
 5099                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 5100                 q->n_posted = 0;
 5101                 break;
 5102         case SLI_QTYPE_CQ:
 5103                 if (sli4->if_type == SLI4_IF_TYPE_LANCER_G7)
 5104                         val = sli_iftype6_cq_doorbell(q->n_posted, q->id, arm);
 5105                 else
 5106                         val = sli_cq_doorbell(q->n_posted, q->id, arm);
 5107                 ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
 5108                 q->n_posted = 0;
 5109                 break;
 5110         default:
 5111                 ocs_log_test(sli4->os, "should only be used for EQ/CQ, not %s\n",
 5112                              SLI_QNAME[q->type]);
 5113         }
 5114 
 5115         ocs_unlock(&q->lock);
 5116 
 5117         return 0;
 5118 }
 5119 
 5120 /**
 5121  * @ingroup sli
 5122  * @brief Write an entry to the queue object.
 5123  *
 5124  * Note: Assumes the q->lock will be locked and released by the caller.
 5125  *
 5126  * @param sli4 SLI context.
 5127  * @param q Pointer to the queue object.
 5128  * @param entry Pointer to the entry contents.
 5129  *
 5130  * @return Returns queue index on success, or negative error value otherwise.
 5131  */
 5132 int32_t
 5133 _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 5134 {
 5135         int32_t         rc = 0;
 5136         uint8_t         *qe = q->dma.virt;
 5137         uint32_t        qindex;
 5138 
 5139         qindex = q->index;
 5140         qe += q->index * q->size;
 5141 
 5142         if (entry) {
 5143                 if ((SLI_QTYPE_WQ == q->type) && sli4->config.perf_wq_id_association) {
 5144                         sli_set_wq_id_association(entry, q->id);
 5145                 }
 5146 #if defined(OCS_INCLUDE_DEBUG)
 5147                 switch (q->type) {
 5148                 case SLI_QTYPE_WQ: {
 5149                         ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, "wqe", entry, q->size);
 5150                         break;
 5151                 }
 5152                 case SLI_QTYPE_MQ:
 5153                         /* Note: we don't really need to dump the whole 
 5154                          * 256 bytes, just do 64 */
 5155                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mqe outbound", entry, 64);
 5156                         break;
 5157 
 5158                 default:
 5159                         break;
 5160                 }
 5161 #endif
 5162                 ocs_memcpy(qe, entry, q->size);
 5163                 q->n_posted = 1;
 5164         }
 5165 
 5166         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5167 
 5168         rc = sli_queue_doorbell(sli4, q);
 5169 
 5170         q->index = (q->index + q->n_posted) & (q->length - 1);
 5171         q->n_posted = 0;
 5172 
 5173         if (rc < 0) {
 5174                 /* failure */
 5175                 return rc;
 5176         } else if (rc > 0) {
 5177                 /* failure, but we need to return a negative value on failure */
 5178                 return -rc;
 5179         } else {
 5180                 return qindex;
 5181         }
 5182 }
 5183 
 5184 /**
 5185  * @ingroup sli
 5186  * @brief Write an entry to the queue object.
 5187  *
 5188  * Note: Assumes the q->lock will be locked and released by the caller.
 5189  *
 5190  * @param sli4 SLI context.
 5191  * @param q Pointer to the queue object.
 5192  * @param entry Pointer to the entry contents.
 5193  *
 5194  * @return Returns queue index on success, or negative error value otherwise.
 5195  */
 5196 int32_t
 5197 sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 5198 {
 5199         int32_t rc;
 5200 
 5201         ocs_lock(&q->lock);
 5202                 rc = _sli_queue_write(sli4, q, entry);
 5203         ocs_unlock(&q->lock);
 5204 
 5205         return rc;
 5206 }
 5207 
 5208 /**
 5209  * @brief Check if the current queue entry is valid.
 5210  *
 5211  * @param q Pointer to the queue object.
 5212  * @param qe Pointer to the queue entry.
 5213  * @param clear Boolean to clear valid bit.
 5214  *
 5215  * @return Returns TRUE if the entry is valid, or FALSE otherwise.
 5216  */
 5217 static uint8_t
 5218 sli_queue_entry_is_valid(sli4_queue_t *q, uint8_t *qe, uint8_t clear)
 5219 {
 5220         uint8_t         valid = FALSE;
 5221         uint8_t         valid_bit_set = 0;
 5222 
 5223         switch (q->type) {
 5224         case SLI_QTYPE_EQ:
 5225                 valid = (((sli4_eqe_t *)qe)->vld == q->phase) ? 1 : 0;
 5226                 if (valid && clear) {
 5227                         ((sli4_eqe_t *)qe)->vld = 0;
 5228                 }
 5229                 break;
 5230         case SLI_QTYPE_CQ:
 5231                 /*
 5232                  * For both MCQE and WCQE/RCQE, the valid bit
 5233                  * is bit 31 of dword 3 (0 based)
 5234                  */
 5235                 valid_bit_set = (qe[15] & 0x80) != 0;
 5236                 if (valid_bit_set == q->phase)
 5237                         valid = 1;
 5238 
 5239                 if (valid & clear) {
 5240                         qe[15] &= ~0x80;
 5241                 }
 5242                 break;
 5243         case SLI_QTYPE_MQ:
 5244                 valid = q->index != q->u.r_idx;
 5245                 break;
 5246         case SLI_QTYPE_RQ:
 5247                 valid = TRUE;
 5248                 clear = FALSE;
 5249                 break;
 5250         default:
 5251                 ocs_log_test(NULL, "doesn't handle type=%#x\n", q->type);
 5252         }
 5253 
 5254         if (clear) {
 5255 
 5256                 ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5257         }
 5258 
 5259         return valid;
 5260 }
 5261 
 5262 /**
 5263  * @ingroup sli
 5264  * @brief Read an entry from the queue object.
 5265  *
 5266  * @param sli4 SLI context.
 5267  * @param q Pointer to the queue object.
 5268  * @param entry Destination pointer for the queue entry contents.
 5269  *
 5270  * @return Returns 0 on success, or non-zero otherwise.
 5271  */
 5272 int32_t
 5273 sli_queue_read(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
 5274 {
 5275         int32_t         rc = 0;
 5276         uint8_t         *qe = q->dma.virt;
 5277         uint32_t        *qindex = NULL;
 5278 
 5279         uint8_t         clear = (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) ?  FALSE : TRUE;
 5280         if (SLI_QTYPE_MQ == q->type) {
 5281                 qindex = &q->u.r_idx;
 5282         } else {
 5283                 qindex = &q->index;
 5284         }
 5285 
 5286         ocs_lock(&q->lock);
 5287 
 5288         ocs_dma_sync(&q->dma, OCS_DMASYNC_POSTREAD);
 5289 
 5290         qe += *qindex * q->size;
 5291 
 5292         if (!sli_queue_entry_is_valid(q, qe, clear)) {
 5293                 ocs_unlock(&q->lock);
 5294                 return -1;
 5295         }
 5296 
 5297         if (entry) {
 5298                 ocs_memcpy(entry, qe, q->size);
 5299 #if defined(OCS_INCLUDE_DEBUG)
 5300                 switch(q->type) {
 5301                 case SLI_QTYPE_CQ:
 5302                         ocs_dump32(OCS_DEBUG_ENABLE_CQ_DUMP, sli4->os, "cq", entry, q->size);
 5303                         break;
 5304                 case SLI_QTYPE_MQ:
 5305                         ocs_dump32(OCS_DEBUG_ENABLE_MQ_DUMP, sli4->os, "mq Compl", entry, 64);
 5306                         break;
 5307                 case SLI_QTYPE_EQ:
 5308                         ocs_dump32(OCS_DEBUG_ENABLE_EQ_DUMP, sli4->os, "eq Compl", entry, q->size);
 5309                         break;
 5310                 default:
 5311                         break;
 5312                 }
 5313 #endif
 5314         }
 5315 
 5316         switch (q->type) {
 5317                 case SLI_QTYPE_EQ:
 5318                 case SLI_QTYPE_CQ:
 5319                 case SLI_QTYPE_MQ:
 5320                         *qindex = (*qindex + 1) & (q->length - 1);
 5321                         if (SLI_QTYPE_MQ != q->type) {
 5322                                 q->n_posted++;
 5323                                 /*
 5324                                  * For prism, the phase value will be used to check the validity of eq/cq entries.
 5325                                  * The value toggles after a complete sweep through the queue.
 5326                                  */
 5327                                 if ((SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4)) && (*qindex == 0)) {
 5328                                         q->phase ^= (uint16_t) 0x1;
 5329                                 }
 5330                         }
 5331                         break;
 5332                 default:
 5333                         /* reads don't update the index */
 5334                         break;
 5335         }
 5336 
 5337         ocs_unlock(&q->lock);
 5338 
 5339         return rc;
 5340 }
 5341 
 5342 int32_t
 5343 sli_queue_index(sli4_t *sli4, sli4_queue_t *q)
 5344 {
 5345 
 5346         if (q) {
 5347                 return q->index;
 5348         } else {
 5349                 return -1;
 5350         }
 5351 }
 5352 
 5353 int32_t
 5354 sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
 5355 {
 5356         int32_t rc;
 5357 
 5358         ocs_lock(&q->lock);
 5359                 rc = _sli_queue_poke(sli4, q, index, entry);
 5360         ocs_unlock(&q->lock);
 5361 
 5362         return rc;
 5363 }
 5364 
 5365 int32_t
 5366 _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
 5367 {
 5368         int32_t         rc = 0;
 5369         uint8_t         *qe = q->dma.virt;
 5370 
 5371         if (index >= q->length) {
 5372                 return -1;
 5373         }
 5374 
 5375         qe += index * q->size;
 5376 
 5377         if (entry) {
 5378                 ocs_memcpy(qe, entry, q->size);
 5379         }
 5380 
 5381         ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
 5382 
 5383         return rc;
 5384 }
 5385 
 5386 /**
 5387  * @ingroup sli
 5388  * @brief Allocate SLI Port resources.
 5389  *
 5390  * @par Description
 5391  * Allocate port-related resources, such as VFI, RPI, XRI, and so on.
 5392  * Resources are modeled using extents, regardless of whether the underlying
 5393  * device implements resource extents. If the device does not implement
 5394  * extents, the SLI layer models this as a single (albeit large) extent.
 5395  *
 5396  * @param sli4 SLI context.
 5397  * @param rtype Resource type (for example, RPI or XRI)
 5398  * @param rid Allocated resource ID.
 5399  * @param index Index into the bitmap.
 5400  *
 5401  * @return Returns 0 on success, or a non-zero value on failure.
 5402  */
 5403 int32_t
 5404 sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
 5405 {
 5406         int32_t         rc = 0;
 5407         uint32_t        size;
 5408         uint32_t        extent_idx;
 5409         uint32_t        item_idx;
 5410         int             status;
 5411 
 5412         *rid = UINT32_MAX;
 5413         *index = UINT32_MAX;
 5414 
 5415         switch (rtype) {
 5416         case SLI_RSRC_FCOE_VFI:
 5417         case SLI_RSRC_FCOE_VPI:
 5418         case SLI_RSRC_FCOE_RPI:
 5419         case SLI_RSRC_FCOE_XRI:
 5420                 status = ocs_bitmap_find(sli4->config.extent[rtype].use_map,
 5421                                 sli4->config.extent[rtype].map_size);
 5422                 if (status < 0) {
 5423                         ocs_log_err(sli4->os, "out of resource %d (alloc=%d)\n",
 5424                                         rtype, sli4->config.extent[rtype].n_alloc);
 5425                         rc = -1;
 5426                         break;
 5427                 } else {
 5428                         *index = status;
 5429                 }
 5430 
 5431                 size = sli4->config.extent[rtype].size;
 5432 
 5433                 extent_idx = *index / size;
 5434                 item_idx   = *index % size;
 5435 
 5436                 *rid = sli4->config.extent[rtype].base[extent_idx] + item_idx;
 5437 
 5438                 sli4->config.extent[rtype].n_alloc++;
 5439                 break;
 5440         default:
 5441                 rc = -1;
 5442         }
 5443 
 5444         return rc;
 5445 }
 5446 
 5447 /**
 5448  * @ingroup sli
 5449  * @brief Free the SLI Port resources.
 5450  *
 5451  * @par Description
 5452  * Free port-related resources, such as VFI, RPI, XRI, and so. See discussion of
 5453  * "extent" usage in sli_resource_alloc.
 5454  *
 5455  * @param sli4 SLI context.
 5456  * @param rtype Resource type (for example, RPI or XRI).
 5457  * @param rid Allocated resource ID.
 5458  *
 5459  * @return Returns 0 on success, or a non-zero value on failure.
 5460  */
 5461 int32_t
 5462 sli_resource_free(sli4_t *sli4, sli4_resource_e rtype, uint32_t rid)
 5463 {
 5464         int32_t         rc = -1;
 5465         uint32_t        x;
 5466         uint32_t        size, *base;
 5467 
 5468         switch (rtype) {
 5469         case SLI_RSRC_FCOE_VFI:
 5470         case SLI_RSRC_FCOE_VPI:
 5471         case SLI_RSRC_FCOE_RPI:
 5472         case SLI_RSRC_FCOE_XRI:
 5473                 /*
 5474                  * Figure out which extent contains the resource ID. I.e. find
 5475                  * the extent such that
 5476                  *   extent->base <= resource ID < extent->base + extent->size
 5477                  */
 5478                 base = sli4->config.extent[rtype].base;
 5479                 size = sli4->config.extent[rtype].size;
 5480 
 5481                 /*
 5482                  * In the case of FW reset, this may be cleared but the force_free path will
 5483                  * still attempt to free the resource. Prevent a NULL pointer access.
 5484                  */
 5485                 if (base != NULL) {
 5486                         for (x = 0; x < sli4->config.extent[rtype].number; x++) {
 5487                                 if ((rid >= base[x]) && (rid < (base[x] + size))) {
 5488                                         rid -= base[x];
 5489                                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map,
 5490                                                          (x * size) + rid);
 5491                                         rc = 0;
 5492                                         break;
 5493                                 }
 5494                         }
 5495                 }
 5496                 break;
 5497         default:
 5498                 ;
 5499         }
 5500 
 5501         return rc;
 5502 }
 5503 
 5504 int32_t
 5505 sli_resource_reset(sli4_t *sli4, sli4_resource_e rtype)
 5506 {
 5507         int32_t         rc = -1;
 5508         uint32_t        i;
 5509 
 5510         switch (rtype) {
 5511         case SLI_RSRC_FCOE_VFI:
 5512         case SLI_RSRC_FCOE_VPI:
 5513         case SLI_RSRC_FCOE_RPI:
 5514         case SLI_RSRC_FCOE_XRI:
 5515                 for (i = 0; i < sli4->config.extent[rtype].map_size; i++) {
 5516                         ocs_bitmap_clear(sli4->config.extent[rtype].use_map, i);
 5517                 }
 5518                 rc = 0;
 5519                 break;
 5520         default:
 5521                 ;
 5522         }
 5523 
 5524         return rc;
 5525 }
 5526 
 5527 /**
 5528  * @ingroup sli
 5529  * @brief Parse an EQ entry to retrieve the CQ_ID for this event.
 5530  *
 5531  * @param sli4 SLI context.
 5532  * @param buf Pointer to the EQ entry.
 5533  * @param cq_id CQ_ID for this entry (only valid on success).
 5534  *
 5535  * @return
 5536  * - 0 if success.
 5537  * - < 0 if error.
 5538  * - > 0 if firmware detects EQ overflow.
 5539  */
 5540 int32_t
 5541 sli_eq_parse(sli4_t *sli4, uint8_t *buf, uint16_t *cq_id)
 5542 {
 5543         sli4_eqe_t      *eqe = (void *)buf;
 5544         int32_t         rc = 0;
 5545 
 5546         if (!sli4 || !buf || !cq_id) {
 5547                 ocs_log_err(NULL, "bad parameters sli4=%p buf=%p cq_id=%p\n",
 5548                                 sli4, buf, cq_id);
 5549                 return -1;
 5550         }
 5551 
 5552         switch (eqe->major_code) {
 5553         case SLI4_MAJOR_CODE_STANDARD:
 5554                 *cq_id = eqe->resource_id;
 5555                 break;
 5556         case SLI4_MAJOR_CODE_SENTINEL:
 5557                 ocs_log_debug(sli4->os, "sentinel EQE\n");
 5558                 rc = 1;
 5559                 break;
 5560         default:
 5561                 ocs_log_test(sli4->os, "Unsupported EQE: major %x minor %x\n",
 5562                                 eqe->major_code, eqe->minor_code);
 5563                 rc = -1;
 5564         }
 5565 
 5566         return rc;
 5567 }
 5568 
 5569 /**
 5570  * @ingroup sli
 5571  * @brief Parse a CQ entry to retrieve the event type and the associated queue.
 5572  *
 5573  * @param sli4 SLI context.
 5574  * @param cq CQ to process.
 5575  * @param cqe Pointer to the CQ entry.
 5576  * @param etype CQ event type.
 5577  * @param q_id Queue ID associated with this completion message
 5578  * (that is, MQ_ID, RQ_ID, and so on).
 5579  *
 5580  * @return
 5581  * - 0 if call completed correctly and CQE status is SUCCESS.
 5582  * - -1 if call failed (no CQE status).
 5583  * - Other value if call completed correctly and return value is a CQE status value.
 5584  */
 5585 int32_t
 5586 sli_cq_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
 5587                 uint16_t *q_id)
 5588 {
 5589         int32_t rc = 0;
 5590 
 5591         if (!sli4 || !cq || !cqe || !etype) {
 5592                 ocs_log_err(NULL, "bad parameters sli4=%p cq=%p cqe=%p etype=%p q_id=%p\n",
 5593                             sli4, cq, cqe, etype, q_id);
 5594                 return -1;
 5595         }
 5596 
 5597         if (cq->u.flag.is_mq) {
 5598                 sli4_mcqe_t     *mcqe = (void *)cqe;
 5599 
 5600                 if (mcqe->ae) {
 5601                         *etype = SLI_QENTRY_ASYNC;
 5602                 } else {
 5603                         *etype = SLI_QENTRY_MQ;
 5604                         rc = sli_cqe_mq(mcqe);
 5605                 }
 5606                 *q_id = -1;
 5607         } else if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5608                 rc = sli_fc_cqe_parse(sli4, cq, cqe, etype, q_id);
 5609         } else {
 5610                 ocs_log_test(sli4->os, "implement CQE parsing type = %#x\n",
 5611                              sli4->port_type);
 5612                 rc = -1;
 5613         }
 5614 
 5615         return rc;
 5616 }
 5617 
 5618 /**
 5619  * @ingroup sli
 5620  * @brief Cause chip to enter an unrecoverable error state.
 5621  *
 5622  * @par Description
 5623  * Cause chip to enter an unrecoverable error state. This is
 5624  * used when detecting unexpected FW behavior so FW can be
 5625  * hwted from the driver as soon as error is detected.
 5626  *
 5627  * @param sli4 SLI context.
 5628  * @param dump Generate dump as part of reset.
 5629  *
 5630  * @return Returns 0 if call completed correctly, or -1 if call failed (unsupported chip).
 5631  */
 5632 int32_t sli_raise_ue(sli4_t *sli4, uint8_t dump)
 5633 {
 5634 #define FDD 2
 5635         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5636                 switch(sli_get_asic_type(sli4)) {
 5637                 case SLI4_ASIC_TYPE_BE3: {
 5638                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR1, 0xffffffff);
 5639                         sli_reg_write(sli4, SLI4_REG_SW_UE_CSR2, 0);
 5640                         break;
 5641                 }
 5642                 case SLI4_ASIC_TYPE_SKYHAWK: {
 5643                         uint32_t value;
 5644                         value = ocs_config_read32(sli4->os, SLI4_SW_UE_REG);
 5645                         ocs_config_write32(sli4->os, SLI4_SW_UE_REG, (value | (1U << 24)));
 5646                         break;
 5647                 }
 5648                 default:
 5649                         ocs_log_test(sli4->os, "invalid asic type %d\n", sli_get_asic_type(sli4));
 5650                         return -1;
 5651                 }
 5652         } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) ||
 5653                    (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) {
 5654                 if (FDD == dump) {
 5655                         sli_reg_write(sli4, SLI4_REG_SLIPORT_CONTROL, SLI4_SLIPORT_CONTROL_FDD | SLI4_SLIPORT_CONTROL_IP);
 5656                 } else {
 5657                         uint32_t value = SLI4_PHYDEV_CONTROL_FRST;
 5658                         if (dump == 1) {
 5659                                 value |= SLI4_PHYDEV_CONTROL_DD;
 5660                         }
 5661                         sli_reg_write(sli4, SLI4_REG_PHYSDEV_CONTROL, value);
 5662                 }
 5663         } else {
 5664                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
 5665                 return -1;
 5666         }
 5667         return 0;
 5668 }
 5669 
 5670 /**
 5671  * @ingroup sli
 5672  * @brief Read the SLIPORT_STATUS register to check if a dump is present.
 5673  *
 5674  * @param sli4 SLI context.
 5675  *
 5676  * @return  Returns 1 if the chip is ready, or 0 if the chip is not ready, 2 if fdp is present.
 5677  */
 5678 int32_t sli_dump_is_ready(sli4_t *sli4)
 5679 {
 5680         int32_t rc = 0;
 5681         uint32_t port_val;
 5682         uint32_t bmbx_val;
 5683         uint32_t uerr_lo;
 5684         uint32_t uerr_hi;
 5685         uint32_t uerr_mask_lo;
 5686         uint32_t uerr_mask_hi;
 5687 
 5688         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5689                 /* for iftype=0, dump ready when UE is encountered */
 5690                 uerr_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
 5691                 uerr_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
 5692                 uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
 5693                 uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
 5694                 if ((uerr_lo & ~uerr_mask_lo) || (uerr_hi & ~uerr_mask_hi)) {
 5695                         rc = 1;
 5696                 }
 5697 
 5698         } else if ((SLI4_IF_TYPE_LANCER_FC_ETH == sli_get_if_type(sli4)) ||
 5699                    (SLI4_IF_TYPE_LANCER_G7 == sli_get_if_type(sli4))) {
 5700                 /*
 5701                  * Ensure that the port is ready AND the mailbox is
 5702                  * ready before signaling that the dump is ready to go.
 5703                  */
 5704                 port_val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5705                 bmbx_val = sli_reg_read(sli4, SLI4_REG_BMBX);
 5706 
 5707                 if ((bmbx_val & SLI4_BMBX_RDY) &&
 5708                     SLI4_PORT_STATUS_READY(port_val)) { 
 5709                         if(SLI4_PORT_STATUS_DUMP_PRESENT(port_val)) {
 5710                                 rc = 1;
 5711                         }else if( SLI4_PORT_STATUS_FDP_PRESENT(port_val)) {
 5712                                 rc = 2;
 5713                         }
 5714                 }
 5715         } else {
 5716                 ocs_log_test(sli4->os, "invalid iftype=%d\n", sli_get_if_type(sli4));
 5717                 return -1;
 5718         }
 5719         return rc;
 5720 }
 5721 
 5722 /**
 5723  * @ingroup sli
 5724  * @brief Read the SLIPORT_STATUS register to check if a dump is present.
 5725  *
 5726  * @param sli4 SLI context.
 5727  *
 5728  * @return
 5729  * - 0 if call completed correctly and no dump is present.
 5730  * - 1 if call completed and dump is present.
 5731  * - -1 if call failed (unsupported chip).
 5732  */
 5733 int32_t sli_dump_is_present(sli4_t *sli4)
 5734 {
 5735         uint32_t val;
 5736         uint32_t ready;
 5737 
 5738         if ((SLI4_IF_TYPE_LANCER_FC_ETH != sli_get_if_type(sli4)) &&
 5739             (SLI4_IF_TYPE_LANCER_G7 != sli_get_if_type(sli4))) {
 5740                 ocs_log_test(sli4->os, "Function only supported for I/F type 2");
 5741                 return -1;
 5742         }
 5743 
 5744         /* If the chip is not ready, then there cannot be a dump */
 5745         ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US);
 5746         if (!ready) {
 5747                 return 0;
 5748         }
 5749 
 5750         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5751         if (UINT32_MAX == val) {
 5752                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
 5753                 return -1;
 5754         } else {
 5755                 return ((val & SLI4_PORT_STATUS_DIP) ? 1 : 0);
 5756         }
 5757 }
 5758 
 5759 /**
 5760  * @ingroup sli
 5761  * @brief Read the SLIPORT_STATUS register to check if the reset required is set.
 5762  *
 5763  * @param sli4 SLI context.
 5764  *
 5765  * @return
 5766  * - 0 if call completed correctly and reset is not required.
 5767  * - 1 if call completed and reset is required.
 5768  * - -1 if call failed.
 5769  */
 5770 int32_t sli_reset_required(sli4_t *sli4)
 5771 {
 5772         uint32_t val;
 5773 
 5774         if (SLI4_IF_TYPE_BE3_SKH_PF == sli_get_if_type(sli4)) {
 5775                 ocs_log_test(sli4->os, "reset required N/A for iftype 0\n");
 5776                 return 0;
 5777         }
 5778 
 5779         val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5780         if (UINT32_MAX == val) {
 5781                 ocs_log_err(sli4->os, "error reading SLIPORT_STATUS\n");
 5782                 return -1;
 5783         } else {
 5784                 return ((val & SLI4_PORT_STATUS_RN) ? 1 : 0);
 5785         }
 5786 }
 5787 
 5788 /**
 5789  * @ingroup sli
 5790  * @brief Read the SLIPORT_SEMAPHORE and SLIPORT_STATUS registers to check if
 5791  * the port status indicates that a FW error has occurred.
 5792  *
 5793  * @param sli4 SLI context.
 5794  *
 5795  * @return
 5796  * - 0 if call completed correctly and no FW error occurred.
 5797  * - > 0 which indicates that a FW error has occurred.
 5798  * - -1 if call failed.
 5799  */
 5800 int32_t sli_fw_error_status(sli4_t *sli4)
 5801 {
 5802         uint32_t sliport_semaphore;
 5803         int32_t rc = 0;
 5804 
 5805         sliport_semaphore = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
 5806         if (UINT32_MAX == sliport_semaphore) {
 5807                 ocs_log_err(sli4->os, "error reading SLIPORT_SEMAPHORE register\n");
 5808                 return 1;
 5809         }
 5810         rc = (SLI4_PORT_SEMAPHORE_IN_ERR(sliport_semaphore) ? 1 : 0);
 5811 
 5812         if (rc == 0) {
 5813                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
 5814                     (SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type)) {
 5815                         uint32_t uerr_mask_lo, uerr_mask_hi;
 5816                         uint32_t uerr_status_lo, uerr_status_hi;
 5817 
 5818                         uerr_mask_lo = sli_reg_read(sli4, SLI4_REG_UERR_MASK_LO);
 5819                         uerr_mask_hi = sli_reg_read(sli4, SLI4_REG_UERR_MASK_HI);
 5820                         uerr_status_lo = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_LO);
 5821                         uerr_status_hi = sli_reg_read(sli4, SLI4_REG_UERR_STATUS_HI);
 5822                         if ((uerr_mask_lo & uerr_status_lo) != 0 ||
 5823                             (uerr_mask_hi & uerr_status_hi) != 0) {
 5824                                 rc = 1;
 5825                         }
 5826                 } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type ||
 5827                    SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) {
 5828                         uint32_t sliport_status;
 5829 
 5830                         sliport_status = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5831                         rc = (SLI4_PORT_STATUS_ERROR(sliport_status) ? 1 : 0);
 5832                 }
 5833         }
 5834         return rc;
 5835 }
 5836 
 5837 /**
 5838  * @ingroup sli
 5839  * @brief Determine if the chip FW is in a ready state
 5840  *
 5841  * @param sli4 SLI context.
 5842  *
 5843  * @return
 5844  * - 0 if call completed correctly and FW is not ready.
 5845  * - 1 if call completed correctly and FW is ready.
 5846  * - -1 if call failed.
 5847  */
 5848 int32_t
 5849 sli_fw_ready(sli4_t *sli4)
 5850 {
 5851         uint32_t val;
 5852         int32_t rc = -1;
 5853 
 5854         /*
 5855          * Is firmware ready for operation? Check needed depends on IF_TYPE
 5856          */
 5857         if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type ||
 5858             SLI4_IF_TYPE_BE3_SKH_VF == sli4->if_type) {
 5859                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_SEMAPHORE);
 5860                 rc = ((SLI4_PORT_SEMAPHORE_STATUS_POST_READY ==
 5861                     SLI4_PORT_SEMAPHORE_PORT(val)) &&
 5862                     (!SLI4_PORT_SEMAPHORE_IN_ERR(val)) ? 1 : 0);
 5863         } else if (SLI4_IF_TYPE_LANCER_FC_ETH == sli4->if_type ||
 5864                    SLI4_IF_TYPE_LANCER_G7 == sli4->if_type) {
 5865                 val = sli_reg_read(sli4, SLI4_REG_SLIPORT_STATUS);
 5866                 rc = (SLI4_PORT_STATUS_READY(val) ? 1 : 0);
 5867         }
 5868         return rc;
 5869 }
 5870 
 5871 /**
 5872  * @ingroup sli
 5873  * @brief Determine if the link can be configured
 5874  *
 5875  * @param sli4 SLI context.
 5876  *
 5877  * @return
 5878  * - 0 if link is not configurable.
 5879  * - 1 if link is configurable.
 5880  */
 5881 int32_t sli_link_is_configurable(sli4_t *sli)
 5882 {
 5883         int32_t rc = 0;
 5884         /*
 5885          * Link config works on: Skyhawk and Lancer
 5886          * Link config does not work on: LancerG6
 5887          */
 5888 
 5889         switch (sli_get_asic_type(sli)) {
 5890         case SLI4_ASIC_TYPE_SKYHAWK:
 5891         case SLI4_ASIC_TYPE_LANCER:
 5892         case SLI4_ASIC_TYPE_CORSAIR:
 5893                 rc = 1;
 5894                 break;
 5895         case SLI4_ASIC_TYPE_LANCERG6:
 5896         case SLI4_ASIC_TYPE_LANCERG7:
 5897         case SLI4_ASIC_TYPE_BE3:
 5898         default:
 5899                 rc = 0;
 5900                 break;
 5901         }
 5902 
 5903         return rc;
 5904 
 5905 }
 5906 
 5907 /* vim: set noexpandtab textwidth=120: */
 5908 
 5909 /**
 5910  * @ingroup sli_fc
 5911  * @brief Write an FCOE_WQ_CREATE command.
 5912  *
 5913  * @param sli4 SLI context.
 5914  * @param buf Destination buffer for the command.
 5915  * @param size Buffer size, in bytes.
 5916  * @param qmem DMA memory for the queue.
 5917  * @param cq_id Associated CQ_ID.
 5918  * @param ulp The ULP to bind
 5919  *
 5920  * @note This creates a Version 0 message.
 5921  *
 5922  * @return Returns the number of bytes written.
 5923  */
 5924 int32_t
 5925 sli_cmd_fcoe_wq_create(sli4_t *sli4, void *buf, size_t size,
 5926                         ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp)
 5927 {
 5928         sli4_req_fcoe_wq_create_t       *wq = NULL;
 5929         uint32_t        sli_config_off = 0;
 5930         uint32_t        p;
 5931         uintptr_t       addr;
 5932 
 5933         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 5934                 uint32_t payload_size;
 5935 
 5936                 /* Payload length must accommodate both request and response */
 5937                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_t),
 5938                                 sizeof(sli4_res_common_create_queue_t));
 5939 
 5940                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 5941                                 NULL);
 5942         }
 5943         wq = (sli4_req_fcoe_wq_create_t *)((uint8_t *)buf + sli_config_off);
 5944 
 5945         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
 5946         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 5947         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_t) -
 5948                                         sizeof(sli4_req_hdr_t);
 5949         /* valid values for number of pages: 1-4 (sec 4.5.1) */
 5950         wq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 5951         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V0_MAX_PAGES)) {
 5952                 return 0;
 5953         }
 5954 
 5955         wq->cq_id = cq_id;
 5956 
 5957         if (sli4->config.dual_ulp_capable) {
 5958                 wq->dua = 1;
 5959                 wq->bqu = 1;
 5960                 wq->ulp = ulp;
 5961         }
 5962 
 5963         for (p = 0, addr = qmem->phys;
 5964                         p < wq->num_pages;
 5965                         p++, addr += SLI_PAGE_SIZE) {
 5966                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 5967                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
 5968         }
 5969 
 5970         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_t));
 5971 }
 5972 
 5973 /**
 5974  * @ingroup sli_fc
 5975  * @brief Write an FCOE_WQ_CREATE_V1 command.
 5976  *
 5977  * @param sli4 SLI context.
 5978  * @param buf Destination buffer for the command.
 5979  * @param size Buffer size, in bytes.
 5980  * @param qmem DMA memory for the queue.
 5981  * @param cq_id Associated CQ_ID.
 5982  * @param ignored This parameter carries the ULP for WQ (ignored for V1)
 5983 
 5984  *
 5985  * @return Returns the number of bytes written.
 5986  */
 5987 int32_t
 5988 sli_cmd_fcoe_wq_create_v1(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *qmem,
 5989                           uint16_t cq_id, uint16_t ignored)
 5990 {
 5991         sli4_req_fcoe_wq_create_v1_t    *wq = NULL;
 5992         uint32_t        sli_config_off = 0;
 5993         uint32_t        p;
 5994         uintptr_t       addr;
 5995         uint32_t        page_size = 0;
 5996         uint32_t        page_bytes = 0;
 5997         uint32_t        n_wqe = 0;
 5998 
 5999         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6000                 uint32_t payload_size;
 6001 
 6002                 /* Payload length must accommodate both request and response */
 6003                 payload_size = max(sizeof(sli4_req_fcoe_wq_create_v1_t),
 6004                                 sizeof(sli4_res_common_create_queue_t));
 6005 
 6006                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6007                                 NULL);
 6008         }
 6009         wq = (sli4_req_fcoe_wq_create_v1_t *)((uint8_t *)buf + sli_config_off);
 6010 
 6011         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_CREATE;
 6012         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6013         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_create_v1_t) -
 6014                                         sizeof(sli4_req_hdr_t);
 6015         wq->hdr.version = 1;
 6016 
 6017         n_wqe = qmem->size / sli4->config.wqe_size;
 6018 
 6019         /* This heuristic to determine the page size is simplistic 
 6020          * but could be made more sophisticated
 6021          */
 6022         switch (qmem->size) {
 6023         case 4096:
 6024         case 8192:
 6025         case 16384:
 6026         case 32768:
 6027                 page_size = 1;
 6028                 break;
 6029         case 65536:
 6030                 page_size = 2;
 6031                 break;
 6032         case 131072:
 6033                 page_size = 4;
 6034                 break;
 6035         case 262144:
 6036                 page_size = 8;
 6037                 break;
 6038         case 524288:
 6039                 page_size = 10;
 6040                 break;
 6041         default:
 6042                 return 0;
 6043         }
 6044         page_bytes = page_size * SLI_PAGE_SIZE;
 6045 
 6046         /* valid values for number of pages: 1-8 */
 6047         wq->num_pages = sli_page_count(qmem->size, page_bytes);
 6048         if (!wq->num_pages || (wq->num_pages > SLI4_FCOE_WQ_CREATE_V1_MAX_PAGES)) {
 6049                 return 0;
 6050         }
 6051 
 6052         wq->cq_id = cq_id;
 6053 
 6054         wq->page_size = page_size;
 6055 
 6056         if (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) {
 6057                 wq->wqe_size = SLI4_WQE_EXT_SIZE;
 6058         } else {
 6059                 wq->wqe_size = SLI4_WQE_SIZE;
 6060         }
 6061 
 6062         wq->wqe_count = n_wqe;
 6063 
 6064         for (p = 0, addr = qmem->phys;
 6065                         p < wq->num_pages;
 6066                         p++, addr += page_bytes) {
 6067                 wq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 6068                 wq->page_physical_address[p].high = ocs_addr32_hi(addr);
 6069         }
 6070 
 6071         return(sli_config_off + sizeof(sli4_req_fcoe_wq_create_v1_t));
 6072 }
 6073 
 6074 /**
 6075  * @ingroup sli_fc
 6076  * @brief Write an FCOE_WQ_DESTROY command.
 6077  *
 6078  * @param sli4 SLI context.
 6079  * @param buf Destination buffer for the command.
 6080  * @param size Buffer size, in bytes.
 6081  * @param wq_id WQ_ID.
 6082  *
 6083  * @return Returns the number of bytes written.
 6084  */
 6085 int32_t
 6086 sli_cmd_fcoe_wq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t wq_id)
 6087 {
 6088         sli4_req_fcoe_wq_destroy_t      *wq = NULL;
 6089         uint32_t        sli_config_off = 0;
 6090 
 6091         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6092                 uint32_t payload_size;
 6093 
 6094                 /* Payload length must accommodate both request and response */
 6095                 payload_size = max(sizeof(sli4_req_fcoe_wq_destroy_t),
 6096                                 sizeof(sli4_res_hdr_t));
 6097 
 6098                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6099                                 NULL);
 6100         }
 6101         wq = (sli4_req_fcoe_wq_destroy_t *)((uint8_t *)buf + sli_config_off);
 6102 
 6103         wq->hdr.opcode = SLI4_OPC_FCOE_WQ_DESTROY;
 6104         wq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6105         wq->hdr.request_length = sizeof(sli4_req_fcoe_wq_destroy_t) -
 6106                                         sizeof(sli4_req_hdr_t);
 6107 
 6108         wq->wq_id = wq_id;
 6109 
 6110         return(sli_config_off + sizeof(sli4_req_fcoe_wq_destroy_t));
 6111 }
 6112 
 6113 /**
 6114  * @ingroup sli_fc
 6115  * @brief Write an FCOE_POST_SGL_PAGES command.
 6116  *
 6117  * @param sli4 SLI context.
 6118  * @param buf Destination buffer for the command.
 6119  * @param size Buffer size, in bytes.
 6120  * @param xri starting XRI
 6121  * @param xri_count XRI
 6122  * @param page0 First SGL memory page.
 6123  * @param page1 Second SGL memory page (optional).
 6124  * @param dma DMA buffer for non-embedded mailbox command (options)
 6125  *
 6126  * if non-embedded mbx command is used, dma buffer must be at least (32 + xri_count*16) in length
 6127  *
 6128  * @return Returns the number of bytes written.
 6129  */
 6130 int32_t
 6131 sli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size,
 6132                 uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma)
 6133 {
 6134         sli4_req_fcoe_post_sgl_pages_t  *post = NULL;
 6135         uint32_t        sli_config_off = 0;
 6136         uint32_t        i;
 6137 
 6138         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6139                 uint32_t payload_size;
 6140 
 6141                 /* Payload length must accommodate both request and response */
 6142                 payload_size = max(sizeof(sli4_req_fcoe_post_sgl_pages_t),
 6143                                 sizeof(sli4_res_hdr_t));
 6144 
 6145                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6146                                 dma);
 6147         }
 6148         if (dma) {
 6149                 post = dma->virt;
 6150                 ocs_memset(post, 0, dma->size);
 6151         } else {
 6152                 post = (sli4_req_fcoe_post_sgl_pages_t *)((uint8_t *)buf + sli_config_off);
 6153         }
 6154 
 6155         post->hdr.opcode = SLI4_OPC_FCOE_POST_SGL_PAGES;
 6156         post->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6157         /* payload size calculation
 6158          *   4 = xri_start + xri_count
 6159          *   xri_count = # of XRI's registered
 6160          *   sizeof(uint64_t) = physical address size
 6161          *   2 = # of physical addresses per page set
 6162          */
 6163         post->hdr.request_length = 4 + (xri_count * (sizeof(uint64_t) * 2));
 6164 
 6165         post->xri_start = xri;
 6166         post->xri_count = xri_count;
 6167 
 6168         for (i = 0; i < xri_count; i++) {
 6169                 post->page_set[i].page0_low  = ocs_addr32_lo(page0[i]->phys);
 6170                 post->page_set[i].page0_high = ocs_addr32_hi(page0[i]->phys);
 6171         }
 6172 
 6173         if (page1) {
 6174                 for (i = 0; i < xri_count; i++) {
 6175                         post->page_set[i].page1_low  = ocs_addr32_lo(page1[i]->phys);
 6176                         post->page_set[i].page1_high = ocs_addr32_hi(page1[i]->phys);
 6177                 }
 6178         }
 6179 
 6180         return dma ? sli_config_off : (sli_config_off + sizeof(sli4_req_fcoe_post_sgl_pages_t));
 6181 }
 6182 
 6183 /**
 6184  * @ingroup sli_fc
 6185  * @brief Write an FCOE_RQ_CREATE command.
 6186  *
 6187  * @param sli4 SLI context.
 6188  * @param buf Destination buffer for the command.
 6189  * @param size Buffer size, in bytes.
 6190  * @param qmem DMA memory for the queue.
 6191  * @param cq_id Associated CQ_ID.
 6192  * @param ulp This parameter carries the ULP for the RQ
 6193  * @param buffer_size Buffer size pointed to by each RQE.
 6194  *
 6195  * @note This creates a Version 0 message.
 6196  *
 6197  * @return Returns the number of bytes written.
 6198  */
 6199 int32_t
 6200 sli_cmd_fcoe_rq_create(sli4_t *sli4, void *buf, size_t size,
 6201                 ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp, uint16_t buffer_size)
 6202 {
 6203         sli4_req_fcoe_rq_create_t       *rq = NULL;
 6204         uint32_t        sli_config_off = 0;
 6205         uint32_t        p;
 6206         uintptr_t       addr;
 6207 
 6208         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6209                 uint32_t payload_size;
 6210 
 6211                 /* Payload length must accommodate both request and response */
 6212                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_t),
 6213                                 sizeof(sli4_res_common_create_queue_t));
 6214 
 6215                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6216                                 NULL);
 6217         }
 6218         rq = (sli4_req_fcoe_rq_create_t *)((uint8_t *)buf + sli_config_off);
 6219 
 6220         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
 6221         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6222         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_t) -
 6223                                         sizeof(sli4_req_hdr_t);
 6224         /* valid values for number of pages: 1-8 (sec 4.5.6) */
 6225         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 6226         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V0_MAX_PAGES)) {
 6227                 ocs_log_test(sli4->os, "num_pages %d not valid\n", rq->num_pages);
 6228                 return 0;
 6229         }
 6230 
 6231         /*
 6232          * RQE count is the log base 2 of the total number of entries
 6233          */
 6234         rq->rqe_count = ocs_lg2(qmem->size / SLI4_FCOE_RQE_SIZE);
 6235 
 6236         if ((buffer_size < SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE) ||
 6237                         (buffer_size > SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE)) {
 6238                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
 6239                                 buffer_size,
 6240                                 SLI4_FCOE_RQ_CREATE_V0_MIN_BUF_SIZE,
 6241                                 SLI4_FCOE_RQ_CREATE_V0_MAX_BUF_SIZE);
 6242                 return -1;
 6243         }
 6244         rq->buffer_size = buffer_size;
 6245 
 6246         rq->cq_id = cq_id;
 6247 
 6248         if (sli4->config.dual_ulp_capable) {
 6249                 rq->dua = 1;
 6250                 rq->bqu = 1;
 6251                 rq->ulp = ulp;
 6252         }
 6253 
 6254         for (p = 0, addr = qmem->phys;
 6255                         p < rq->num_pages;
 6256                         p++, addr += SLI_PAGE_SIZE) {
 6257                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 6258                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
 6259         }
 6260 
 6261         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_t));
 6262 }
 6263 
 6264 /**
 6265  * @ingroup sli_fc
 6266  * @brief Write an FCOE_RQ_CREATE_V1 command.
 6267  *
 6268  * @param sli4 SLI context.
 6269  * @param buf Destination buffer for the command.
 6270  * @param size Buffer size, in bytes.
 6271  * @param qmem DMA memory for the queue.
 6272  * @param cq_id Associated CQ_ID.
 6273  * @param ulp This parameter carries the ULP for RQ (ignored for V1)
 6274  * @param buffer_size Buffer size pointed to by each RQE.
 6275  *
 6276  * @note This creates a Version 0 message
 6277  *
 6278  * @return Returns the number of bytes written.
 6279  */
 6280 int32_t
 6281 sli_cmd_fcoe_rq_create_v1(sli4_t *sli4, void *buf, size_t size,
 6282                           ocs_dma_t *qmem, uint16_t cq_id, uint16_t ulp,
 6283                           uint16_t buffer_size)
 6284 {
 6285         sli4_req_fcoe_rq_create_v1_t    *rq = NULL;
 6286         uint32_t        sli_config_off = 0;
 6287         uint32_t        p;
 6288         uintptr_t       addr;
 6289 
 6290         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6291                 uint32_t payload_size;
 6292 
 6293                 /* Payload length must accommodate both request and response */
 6294                 payload_size = max(sizeof(sli4_req_fcoe_rq_create_v1_t),
 6295                                 sizeof(sli4_res_common_create_queue_t));
 6296 
 6297                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6298                                 NULL);
 6299         }
 6300         rq = (sli4_req_fcoe_rq_create_v1_t *)((uint8_t *)buf + sli_config_off);
 6301 
 6302         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_CREATE;
 6303         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6304         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v1_t) -
 6305                                         sizeof(sli4_req_hdr_t);
 6306         rq->hdr.version = 1;
 6307 
 6308         /* Disable "no buffer warnings" to avoid Lancer bug */
 6309         rq->dnb = TRUE;
 6310 
 6311         /* valid values for number of pages: 1-8 (sec 4.5.6) */
 6312         rq->num_pages = sli_page_count(qmem->size, SLI_PAGE_SIZE);
 6313         if (!rq->num_pages || (rq->num_pages > SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES)) {
 6314                 ocs_log_test(sli4->os, "num_pages %d not valid, max %d\n",
 6315                 rq->num_pages, SLI4_FCOE_RQ_CREATE_V1_MAX_PAGES);
 6316                 return 0;
 6317         }
 6318 
 6319         /*
 6320          * RQE count is the total number of entries (note not lg2(# entries))
 6321          */
 6322         rq->rqe_count = qmem->size / SLI4_FCOE_RQE_SIZE;
 6323 
 6324         rq->rqe_size = SLI4_FCOE_RQE_SIZE_8;
 6325 
 6326         rq->page_size = SLI4_FCOE_RQ_PAGE_SIZE_4096;
 6327 
 6328         if ((buffer_size < sli4->config.rq_min_buf_size) ||
 6329             (buffer_size > sli4->config.rq_max_buf_size)) {
 6330                 ocs_log_err(sli4->os, "buffer_size %d out of range (%d-%d)\n",
 6331                                 buffer_size,
 6332                                 sli4->config.rq_min_buf_size,
 6333                                 sli4->config.rq_max_buf_size);
 6334                 return -1;
 6335         }
 6336         rq->buffer_size = buffer_size;
 6337 
 6338         rq->cq_id = cq_id;
 6339 
 6340         for (p = 0, addr = qmem->phys;
 6341                         p < rq->num_pages;
 6342                         p++, addr += SLI_PAGE_SIZE) {
 6343                 rq->page_physical_address[p].low  = ocs_addr32_lo(addr);
 6344                 rq->page_physical_address[p].high = ocs_addr32_hi(addr);
 6345         }
 6346 
 6347         return(sli_config_off + sizeof(sli4_req_fcoe_rq_create_v1_t));
 6348 }
 6349 
 6350 /**
 6351  * @ingroup sli_fc
 6352  * @brief Write an FCOE_RQ_DESTROY command.
 6353  *
 6354  * @param sli4 SLI context.
 6355  * @param buf Destination buffer for the command.
 6356  * @param size Buffer size, in bytes.
 6357  * @param rq_id RQ_ID.
 6358  *
 6359  * @return Returns the number of bytes written.
 6360  */
 6361 int32_t
 6362 sli_cmd_fcoe_rq_destroy(sli4_t *sli4, void *buf, size_t size, uint16_t rq_id)
 6363 {
 6364         sli4_req_fcoe_rq_destroy_t      *rq = NULL;
 6365         uint32_t        sli_config_off = 0;
 6366 
 6367         if (SLI4_PORT_TYPE_FC == sli4->port_type) {
 6368                 uint32_t payload_size;
 6369 
 6370                 /* Payload length must accommodate both request and response */
 6371                 payload_size = max(sizeof(sli4_req_fcoe_rq_destroy_t),
 6372                                 sizeof(sli4_res_hdr_t));
 6373 
 6374                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size,
 6375                                 NULL);
 6376         }
 6377         rq = (sli4_req_fcoe_rq_destroy_t *)((uint8_t *)buf + sli_config_off);
 6378 
 6379         rq->hdr.opcode = SLI4_OPC_FCOE_RQ_DESTROY;
 6380         rq->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6381         rq->hdr.request_length = sizeof(sli4_req_fcoe_rq_destroy_t) -
 6382                                         sizeof(sli4_req_hdr_t);
 6383 
 6384         rq->rq_id = rq_id;
 6385 
 6386         return(sli_config_off + sizeof(sli4_req_fcoe_rq_destroy_t));
 6387 }
 6388 
 6389 /**
 6390  * @ingroup sli_fc
 6391  * @brief Write an FCOE_READ_FCF_TABLE command.
 6392  *
 6393  * @note
 6394  * The response of this command exceeds the size of an embedded
 6395  * command and requires an external buffer with DMA capability to hold the results.
 6396  * The caller should allocate the ocs_dma_t structure / memory.
 6397  *
 6398  * @param sli4 SLI context.
 6399  * @param buf Destination buffer for the command.
 6400  * @param size Buffer size, in bytes.
 6401  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
 6402  * @param index FCF table index to retrieve.
 6403  *
 6404  * @return Returns the number of bytes written.
 6405  */
 6406 int32_t
 6407 sli_cmd_fcoe_read_fcf_table(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *dma, uint16_t index)
 6408 {
 6409         sli4_req_fcoe_read_fcf_table_t *read_fcf = NULL;
 6410 
 6411         if (SLI4_PORT_TYPE_FC != sli4->port_type) {
 6412                 ocs_log_test(sli4->os, "FCOE_READ_FCF_TABLE only supported on FC\n");
 6413                 return -1;
 6414         }
 6415 
 6416         read_fcf = dma->virt;
 6417 
 6418         ocs_memset(read_fcf, 0, sizeof(sli4_req_fcoe_read_fcf_table_t));
 6419 
 6420         read_fcf->hdr.opcode = SLI4_OPC_FCOE_READ_FCF_TABLE;
 6421         read_fcf->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6422         read_fcf->hdr.request_length = dma->size -
 6423                 sizeof(sli4_req_fcoe_read_fcf_table_t);
 6424         read_fcf->fcf_index = index;
 6425 
 6426         return sli_cmd_sli_config(sli4, buf, size, 0, dma);
 6427 }
 6428 
 6429 /**
 6430  * @ingroup sli_fc
 6431  * @brief Write an FCOE_POST_HDR_TEMPLATES command.
 6432  *
 6433  * @param sli4 SLI context.
 6434  * @param buf Destination buffer for the command.
 6435  * @param size Buffer size, in bytes.
 6436  * @param dma Pointer to DMA memory structure. This is allocated by the caller.
 6437  * @param rpi Starting RPI index for the header templates.
 6438  * @param payload_dma Pointer to DMA memory used to hold larger descriptor counts.
 6439  *
 6440  * @return Returns the number of bytes written.
 6441  */
 6442 int32_t
 6443 sli_cmd_fcoe_post_hdr_templates(sli4_t *sli4, void *buf, size_t size,
 6444                 ocs_dma_t *dma, uint16_t rpi, ocs_dma_t *payload_dma)
 6445 {
 6446         sli4_req_fcoe_post_hdr_templates_t *template = NULL;
 6447         uint32_t        sli_config_off = 0;
 6448         uintptr_t       phys = 0;
 6449         uint32_t        i = 0;
 6450         uint32_t        page_count;
 6451         uint32_t        payload_size;
 6452 
 6453         page_count = sli_page_count(dma->size, SLI_PAGE_SIZE);
 6454 
 6455         payload_size = sizeof(sli4_req_fcoe_post_hdr_templates_t) +
 6456                                 page_count * sizeof(sli4_physical_page_descriptor_t);
 6457 
 6458         if (page_count > 16) {
 6459                 /* We can't fit more than 16 descriptors into an embedded mailbox
 6460                    command, it has to be non-embedded */
 6461                 if (ocs_dma_alloc(sli4->os, payload_dma, payload_size, 4)) {
 6462                         ocs_log_err(sli4->os, "mailbox payload memory allocation fail\n");
 6463                         return 0;
 6464                 }
 6465                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, payload_dma);
 6466                 template = (sli4_req_fcoe_post_hdr_templates_t *)payload_dma->virt;
 6467         } else {
 6468                 sli_config_off = sli_cmd_sli_config(sli4, buf, size, payload_size, NULL);
 6469                 template = (sli4_req_fcoe_post_hdr_templates_t *)((uint8_t *)buf + sli_config_off);
 6470         }
 6471 
 6472         if (UINT16_MAX == rpi) {
 6473                 rpi = sli4->config.extent[SLI_RSRC_FCOE_RPI].base[0];
 6474         }
 6475 
 6476         template->hdr.opcode = SLI4_OPC_FCOE_POST_HDR_TEMPLATES;
 6477         template->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6478         template->hdr.request_length = sizeof(sli4_req_fcoe_post_hdr_templates_t) -
 6479                                         sizeof(sli4_req_hdr_t);
 6480 
 6481         template->rpi_offset = rpi;
 6482         template->page_count = page_count;
 6483         phys = dma->phys;
 6484         for (i = 0; i < template->page_count; i++) {
 6485                 template->page_descriptor[i].low  = ocs_addr32_lo(phys);
 6486                 template->page_descriptor[i].high = ocs_addr32_hi(phys);
 6487 
 6488                 phys += SLI_PAGE_SIZE;
 6489         }
 6490 
 6491         return(sli_config_off + payload_size);
 6492 }
 6493 
 6494 int32_t
 6495 sli_cmd_fcoe_rediscover_fcf(sli4_t *sli4, void *buf, size_t size, uint16_t index)
 6496 {
 6497         sli4_req_fcoe_rediscover_fcf_t *redisc = NULL;
 6498         uint32_t        sli_config_off = 0;
 6499 
 6500         sli_config_off = sli_cmd_sli_config(sli4, buf, size,
 6501                         sizeof(sli4_req_fcoe_rediscover_fcf_t),
 6502                         NULL);
 6503 
 6504         redisc = (sli4_req_fcoe_rediscover_fcf_t *)((uint8_t *)buf + sli_config_off);
 6505 
 6506         redisc->hdr.opcode = SLI4_OPC_FCOE_REDISCOVER_FCF;
 6507         redisc->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 6508         redisc->hdr.request_length = sizeof(sli4_req_fcoe_rediscover_fcf_t) -
 6509                                         sizeof(sli4_req_hdr_t);
 6510 
 6511         if (index == UINT16_MAX) {
 6512                 redisc->fcf_count = 0;
 6513         } else {
 6514                 redisc->fcf_count = 1;
 6515                 redisc->fcf_index[0] = index;
 6516         }
 6517 
 6518         return(sli_config_off + sizeof(sli4_req_fcoe_rediscover_fcf_t));
 6519 }
 6520 
 6521 /**
 6522  * @ingroup sli_fc
 6523  * @brief Write an ABORT_WQE work queue entry.
 6524  *
 6525  * @param sli4 SLI context.
 6526  * @param buf Destination buffer for the WQE.
 6527  * @param size Buffer size, in bytes.
 6528  * @param type Abort type, such as XRI, abort tag, and request tag.
 6529  * @param send_abts Boolean to cause the hardware to automatically generate an ABTS.
 6530  * @param ids ID of IOs to abort.
 6531  * @param mask Mask applied to the ID values to abort.
 6532  * @param tag Tag value associated with this abort.
 6533  * @param cq_id The id of the completion queue where the WQE response is sent.
 6534  * @param dnrx When set to 1, this field indicates that the SLI Port must not return the associated XRI to the SLI
 6535  *             Port's optimized write XRI pool.
 6536  *
 6537  * @return Returns 0 on success, or a non-zero value on failure.
 6538  */
 6539 int32_t
 6540 sli_abort_wqe(sli4_t *sli4, void *buf, size_t size, sli4_abort_type_e type, uint32_t send_abts,
 6541               uint32_t ids, uint32_t mask, uint16_t tag, uint16_t cq_id)
 6542 {
 6543         sli4_abort_wqe_t        *abort = buf;
 6544 
 6545         ocs_memset(buf, 0, size);
 6546 
 6547         switch (type) {
 6548         case SLI_ABORT_XRI:
 6549                 abort->criteria = SLI4_ABORT_CRITERIA_XRI_TAG;
 6550                 if (mask) {
 6551                         ocs_log_warn(sli4->os, "warning non-zero mask %#x when aborting XRI %#x\n", mask, ids);
 6552                         mask = 0;
 6553                 }
 6554                 break;
 6555         case SLI_ABORT_ABORT_ID:
 6556                 abort->criteria = SLI4_ABORT_CRITERIA_ABORT_TAG;
 6557                 break;
 6558         case SLI_ABORT_REQUEST_ID:
 6559                 abort->criteria = SLI4_ABORT_CRITERIA_REQUEST_TAG;
 6560                 break;
 6561         default:
 6562                 ocs_log_test(sli4->os, "unsupported type %#x\n", type);
 6563                 return -1;
 6564         }
 6565 
 6566         abort->ia = send_abts ? 0 : 1;
 6567 
 6568         /* Suppress ABTS retries */
 6569         abort->ir = 1;
 6570 
 6571         abort->t_mask = mask;
 6572         abort->t_tag  = ids;
 6573         abort->command = SLI4_WQE_ABORT;
 6574         abort->request_tag = tag;
 6575         abort->qosd = TRUE;
 6576         abort->cq_id = cq_id;
 6577         abort->cmd_type = SLI4_CMD_ABORT_WQE;
 6578 
 6579         return 0;
 6580 }
 6581 
 6582 /**
 6583  * @ingroup sli_fc
 6584  * @brief Write an ELS_REQUEST64_WQE work queue entry.
 6585  *
 6586  * @param sli4 SLI context.
 6587  * @param buf Destination buffer for the WQE.
 6588  * @param size Buffer size, in bytes.
 6589  * @param sgl DMA memory for the ELS request.
 6590  * @param req_type ELS request type.
 6591  * @param req_len Length of ELS request in bytes.
 6592  * @param max_rsp_len Max length of ELS response in bytes.
 6593  * @param timeout Time, in seconds, before an IO times out. Zero means 2 * R_A_TOV.
 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 rnode Destination of ELS request (that is, the remote node).
 6598  *
 6599  * @return Returns 0 on success, or a non-zero value on failure.
 6600  */
 6601 int32_t
 6602 sli_els_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint8_t req_type,
 6603                       uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
 6604                       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode)
 6605 {
 6606         sli4_els_request64_wqe_t        *els = buf;
 6607         sli4_sge_t      *sge = sgl->virt;
 6608         uint8_t         is_fabric = FALSE;
 6609 
 6610         ocs_memset(buf, 0, size);
 6611 
 6612         if (sli4->config.sgl_pre_registered) {
 6613                 els->xbl = FALSE;
 6614 
 6615                 els->dbde = TRUE;
 6616                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
 6617 
 6618                 els->els_request_payload.buffer_length = req_len;
 6619                 els->els_request_payload.u.data.buffer_address_low  = sge[0].buffer_address_low;
 6620                 els->els_request_payload.u.data.buffer_address_high = sge[0].buffer_address_high;
 6621         } else {
 6622                 els->xbl = TRUE;
 6623 
 6624                 els->els_request_payload.bde_type = SLI4_BDE_TYPE_BLP;
 6625 
 6626                 els->els_request_payload.buffer_length = 2 * sizeof(sli4_sge_t);
 6627                 els->els_request_payload.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 6628                 els->els_request_payload.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 6629         }
 6630 
 6631         els->els_request_payload_length = req_len;
 6632         els->max_response_payload_length = max_rsp_len;
 6633 
 6634         els->xri_tag = xri;
 6635         els->timer = timeout;
 6636         els->class = SLI4_ELS_REQUEST64_CLASS_3;
 6637 
 6638         els->command = SLI4_WQE_ELS_REQUEST64;
 6639 
 6640         els->request_tag = tag;
 6641 
 6642         if (rnode->node_group) {
 6643                 els->hlm = TRUE;
 6644                 els->remote_id = rnode->fc_id & 0x00ffffff;
 6645         }
 6646 
 6647         els->iod = SLI4_ELS_REQUEST64_DIR_READ;
 6648 
 6649         els->qosd = TRUE;
 6650 
 6651         /* figure out the ELS_ID value from the request buffer */
 6652 
 6653         switch (req_type) {
 6654         case FC_ELS_CMD_LOGO:
 6655                 els->els_id = SLI4_ELS_REQUEST64_LOGO;
 6656                 if (rnode->attached) {
 6657                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6658                         els->context_tag = rnode->indicator;
 6659                 } else {
 6660                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6661                         els->context_tag = rnode->sport->indicator;
 6662                 }
 6663                 if (FC_ADDR_FABRIC == rnode->fc_id) {
 6664                         is_fabric = TRUE;
 6665                 }
 6666                 break;
 6667         case FC_ELS_CMD_FDISC:
 6668                 if (FC_ADDR_FABRIC == rnode->fc_id) {
 6669                         is_fabric = TRUE;
 6670                 }
 6671                 if (0 == rnode->sport->fc_id) {
 6672                         els->els_id = SLI4_ELS_REQUEST64_FDISC;
 6673                         is_fabric = TRUE;
 6674                 } else {
 6675                         els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6676                 }
 6677                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6678                 els->context_tag = rnode->sport->indicator;
 6679                 els->sp = TRUE;
 6680                 break;
 6681         case FC_ELS_CMD_FLOGI:
 6682                 els->els_id = SLI4_ELS_REQUEST64_FLOGIN;
 6683                 is_fabric = TRUE;
 6684                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 6685                         if (!rnode->sport->domain) {
 6686                                 ocs_log_test(sli4->os, "invalid domain handle\n");
 6687                                 return -1;
 6688                         }
 6689                         /*
 6690                          * IF_TYPE 0 skips INIT_VFI/INIT_VPI and therefore must use the
 6691                          * FCFI here
 6692                          */
 6693                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_FCFI;
 6694                         els->context_tag = rnode->sport->domain->fcf_indicator;
 6695                         els->sp = TRUE;
 6696                 } else {
 6697                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6698                         els->context_tag = rnode->sport->indicator;
 6699 
 6700                         /*
 6701                          * Set SP here ... we haven't done a REG_VPI yet
 6702                          * TODO: need to maybe not set this when we have
 6703                          *       completed VFI/VPI registrations ...
 6704                          *
 6705                          * Use the FC_ID of the SPORT if it has been allocated, otherwise
 6706                          * use an S_ID of zero.
 6707                          */
 6708                         els->sp = TRUE;
 6709                         if (rnode->sport->fc_id != UINT32_MAX) {
 6710                                 els->sid = rnode->sport->fc_id;
 6711                         }
 6712                 }
 6713                 break;
 6714         case FC_ELS_CMD_PLOGI:
 6715                 els->els_id = SLI4_ELS_REQUEST64_PLOGI;
 6716                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6717                 els->context_tag = rnode->sport->indicator;
 6718                 break;
 6719         case FC_ELS_CMD_SCR:
 6720                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6721                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6722                 els->context_tag = rnode->sport->indicator;
 6723                 break;
 6724         default:
 6725                 els->els_id = SLI4_ELS_REQUEST64_OTHER;
 6726                 if (rnode->attached) {
 6727                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6728                         els->context_tag = rnode->indicator;
 6729                 } else {
 6730                         els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 6731                         els->context_tag = rnode->sport->indicator;
 6732                 }
 6733                 break;
 6734         }
 6735 
 6736         if (is_fabric) {
 6737                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_FABRIC;
 6738         } else {
 6739                 els->cmd_type = SLI4_ELS_REQUEST64_CMD_NON_FABRIC;
 6740         }
 6741 
 6742         els->cq_id = cq_id;
 6743 
 6744         if (SLI4_ELS_REQUEST64_CONTEXT_RPI != els->ct) {
 6745                 els->remote_id = rnode->fc_id;
 6746         }
 6747         if (SLI4_ELS_REQUEST64_CONTEXT_VPI == els->ct) {
 6748                 els->temporary_rpi = rnode->indicator;
 6749         }
 6750 
 6751         return 0;
 6752 }
 6753 
 6754 /**
 6755  * @ingroup sli_fc
 6756  * @brief Write an FCP_ICMND64_WQE work queue entry.
 6757  *
 6758  * @param sli4 SLI context.
 6759  * @param buf Destination buffer for the WQE.
 6760  * @param size Buffer size, in bytes.
 6761  * @param sgl DMA memory for the scatter gather list.
 6762  * @param xri XRI for this exchange.
 6763  * @param tag IO tag value.
 6764  * @param cq_id The id of the completion queue where the WQE response is sent.
 6765  * @param rpi remote node indicator (RPI)
 6766  * @param rnode Destination request (that is, the remote node).
 6767  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
 6768  *
 6769  * @return Returns 0 on success, or a non-zero value on failure.
 6770  */
 6771 int32_t
 6772 sli_fcp_icmnd64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
 6773                     uint16_t xri, uint16_t tag, uint16_t cq_id,
 6774                     uint32_t rpi, ocs_remote_node_t *rnode, uint8_t timeout)
 6775 {
 6776         sli4_fcp_icmnd64_wqe_t *icmnd = buf;
 6777         sli4_sge_t      *sge = NULL;
 6778 
 6779         ocs_memset(buf, 0, size);
 6780 
 6781         if (!sgl || !sgl->virt) {
 6782                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 6783                             sgl, sgl ? sgl->virt : NULL);
 6784                 return -1;
 6785         }
 6786         sge = sgl->virt;
 6787 
 6788         if (sli4->config.sgl_pre_registered) {
 6789                 icmnd->xbl = FALSE;
 6790 
 6791                 icmnd->dbde = TRUE;
 6792                 icmnd->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 6793 
 6794                 icmnd->bde.buffer_length = sge[0].buffer_length;
 6795                 icmnd->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 6796                 icmnd->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 6797         } else {
 6798                 icmnd->xbl = TRUE;
 6799 
 6800                 icmnd->bde.bde_type = SLI4_BDE_TYPE_BLP;
 6801 
 6802                 icmnd->bde.buffer_length = sgl->size;
 6803                 icmnd->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 6804                 icmnd->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 6805         }
 6806 
 6807         icmnd->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
 6808         icmnd->xri_tag = xri;
 6809         icmnd->context_tag = rpi;
 6810         icmnd->timer = timeout;
 6811 
 6812         icmnd->pu = 2;  /* WQE word 4 contains read transfer length */
 6813         icmnd->class = SLI4_ELS_REQUEST64_CLASS_3;
 6814         icmnd->command = SLI4_WQE_FCP_ICMND64;
 6815         icmnd->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6816 
 6817         icmnd->abort_tag = xri;
 6818 
 6819         icmnd->request_tag = tag;
 6820         icmnd->len_loc = 3;
 6821         if (rnode->node_group) {
 6822                 icmnd->hlm = TRUE;
 6823                 icmnd->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 6824         }
 6825         if (((ocs_node_t *)rnode->node)->fcp2device) {
 6826                 icmnd->erp = TRUE;
 6827         }
 6828         icmnd->cmd_type = SLI4_CMD_FCP_ICMND64_WQE;
 6829         icmnd->cq_id = cq_id;
 6830 
 6831         return  0;
 6832 }
 6833 
 6834 /**
 6835  * @ingroup sli_fc
 6836  * @brief Write an FCP_IREAD64_WQE work queue entry.
 6837  *
 6838  * @param sli4 SLI context.
 6839  * @param buf Destination buffer for the WQE.
 6840  * @param size Buffer size, in bytes.
 6841  * @param sgl DMA memory for the scatter gather list.
 6842  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
 6843  * @param xfer_len Data transfer length.
 6844  * @param xri XRI for this exchange.
 6845  * @param tag IO tag value.
 6846  * @param cq_id The id of the completion queue where the WQE response is sent.
 6847  * @param rpi remote node indicator (RPI)
 6848  * @param rnode Destination request (i.e. remote node).
 6849  * @param dif T10 DIF operation, or 0 to disable.
 6850  * @param bs T10 DIF block size, or 0 if DIF is disabled.
 6851  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
 6852  *
 6853  * @return Returns 0 on success, or a non-zero value on failure.
 6854  */
 6855 int32_t
 6856 sli_fcp_iread64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
 6857                     uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
 6858                     uint32_t rpi, ocs_remote_node_t *rnode,
 6859                     uint8_t dif, uint8_t bs, uint8_t timeout)
 6860 {
 6861         sli4_fcp_iread64_wqe_t *iread = buf;
 6862         sli4_sge_t      *sge = NULL;
 6863 
 6864         ocs_memset(buf, 0, size);
 6865 
 6866         if (!sgl || !sgl->virt) {
 6867                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 6868                             sgl, sgl ? sgl->virt : NULL);
 6869                 return -1;
 6870         }
 6871         sge = sgl->virt;
 6872 
 6873         if (sli4->config.sgl_pre_registered) {
 6874                 iread->xbl = FALSE;
 6875 
 6876                 iread->dbde = TRUE;
 6877                 iread->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 6878 
 6879                 iread->bde.buffer_length = sge[0].buffer_length;
 6880                 iread->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 6881                 iread->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 6882         } else {
 6883                 iread->xbl = TRUE;
 6884 
 6885                 iread->bde.bde_type = SLI4_BDE_TYPE_BLP;
 6886 
 6887                 iread->bde.buffer_length = sgl->size;
 6888                 iread->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 6889                 iread->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 6890 
 6891                 /* fill out fcp_cmnd buffer len and change resp buffer to be of type
 6892                  * "skip" (note: response will still be written to sge[1] if necessary) */
 6893                 iread->fcp_cmd_buffer_length = sge[0].buffer_length;
 6894                 sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
 6895         }
 6896 
 6897         iread->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
 6898         iread->total_transfer_length = xfer_len;
 6899 
 6900         iread->xri_tag = xri;
 6901         iread->context_tag = rpi;
 6902 
 6903         iread->timer = timeout;
 6904 
 6905         iread->pu = 2;  /* WQE word 4 contains read transfer length */
 6906         iread->class = SLI4_ELS_REQUEST64_CLASS_3;
 6907         iread->command = SLI4_WQE_FCP_IREAD64;
 6908         iread->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 6909         iread->dif = dif;
 6910         iread->bs  = bs;
 6911 
 6912         iread->abort_tag = xri;
 6913 
 6914         iread->request_tag = tag;
 6915         iread->len_loc = 3;
 6916         if (rnode->node_group) {
 6917                 iread->hlm = TRUE;
 6918                 iread->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 6919         }
 6920         if (((ocs_node_t *)rnode->node)->fcp2device) {
 6921                 iread->erp = TRUE;
 6922         }
 6923         iread->iod = 1;
 6924         iread->cmd_type = SLI4_CMD_FCP_IREAD64_WQE;
 6925         iread->cq_id = cq_id;
 6926 
 6927         if (sli4->config.perf_hint) {
 6928                 iread->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 6929                 iread->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
 6930                 iread->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
 6931                 iread->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
 6932         }
 6933 
 6934         return  0;
 6935 }
 6936 
 6937 /**
 6938  * @ingroup sli_fc
 6939  * @brief Write an FCP_IWRITE64_WQE work queue entry.
 6940  *
 6941  * @param sli4 SLI context.
 6942  * @param buf Destination buffer for the WQE.
 6943  * @param size Buffer size, in bytes.
 6944  * @param sgl DMA memory for the scatter gather list.
 6945  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
 6946  * @param xfer_len Data transfer length.
 6947  * @param first_burst The number of first burst bytes
 6948  * @param xri XRI for this exchange.
 6949  * @param tag IO tag value.
 6950  * @param cq_id The id of the completion queue where the WQE response is sent.
 6951  * @param rpi remote node indicator (RPI)
 6952  * @param rnode Destination request (i.e. remote node)
 6953  * @param dif T10 DIF operation, or 0 to disable
 6954  * @param bs T10 DIF block size, or 0 if DIF is disabled
 6955  * @param timeout Time, in seconds, before an IO times out. Zero means no timeout.
 6956  *
 6957  * @return Returns 0 on success, or a non-zero value on failure.
 6958  */
 6959 int32_t
 6960 sli_fcp_iwrite64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
 6961                      uint32_t xfer_len, uint32_t first_burst, uint16_t xri, uint16_t tag, uint16_t cq_id,
 6962                      uint32_t rpi, ocs_remote_node_t *rnode,
 6963                      uint8_t dif, uint8_t bs, uint8_t timeout)
 6964 {
 6965         sli4_fcp_iwrite64_wqe_t *iwrite = buf;
 6966         sli4_sge_t      *sge = NULL;
 6967 
 6968         ocs_memset(buf, 0, size);
 6969 
 6970         if (!sgl || !sgl->virt) {
 6971                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 6972                             sgl, sgl ? sgl->virt : NULL);
 6973                 return -1;
 6974         }
 6975         sge = sgl->virt;
 6976 
 6977         if (sli4->config.sgl_pre_registered) {
 6978                 iwrite->xbl = FALSE;
 6979 
 6980                 iwrite->dbde = TRUE;
 6981                 iwrite->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 6982 
 6983                 iwrite->bde.buffer_length = sge[0].buffer_length;
 6984                 iwrite->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 6985                 iwrite->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 6986         } else {
 6987                 iwrite->xbl = TRUE;
 6988 
 6989                 iwrite->bde.bde_type = SLI4_BDE_TYPE_BLP;
 6990 
 6991                 iwrite->bde.buffer_length = sgl->size;
 6992                 iwrite->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 6993                 iwrite->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 6994 
 6995                 /* fill out fcp_cmnd buffer len and change resp buffer to be of type
 6996                  * "skip" (note: response will still be written to sge[1] if necessary) */
 6997                 iwrite->fcp_cmd_buffer_length = sge[0].buffer_length;
 6998                 sge[1].sge_type = SLI4_SGE_TYPE_SKIP;
 6999         }
 7000 
 7001         iwrite->payload_offset_length = sge[0].buffer_length + sge[1].buffer_length;
 7002         iwrite->total_transfer_length = xfer_len;
 7003         iwrite->initial_transfer_length = MIN(xfer_len, first_burst);
 7004 
 7005         iwrite->xri_tag = xri;
 7006         iwrite->context_tag = rpi;
 7007 
 7008         iwrite->timer = timeout;
 7009 
 7010         iwrite->pu = 2; /* WQE word 4 contains read transfer length */
 7011         iwrite->class = SLI4_ELS_REQUEST64_CLASS_3;
 7012         iwrite->command = SLI4_WQE_FCP_IWRITE64;
 7013         iwrite->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7014         iwrite->dif = dif;
 7015         iwrite->bs  = bs;
 7016 
 7017         iwrite->abort_tag = xri;
 7018 
 7019         iwrite->request_tag = tag;
 7020         iwrite->len_loc = 3;
 7021         if (rnode->node_group) {
 7022                 iwrite->hlm = TRUE;
 7023                 iwrite->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 7024         }
 7025         if (((ocs_node_t *)rnode->node)->fcp2device) {
 7026                 iwrite->erp = TRUE;
 7027         }
 7028         iwrite->cmd_type = SLI4_CMD_FCP_IWRITE64_WQE;
 7029         iwrite->cq_id = cq_id;
 7030 
 7031         if (sli4->config.perf_hint) {
 7032                 iwrite->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7033                 iwrite->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
 7034                 iwrite->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
 7035                 iwrite->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
 7036         }
 7037 
 7038         return  0;
 7039 }
 7040 
 7041 /**
 7042  * @ingroup sli_fc
 7043  * @brief Write an FCP_TRECEIVE64_WQE work queue entry.
 7044  *
 7045  * @param sli4 SLI context.
 7046  * @param buf Destination buffer for the WQE.
 7047  * @param size Buffer size, in bytes.
 7048  * @param sgl DMA memory for the Scatter-Gather List.
 7049  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
 7050  * @param relative_off Relative offset of the IO (if any).
 7051  * @param xfer_len Data transfer length.
 7052  * @param xri XRI for this exchange.
 7053  * @param tag IO tag value.
 7054  * @param xid OX_ID for the exchange.
 7055  * @param cq_id The id of the completion queue where the WQE response is sent.
 7056  * @param rpi remote node indicator (RPI)
 7057  * @param rnode Destination request (i.e. remote node).
 7058  * @param flags Optional attributes, including:
 7059  *  - ACTIVE - IO is already active.
 7060  *  - AUTO RSP - Automatically generate a good FCP_RSP.
 7061  * @param dif T10 DIF operation, or 0 to disable.
 7062  * @param bs T10 DIF block size, or 0 if DIF is disabled.
 7063  * @param csctl value of csctl field.
 7064  * @param app_id value for VM application header.
 7065  *
 7066  * @return Returns 0 on success, or a non-zero value on failure.
 7067  */
 7068 int32_t
 7069 sli_fcp_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
 7070                        uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
 7071                        uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags, uint8_t dif, uint8_t bs,
 7072                        uint8_t csctl, uint32_t app_id)
 7073 {
 7074         sli4_fcp_treceive64_wqe_t *trecv = buf;
 7075         sli4_fcp_128byte_wqe_t *trecv_128 = buf;
 7076         sli4_sge_t      *sge = NULL;
 7077 
 7078         ocs_memset(buf, 0, size);
 7079 
 7080         if (!sgl || !sgl->virt) {
 7081                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 7082                             sgl, sgl ? sgl->virt : NULL);
 7083                 return -1;
 7084         }
 7085         sge = sgl->virt;
 7086 
 7087         if (sli4->config.sgl_pre_registered) {
 7088                 trecv->xbl = FALSE;
 7089 
 7090                 trecv->dbde = TRUE;
 7091                 trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7092 
 7093                 trecv->bde.buffer_length = sge[0].buffer_length;
 7094                 trecv->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 7095                 trecv->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 7096 
 7097                 trecv->payload_offset_length = sge[0].buffer_length;
 7098         } else {
 7099                 trecv->xbl = TRUE;
 7100 
 7101                 /* if data is a single physical address, use a BDE */
 7102                 if (!dif && (xfer_len <= sge[2].buffer_length)) {
 7103                         trecv->dbde = TRUE;
 7104                         trecv->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7105 
 7106                         trecv->bde.buffer_length = sge[2].buffer_length;
 7107                         trecv->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
 7108                         trecv->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
 7109                 } else {
 7110                         trecv->bde.bde_type = SLI4_BDE_TYPE_BLP;
 7111                         trecv->bde.buffer_length = sgl->size;
 7112                         trecv->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 7113                         trecv->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 7114                 }
 7115         }
 7116 
 7117         trecv->relative_offset = relative_off;
 7118 
 7119         if (flags & SLI4_IO_CONTINUATION) {
 7120                 trecv->xc = TRUE;
 7121         }
 7122         trecv->xri_tag = xri;
 7123 
 7124         trecv->context_tag = rpi;
 7125 
 7126         trecv->pu = TRUE;       /* WQE uses relative offset */
 7127 
 7128         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
 7129                 trecv->ar = TRUE;
 7130         }
 7131 
 7132         trecv->command = SLI4_WQE_FCP_TRECEIVE64;
 7133         trecv->class = SLI4_ELS_REQUEST64_CLASS_3;
 7134         trecv->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7135         trecv->dif = dif;
 7136         trecv->bs  = bs;
 7137 
 7138         trecv->remote_xid = xid;
 7139 
 7140         trecv->request_tag = tag;
 7141 
 7142         trecv->iod = 1;
 7143 
 7144         trecv->len_loc = 0x2;
 7145 
 7146         if (rnode->node_group) {
 7147                 trecv->hlm = TRUE;
 7148                 trecv->dword5.dword = rnode->fc_id & 0x00ffffff;
 7149         }
 7150 
 7151         trecv->cmd_type = SLI4_CMD_FCP_TRECEIVE64_WQE;
 7152 
 7153         trecv->cq_id = cq_id;
 7154 
 7155         trecv->fcp_data_receive_length = xfer_len;
 7156 
 7157         if (sli4->config.perf_hint) {
 7158                 trecv->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7159                 trecv->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
 7160                 trecv->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
 7161                 trecv->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
 7162         }
 7163 
 7164         /* The upper 7 bits of csctl is the priority */
 7165         if (csctl & SLI4_MASK_CCP) {
 7166                 trecv->ccpe = 1;
 7167                 trecv->ccp = (csctl & SLI4_MASK_CCP);
 7168         }
 7169 
 7170         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trecv->eat) {
 7171                 trecv->app_id_valid = 1;
 7172                 trecv->wqes = 1;
 7173                 trecv_128->dw[31] = app_id;
 7174         }
 7175         return 0;
 7176 }
 7177 
 7178 /**
 7179  * @ingroup sli_fc
 7180  * @brief Write an FCP_CONT_TRECEIVE64_WQE work queue entry.
 7181  *
 7182  * @param sli4 SLI context.
 7183  * @param buf Destination buffer for the WQE.
 7184  * @param size Buffer size, in bytes.
 7185  * @param sgl DMA memory for the Scatter-Gather List.
 7186  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
 7187  * @param relative_off Relative offset of the IO (if any).
 7188  * @param xfer_len Data transfer length.
 7189  * @param xri XRI for this exchange.
 7190  * @param sec_xri Secondary XRI for this exchange. (BZ 161832 workaround)
 7191  * @param tag IO tag value.
 7192  * @param xid OX_ID for the exchange.
 7193  * @param cq_id The id of the completion queue where the WQE response is sent.
 7194  * @param rpi remote node indicator (RPI)
 7195  * @param rnode Destination request (i.e. remote node).
 7196  * @param flags Optional attributes, including:
 7197  *  - ACTIVE - IO is already active.
 7198  *  - AUTO RSP - Automatically generate a good FCP_RSP.
 7199  * @param dif T10 DIF operation, or 0 to disable.
 7200  * @param bs T10 DIF block size, or 0 if DIF is disabled.
 7201  * @param csctl value of csctl field.
 7202  * @param app_id value for VM application header.
 7203  *
 7204  * @return Returns 0 on success, or a non-zero value on failure.
 7205  */
 7206 int32_t
 7207 sli_fcp_cont_treceive64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
 7208                         uint32_t relative_off, uint32_t xfer_len, uint16_t xri, uint16_t sec_xri, uint16_t tag,
 7209                         uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode, uint32_t flags,
 7210                         uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
 7211 {
 7212         int32_t rc;
 7213 
 7214         rc = sli_fcp_treceive64_wqe(sli4, buf, size, sgl, first_data_sge, relative_off, xfer_len, xri, tag,
 7215                         cq_id, xid, rpi, rnode, flags, dif, bs, csctl, app_id);
 7216         if (rc == 0) {
 7217                 sli4_fcp_treceive64_wqe_t *trecv = buf;
 7218 
 7219                 trecv->command = SLI4_WQE_FCP_CONT_TRECEIVE64;
 7220                 trecv->dword5.sec_xri_tag = sec_xri;
 7221         }
 7222         return rc;
 7223 }
 7224 
 7225 /**
 7226  * @ingroup sli_fc
 7227  * @brief Write an FCP_TRSP64_WQE work queue entry.
 7228  *
 7229  * @param sli4 SLI context.
 7230  * @param buf Destination buffer for the WQE.
 7231  * @param size Buffer size, in bytes.
 7232  * @param sgl DMA memory for the Scatter-Gather List.
 7233  * @param rsp_len Response data length.
 7234  * @param xri XRI for this exchange.
 7235  * @param tag IO tag value.
 7236  * @param cq_id The id of the completion queue where the WQE response is sent.
 7237  * @param xid OX_ID for the exchange.
 7238  * @param rpi remote node indicator (RPI)
 7239  * @param rnode Destination request (i.e. remote node).
 7240  * @param flags Optional attributes, including:
 7241  *  - ACTIVE - IO is already active
 7242  *  - AUTO RSP - Automatically generate a good FCP_RSP.
 7243  * @param csctl value of csctl field.
 7244  * @param port_owned 0/1 to indicate if the XRI is port owned (used to set XBL=0)
 7245  * @param app_id value for VM application header.
 7246  *
 7247  * @return Returns 0 on success, or a non-zero value on failure.
 7248  */
 7249 int32_t
 7250 sli_fcp_trsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t rsp_len,
 7251                    uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
 7252                    uint32_t flags, uint8_t csctl, uint8_t port_owned, uint32_t app_id)
 7253 {
 7254         sli4_fcp_trsp64_wqe_t *trsp = buf;
 7255         sli4_fcp_128byte_wqe_t *trsp_128 = buf;
 7256 
 7257         ocs_memset(buf, 0, size);
 7258 
 7259         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
 7260                 trsp->ag = TRUE;
 7261                 /*
 7262                  * The SLI-4 documentation states that the BDE is ignored when
 7263                  * using auto-good response, but, at least for IF_TYPE 0 devices,
 7264                  * this does not appear to be true.
 7265                  */
 7266                 if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 7267                         trsp->bde.buffer_length = 12;   /* byte size of RSP */
 7268                 }
 7269         } else {
 7270                 sli4_sge_t      *sge = sgl->virt;
 7271 
 7272                 if (sli4->config.sgl_pre_registered || port_owned) {
 7273                         trsp->dbde = TRUE;
 7274                 } else {
 7275                         trsp->xbl = TRUE;
 7276                 }
 7277 
 7278                 trsp->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7279                 trsp->bde.buffer_length = sge[0].buffer_length;
 7280                 trsp->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 7281                 trsp->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 7282 
 7283                 trsp->fcp_response_length = rsp_len;
 7284         }
 7285 
 7286         if (flags & SLI4_IO_CONTINUATION) {
 7287                 trsp->xc = TRUE;
 7288         }
 7289 
 7290         if (rnode->node_group) {
 7291                 trsp->hlm = TRUE;
 7292                 trsp->dword5 = rnode->fc_id & 0x00ffffff;
 7293         }
 7294 
 7295         trsp->xri_tag = xri;
 7296         trsp->rpi = rpi;
 7297 
 7298         trsp->command = SLI4_WQE_FCP_TRSP64;
 7299         trsp->class = SLI4_ELS_REQUEST64_CLASS_3;
 7300 
 7301         trsp->remote_xid = xid;
 7302         trsp->request_tag = tag;
 7303         trsp->dnrx = ((flags & SLI4_IO_DNRX) == 0 ? 0 : 1);
 7304         trsp->len_loc = 0x1;
 7305         trsp->cq_id = cq_id;
 7306         trsp->cmd_type = SLI4_CMD_FCP_TRSP64_WQE;
 7307 
 7308         /* The upper 7 bits of csctl is the priority */
 7309         if (csctl & SLI4_MASK_CCP) {
 7310                 trsp->ccpe = 1;
 7311                 trsp->ccp = (csctl & SLI4_MASK_CCP);
 7312         }
 7313 
 7314         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !trsp->eat) {
 7315                 trsp->app_id_valid = 1;
 7316                 trsp->wqes = 1;
 7317                 trsp_128->dw[31] = app_id;
 7318         }
 7319         return 0;
 7320 }
 7321 
 7322 /**
 7323  * @ingroup sli_fc
 7324  * @brief Write an FCP_TSEND64_WQE work queue entry.
 7325  *
 7326  * @param sli4 SLI context.
 7327  * @param buf Destination buffer for the WQE.
 7328  * @param size Buffer size, in bytes.
 7329  * @param sgl DMA memory for the scatter gather list.
 7330  * @param first_data_sge Index of first data sge (used if perf hints are enabled)
 7331  * @param relative_off Relative offset of the IO (if any).
 7332  * @param xfer_len Data transfer length.
 7333  * @param xri XRI for this exchange.
 7334  * @param tag IO tag value.
 7335  * @param cq_id The id of the completion queue where the WQE response is sent.
 7336  * @param xid OX_ID for the exchange.
 7337  * @param rpi remote node indicator (RPI)
 7338  * @param rnode Destination request (i.e. remote node).
 7339  * @param flags Optional attributes, including:
 7340  *  - ACTIVE - IO is already active.
 7341  *  - AUTO RSP - Automatically generate a good FCP_RSP.
 7342  * @param dif T10 DIF operation, or 0 to disable.
 7343  * @param bs T10 DIF block size, or 0 if DIF is disabled.
 7344  * @param csctl value of csctl field.
 7345  * @param app_id value for VM application header.
 7346  *
 7347  * @return Returns 0 on success, or a non-zero value on failure.
 7348  */
 7349 int32_t
 7350 sli_fcp_tsend64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl, uint32_t first_data_sge,
 7351                     uint32_t relative_off, uint32_t xfer_len,
 7352                     uint16_t xri, uint16_t tag, uint16_t cq_id, uint16_t xid, uint32_t rpi, ocs_remote_node_t *rnode,
 7353                     uint32_t flags, uint8_t dif, uint8_t bs, uint8_t csctl, uint32_t app_id)
 7354 {
 7355         sli4_fcp_tsend64_wqe_t *tsend = buf;
 7356         sli4_fcp_128byte_wqe_t *tsend_128 = buf;
 7357         sli4_sge_t      *sge = NULL;
 7358 
 7359         ocs_memset(buf, 0, size);
 7360 
 7361         if (!sgl || !sgl->virt) {
 7362                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 7363                             sgl, sgl ? sgl->virt : NULL);
 7364                 return -1;
 7365         }
 7366         sge = sgl->virt;
 7367 
 7368         if (sli4->config.sgl_pre_registered) {
 7369                 tsend->xbl = FALSE;
 7370 
 7371                 tsend->dbde = TRUE;
 7372                 tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7373 
 7374                 /* TSEND64_WQE specifies first two SGE are skipped
 7375                  * (i.e. 3rd is valid) */
 7376                 tsend->bde.buffer_length = sge[2].buffer_length;
 7377                 tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
 7378                 tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
 7379         } else {
 7380                 tsend->xbl = TRUE;
 7381 
 7382                 /* if data is a single physical address, use a BDE */
 7383                 if (!dif && (xfer_len <= sge[2].buffer_length)) {
 7384                         tsend->dbde = TRUE;
 7385                         tsend->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7386                         /* TSEND64_WQE specifies first two SGE are skipped
 7387                          * (i.e. 3rd is valid) */
 7388                         tsend->bde.buffer_length = sge[2].buffer_length;
 7389                         tsend->bde.u.data.buffer_address_low  = sge[2].buffer_address_low;
 7390                         tsend->bde.u.data.buffer_address_high = sge[2].buffer_address_high;
 7391                 } else {
 7392                         tsend->bde.bde_type = SLI4_BDE_TYPE_BLP;
 7393                         tsend->bde.buffer_length = sgl->size;
 7394                         tsend->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 7395                         tsend->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 7396                 }
 7397         }
 7398 
 7399         tsend->relative_offset = relative_off;
 7400 
 7401         if (flags & SLI4_IO_CONTINUATION) {
 7402                 tsend->xc = TRUE;
 7403         }
 7404         tsend->xri_tag = xri;
 7405 
 7406         tsend->rpi = rpi;
 7407 
 7408         tsend->pu = TRUE;       /* WQE uses relative offset */
 7409 
 7410         if (flags & SLI4_IO_AUTO_GOOD_RESPONSE) {
 7411                 tsend->ar = TRUE;
 7412         }
 7413 
 7414         tsend->command = SLI4_WQE_FCP_TSEND64;
 7415         tsend->class = SLI4_ELS_REQUEST64_CLASS_3;
 7416         tsend->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7417         tsend->dif = dif;
 7418         tsend->bs  = bs;
 7419 
 7420         tsend->remote_xid = xid;
 7421 
 7422         tsend->request_tag = tag;
 7423 
 7424         tsend->len_loc = 0x2;
 7425 
 7426         if (rnode->node_group) {
 7427                 tsend->hlm = TRUE;
 7428                 tsend->dword5 = rnode->fc_id & 0x00ffffff;
 7429         }
 7430 
 7431         tsend->cq_id = cq_id;
 7432 
 7433         tsend->cmd_type = SLI4_CMD_FCP_TSEND64_WQE;
 7434 
 7435         tsend->fcp_data_transmit_length = xfer_len;
 7436 
 7437         if (sli4->config.perf_hint) {
 7438                 tsend->first_data_bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7439                 tsend->first_data_bde.buffer_length = sge[first_data_sge].buffer_length;
 7440                 tsend->first_data_bde.u.data.buffer_address_low  = sge[first_data_sge].buffer_address_low;
 7441                 tsend->first_data_bde.u.data.buffer_address_high = sge[first_data_sge].buffer_address_high;
 7442         }
 7443 
 7444         /* The upper 7 bits of csctl is the priority */
 7445         if (csctl & SLI4_MASK_CCP) {
 7446                 tsend->ccpe = 1;
 7447                 tsend->ccp = (csctl & SLI4_MASK_CCP);
 7448         }
 7449 
 7450         if (app_id && (sli4->config.wqe_size == SLI4_WQE_EXT_BYTES) && !tsend->eat) {
 7451                 tsend->app_id_valid = 1;
 7452                 tsend->wqes = 1;
 7453                 tsend_128->dw[31] = app_id;
 7454         }
 7455         return 0;
 7456 }
 7457 
 7458 /**
 7459  * @ingroup sli_fc
 7460  * @brief Write a GEN_REQUEST64 work queue entry.
 7461  *
 7462  * @note This WQE is only used to send FC-CT commands.
 7463  *
 7464  * @param sli4 SLI context.
 7465  * @param buf Destination buffer for the WQE.
 7466  * @param size Buffer size, in bytes.
 7467  * @param sgl DMA memory for the request.
 7468  * @param req_len Length of request.
 7469  * @param max_rsp_len Max length of response.
 7470  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
 7471  * @param xri XRI for this exchange.
 7472  * @param tag IO tag value.
 7473  * @param cq_id The id of the completion queue where the WQE response is sent.
 7474  * @param rnode Destination of request (that is, the remote node).
 7475  * @param r_ctl R_CTL value for sequence.
 7476  * @param type TYPE value for sequence.
 7477  * @param df_ctl DF_CTL value for sequence.
 7478  *
 7479  * @return Returns 0 on success, or a non-zero value on failure.
 7480  */
 7481 int32_t
 7482 sli_gen_request64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *sgl,
 7483                       uint32_t req_len, uint32_t max_rsp_len, uint8_t timeout,
 7484                       uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode,
 7485                       uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
 7486 {
 7487         sli4_gen_request64_wqe_t        *gen = buf;
 7488         sli4_sge_t      *sge = NULL;
 7489 
 7490         ocs_memset(buf, 0, size);
 7491 
 7492         if (!sgl || !sgl->virt) {
 7493                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 7494                             sgl, sgl ? sgl->virt : NULL);
 7495                 return -1;
 7496         }
 7497         sge = sgl->virt;
 7498 
 7499         if (sli4->config.sgl_pre_registered) {
 7500                 gen->xbl = FALSE;
 7501 
 7502                 gen->dbde = TRUE;
 7503                 gen->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7504 
 7505                 gen->bde.buffer_length = req_len;
 7506                 gen->bde.u.data.buffer_address_low  = sge[0].buffer_address_low;
 7507                 gen->bde.u.data.buffer_address_high = sge[0].buffer_address_high;
 7508         } else {
 7509                 gen->xbl = TRUE;
 7510 
 7511                 gen->bde.bde_type = SLI4_BDE_TYPE_BLP;
 7512 
 7513                 gen->bde.buffer_length = 2 * sizeof(sli4_sge_t);
 7514                 gen->bde.u.blp.sgl_segment_address_low  = ocs_addr32_lo(sgl->phys);
 7515                 gen->bde.u.blp.sgl_segment_address_high = ocs_addr32_hi(sgl->phys);
 7516         }
 7517 
 7518         gen->request_payload_length = req_len;
 7519         gen->max_response_payload_length = max_rsp_len;
 7520 
 7521         gen->df_ctl = df_ctl;
 7522         gen->type = type;
 7523         gen->r_ctl = r_ctl;
 7524 
 7525         gen->xri_tag = xri;
 7526 
 7527         gen->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7528         gen->context_tag = rnode->indicator;
 7529 
 7530         gen->class = SLI4_ELS_REQUEST64_CLASS_3;
 7531 
 7532         gen->command = SLI4_WQE_GEN_REQUEST64;
 7533 
 7534         gen->timer = timeout;
 7535 
 7536         gen->request_tag = tag;
 7537 
 7538         gen->iod = SLI4_ELS_REQUEST64_DIR_READ;
 7539 
 7540         gen->qosd = TRUE;
 7541 
 7542         if (rnode->node_group) {
 7543                 gen->hlm = TRUE;
 7544                 gen->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 7545         }
 7546 
 7547         gen->cmd_type = SLI4_CMD_GEN_REQUEST64_WQE;
 7548 
 7549         gen->cq_id = cq_id;
 7550 
 7551         return 0;
 7552 }
 7553 
 7554 /**
 7555  * @ingroup sli_fc
 7556  * @brief Write a SEND_FRAME work queue entry
 7557  *
 7558  * @param sli4 SLI context.
 7559  * @param buf Destination buffer for the WQE.
 7560  * @param size Buffer size, in bytes.
 7561  * @param sof Start of frame value
 7562  * @param eof End of frame value
 7563  * @param hdr Pointer to FC header data
 7564  * @param payload DMA memory for the payload.
 7565  * @param req_len Length of payload.
 7566  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
 7567  * @param xri XRI for this exchange.
 7568  * @param req_tag IO tag value.
 7569  *
 7570  * @return Returns 0 on success, or a non-zero value on failure.
 7571  */
 7572 int32_t
 7573 sli_send_frame_wqe(sli4_t *sli4, void *buf, size_t size, uint8_t sof, uint8_t eof, uint32_t *hdr,
 7574                    ocs_dma_t *payload, uint32_t req_len, uint8_t timeout,
 7575                    uint16_t xri, uint16_t req_tag)
 7576 {
 7577         sli4_send_frame_wqe_t *sf = buf;
 7578 
 7579         ocs_memset(buf, 0, size);
 7580 
 7581         sf->dbde = TRUE;
 7582         sf->bde.buffer_length = req_len;
 7583         sf->bde.u.data.buffer_address_low = ocs_addr32_lo(payload->phys);
 7584         sf->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
 7585 
 7586         /* Copy FC header */
 7587         sf->fc_header_0_1[0] = hdr[0];
 7588         sf->fc_header_0_1[1] = hdr[1];
 7589         sf->fc_header_2_5[0] = hdr[2];
 7590         sf->fc_header_2_5[1] = hdr[3];
 7591         sf->fc_header_2_5[2] = hdr[4];
 7592         sf->fc_header_2_5[3] = hdr[5];
 7593 
 7594         sf->frame_length = req_len;
 7595 
 7596         sf->xri_tag = xri;
 7597         sf->pu = 0;
 7598         sf->context_tag = 0;
 7599 
 7600         sf->ct = 0;
 7601         sf->command = SLI4_WQE_SEND_FRAME;
 7602         sf->class = SLI4_ELS_REQUEST64_CLASS_3;
 7603         sf->timer = timeout;
 7604 
 7605         sf->request_tag = req_tag;
 7606         sf->eof = eof;
 7607         sf->sof = sof;
 7608 
 7609         sf->qosd = 0;
 7610         sf->lenloc = 1;
 7611         sf->xc = 0;
 7612 
 7613         sf->xbl = 1;
 7614 
 7615         sf->cmd_type = SLI4_CMD_SEND_FRAME_WQE;
 7616         sf->cq_id = 0xffff;
 7617 
 7618         return 0;
 7619 }
 7620 
 7621 /**
 7622  * @ingroup sli_fc
 7623  * @brief Write a XMIT_SEQUENCE64 work queue entry.
 7624  *
 7625  * This WQE is used to send FC-CT response frames.
 7626  *
 7627  * @note This API implements a restricted use for this WQE, a TODO: would
 7628  * include passing in sequence initiative, and full SGL's
 7629  *
 7630  * @param sli4 SLI context.
 7631  * @param buf Destination buffer for the WQE.
 7632  * @param size Buffer size, in bytes.
 7633  * @param payload DMA memory for the request.
 7634  * @param payload_len Length of request.
 7635  * @param timeout Time, in seconds, before an IO times out. Zero means infinite.
 7636  * @param ox_id originator exchange ID
 7637  * @param xri XRI for this exchange.
 7638  * @param tag IO tag value.
 7639  * @param rnode Destination of request (that is, the remote node).
 7640  * @param r_ctl R_CTL value for sequence.
 7641  * @param type TYPE value for sequence.
 7642  * @param df_ctl DF_CTL value for sequence.
 7643  *
 7644  * @return Returns 0 on success, or a non-zero value on failure.
 7645  */
 7646 int32_t
 7647 sli_xmit_sequence64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
 7648                       uint32_t payload_len, uint8_t timeout, uint16_t ox_id,
 7649                       uint16_t xri, uint16_t tag, ocs_remote_node_t *rnode,
 7650                       uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
 7651 {
 7652         sli4_xmit_sequence64_wqe_t      *xmit = buf;
 7653 
 7654         ocs_memset(buf, 0, size);
 7655 
 7656         if ((payload == NULL) || (payload->virt == NULL)) {
 7657                 ocs_log_err(sli4->os, "bad parameter sgl=%p virt=%p\n",
 7658                             payload, payload ? payload->virt : NULL);
 7659                 return -1;
 7660         }
 7661 
 7662         if (sli4->config.sgl_pre_registered) {
 7663                 xmit->dbde = TRUE;
 7664         } else {
 7665                 xmit->xbl = TRUE;
 7666         }
 7667 
 7668         xmit->bde.bde_type = SLI4_BDE_TYPE_BDE_64;
 7669         xmit->bde.buffer_length = payload_len;
 7670         xmit->bde.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
 7671         xmit->bde.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
 7672         xmit->sequence_payload_len = payload_len;
 7673 
 7674         xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 7675 
 7676         xmit->relative_offset = 0;
 7677 
 7678         xmit->si = 0;                   /* sequence initiative - this matches what is seen from
 7679                                          * FC switches in response to FCGS commands */
 7680         xmit->ft = 0;                   /* force transmit */
 7681         xmit->xo = 0;                   /* exchange responder */
 7682         xmit->ls = 1;                   /* last in seqence */
 7683         xmit->df_ctl = df_ctl;
 7684         xmit->type = type;
 7685         xmit->r_ctl = r_ctl;
 7686 
 7687         xmit->xri_tag = xri;
 7688         xmit->context_tag = rnode->indicator;
 7689 
 7690         xmit->dif = 0;
 7691         xmit->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7692         xmit->bs = 0;
 7693 
 7694         xmit->command = SLI4_WQE_XMIT_SEQUENCE64;
 7695         xmit->class = SLI4_ELS_REQUEST64_CLASS_3;
 7696         xmit->pu = 0;
 7697         xmit->timer = timeout;
 7698 
 7699         xmit->abort_tag = 0;
 7700         xmit->request_tag = tag;
 7701         xmit->remote_xid = ox_id;
 7702 
 7703         xmit->iod = SLI4_ELS_REQUEST64_DIR_READ;
 7704 
 7705         if (rnode->node_group) {
 7706                 xmit->hlm = TRUE;
 7707                 xmit->remote_n_port_id = rnode->fc_id & 0x00ffffff;
 7708         }
 7709 
 7710         xmit->cmd_type = SLI4_CMD_XMIT_SEQUENCE64_WQE;
 7711 
 7712         xmit->len_loc = 2;
 7713 
 7714         xmit->cq_id = 0xFFFF;
 7715 
 7716         return 0;
 7717 }
 7718 
 7719 /**
 7720  * @ingroup sli_fc
 7721  * @brief Write a REQUEUE_XRI_WQE work queue entry.
 7722  *
 7723  * @param sli4 SLI context.
 7724  * @param buf Destination buffer for the WQE.
 7725  * @param size Buffer size, in bytes.
 7726  * @param xri XRI for this exchange.
 7727  * @param tag IO tag value.
 7728  * @param cq_id The id of the completion queue where the WQE response is sent.
 7729  *
 7730  * @return Returns 0 on success, or a non-zero value on failure.
 7731  */
 7732 int32_t
 7733 sli_requeue_xri_wqe(sli4_t *sli4, void *buf, size_t size, uint16_t xri, uint16_t tag, uint16_t cq_id)
 7734 {
 7735         sli4_requeue_xri_wqe_t  *requeue = buf;
 7736 
 7737         ocs_memset(buf, 0, size);
 7738 
 7739         requeue->command = SLI4_WQE_REQUEUE_XRI;
 7740         requeue->xri_tag = xri;
 7741         requeue->request_tag = tag;
 7742         requeue->xc = 1;
 7743         requeue->qosd = 1;
 7744         requeue->cq_id = cq_id;
 7745         requeue->cmd_type = SLI4_CMD_REQUEUE_XRI_WQE;
 7746         return 0;
 7747 }
 7748 
 7749 int32_t
 7750 sli_xmit_bcast64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *payload,
 7751                 uint32_t payload_len, uint8_t timeout, uint16_t xri, uint16_t tag,
 7752                 uint16_t cq_id, ocs_remote_node_t *rnode,
 7753                 uint8_t r_ctl, uint8_t type, uint8_t df_ctl)
 7754 {
 7755         sli4_xmit_bcast64_wqe_t *bcast = buf;
 7756 
 7757         /* Command requires a temporary RPI (i.e. unused remote node) */
 7758         if (rnode->attached) {
 7759                 ocs_log_test(sli4->os, "remote node %d in use\n", rnode->indicator);
 7760                 return -1;
 7761         }
 7762 
 7763         ocs_memset(buf, 0, size);
 7764 
 7765         bcast->dbde = TRUE;
 7766         bcast->sequence_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
 7767         bcast->sequence_payload.buffer_length = payload_len;
 7768         bcast->sequence_payload.u.data.buffer_address_low  = ocs_addr32_lo(payload->phys);
 7769         bcast->sequence_payload.u.data.buffer_address_high = ocs_addr32_hi(payload->phys);
 7770 
 7771         bcast->sequence_payload_length = payload_len;
 7772 
 7773         bcast->df_ctl = df_ctl;
 7774         bcast->type = type;
 7775         bcast->r_ctl = r_ctl;
 7776 
 7777         bcast->xri_tag = xri;
 7778 
 7779         bcast->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 7780         bcast->context_tag = rnode->sport->indicator;
 7781 
 7782         bcast->class = SLI4_ELS_REQUEST64_CLASS_3;
 7783 
 7784         bcast->command = SLI4_WQE_XMIT_BCAST64;
 7785 
 7786         bcast->timer = timeout;
 7787 
 7788         bcast->request_tag = tag;
 7789 
 7790         bcast->temporary_rpi = rnode->indicator;
 7791 
 7792         bcast->len_loc = 0x1;
 7793 
 7794         bcast->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
 7795 
 7796         bcast->cmd_type = SLI4_CMD_XMIT_BCAST64_WQE;
 7797 
 7798         bcast->cq_id = cq_id;
 7799 
 7800         return 0;
 7801 }
 7802 
 7803 /**
 7804  * @ingroup sli_fc
 7805  * @brief Write an XMIT_BLS_RSP64_WQE work queue entry.
 7806  *
 7807  * @param sli4 SLI context.
 7808  * @param buf Destination buffer for the WQE.
 7809  * @param size Buffer size, in bytes.
 7810  * @param payload Contents of the BLS payload to be sent.
 7811  * @param xri XRI for this exchange.
 7812  * @param tag IO tag value.
 7813  * @param cq_id The id of the completion queue where the WQE response is sent.
 7814  * @param rnode Destination of request (that is, the remote node).
 7815  * @param s_id Source ID to use in the response. If UINT32_MAX, use SLI Port's ID.
 7816  *
 7817  * @return Returns 0 on success, or a non-zero value on failure.
 7818  */
 7819 int32_t
 7820 sli_xmit_bls_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, sli_bls_payload_t *payload,
 7821                        uint16_t xri, uint16_t tag, uint16_t cq_id, ocs_remote_node_t *rnode, uint32_t s_id)
 7822 {
 7823         sli4_xmit_bls_rsp_wqe_t *bls = buf;
 7824 
 7825         /*
 7826          * Callers can either specify RPI or S_ID, but not both
 7827          */
 7828         if (rnode->attached && (s_id != UINT32_MAX)) {
 7829                 ocs_log_test(sli4->os, "S_ID specified for attached remote node %d\n",
 7830                              rnode->indicator);
 7831                 return -1;
 7832         }
 7833 
 7834         ocs_memset(buf, 0, size);
 7835 
 7836         if (SLI_BLS_ACC == payload->type) {
 7837                 bls->payload_word0 = (payload->u.acc.seq_id_last << 16) |
 7838                         (payload->u.acc.seq_id_validity << 24);
 7839                 bls->high_seq_cnt = payload->u.acc.high_seq_cnt;
 7840                 bls->low_seq_cnt = payload->u.acc.low_seq_cnt;
 7841         } else if (SLI_BLS_RJT == payload->type) {
 7842                 bls->payload_word0 = *((uint32_t *)&payload->u.rjt);
 7843                 bls->ar = TRUE;
 7844         } else {
 7845                 ocs_log_test(sli4->os, "bad BLS type %#x\n",
 7846                                 payload->type);
 7847                 return -1;
 7848         }
 7849 
 7850         bls->ox_id = payload->ox_id;
 7851         bls->rx_id = payload->rx_id;
 7852 
 7853         if (rnode->attached) {
 7854                 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7855                 bls->context_tag = rnode->indicator;
 7856         } else {
 7857                 bls->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 7858                 bls->context_tag = rnode->sport->indicator;
 7859 
 7860                 if (UINT32_MAX != s_id) {
 7861                         bls->local_n_port_id = s_id & 0x00ffffff;
 7862                 } else {
 7863                         bls->local_n_port_id = rnode->sport->fc_id & 0x00ffffff;
 7864                 }
 7865                 bls->remote_id = rnode->fc_id & 0x00ffffff;
 7866 
 7867                 bls->temporary_rpi = rnode->indicator;
 7868         }
 7869 
 7870         bls->xri_tag = xri;
 7871 
 7872         bls->class = SLI4_ELS_REQUEST64_CLASS_3;
 7873 
 7874         bls->command = SLI4_WQE_XMIT_BLS_RSP;
 7875 
 7876         bls->request_tag = tag;
 7877 
 7878         bls->qosd = TRUE;
 7879 
 7880         if (rnode->node_group) {
 7881                 bls->hlm = TRUE;
 7882                 bls->remote_id = rnode->fc_id & 0x00ffffff;
 7883         }
 7884 
 7885         bls->cq_id = cq_id;
 7886 
 7887         bls->cmd_type = SLI4_CMD_XMIT_BLS_RSP64_WQE;
 7888 
 7889         return 0;
 7890 }
 7891 
 7892 /**
 7893  * @ingroup sli_fc
 7894  * @brief Write a XMIT_ELS_RSP64_WQE work queue entry.
 7895  *
 7896  * @param sli4 SLI context.
 7897  * @param buf Destination buffer for the WQE.
 7898  * @param size Buffer size, in bytes.
 7899  * @param rsp DMA memory for the ELS response.
 7900  * @param rsp_len Length of ELS response, in bytes.
 7901  * @param xri XRI for this exchange.
 7902  * @param tag IO tag value.
 7903  * @param cq_id The id of the completion queue where the WQE response is sent.
 7904  * @param ox_id OX_ID of the exchange containing the request.
 7905  * @param rnode Destination of the ELS response (that is, the remote node).
 7906  * @param flags Optional attributes, including:
 7907  *  - SLI4_IO_CONTINUATION - IO is already active.
 7908  * @param s_id S_ID used for special responses.
 7909  *
 7910  * @return Returns 0 on success, or a non-zero value on failure.
 7911  */
 7912 int32_t
 7913 sli_xmit_els_rsp64_wqe(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *rsp,
 7914                        uint32_t rsp_len, uint16_t xri, uint16_t tag, uint16_t cq_id,
 7915                        uint16_t ox_id, ocs_remote_node_t *rnode, uint32_t flags, uint32_t s_id)
 7916 {
 7917         sli4_xmit_els_rsp64_wqe_t       *els = buf;
 7918 
 7919         ocs_memset(buf, 0, size);
 7920 
 7921         if (sli4->config.sgl_pre_registered) {
 7922                 els->dbde = TRUE;
 7923         } else {
 7924                 els->xbl = TRUE;
 7925         }
 7926 
 7927         els->els_response_payload.bde_type = SLI4_BDE_TYPE_BDE_64;
 7928         els->els_response_payload.buffer_length = rsp_len;
 7929         els->els_response_payload.u.data.buffer_address_low  = ocs_addr32_lo(rsp->phys);
 7930         els->els_response_payload.u.data.buffer_address_high = ocs_addr32_hi(rsp->phys);
 7931 
 7932         els->els_response_payload_length = rsp_len;
 7933 
 7934         els->xri_tag = xri;
 7935 
 7936         els->class = SLI4_ELS_REQUEST64_CLASS_3;
 7937 
 7938         els->command = SLI4_WQE_ELS_RSP64;
 7939 
 7940         els->request_tag = tag;
 7941 
 7942         els->ox_id = ox_id;
 7943 
 7944         els->iod = SLI4_ELS_REQUEST64_DIR_WRITE;
 7945 
 7946         els->qosd = TRUE;
 7947 
 7948         if (flags & SLI4_IO_CONTINUATION) {
 7949                 els->xc = TRUE;
 7950         }
 7951 
 7952         if (rnode->attached) {
 7953                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_RPI;
 7954                 els->context_tag = rnode->indicator;
 7955         } else {
 7956                 els->ct = SLI4_ELS_REQUEST64_CONTEXT_VPI;
 7957                 els->context_tag = rnode->sport->indicator;
 7958                 els->remote_id = rnode->fc_id & 0x00ffffff;
 7959                 els->temporary_rpi = rnode->indicator;
 7960                 if (UINT32_MAX != s_id) {
 7961                         els->sp = TRUE;
 7962                         els->s_id = s_id & 0x00ffffff;
 7963                 }
 7964         }
 7965 
 7966         if (rnode->node_group) {
 7967                 els->hlm = TRUE;
 7968                 els->remote_id = rnode->fc_id & 0x00ffffff;
 7969         }
 7970 
 7971         els->cmd_type = SLI4_ELS_REQUEST64_CMD_GEN;
 7972 
 7973         els->cq_id = cq_id;
 7974 
 7975         return 0;
 7976 }
 7977 
 7978 /**
 7979  * @ingroup sli_fc
 7980  * @brief Process an asynchronous Link State event entry.
 7981  *
 7982  * @par Description
 7983  * Parses Asynchronous Completion Queue Entry (ACQE),
 7984  * creates an abstracted event, and calls registered callback functions.
 7985  *
 7986  * @param sli4 SLI context.
 7987  * @param acqe Pointer to the ACQE.
 7988  *
 7989  * @return Returns 0 on success, or a non-zero value on failure.
 7990  */
 7991 int32_t
 7992 sli_fc_process_link_state(sli4_t *sli4, void *acqe)
 7993 {
 7994         sli4_link_state_t       *link_state = acqe;
 7995         sli4_link_event_t       event = { 0 };
 7996         int32_t                 rc = 0;
 7997 
 7998         if (!sli4->link) {
 7999                 /* bail if there is no callback */
 8000                 return 0;
 8001         }
 8002 
 8003         if (SLI4_LINK_TYPE_ETHERNET == link_state->link_type) {
 8004                 event.topology = SLI_LINK_TOPO_NPORT;
 8005                 event.medium   = SLI_LINK_MEDIUM_ETHERNET;
 8006         } else {
 8007                 /* TODO is this supported for anything other than FCoE? */
 8008                 ocs_log_test(sli4->os, "unsupported link type %#x\n",
 8009                                 link_state->link_type);
 8010                 event.topology = SLI_LINK_TOPO_MAX;
 8011                 event.medium   = SLI_LINK_MEDIUM_MAX;
 8012                 rc = -1;
 8013         }
 8014 
 8015         switch (link_state->port_link_status) {
 8016         case SLI4_PORT_LINK_STATUS_PHYSICAL_DOWN:
 8017         case SLI4_PORT_LINK_STATUS_LOGICAL_DOWN:
 8018                 event.status = SLI_LINK_STATUS_DOWN;
 8019                 break;
 8020         case SLI4_PORT_LINK_STATUS_PHYSICAL_UP:
 8021         case SLI4_PORT_LINK_STATUS_LOGICAL_UP:
 8022                 event.status = SLI_LINK_STATUS_UP;
 8023                 break;
 8024         default:
 8025                 ocs_log_test(sli4->os, "unsupported link status %#x\n",
 8026                                 link_state->port_link_status);
 8027                 event.status = SLI_LINK_STATUS_MAX;
 8028                 rc = -1;
 8029         }
 8030 
 8031         switch (link_state->port_speed) {
 8032         case 0:
 8033                 event.speed = 0;
 8034                 break;
 8035         case 1:
 8036                 event.speed = 10;
 8037                 break;
 8038         case 2:
 8039                 event.speed = 100;
 8040                 break;
 8041         case 3:
 8042                 event.speed = 1000;
 8043                 break;
 8044         case 4:
 8045                 event.speed = 10000;
 8046                 break;
 8047         case 5:
 8048                 event.speed = 20000;
 8049                 break;
 8050         case 6:
 8051                 event.speed = 25000;
 8052                 break;
 8053         case 7:
 8054                 event.speed = 40000;
 8055                 break;
 8056         case 8:
 8057                 event.speed = 100000;
 8058                 break;
 8059         default:
 8060                 ocs_log_test(sli4->os, "unsupported port_speed %#x\n",
 8061                                 link_state->port_speed);
 8062                 rc = -1;
 8063         }
 8064 
 8065         sli4->link(sli4->link_arg, (void *)&event);
 8066 
 8067         return rc;
 8068 }
 8069 
 8070 /**
 8071  * @ingroup sli_fc
 8072  * @brief Process an asynchronous Link Attention event entry.
 8073  *
 8074  * @par Description
 8075  * Parses Asynchronous Completion Queue Entry (ACQE),
 8076  * creates an abstracted event, and calls the registered callback functions.
 8077  *
 8078  * @param sli4 SLI context.
 8079  * @param acqe Pointer to the ACQE.
 8080  *
 8081  * @todo XXX all events return LINK_UP.
 8082  *
 8083  * @return Returns 0 on success, or a non-zero value on failure.
 8084  */
 8085 int32_t
 8086 sli_fc_process_link_attention(sli4_t *sli4, void *acqe)
 8087 {
 8088         sli4_link_attention_t   *link_attn = acqe;
 8089         sli4_link_event_t       event = { 0 };
 8090 
 8091         ocs_log_debug(sli4->os, "link_number=%d attn_type=%#x topology=%#x port_speed=%#x "
 8092                         "port_fault=%#x shared_link_status=%#x logical_link_speed=%#x "
 8093                         "event_tag=%#x\n", link_attn->link_number, link_attn->attn_type,
 8094                         link_attn->topology, link_attn->port_speed, link_attn->port_fault,
 8095                         link_attn->shared_link_status, link_attn->logical_link_speed,
 8096                         link_attn->event_tag);
 8097 
 8098         if (!sli4->link) {
 8099                 return 0;
 8100         }
 8101 
 8102         event.medium   = SLI_LINK_MEDIUM_FC;
 8103 
 8104         switch (link_attn->attn_type) {
 8105         case SLI4_LINK_ATTN_TYPE_LINK_UP:
 8106                 event.status = SLI_LINK_STATUS_UP;
 8107                 break;
 8108         case SLI4_LINK_ATTN_TYPE_LINK_DOWN:
 8109                 event.status = SLI_LINK_STATUS_DOWN;
 8110                 break;
 8111         case SLI4_LINK_ATTN_TYPE_NO_HARD_ALPA:
 8112                 ocs_log_debug(sli4->os, "attn_type: no hard alpa\n");
 8113                 event.status = SLI_LINK_STATUS_NO_ALPA;
 8114                 break;
 8115         default:
 8116                 ocs_log_test(sli4->os, "attn_type: unknown\n");
 8117                 break;
 8118         }
 8119 
 8120         switch (link_attn->event_type) {
 8121         case SLI4_FC_EVENT_LINK_ATTENTION:
 8122                 break;
 8123         case SLI4_FC_EVENT_SHARED_LINK_ATTENTION:
 8124                 ocs_log_debug(sli4->os, "event_type: FC shared link event \n");
 8125                 break;
 8126         default:
 8127                 ocs_log_test(sli4->os, "event_type: unknown\n");
 8128                 break;
 8129         }
 8130 
 8131         switch (link_attn->topology) {
 8132         case SLI4_LINK_ATTN_P2P:
 8133                 event.topology = SLI_LINK_TOPO_NPORT;
 8134                 break;
 8135         case SLI4_LINK_ATTN_FC_AL:
 8136                 event.topology = SLI_LINK_TOPO_LOOP;
 8137                 break;
 8138         case SLI4_LINK_ATTN_INTERNAL_LOOPBACK:
 8139                 ocs_log_debug(sli4->os, "topology Internal loopback\n");
 8140                 event.topology = SLI_LINK_TOPO_LOOPBACK_INTERNAL;
 8141                 break;
 8142         case SLI4_LINK_ATTN_SERDES_LOOPBACK:
 8143                 ocs_log_debug(sli4->os, "topology serdes loopback\n");
 8144                 event.topology = SLI_LINK_TOPO_LOOPBACK_EXTERNAL;
 8145                 break;
 8146         default:
 8147                 ocs_log_test(sli4->os, "topology: unknown\n");
 8148                 break;
 8149         }
 8150 
 8151         event.speed    = link_attn->port_speed * 1000;
 8152 
 8153         sli4->link(sli4->link_arg, (void *)&event);
 8154 
 8155         return 0;
 8156 }
 8157 
 8158 /**
 8159  * @ingroup sli_fc
 8160  * @brief Parse an FC/FCoE work queue CQ entry.
 8161  *
 8162  * @param sli4 SLI context.
 8163  * @param cq CQ to process.
 8164  * @param cqe Pointer to the CQ entry.
 8165  * @param etype CQ event type.
 8166  * @param r_id Resource ID associated with this completion message (such as the IO tag).
 8167  *
 8168  * @return Returns 0 on success, or a non-zero value on failure.
 8169  */
 8170 int32_t
 8171 sli_fc_cqe_parse(sli4_t *sli4, sli4_queue_t *cq, uint8_t *cqe, sli4_qentry_e *etype,
 8172                 uint16_t *r_id)
 8173 {
 8174         uint8_t         code = cqe[SLI4_CQE_CODE_OFFSET];
 8175         int32_t         rc = -1;
 8176 
 8177         switch (code) {
 8178         case SLI4_CQE_CODE_WORK_REQUEST_COMPLETION:
 8179         {
 8180                 sli4_fc_wcqe_t *wcqe = (void *)cqe;
 8181 
 8182                 *etype = SLI_QENTRY_WQ;
 8183                 *r_id = wcqe->request_tag;
 8184                 rc = wcqe->status;
 8185 
 8186                 /* Flag errors except for FCP_RSP_FAILURE */
 8187                 if (rc && (rc != SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE)) {
 8188                         ocs_log_test(sli4->os, "WCQE: status=%#x hw_status=%#x tag=%#x w1=%#x w2=%#x xb=%d\n",
 8189                                 wcqe->status, wcqe->hw_status,
 8190                                 wcqe->request_tag, wcqe->wqe_specific_1,
 8191                                 wcqe->wqe_specific_2, wcqe->xb);
 8192                         ocs_log_test(sli4->os, "      %08X %08X %08X %08X\n", ((uint32_t*) cqe)[0], ((uint32_t*) cqe)[1],
 8193                                 ((uint32_t*) cqe)[2], ((uint32_t*) cqe)[3]);
 8194                 }
 8195 
 8196                 /* TODO: need to pass additional status back out of here as well
 8197                  * as status (could overload rc as status/addlstatus are only 8 bits each)
 8198                  */
 8199 
 8200                 break;
 8201         }
 8202         case SLI4_CQE_CODE_RQ_ASYNC:
 8203         {
 8204                 sli4_fc_async_rcqe_t *rcqe = (void *)cqe;
 8205 
 8206                 *etype = SLI_QENTRY_RQ;
 8207                 *r_id = rcqe->rq_id;
 8208                 rc = rcqe->status;
 8209                 break;
 8210         }
 8211         case SLI4_CQE_CODE_RQ_ASYNC_V1:
 8212         {
 8213                 sli4_fc_async_rcqe_v1_t *rcqe = (void *)cqe;
 8214 
 8215                 *etype = SLI_QENTRY_RQ;
 8216                 *r_id = rcqe->rq_id;
 8217                 rc = rcqe->status;
 8218                 break;
 8219         }
 8220         case SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD:
 8221         {
 8222                 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
 8223 
 8224                 *etype = SLI_QENTRY_OPT_WRITE_CMD;
 8225                 *r_id = optcqe->rq_id;
 8226                 rc = optcqe->status;
 8227                 break;
 8228         }
 8229         case SLI4_CQE_CODE_OPTIMIZED_WRITE_DATA:
 8230         {
 8231                 sli4_fc_optimized_write_data_cqe_t *dcqe = (void *)cqe;
 8232 
 8233                 *etype = SLI_QENTRY_OPT_WRITE_DATA;
 8234                 *r_id = dcqe->xri;
 8235                 rc = dcqe->status;
 8236 
 8237                 /* Flag errors */
 8238                 if (rc != SLI4_FC_WCQE_STATUS_SUCCESS) {
 8239                         ocs_log_test(sli4->os, "Optimized DATA CQE: status=%#x hw_status=%#x xri=%#x dpl=%#x w3=%#x xb=%d\n",
 8240                                 dcqe->status, dcqe->hw_status,
 8241                                 dcqe->xri, dcqe->total_data_placed,
 8242                                 ((uint32_t*) cqe)[3], dcqe->xb);
 8243                 }
 8244                 break;
 8245         }
 8246         case SLI4_CQE_CODE_RQ_COALESCING:
 8247         {
 8248                 sli4_fc_coalescing_rcqe_t *rcqe = (void *)cqe;
 8249 
 8250                 *etype = SLI_QENTRY_RQ;
 8251                 *r_id = rcqe->rq_id;
 8252                 rc = rcqe->status;
 8253                 break;
 8254         }
 8255         case SLI4_CQE_CODE_XRI_ABORTED:
 8256         {
 8257                 sli4_fc_xri_aborted_cqe_t *xa = (void *)cqe;
 8258 
 8259                 *etype = SLI_QENTRY_XABT;
 8260                 *r_id = xa->xri;
 8261                 rc = 0;
 8262                 break;
 8263         }
 8264         case SLI4_CQE_CODE_RELEASE_WQE: {
 8265                 sli4_fc_wqec_t *wqec = (void*) cqe;
 8266 
 8267                 *etype = SLI_QENTRY_WQ_RELEASE;
 8268                 *r_id = wqec->wq_id;
 8269                 rc = 0;
 8270                 break;
 8271         }
 8272         default:
 8273                 ocs_log_test(sli4->os, "CQE completion code %d not handled\n", code);
 8274                 *etype = SLI_QENTRY_MAX;
 8275                 *r_id = UINT16_MAX;
 8276         }
 8277 
 8278         return rc;
 8279 }
 8280 
 8281 /**
 8282  * @ingroup sli_fc
 8283  * @brief Return the ELS/CT response length.
 8284  *
 8285  * @param sli4 SLI context.
 8286  * @param cqe Pointer to the CQ entry.
 8287  *
 8288  * @return Returns the length, in bytes.
 8289  */
 8290 uint32_t
 8291 sli_fc_response_length(sli4_t *sli4, uint8_t *cqe)
 8292 {
 8293         sli4_fc_wcqe_t *wcqe = (void *)cqe;
 8294 
 8295         return wcqe->wqe_specific_1;
 8296 }
 8297 
 8298 /**
 8299  * @ingroup sli_fc
 8300  * @brief Return the FCP IO length.
 8301  *
 8302  * @param sli4 SLI context.
 8303  * @param cqe Pointer to the CQ entry.
 8304  *
 8305  * @return Returns the length, in bytes.
 8306  */
 8307 uint32_t
 8308 sli_fc_io_length(sli4_t *sli4, uint8_t *cqe)
 8309 {
 8310         sli4_fc_wcqe_t *wcqe = (void *)cqe;
 8311 
 8312         return wcqe->wqe_specific_1;
 8313 }
 8314 
 8315 /**
 8316  * @ingroup sli_fc
 8317  * @brief Retrieve the D_ID from the completion.
 8318  *
 8319  * @param sli4 SLI context.
 8320  * @param cqe Pointer to the CQ entry.
 8321  * @param d_id Pointer where the D_ID is written.
 8322  *
 8323  * @return Returns 0 on success, or a non-zero value on failure.
 8324  */
 8325 int32_t
 8326 sli_fc_els_did(sli4_t *sli4, uint8_t *cqe, uint32_t *d_id)
 8327 {
 8328         sli4_fc_wcqe_t *wcqe = (void *)cqe;
 8329 
 8330         *d_id = 0;
 8331 
 8332         if (wcqe->status) {
 8333                 return -1;
 8334         } else {
 8335                 *d_id = wcqe->wqe_specific_2 & 0x00ffffff;
 8336                 return 0;
 8337         }
 8338 }
 8339 
 8340 uint32_t
 8341 sli_fc_ext_status(sli4_t *sli4, uint8_t *cqe)
 8342 {
 8343         sli4_fc_wcqe_t *wcqe = (void *)cqe;
 8344         uint32_t        mask;
 8345 
 8346         switch (wcqe->status) {
 8347         case SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE:
 8348                 mask = UINT32_MAX;
 8349                 break;
 8350         case SLI4_FC_WCQE_STATUS_LOCAL_REJECT:
 8351         case SLI4_FC_WCQE_STATUS_CMD_REJECT:
 8352                 mask = 0xff;
 8353                 break;
 8354         case SLI4_FC_WCQE_STATUS_NPORT_RJT:
 8355         case SLI4_FC_WCQE_STATUS_FABRIC_RJT:
 8356         case SLI4_FC_WCQE_STATUS_NPORT_BSY:
 8357         case SLI4_FC_WCQE_STATUS_FABRIC_BSY:
 8358         case SLI4_FC_WCQE_STATUS_LS_RJT:
 8359                 mask = UINT32_MAX;
 8360                 break;
 8361         case SLI4_FC_WCQE_STATUS_DI_ERROR:
 8362                 mask = UINT32_MAX;
 8363                 break;
 8364         default:
 8365                 mask = 0;
 8366         }
 8367 
 8368         return wcqe->wqe_specific_2 & mask;
 8369 }
 8370 
 8371 /**
 8372  * @ingroup sli_fc
 8373  * @brief Retrieve the RQ index from the completion.
 8374  *
 8375  * @param sli4 SLI context.
 8376  * @param cqe Pointer to the CQ entry.
 8377  * @param rq_id Pointer where the rq_id is written.
 8378  * @param index Pointer where the index is written.
 8379  *
 8380  * @return Returns 0 on success, or a non-zero value on failure.
 8381  */
 8382 int32_t
 8383 sli_fc_rqe_rqid_and_index(sli4_t *sli4, uint8_t *cqe, uint16_t *rq_id, uint32_t *index)
 8384 {
 8385         sli4_fc_async_rcqe_t    *rcqe = (void *)cqe;
 8386         sli4_fc_async_rcqe_v1_t *rcqe_v1 = (void *)cqe;
 8387         int32_t rc = -1;
 8388         uint8_t code = 0;
 8389 
 8390         *rq_id = 0;
 8391         *index = UINT32_MAX;
 8392 
 8393         code = cqe[SLI4_CQE_CODE_OFFSET];
 8394 
 8395         if (code == SLI4_CQE_CODE_RQ_ASYNC) {
 8396                 *rq_id = rcqe->rq_id;
 8397                 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe->status) {
 8398                         *index = rcqe->rq_element_index;
 8399                         rc = 0;
 8400                 } else {
 8401                         *index = rcqe->rq_element_index;
 8402                         rc = rcqe->status;
 8403                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
 8404                                 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
 8405                                 rcqe->rq_element_index, rcqe->payload_data_placement_length, rcqe->sof_byte,
 8406                                 rcqe->eof_byte, rcqe->header_data_placement_length);
 8407                 }
 8408         } else if (code == SLI4_CQE_CODE_RQ_ASYNC_V1) {
 8409                 *rq_id = rcqe_v1->rq_id;
 8410                 if (SLI4_FC_ASYNC_RQ_SUCCESS == rcqe_v1->status) {
 8411                         *index = rcqe_v1->rq_element_index;
 8412                         rc = 0;
 8413                 } else {
 8414                         *index = rcqe_v1->rq_element_index;
 8415                         rc = rcqe_v1->status;
 8416                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
 8417                                 rcqe_v1->status, sli_fc_get_status_string(rcqe_v1->status),
 8418                                 rcqe_v1->rq_id, rcqe_v1->rq_element_index,
 8419                                 rcqe_v1->payload_data_placement_length, rcqe_v1->sof_byte,
 8420                                 rcqe_v1->eof_byte, rcqe_v1->header_data_placement_length);
 8421                 }
 8422         } else if (code == SLI4_CQE_CODE_OPTIMIZED_WRITE_CMD) {
 8423                 sli4_fc_optimized_write_cmd_cqe_t *optcqe = (void *)cqe;
 8424 
 8425                 *rq_id = optcqe->rq_id;
 8426                 if (SLI4_FC_ASYNC_RQ_SUCCESS == optcqe->status) {
 8427                         *index = optcqe->rq_element_index;
 8428                         rc = 0;
 8429                 } else {
 8430                         *index = optcqe->rq_element_index;
 8431                         rc = optcqe->status;
 8432                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x pdpl=%x hdpl=%x oox=%d agxr=%d xri=0x%x rpi=0x%x\n",
 8433                                 optcqe->status, sli_fc_get_status_string(optcqe->status), optcqe->rq_id,
 8434                                 optcqe->rq_element_index, optcqe->payload_data_placement_length,
 8435                                 optcqe->header_data_placement_length, optcqe->oox, optcqe->agxr, optcqe->xri,
 8436                                 optcqe->rpi);
 8437                 }
 8438         } else if (code == SLI4_CQE_CODE_RQ_COALESCING) {
 8439                 sli4_fc_coalescing_rcqe_t       *rcqe = (void *)cqe;
 8440 
 8441                 *rq_id = rcqe->rq_id;
 8442                 if (SLI4_FC_COALESCE_RQ_SUCCESS == rcqe->status) {
 8443                         *index = rcqe->rq_element_index;
 8444                         rc = 0;
 8445                 } else {
 8446                         *index = UINT32_MAX;
 8447                         rc = rcqe->status;
 8448 
 8449                         ocs_log_test(sli4->os, "status=%02x (%s) rq_id=%d, index=%x rq_id=%#x sdpl=%x\n",
 8450                                 rcqe->status, sli_fc_get_status_string(rcqe->status), rcqe->rq_id,
 8451                                 rcqe->rq_element_index, rcqe->rq_id, rcqe->sequence_reporting_placement_length);
 8452                 }
 8453         } else {
 8454                 *index = UINT32_MAX;
 8455 
 8456                 rc = rcqe->status;
 8457 
 8458                 ocs_log_debug(sli4->os, "status=%02x rq_id=%d, index=%x pdpl=%x sof=%02x eof=%02x hdpl=%x\n",
 8459                         rcqe->status, rcqe->rq_id, rcqe->rq_element_index, rcqe->payload_data_placement_length,
 8460                         rcqe->sof_byte, rcqe->eof_byte, rcqe->header_data_placement_length);
 8461         }
 8462 
 8463         return rc;
 8464 }
 8465 
 8466 /**
 8467  * @ingroup sli_fc
 8468  * @brief Process an asynchronous FCoE event entry.
 8469  *
 8470  * @par Description
 8471  * Parses Asynchronous Completion Queue Entry (ACQE),
 8472  * creates an abstracted event, and calls the registered callback functions.
 8473  *
 8474  * @param sli4 SLI context.
 8475  * @param acqe Pointer to the ACQE.
 8476  *
 8477  * @return Returns 0 on success, or a non-zero value on failure.
 8478  */
 8479 int32_t
 8480 sli_fc_process_fcoe(sli4_t *sli4, void *acqe)
 8481 {
 8482         sli4_fcoe_fip_t *fcoe = acqe;
 8483         sli4_fip_event_t event = { 0 };
 8484         uint32_t        mask = UINT32_MAX;
 8485 
 8486         ocs_log_debug(sli4->os, "ACQE FCoE FIP type=%02x count=%d tag=%#x\n",
 8487                         fcoe->event_type,
 8488                         fcoe->fcf_count,
 8489                         fcoe->event_tag);
 8490 
 8491         if (!sli4->fip) {
 8492                 return 0;
 8493         }
 8494 
 8495         event.type = fcoe->event_type;
 8496         event.index = UINT32_MAX;
 8497 
 8498         switch (fcoe->event_type) {
 8499         case SLI4_FCOE_FIP_FCF_DISCOVERED:
 8500                 ocs_log_debug(sli4->os, "FCF Discovered index=%d\n", fcoe->event_information);
 8501                 break;
 8502         case SLI4_FCOE_FIP_FCF_TABLE_FULL:
 8503                 ocs_log_debug(sli4->os, "FCF Table Full\n");
 8504                 mask = 0;
 8505                 break;
 8506         case SLI4_FCOE_FIP_FCF_DEAD:
 8507                 ocs_log_debug(sli4->os, "FCF Dead/Gone index=%d\n", fcoe->event_information);
 8508                 break;
 8509         case SLI4_FCOE_FIP_FCF_CLEAR_VLINK:
 8510                 mask = UINT16_MAX;
 8511                 ocs_log_debug(sli4->os, "Clear VLINK Received VPI=%#x\n", fcoe->event_information & mask);
 8512                 break;
 8513         case SLI4_FCOE_FIP_FCF_MODIFIED:
 8514                 ocs_log_debug(sli4->os, "FCF Modified\n");
 8515                 break;
 8516         default:
 8517                 ocs_log_test(sli4->os, "bad FCoE type %#x", fcoe->event_type);
 8518                 mask = 0;
 8519         }
 8520 
 8521         if (mask != 0) {
 8522                 event.index = fcoe->event_information & mask;
 8523         }
 8524 
 8525         sli4->fip(sli4->fip_arg, &event);
 8526 
 8527         return 0;
 8528 }
 8529 
 8530 /**
 8531  * @ingroup sli_fc
 8532  * @brief Allocate a receive queue.
 8533  *
 8534  * @par Description
 8535  * Allocates DMA memory and configures the requested queue type.
 8536  *
 8537  * @param sli4 SLI context.
 8538  * @param q Pointer to the queue object for the header.
 8539  * @param n_entries Number of entries to allocate.
 8540  * @param buffer_size buffer size for the queue.
 8541  * @param cq Associated CQ.
 8542  * @param ulp The ULP to bind
 8543  * @param is_hdr Used to validate the rq_id and set the type of queue
 8544  *
 8545  * @return Returns 0 on success, or -1 on failure.
 8546  */
 8547 int32_t
 8548 sli_fc_rq_alloc(sli4_t *sli4, sli4_queue_t *q,
 8549                 uint32_t n_entries, uint32_t buffer_size,
 8550                 sli4_queue_t *cq, uint16_t ulp, uint8_t is_hdr)
 8551 {
 8552         int32_t (*rq_create)(sli4_t *, void *, size_t, ocs_dma_t *, uint16_t, uint16_t, uint16_t);
 8553 
 8554         if ((sli4 == NULL) || (q == NULL)) {
 8555                 void *os = sli4 != NULL ? sli4->os : NULL;
 8556 
 8557                 ocs_log_err(os, "bad parameter sli4=%p q=%p\n", sli4, q);
 8558                 return -1;
 8559         }
 8560 
 8561         if (__sli_queue_init(sli4, q, SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
 8562                                 n_entries, SLI_PAGE_SIZE)) {
 8563                 return -1;
 8564         }
 8565 
 8566         if (sli4->if_type == SLI4_IF_TYPE_BE3_SKH_PF) {
 8567                 rq_create = sli_cmd_fcoe_rq_create;
 8568         } else {
 8569                 rq_create = sli_cmd_fcoe_rq_create_v1;
 8570         }
 8571 
 8572         if (rq_create(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE, &q->dma,
 8573                       cq->id, ulp, buffer_size)) {
 8574                 if (__sli_create_queue(sli4, q)) {
 8575                         ocs_dma_free(sli4->os, &q->dma);
 8576                         return -1;
 8577                 }
 8578                 if (is_hdr && q->id & 1) {
 8579                         ocs_log_test(sli4->os, "bad header RQ_ID %d\n", q->id);
 8580                         ocs_dma_free(sli4->os, &q->dma);
 8581                         return -1;
 8582                 } else if (!is_hdr  && (q->id & 1) == 0) {
 8583                         ocs_log_test(sli4->os, "bad data RQ_ID %d\n", q->id);
 8584                         ocs_dma_free(sli4->os, &q->dma);
 8585                         return -1;
 8586                 }
 8587         } else {
 8588                 return -1;
 8589         }
 8590         q->u.flag.is_hdr = is_hdr;
 8591         if (SLI4_IF_TYPE_BE3_SKH_PF == sli4->if_type) {
 8592                 q->u.flag.rq_batch = TRUE;
 8593         }
 8594         return 0;
 8595 }
 8596 
 8597 /**
 8598  * @ingroup sli_fc
 8599  * @brief Allocate a receive queue set.
 8600  *
 8601  * @param sli4 SLI context.
 8602  * @param num_rq_pairs to create
 8603  * @param qs Pointers to the queue objects for both header and data.
 8604  *      Length of this arrays should be 2 * num_rq_pairs
 8605  * @param base_cq_id. Assumes base_cq_id : (base_cq_id + num_rq_pairs) cqs as allotted.
 8606  * @param n_entries number of entries in each RQ queue.
 8607  * @param header_buffer_size
 8608  * @param payload_buffer_size
 8609  * @param ulp The ULP to bind
 8610  *
 8611  * @return Returns 0 on success, or -1 on failure.
 8612  */
 8613 int32_t
 8614 sli_fc_rq_set_alloc(sli4_t *sli4, uint32_t num_rq_pairs,
 8615                     sli4_queue_t *qs[], uint32_t base_cq_id,
 8616                     uint32_t n_entries, uint32_t header_buffer_size,
 8617                     uint32_t payload_buffer_size,  uint16_t ulp)
 8618 {
 8619         uint32_t i, p, offset = 0;
 8620         uint32_t payload_size, total_page_count = 0;
 8621         uintptr_t addr;
 8622         ocs_dma_t dma;
 8623         sli4_res_common_create_queue_set_t *rsp = NULL;
 8624         sli4_req_fcoe_rq_create_v2_t    *req = NULL;
 8625 
 8626         ocs_memset(&dma, 0, sizeof(dma));
 8627 
 8628         for (i = 0; i < (num_rq_pairs * 2); i++) {
 8629                 if (__sli_queue_init(sli4, qs[i], SLI_QTYPE_RQ, SLI4_FCOE_RQE_SIZE,
 8630                                         n_entries, SLI_PAGE_SIZE)) {
 8631                         goto error;
 8632                 }
 8633         }
 8634 
 8635         total_page_count = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE) * num_rq_pairs * 2;
 8636 
 8637         /* Payload length must accommodate both request and response */
 8638         payload_size = max((sizeof(sli4_req_fcoe_rq_create_v1_t) + (8 * total_page_count)),
 8639                          sizeof(sli4_res_common_create_queue_set_t));
 8640 
 8641         if (ocs_dma_alloc(sli4->os, &dma, payload_size, SLI_PAGE_SIZE)) {
 8642                 ocs_log_err(sli4->os, "DMA allocation failed\n");
 8643                 goto error;
 8644         }
 8645         ocs_memset(dma.virt, 0, payload_size);
 8646 
 8647         if (sli_cmd_sli_config(sli4, sli4->bmbx.virt, SLI4_BMBX_SIZE,
 8648                         payload_size, &dma) == -1) {
 8649                 goto error;
 8650         }
 8651         req = (sli4_req_fcoe_rq_create_v2_t *)((uint8_t *)dma.virt);
 8652 
 8653         /* Fill Header fields */
 8654         req->hdr.opcode    = SLI4_OPC_FCOE_RQ_CREATE;
 8655         req->hdr.subsystem = SLI4_SUBSYSTEM_FCFCOE;
 8656         req->hdr.version   = 2;
 8657         req->hdr.request_length = sizeof(sli4_req_fcoe_rq_create_v2_t) - sizeof(sli4_req_hdr_t)
 8658                                         + (8 * total_page_count);
 8659 
 8660         /* Fill Payload fields */
 8661         req->dnb           = TRUE;
 8662         req->num_pages     = sli_page_count(qs[0]->dma.size, SLI_PAGE_SIZE);
 8663         req->rqe_count     = qs[0]->dma.size / SLI4_FCOE_RQE_SIZE;
 8664         req->rqe_size      = SLI4_FCOE_RQE_SIZE_8;
 8665         req->page_size     = SLI4_FCOE_RQ_PAGE_SIZE_4096;
 8666         req->rq_count      = num_rq_pairs * 2;
 8667         req->base_cq_id    = base_cq_id;
 8668         req->hdr_buffer_size     = header_buffer_size;
 8669         req->payload_buffer_size = payload_buffer_size;
 8670 
 8671         for (i = 0; i < (num_rq_pairs * 2); i++) {
 8672                 for (p = 0, addr = qs[i]->dma.phys; p < req->num_pages; p++, addr += SLI_PAGE_SIZE) {
 8673                         req->page_physical_address[offset].low  = ocs_addr32_lo(addr);
 8674                         req->page_physical_address[offset].high = ocs_addr32_hi(addr);
 8675                         offset++;
 8676                 }
 8677         }
 8678 
 8679         if (sli_bmbx_command(sli4)){
 8680                 ocs_log_crit(sli4->os, "bootstrap mailbox write failed RQSet\n");
 8681                 goto error;
 8682         }
 8683 
 8684         rsp = (void *)((uint8_t *)dma.virt);
 8685         if (rsp->hdr.status) {
 8686                 ocs_log_err(sli4->os, "bad create RQSet status=%#x addl=%#x\n",
 8687                         rsp->hdr.status, rsp->hdr.additional_status);
 8688                 goto error;
 8689         } else {
 8690                 for (i = 0; i < (num_rq_pairs * 2); i++) {
 8691                         qs[i]->id = i + rsp->q_id;
 8692                         if ((qs[i]->id & 1) == 0) {
 8693                                 qs[i]->u.flag.is_hdr = TRUE;
 8694                         } else {
 8695                                 qs[i]->u.flag.is_hdr = FALSE;
 8696                         }
 8697                         qs[i]->doorbell_offset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].off;
 8698                         qs[i]->doorbell_rset = regmap[SLI4_REG_FCOE_RQ_DOORBELL][sli4->if_type].rset;
 8699                 }
 8700         }
 8701 
 8702         ocs_dma_free(sli4->os, &dma);
 8703 
 8704         return 0;
 8705 
 8706 error:
 8707         for (i = 0; i < (num_rq_pairs * 2); i++) {
 8708                 if (qs[i]->dma.size) {
 8709                         ocs_dma_free(sli4->os, &qs[i]->dma);
 8710                 }
 8711         }
 8712 
 8713         if (dma.size) {
 8714                 ocs_dma_free(sli4->os, &dma);
 8715         }
 8716 
 8717         return -1;
 8718 }
 8719 
 8720 /**
 8721  * @ingroup sli_fc
 8722  * @brief Get the RPI resource requirements.
 8723  *
 8724  * @param sli4 SLI context.
 8725  * @param n_rpi Number of RPIs desired.
 8726  *
 8727  * @return Returns the number of bytes needed. This value may be zero.
 8728  */
 8729 uint32_t
 8730 sli_fc_get_rpi_requirements(sli4_t *sli4, uint32_t n_rpi)
 8731 {
 8732         uint32_t        bytes = 0;
 8733 
 8734         /* Check if header templates needed */
 8735         if (sli4->config.hdr_template_req) {
 8736                 /* round up to a page */
 8737                 bytes = SLI_ROUND_PAGE(n_rpi * SLI4_FCOE_HDR_TEMPLATE_SIZE);
 8738         }
 8739 
 8740         return bytes;
 8741 }
 8742 
 8743 /**
 8744  * @ingroup sli_fc
 8745  * @brief Return a text string corresponding to a CQE status value
 8746  *
 8747  * @param status Status value
 8748  *
 8749  * @return Returns corresponding string, otherwise "unknown"
 8750  */
 8751 const char *
 8752 sli_fc_get_status_string(uint32_t status)
 8753 {
 8754         static struct {
 8755                 uint32_t code;
 8756                 const char *label;
 8757         } lookup[] = {
 8758                 {SLI4_FC_WCQE_STATUS_SUCCESS,                   "SUCCESS"},
 8759                 {SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE,           "FCP_RSP_FAILURE"},
 8760                 {SLI4_FC_WCQE_STATUS_REMOTE_STOP,               "REMOTE_STOP"},
 8761                 {SLI4_FC_WCQE_STATUS_LOCAL_REJECT,              "LOCAL_REJECT"},
 8762                 {SLI4_FC_WCQE_STATUS_NPORT_RJT,                 "NPORT_RJT"},
 8763                 {SLI4_FC_WCQE_STATUS_FABRIC_RJT,                "FABRIC_RJT"},
 8764                 {SLI4_FC_WCQE_STATUS_NPORT_BSY,                 "NPORT_BSY"},
 8765                 {SLI4_FC_WCQE_STATUS_FABRIC_BSY,                "FABRIC_BSY"},
 8766                 {SLI4_FC_WCQE_STATUS_LS_RJT,                    "LS_RJT"},
 8767                 {SLI4_FC_WCQE_STATUS_CMD_REJECT,                "CMD_REJECT"},
 8768                 {SLI4_FC_WCQE_STATUS_FCP_TGT_LENCHECK,          "FCP_TGT_LENCHECK"},
 8769                 {SLI4_FC_WCQE_STATUS_RQ_BUF_LEN_EXCEEDED,       "BUF_LEN_EXCEEDED"},
 8770                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_BUF_NEEDED,      "RQ_INSUFF_BUF_NEEDED"},
 8771                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_FRM_DISC,        "RQ_INSUFF_FRM_DESC"},
 8772                 {SLI4_FC_WCQE_STATUS_RQ_DMA_FAILURE,            "RQ_DMA_FAILURE"},
 8773                 {SLI4_FC_WCQE_STATUS_FCP_RSP_TRUNCATE,          "FCP_RSP_TRUNCATE"},
 8774                 {SLI4_FC_WCQE_STATUS_DI_ERROR,                  "DI_ERROR"},
 8775                 {SLI4_FC_WCQE_STATUS_BA_RJT,                    "BA_RJT"},
 8776                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_NEEDED,      "RQ_INSUFF_XRI_NEEDED"},
 8777                 {SLI4_FC_WCQE_STATUS_RQ_INSUFF_XRI_DISC,        "INSUFF_XRI_DISC"},
 8778                 {SLI4_FC_WCQE_STATUS_RX_ERROR_DETECT,           "RX_ERROR_DETECT"},
 8779                 {SLI4_FC_WCQE_STATUS_RX_ABORT_REQUEST,          "RX_ABORT_REQUEST"},
 8780                 };
 8781         uint32_t i;
 8782 
 8783         for (i = 0; i < ARRAY_SIZE(lookup); i++) {
 8784                 if (status == lookup[i].code) {
 8785                         return lookup[i].label;
 8786                 }
 8787         }
 8788         return "unknown";
 8789 }

Cache object: c062fa847ad03c89d2945c71ae2bf49b


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


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