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/oce/oce_mbox.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  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (C) 2013 Emulex
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright notice,
   11  *    this list of conditions and the following disclaimer.
   12  *
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * 3. Neither the name of the Emulex Corporation nor the names of its
   18  *    contributors may be used to endorse or promote products derived from
   19  *    this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  * Contact Information:
   34  * freebsd-drivers@emulex.com
   35  *
   36  * Emulex
   37  * 3333 Susan Street
   38  * Costa Mesa, CA 92626
   39  */
   40 
   41 /* $FreeBSD$ */
   42 
   43 #include "oce_if.h"
   44 
   45 int
   46 oce_wait_ready(POCE_SOFTC sc)
   47 {
   48 #define SLIPORT_READY_TIMEOUT 30000
   49         uint32_t sliport_status, i;
   50 
   51         if (!IS_XE201(sc)) 
   52                 return (-1);
   53 
   54         for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
   55                 sliport_status = OCE_READ_REG32(sc, db, SLIPORT_STATUS_OFFSET);
   56                 if (sliport_status & SLIPORT_STATUS_RDY_MASK)
   57                         return 0;
   58 
   59                 if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
   60                         !(sliport_status & SLIPORT_STATUS_RN_MASK)) {
   61                         device_printf(sc->dev, "Error detected in the card\n");
   62                         return EIO;
   63                 }
   64 
   65                 DELAY(1000);
   66         }
   67 
   68         device_printf(sc->dev, "Firmware wait timed out\n");
   69 
   70         return (-1);
   71 }
   72 
   73 /**
   74  * @brief Reset (firmware) common function
   75  * @param sc            software handle to the device
   76  * @returns             0 on success, ETIMEDOUT on failure
   77  */
   78 int
   79 oce_reset_fun(POCE_SOFTC sc)
   80 {
   81         struct oce_mbx *mbx;
   82         struct oce_bmbx *mb;
   83         struct ioctl_common_function_reset *fwcmd;
   84         int rc = 0;
   85 
   86         if (IS_XE201(sc)) {
   87                 OCE_WRITE_REG32(sc, db, SLIPORT_CONTROL_OFFSET,
   88                                         SLI_PORT_CONTROL_IP_MASK);
   89 
   90                 rc = oce_wait_ready(sc);
   91                 if (rc) {
   92                         device_printf(sc->dev, "Firmware reset Failed\n");
   93                 }
   94 
   95                 return rc;
   96         }
   97 
   98         mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
   99         mbx = &mb->mbx;
  100         bzero(mbx, sizeof(struct oce_mbx));
  101 
  102         fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
  103         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  104                         MBX_SUBSYSTEM_COMMON,
  105                         OPCODE_COMMON_FUNCTION_RESET,
  106                         10,     /* MBX_TIMEOUT_SEC */
  107                         sizeof(struct
  108                                 ioctl_common_function_reset),
  109                         OCE_MBX_VER_V0);
  110 
  111         mbx->u0.s.embedded = 1;
  112         mbx->payload_length =
  113                 sizeof(struct ioctl_common_function_reset);
  114 
  115         rc = oce_mbox_dispatch(sc, 2);
  116 
  117         return rc;
  118 }
  119 
  120 
  121 /**
  122  * @brief               This funtions tells firmware we are
  123  *                      done with commands.
  124  * @param sc            software handle to the device
  125  * @returns             0 on success, ETIMEDOUT on failure
  126  */
  127 int
  128 oce_fw_clean(POCE_SOFTC sc)
  129 {
  130         struct oce_bmbx *mbx;
  131         uint8_t *ptr;
  132         int ret = 0;
  133 
  134         mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
  135         ptr = (uint8_t *) &mbx->mbx;
  136 
  137         /* Endian Signature */
  138         *ptr++ = 0xff;
  139         *ptr++ = 0xaa;
  140         *ptr++ = 0xbb;
  141         *ptr++ = 0xff;
  142         *ptr++ = 0xff;
  143         *ptr++ = 0xcc;
  144         *ptr++ = 0xdd;
  145         *ptr = 0xff;
  146 
  147         ret = oce_mbox_dispatch(sc, 2);
  148         
  149         return ret;
  150 }
  151 
  152 
  153 /**
  154  * @brief Mailbox wait
  155  * @param sc            software handle to the device
  156  * @param tmo_sec       timeout in seconds
  157  */
  158 static int
  159 oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
  160 {
  161         tmo_sec *= 10000;
  162         pd_mpu_mbox_db_t mbox_db;
  163 
  164         for (;;) {
  165                 if (tmo_sec != 0) {
  166                         if (--tmo_sec == 0)
  167                                 break;
  168                 }
  169 
  170                 mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
  171 
  172                 if (mbox_db.bits.ready)
  173                         return 0;
  174 
  175                 DELAY(100);
  176         }
  177 
  178         device_printf(sc->dev, "Mailbox timed out\n");
  179 
  180         return ETIMEDOUT;
  181 }
  182 
  183 
  184 /**
  185  * @brief Mailbox dispatch
  186  * @param sc            software handle to the device
  187  * @param tmo_sec       timeout in seconds
  188  */
  189 int
  190 oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
  191 {
  192         pd_mpu_mbox_db_t mbox_db;
  193         uint32_t pa;
  194         int rc;
  195 
  196         oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
  197         pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
  198         bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
  199         mbox_db.bits.ready = 0;
  200         mbox_db.bits.hi = 1;
  201         mbox_db.bits.address = pa;
  202 
  203         rc = oce_mbox_wait(sc, tmo_sec);
  204         if (rc == 0) {
  205                 OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
  206 
  207                 pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
  208                 mbox_db.bits.ready = 0;
  209                 mbox_db.bits.hi = 0;
  210                 mbox_db.bits.address = pa;
  211 
  212                 rc = oce_mbox_wait(sc, tmo_sec);
  213 
  214                 if (rc == 0) {
  215                         OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
  216 
  217                         rc = oce_mbox_wait(sc, tmo_sec);
  218 
  219                         oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
  220                 }
  221         }
  222 
  223         return rc;
  224 }
  225 
  226 
  227 
  228 /**
  229  * @brief               Mailbox common request header initialization
  230  * @param hdr           mailbox header
  231  * @param dom           domain
  232  * @param port          port
  233  * @param subsys        subsystem
  234  * @param opcode        opcode
  235  * @param timeout       timeout
  236  * @param pyld_len      payload length
  237  */
  238 void
  239 mbx_common_req_hdr_init(struct mbx_hdr *hdr,
  240                         uint8_t dom, uint8_t port,
  241                         uint8_t subsys, uint8_t opcode,
  242                         uint32_t timeout, uint32_t pyld_len,
  243                         uint8_t version)
  244 {
  245         hdr->u0.req.opcode = opcode;
  246         hdr->u0.req.subsystem = subsys;
  247         hdr->u0.req.port_number = port;
  248         hdr->u0.req.domain = dom;
  249 
  250         hdr->u0.req.timeout = timeout;
  251         hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
  252         hdr->u0.req.version = version;
  253 }
  254 
  255 
  256 
  257 /**
  258  * @brief Function to initialize the hw with host endian information
  259  * @param sc            software handle to the device
  260  * @returns             0 on success, ETIMEDOUT on failure
  261  */
  262 int
  263 oce_mbox_init(POCE_SOFTC sc)
  264 {
  265         struct oce_bmbx *mbx;
  266         uint8_t *ptr;
  267         int ret = 0;
  268 
  269         if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
  270                 mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
  271                 ptr = (uint8_t *) &mbx->mbx;
  272 
  273                 /* Endian Signature */
  274                 *ptr++ = 0xff;
  275                 *ptr++ = 0x12;
  276                 *ptr++ = 0x34;
  277                 *ptr++ = 0xff;
  278                 *ptr++ = 0xff;
  279                 *ptr++ = 0x56;
  280                 *ptr++ = 0x78;
  281                 *ptr = 0xff;
  282 
  283                 ret = oce_mbox_dispatch(sc, 0);
  284         }
  285         
  286         return ret;
  287 }
  288 
  289 
  290 /**
  291  * @brief               Function to get the firmware version
  292  * @param sc            software handle to the device
  293  * @returns             0 on success, EIO on failure
  294  */
  295 int
  296 oce_get_fw_version(POCE_SOFTC sc)
  297 {
  298         struct oce_mbx mbx;
  299         struct mbx_get_common_fw_version *fwcmd;
  300         int ret = 0;
  301 
  302         bzero(&mbx, sizeof(struct oce_mbx));
  303 
  304         fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
  305         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  306                                 MBX_SUBSYSTEM_COMMON,
  307                                 OPCODE_COMMON_GET_FW_VERSION,
  308                                 MBX_TIMEOUT_SEC,
  309                                 sizeof(struct mbx_get_common_fw_version),
  310                                 OCE_MBX_VER_V0);
  311 
  312         mbx.u0.s.embedded = 1;
  313         mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
  314         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  315 
  316         ret = oce_mbox_post(sc, &mbx, NULL);
  317         if (!ret)
  318                 ret = fwcmd->hdr.u0.rsp.status;
  319         if (ret) {
  320                 device_printf(sc->dev,
  321                               "%s failed - cmd status: %d addi status: %d\n",
  322                               __FUNCTION__, ret,
  323                               fwcmd->hdr.u0.rsp.additional_status);
  324                 goto error;
  325         }
  326 
  327         bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
  328 error:
  329         return ret;
  330 }
  331 
  332 
  333 /**
  334  * @brief       Firmware will send gracious notifications during
  335  *              attach only after sending first mcc commnad. We  
  336  *              use MCC queue only for getting async and mailbox
  337  *              for sending cmds. So to get gracious notifications
  338  *              atleast send one dummy command on mcc.
  339  */
  340 int 
  341 oce_first_mcc_cmd(POCE_SOFTC sc)
  342 {
  343         struct oce_mbx *mbx;
  344         struct oce_mq *mq = sc->mq;
  345         struct mbx_get_common_fw_version *fwcmd;
  346         uint32_t reg_value;
  347 
  348         mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
  349         bzero(mbx, sizeof(struct oce_mbx));
  350         
  351         fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
  352         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  353                                 MBX_SUBSYSTEM_COMMON,
  354                                 OPCODE_COMMON_GET_FW_VERSION,
  355                                 MBX_TIMEOUT_SEC,
  356                                 sizeof(struct mbx_get_common_fw_version),
  357                                 OCE_MBX_VER_V0);
  358         mbx->u0.s.embedded = 1;
  359         mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
  360         bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
  361                                 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  362         RING_PUT(mq->ring, 1);
  363         reg_value = (1 << 16) | mq->mq_id;
  364         OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
  365 
  366         return 0;
  367 }
  368 
  369 /**
  370  * @brief               Function to post a MBX to the mbox
  371  * @param sc            software handle to the device
  372  * @param mbx           pointer to the MBX to send
  373  * @param mbxctx        pointer to the mbx context structure
  374  * @returns             0 on success, error on failure
  375  */
  376 int
  377 oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
  378 {
  379         struct oce_mbx *mb_mbx = NULL;
  380         struct oce_mq_cqe *mb_cqe = NULL;
  381         struct oce_bmbx *mb = NULL;
  382         int rc = 0;
  383         uint32_t tmo = 0;
  384         uint32_t cstatus = 0;
  385         uint32_t xstatus = 0;
  386 
  387         LOCK(&sc->bmbx_lock);
  388 
  389         mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
  390         mb_mbx = &mb->mbx;
  391 
  392         /* get the tmo */
  393         tmo = mbx->tag[0];
  394         mbx->tag[0] = 0;
  395 
  396         /* copy mbx into mbox */
  397         bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
  398 
  399         /* now dispatch */
  400         rc = oce_mbox_dispatch(sc, tmo);
  401         if (rc == 0) {
  402                 /*
  403                  * the command completed successfully. Now get the
  404                  * completion queue entry
  405                  */
  406                 mb_cqe = &mb->cqe;
  407                 DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
  408         
  409                 /* copy mbox mbx back */
  410                 bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
  411 
  412                 /* pick up the mailbox status */
  413                 cstatus = mb_cqe->u0.s.completion_status;
  414                 xstatus = mb_cqe->u0.s.extended_status;
  415 
  416                 /*
  417                  * store the mbx context in the cqe tag section so that
  418                  * the upper layer handling the cqe can associate the mbx
  419                  * with the response
  420                  */
  421                 if (cstatus == 0 && mbxctx) {
  422                         /* save context */
  423                         mbxctx->mbx = mb_mbx;
  424                         bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
  425                                 sizeof(struct oce_mbx_ctx *));
  426                 }
  427         }
  428 
  429         UNLOCK(&sc->bmbx_lock);
  430 
  431         return rc;
  432 }
  433 
  434 /**
  435  * @brief Function to read the mac address associated with an interface
  436  * @param sc            software handle to the device
  437  * @param if_id         interface id to read the address from
  438  * @param perm          set to 1 if reading the factory mac address.
  439  *                      In this case if_id is ignored
  440  * @param type          type of the mac address, whether network or storage
  441  * @param[out] mac      [OUTPUT] pointer to a buffer containing the
  442  *                      mac address when the command succeeds.
  443  * @returns             0 on success, EIO on failure
  444  */
  445 int
  446 oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
  447                 uint8_t perm, uint8_t type, struct mac_address_format *mac)
  448 {
  449         struct oce_mbx mbx;
  450         struct mbx_query_common_iface_mac *fwcmd;
  451         int ret = 0;
  452 
  453         bzero(&mbx, sizeof(struct oce_mbx));
  454 
  455         fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
  456         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  457                                 MBX_SUBSYSTEM_COMMON,
  458                                 OPCODE_COMMON_QUERY_IFACE_MAC,
  459                                 MBX_TIMEOUT_SEC,
  460                                 sizeof(struct mbx_query_common_iface_mac),
  461                                 OCE_MBX_VER_V0);
  462 
  463         fwcmd->params.req.permanent = perm;
  464         if (!perm)
  465                 fwcmd->params.req.if_id = (uint16_t) if_id;
  466         else
  467                 fwcmd->params.req.if_id = 0;
  468 
  469         fwcmd->params.req.type = type;
  470 
  471         mbx.u0.s.embedded = 1;
  472         mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
  473         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  474 
  475         ret = oce_mbox_post(sc, &mbx, NULL);
  476         if (!ret)
  477                 ret = fwcmd->hdr.u0.rsp.status;
  478         if (ret) {
  479                 device_printf(sc->dev,
  480                               "%s failed - cmd status: %d addi status: %d\n",
  481                               __FUNCTION__, ret,
  482                               fwcmd->hdr.u0.rsp.additional_status);
  483                 goto error;
  484         }
  485 
  486         /* copy the mac addres in the output parameter */
  487         mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
  488         bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
  489                 mac->size_of_struct);
  490 error:
  491         return ret;
  492 }
  493 
  494 /**
  495  * @brief Function to query the fw attributes from the hw
  496  * @param sc            software handle to the device
  497  * @returns             0 on success, EIO on failure
  498  */
  499 int 
  500 oce_get_fw_config(POCE_SOFTC sc)
  501 {
  502         struct oce_mbx mbx;
  503         struct mbx_common_query_fw_config *fwcmd;
  504         int ret = 0;
  505 
  506         bzero(&mbx, sizeof(struct oce_mbx));
  507 
  508         fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
  509         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  510                                 MBX_SUBSYSTEM_COMMON,
  511                                 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
  512                                 MBX_TIMEOUT_SEC,
  513                                 sizeof(struct mbx_common_query_fw_config),
  514                                 OCE_MBX_VER_V0);
  515 
  516         mbx.u0.s.embedded = 1;
  517         mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
  518         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  519 
  520         ret = oce_mbox_post(sc, &mbx, NULL);
  521         if (!ret)
  522                 ret = fwcmd->hdr.u0.rsp.status;
  523         if (ret) {
  524                 device_printf(sc->dev,
  525                               "%s failed - cmd status: %d addi status: %d\n",
  526                               __FUNCTION__, ret,
  527                               fwcmd->hdr.u0.rsp.additional_status);
  528                 goto error;
  529         }
  530 
  531         DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
  532 
  533         sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
  534         sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
  535         sc->port_id       = HOST_32(fwcmd->params.rsp.port_id);
  536         sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
  537         if ((sc->function_mode & (ULP_NIC_MODE | ULP_RDMA_MODE)) ==
  538             (ULP_NIC_MODE | ULP_RDMA_MODE)) {
  539           sc->rdma_flags = OCE_RDMA_FLAG_SUPPORTED;
  540         }
  541         sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
  542 
  543         if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
  544                 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
  545                 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
  546         } else {
  547                 sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
  548                 sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
  549         }
  550         
  551 error:
  552         return ret;
  553 
  554 }
  555 
  556 /**
  557  *
  558  * @brief function to create a device interface 
  559  * @param sc            software handle to the device
  560  * @param cap_flags     capability flags
  561  * @param en_flags      enable capability flags
  562  * @param vlan_tag      optional vlan tag to associate with the if
  563  * @param mac_addr      pointer to a buffer containing the mac address
  564  * @param[out] if_id    [OUTPUT] pointer to an integer to hold the ID of the
  565  interface created
  566  * @returns             0 on success, EIO on failure
  567  */
  568 int
  569 oce_if_create(POCE_SOFTC sc,
  570                 uint32_t cap_flags,
  571                 uint32_t en_flags,
  572                 uint16_t vlan_tag,
  573                 uint8_t *mac_addr,
  574                 uint32_t *if_id)
  575 {
  576         struct oce_mbx mbx;
  577         struct mbx_create_common_iface *fwcmd;
  578         int rc = 0;
  579 
  580         bzero(&mbx, sizeof(struct oce_mbx));
  581 
  582         fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
  583         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  584                                 MBX_SUBSYSTEM_COMMON,
  585                                 OPCODE_COMMON_CREATE_IFACE,
  586                                 MBX_TIMEOUT_SEC,
  587                                 sizeof(struct mbx_create_common_iface),
  588                                 OCE_MBX_VER_V0);
  589         DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
  590 
  591         fwcmd->params.req.version = 0;
  592         fwcmd->params.req.cap_flags = LE_32(cap_flags);
  593         fwcmd->params.req.enable_flags = LE_32(en_flags);
  594         if (mac_addr != NULL) {
  595                 bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
  596                 fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
  597                 fwcmd->params.req.mac_invalid = 0;
  598         } else {
  599                 fwcmd->params.req.mac_invalid = 1;
  600         }
  601 
  602         mbx.u0.s.embedded = 1;
  603         mbx.payload_length = sizeof(struct mbx_create_common_iface);
  604         DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
  605 
  606         rc = oce_mbox_post(sc, &mbx, NULL);
  607         if (!rc)
  608                 rc = fwcmd->hdr.u0.rsp.status;
  609         if (rc) {
  610                 device_printf(sc->dev,
  611                               "%s failed - cmd status: %d addi status: %d\n",
  612                               __FUNCTION__, rc,
  613                               fwcmd->hdr.u0.rsp.additional_status);
  614                 goto error;
  615         }
  616 
  617         *if_id = HOST_32(fwcmd->params.rsp.if_id);
  618 
  619         if (mac_addr != NULL)
  620                 sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
  621 error:
  622         return rc;
  623 }
  624 
  625 /**
  626  * @brief               Function to delete an interface
  627  * @param sc            software handle to the device
  628  * @param if_id         ID of the interface to delete
  629  * @returns             0 on success, EIO on failure
  630  */
  631 int
  632 oce_if_del(POCE_SOFTC sc, uint32_t if_id)
  633 {
  634         struct oce_mbx mbx;
  635         struct mbx_destroy_common_iface *fwcmd;
  636         int rc = 0;
  637 
  638         bzero(&mbx, sizeof(struct oce_mbx));
  639 
  640         fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
  641         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  642                                 MBX_SUBSYSTEM_COMMON,
  643                                 OPCODE_COMMON_DESTROY_IFACE,
  644                                 MBX_TIMEOUT_SEC,
  645                                 sizeof(struct mbx_destroy_common_iface),
  646                                 OCE_MBX_VER_V0);
  647 
  648         fwcmd->params.req.if_id = if_id;
  649 
  650         mbx.u0.s.embedded = 1;
  651         mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
  652         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  653 
  654         rc = oce_mbox_post(sc, &mbx, NULL);
  655         if (!rc)
  656                 rc = fwcmd->hdr.u0.rsp.status;
  657         if (rc)
  658                 device_printf(sc->dev,
  659                               "%s failed - cmd status: %d addi status: %d\n",
  660                               __FUNCTION__, rc,
  661                               fwcmd->hdr.u0.rsp.additional_status);
  662         return rc;
  663 }
  664 
  665 /**
  666  * @brief Function to send the mbx command to configure vlan
  667  * @param sc            software handle to the device
  668  * @param if_id         interface identifier index
  669  * @param vtag_arr      array of vlan tags
  670  * @param vtag_cnt      number of elements in array
  671  * @param untagged      boolean TRUE/FLASE
  672  * @param enable_promisc flag to enable/disable VLAN promiscuous mode
  673  * @returns             0 on success, EIO on failure
  674  */
  675 int
  676 oce_config_vlan(POCE_SOFTC sc,
  677                 uint32_t if_id,
  678                 struct normal_vlan *vtag_arr,
  679                 uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
  680 {
  681         struct oce_mbx mbx;
  682         struct mbx_common_config_vlan *fwcmd;
  683         int rc = 0;
  684 
  685         if (sc->vlans_added > sc->max_vlans)
  686                 goto vlan_promisc;
  687 
  688         bzero(&mbx, sizeof(struct oce_mbx));
  689         fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
  690 
  691         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  692                                 MBX_SUBSYSTEM_COMMON,
  693                                 OPCODE_COMMON_CONFIG_IFACE_VLAN,
  694                                 MBX_TIMEOUT_SEC,
  695                                 sizeof(struct mbx_common_config_vlan),
  696                                 OCE_MBX_VER_V0);
  697 
  698         fwcmd->params.req.if_id = (uint8_t) if_id;
  699         fwcmd->params.req.promisc = (uint8_t) enable_promisc;
  700         fwcmd->params.req.untagged = (uint8_t) untagged;
  701         fwcmd->params.req.num_vlans = vtag_cnt;
  702 
  703         if (!enable_promisc) {
  704                 bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
  705                         vtag_cnt * sizeof(struct normal_vlan));
  706         }
  707         mbx.u0.s.embedded = 1;
  708         mbx.payload_length = sizeof(struct mbx_common_config_vlan);
  709         DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
  710 
  711         rc = oce_mbox_post(sc, &mbx, NULL);
  712         if (!rc)
  713                 rc = fwcmd->hdr.u0.rsp.status;
  714         if (rc)
  715                 device_printf(sc->dev,
  716                               "%s failed - cmd status: %d addi status: %d\n",
  717                               __FUNCTION__, rc,
  718                               fwcmd->hdr.u0.rsp.additional_status);
  719 
  720         goto done;
  721 
  722 vlan_promisc:
  723         /* Enable Vlan Promis */
  724         oce_rxf_set_promiscuous(sc, (1 << 1));
  725         device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
  726 done:
  727         return rc;
  728 
  729 }
  730 
  731 /**
  732  * @brief Function to set flow control capability in the hardware
  733  * @param sc            software handle to the device
  734  * @param flow_control  flow control flags to set
  735  * @returns             0 on success, EIO on failure
  736  */
  737 int
  738 oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
  739 {
  740         struct oce_mbx mbx;
  741         struct mbx_common_get_set_flow_control *fwcmd =
  742                 (struct mbx_common_get_set_flow_control *)&mbx.payload;
  743         int rc;
  744 
  745         bzero(&mbx, sizeof(struct oce_mbx));
  746 
  747         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  748                                 MBX_SUBSYSTEM_COMMON,
  749                                 OPCODE_COMMON_SET_FLOW_CONTROL,
  750                                 MBX_TIMEOUT_SEC,
  751                                 sizeof(struct mbx_common_get_set_flow_control),
  752                                 OCE_MBX_VER_V0);
  753 
  754         if (flow_control & OCE_FC_TX)
  755                 fwcmd->tx_flow_control = 1;
  756 
  757         if (flow_control & OCE_FC_RX)
  758                 fwcmd->rx_flow_control = 1;
  759 
  760         mbx.u0.s.embedded = 1;
  761         mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
  762         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  763 
  764         rc = oce_mbox_post(sc, &mbx, NULL);
  765         if (!rc)
  766                 rc = fwcmd->hdr.u0.rsp.status;
  767         if (rc)
  768                 device_printf(sc->dev,
  769                               "%s failed - cmd status: %d addi status: %d\n",
  770                               __FUNCTION__, rc,
  771                               fwcmd->hdr.u0.rsp.additional_status);
  772         return rc;
  773 }
  774 
  775 /**
  776  * @brief Initialize the RSS CPU indirection table
  777  *
  778  * The table is used to choose the queue to place the incomming packets.
  779  * Incomming packets are hashed.  The lowest bits in the hash result
  780  * are used as the index into the CPU indirection table.
  781  * Each entry in the table contains the RSS CPU-ID returned by the NIC
  782  * create.  Based on the CPU ID, the receive completion is routed to
  783  * the corresponding RSS CQs.  (Non-RSS packets are always completed
  784  * on the default (0) CQ).
  785  *
  786  * @param sc            software handle to the device
  787  * @param *fwcmd        pointer to the rss mbox command
  788  * @returns             none
  789  */
  790 static int
  791 oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
  792 {
  793         int i = 0, j = 0, rc = 0;
  794         uint8_t *tbl = fwcmd->params.req.cputable;
  795         struct oce_rq *rq = NULL;
  796 
  797 
  798         for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
  799                 for_all_rss_queues(sc, rq, i) {
  800                         if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
  801                                 break;
  802                         tbl[j + i] = rq->rss_cpuid;
  803                 }
  804         }
  805         if (i == 0) {
  806                 device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
  807                 rc = ENXIO;
  808 
  809         } 
  810         
  811         /* fill log2 value indicating the size of the CPU table */
  812         if (rc == 0)
  813                 fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(INDIRECTION_TABLE_ENTRIES));
  814 
  815         return rc;
  816 }
  817 
  818 /**
  819  * @brief Function to set flow control capability in the hardware
  820  * @param sc            software handle to the device
  821  * @param if_id         interface id to read the address from
  822  * @param enable_rss    0=disable, RSS_ENABLE_xxx flags otherwise
  823  * @returns             0 on success, EIO on failure
  824  */
  825 int
  826 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
  827 {
  828         int rc;
  829         struct oce_mbx mbx;
  830         struct mbx_config_nic_rss *fwcmd =
  831                                 (struct mbx_config_nic_rss *)&mbx.payload;
  832         int version;
  833 
  834         bzero(&mbx, sizeof(struct oce_mbx));
  835 
  836         if (IS_XE201(sc) || IS_SH(sc)) {
  837                 version = OCE_MBX_VER_V1;
  838                 fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
  839                                                RSS_ENABLE_UDP_IPV6;
  840         } else
  841                 version = OCE_MBX_VER_V0; 
  842 
  843         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  844                                 MBX_SUBSYSTEM_NIC,
  845                                 NIC_CONFIG_RSS,
  846                                 MBX_TIMEOUT_SEC,
  847                                 sizeof(struct mbx_config_nic_rss),
  848                                 version);
  849         if (enable_rss)
  850                 fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
  851                                                  RSS_ENABLE_TCP_IPV4 |
  852                                                  RSS_ENABLE_IPV6 |
  853                                                  RSS_ENABLE_TCP_IPV6);
  854 
  855         if(!sc->enable_hwlro) 
  856                 fwcmd->params.req.flush = OCE_FLUSH;
  857         else
  858                 fwcmd->params.req.flush = 0;
  859 
  860         fwcmd->params.req.if_id = LE_32(if_id);
  861 
  862         srandom(arc4random());  /* random entropy seed */
  863         read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
  864         
  865         rc = oce_rss_itbl_init(sc, fwcmd);
  866         if (rc == 0) {
  867                 mbx.u0.s.embedded = 1;
  868                 mbx.payload_length = sizeof(struct mbx_config_nic_rss);
  869                 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  870 
  871                 rc = oce_mbox_post(sc, &mbx, NULL);
  872                 if (!rc)
  873                         rc = fwcmd->hdr.u0.rsp.status;
  874                 if (rc)
  875                 device_printf(sc->dev,
  876                               "%s failed - cmd status: %d addi status: %d\n",
  877                               __FUNCTION__, rc,
  878                               fwcmd->hdr.u0.rsp.additional_status);
  879         }
  880         return rc;
  881 }
  882 
  883 /**
  884  * @brief               RXF function to enable/disable device promiscuous mode
  885  * @param sc            software handle to the device
  886  * @param enable        enable/disable flag
  887  * @returns             0 on success, EIO on failure
  888  * @note
  889  *      The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
  890  *      This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
  891  */
  892 int
  893 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
  894 {
  895         struct mbx_set_common_iface_rx_filter *fwcmd;
  896         int sz = sizeof(struct mbx_set_common_iface_rx_filter);
  897         iface_rx_filter_ctx_t *req;
  898         OCE_DMA_MEM sgl;
  899         int rc;
  900 
  901         /* allocate mbx payload's dma scatter/gather memory */
  902         rc = oce_dma_alloc(sc, sz, &sgl, 0);
  903         if (rc)
  904                 return rc;
  905 
  906         fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
  907 
  908         req =  &fwcmd->params.req;
  909         req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
  910                                 MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
  911         /* Bit 0 Mac promisc, Bit 1 Vlan promisc */
  912         if (enable & 0x01)
  913                 req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
  914 
  915         if (enable & 0x02)
  916                 req->iface_flags |= MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
  917 
  918         req->if_id = sc->if_id;
  919 
  920         rc = oce_set_common_iface_rx_filter(sc, &sgl);
  921         oce_dma_free(sc, &sgl);
  922         
  923         return rc;
  924 }
  925 
  926 
  927 /**
  928  * @brief                       Function modify and select rx filter options
  929  * @param sc                    software handle to the device
  930  * @param sgl                   scatter/gather request/response
  931  * @returns                     0 on success, error code on failure
  932  */
  933 int
  934 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
  935 {
  936         struct oce_mbx mbx;
  937         int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
  938         struct mbx_set_common_iface_rx_filter *fwcmd;
  939         int rc;
  940 
  941         bzero(&mbx, sizeof(struct oce_mbx));
  942         fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
  943 
  944         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  945                                 MBX_SUBSYSTEM_COMMON,
  946                                 OPCODE_COMMON_SET_IFACE_RX_FILTER,
  947                                 MBX_TIMEOUT_SEC,
  948                                 mbx_sz,
  949                                 OCE_MBX_VER_V0);
  950 
  951         oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
  952         mbx.u0.s.embedded = 0;
  953         mbx.u0.s.sge_count = 1;
  954         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
  955         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
  956         mbx.payload.u0.u1.sgl[0].length = mbx_sz;
  957         mbx.payload_length = mbx_sz;
  958         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  959 
  960         rc = oce_mbox_post(sc, &mbx, NULL);
  961         if (!rc)
  962                 rc = fwcmd->hdr.u0.rsp.status;
  963         if (rc)
  964                 device_printf(sc->dev,
  965                               "%s failed - cmd status: %d addi status: %d\n",
  966                               __FUNCTION__, rc,
  967                               fwcmd->hdr.u0.rsp.additional_status);
  968         return rc;
  969 }
  970 
  971 /**
  972  * @brief Function to query the link status from the hardware
  973  * @param sc            software handle to the device
  974  * @param[out] link     pointer to the structure returning link attributes
  975  * @returns             0 on success, EIO on failure
  976  */
  977 int
  978 oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
  979 {
  980         struct oce_mbx mbx;
  981         struct mbx_query_common_link_config *fwcmd;
  982         int rc = 0, version;
  983 
  984         bzero(&mbx, sizeof(struct oce_mbx));
  985 
  986         IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
  987 
  988         fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
  989         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  990                                 MBX_SUBSYSTEM_COMMON,
  991                                 OPCODE_COMMON_QUERY_LINK_CONFIG,
  992                                 MBX_TIMEOUT_SEC,
  993                                 sizeof(struct mbx_query_common_link_config),
  994                                 version);
  995 
  996         mbx.u0.s.embedded = 1;
  997         mbx.payload_length = sizeof(struct mbx_query_common_link_config);
  998         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  999 
 1000         rc = oce_mbox_post(sc, &mbx, NULL);
 1001 
 1002         if (!rc)
 1003                 rc = fwcmd->hdr.u0.rsp.status;
 1004         if (rc) {
 1005                 device_printf(sc->dev,
 1006                               "%s failed - cmd status: %d addi status: %d\n",
 1007                               __FUNCTION__, rc,
 1008                               fwcmd->hdr.u0.rsp.additional_status);
 1009                 goto error;
 1010         }
 1011         /* interpret response */
 1012         link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed);
 1013         link->phys_port_speed = fwcmd->params.rsp.physical_port_speed;
 1014         link->logical_link_status = fwcmd->params.rsp.logical_link_status;
 1015 error:
 1016         return rc;
 1017 }
 1018 
 1019 
 1020 /**
 1021  * @brief Function to get NIC statistics
 1022  * @param sc            software handle to the device
 1023  * @param *stats        pointer to where to store statistics
 1024  * @param reset_stats   resets statistics of set
 1025  * @returns             0 on success, EIO on failure
 1026  * @note                command depricated in Lancer
 1027  */
 1028 #define OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, version)                             \
 1029 int                                                                                     \
 1030 oce_mbox_get_nic_stats_v##version(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)           \
 1031 {                                                                                       \
 1032         struct oce_mbx mbx;                                                             \
 1033         struct mbx_get_nic_stats_v##version *fwcmd;                                     \
 1034         int rc = 0;                                                                     \
 1035                                                                                         \
 1036         bzero(&mbx, sizeof(struct oce_mbx));                                            \
 1037         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v##version);        \
 1038         bzero(fwcmd, sizeof(*fwcmd));                                                   \
 1039                                                                                         \
 1040         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,                                      \
 1041                                 MBX_SUBSYSTEM_NIC,                                      \
 1042                                 NIC_GET_STATS,                                          \
 1043                                 MBX_TIMEOUT_SEC,                                        \
 1044                                 sizeof(*fwcmd),                                         \
 1045                                 OCE_MBX_VER_V##version);                                \
 1046                                                                                         \
 1047         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */              \
 1048         mbx.u0.s.sge_count = 1; /* using scatter gather instead */                      \
 1049                                                                                         \
 1050         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);                             \
 1051         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);                \
 1052         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);                \
 1053         mbx.payload.u0.u1.sgl[0].length = sizeof(*fwcmd);                               \
 1054         mbx.payload_length = sizeof(*fwcmd);                                            \
 1055         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);                   \
 1056                                                                                         \
 1057         rc = oce_mbox_post(sc, &mbx, NULL);                                             \
 1058         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);                            \
 1059         if (!rc)                                                                        \
 1060                 rc = fwcmd->hdr.u0.rsp.status;                                          \
 1061         if (rc)                                                                         \
 1062                 device_printf(sc->dev,                                                  \
 1063                               "%s failed - cmd status: %d addi status: %d\n",           \
 1064                               __FUNCTION__, rc,                                         \
 1065                               fwcmd->hdr.u0.rsp.additional_status);                     \
 1066         return rc;                                                                      \
 1067 }
 1068 
 1069 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 0);
 1070 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 1);
 1071 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 2);
 1072 
 1073 
 1074 /**
 1075  * @brief Function to get pport (physical port) statistics
 1076  * @param sc            software handle to the device
 1077  * @param *stats        pointer to where to store statistics
 1078  * @param reset_stats   resets statistics of set
 1079  * @returns             0 on success, EIO on failure
 1080  */
 1081 int
 1082 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
 1083                                 uint32_t reset_stats)
 1084 {
 1085         struct oce_mbx mbx;
 1086         struct mbx_get_pport_stats *fwcmd;
 1087         int rc = 0;
 1088 
 1089         bzero(&mbx, sizeof(struct oce_mbx));
 1090         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
 1091         bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
 1092 
 1093         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1094                                 MBX_SUBSYSTEM_NIC,
 1095                                 NIC_GET_PPORT_STATS,
 1096                                 MBX_TIMEOUT_SEC,
 1097                                 sizeof(struct mbx_get_pport_stats),
 1098                                 OCE_MBX_VER_V0);
 1099 
 1100         fwcmd->params.req.reset_stats = reset_stats;
 1101         fwcmd->params.req.port_number = sc->port_id;
 1102         
 1103         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
 1104         mbx.u0.s.sge_count = 1; /* using scatter gather instead */
 1105 
 1106         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
 1107         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
 1108         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
 1109         mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
 1110 
 1111         mbx.payload_length = sizeof(struct mbx_get_pport_stats);
 1112         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1113 
 1114         rc = oce_mbox_post(sc, &mbx, NULL);
 1115         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
 1116 
 1117         if (!rc)
 1118                 rc = fwcmd->hdr.u0.rsp.status;
 1119         if (rc)
 1120                 device_printf(sc->dev,
 1121                               "%s failed - cmd status: %d addi status: %d\n",
 1122                               __FUNCTION__, rc,
 1123                               fwcmd->hdr.u0.rsp.additional_status);
 1124         return rc;
 1125 }
 1126 
 1127 
 1128 /**
 1129  * @brief Function to get vport (virtual port) statistics
 1130  * @param sc            software handle to the device
 1131  * @param *stats        pointer to where to store statistics
 1132  * @param reset_stats   resets statistics of set
 1133  * @returns             0 on success, EIO on failure
 1134  */
 1135 int
 1136 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
 1137                                 uint32_t req_size, uint32_t reset_stats)
 1138 {
 1139         struct oce_mbx mbx;
 1140         struct mbx_get_vport_stats *fwcmd;
 1141         int rc = 0;
 1142 
 1143         bzero(&mbx, sizeof(struct oce_mbx));
 1144 
 1145         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
 1146         bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
 1147 
 1148         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1149                                 MBX_SUBSYSTEM_NIC,
 1150                                 NIC_GET_VPORT_STATS,
 1151                                 MBX_TIMEOUT_SEC,
 1152                                 sizeof(struct mbx_get_vport_stats),
 1153                                 OCE_MBX_VER_V0);
 1154 
 1155         fwcmd->params.req.reset_stats = reset_stats;
 1156         fwcmd->params.req.vport_number = sc->if_id;
 1157         
 1158         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
 1159         mbx.u0.s.sge_count = 1; /* using scatter gather instead */
 1160 
 1161         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
 1162         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
 1163         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
 1164         mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
 1165 
 1166         mbx.payload_length = sizeof(struct mbx_get_vport_stats);
 1167         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1168 
 1169         rc = oce_mbox_post(sc, &mbx, NULL);
 1170         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
 1171 
 1172         if (!rc)
 1173                 rc = fwcmd->hdr.u0.rsp.status;
 1174         if (rc)
 1175                 device_printf(sc->dev,
 1176                               "%s failed - cmd status: %d addi status: %d\n",
 1177                               __FUNCTION__, rc,
 1178                               fwcmd->hdr.u0.rsp.additional_status);
 1179         return rc;
 1180 }
 1181 
 1182 
 1183 /**
 1184  * @brief               Function to update the muticast filter with 
 1185  *                      values in dma_mem 
 1186  * @param sc            software handle to the device
 1187  * @param dma_mem       pointer to dma memory region
 1188  * @returns             0 on success, EIO on failure
 1189  */
 1190 int
 1191 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
 1192 {
 1193         struct oce_mbx mbx;
 1194         struct oce_mq_sge *sgl;
 1195         struct mbx_set_common_iface_multicast *req = NULL;
 1196         int rc = 0;
 1197 
 1198         req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
 1199         mbx_common_req_hdr_init(&req->hdr, 0, 0,
 1200                                 MBX_SUBSYSTEM_COMMON,
 1201                                 OPCODE_COMMON_SET_IFACE_MULTICAST,
 1202                                 MBX_TIMEOUT_SEC,
 1203                                 sizeof(struct mbx_set_common_iface_multicast),
 1204                                 OCE_MBX_VER_V0);
 1205 
 1206         bzero(&mbx, sizeof(struct oce_mbx));
 1207 
 1208         mbx.u0.s.embedded = 0; /*Non embeded*/
 1209         mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
 1210         mbx.u0.s.sge_count = 1;
 1211         sgl = &mbx.payload.u0.u1.sgl[0];
 1212         sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
 1213         sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
 1214         sgl->length = htole32(mbx.payload_length);
 1215 
 1216         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1217 
 1218         rc = oce_mbox_post(sc, &mbx, NULL);
 1219         if (!rc)
 1220                 rc = req->hdr.u0.rsp.status;
 1221         if (rc)
 1222                 device_printf(sc->dev,
 1223                               "%s failed - cmd status: %d addi status: %d\n",
 1224                               __FUNCTION__, rc,
 1225                               req->hdr.u0.rsp.additional_status);
 1226         return rc;
 1227 }
 1228 
 1229 
 1230 /**
 1231  * @brief               Function to send passthrough Ioctls
 1232  * @param sc            software handle to the device
 1233  * @param dma_mem       pointer to dma memory region
 1234  * @param req_size      size of dma_mem
 1235  * @returns             0 on success, EIO on failure
 1236  */
 1237 int
 1238 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
 1239 {
 1240         struct oce_mbx mbx;
 1241         struct oce_mq_sge *sgl;
 1242         int rc = 0;
 1243 
 1244         bzero(&mbx, sizeof(struct oce_mbx));
 1245 
 1246         mbx.u0.s.embedded  = 0; /*Non embeded*/
 1247         mbx.payload_length = req_size;
 1248         mbx.u0.s.sge_count = 1;
 1249         sgl = &mbx.payload.u0.u1.sgl[0];
 1250         sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
 1251         sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
 1252         sgl->length = htole32(req_size);
 1253 
 1254         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1255 
 1256         rc = oce_mbox_post(sc, &mbx, NULL);
 1257         return rc;
 1258 }
 1259 
 1260 
 1261 int
 1262 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
 1263                  uint32_t if_id, uint32_t *pmac_id)
 1264 {
 1265         struct oce_mbx mbx;
 1266         struct mbx_add_common_iface_mac *fwcmd;
 1267         int rc = 0;
 1268 
 1269         bzero(&mbx, sizeof(struct oce_mbx));
 1270 
 1271         fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
 1272         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1273                                 MBX_SUBSYSTEM_COMMON,
 1274                                 OPCODE_COMMON_ADD_IFACE_MAC,
 1275                                 MBX_TIMEOUT_SEC,
 1276                                 sizeof(struct mbx_add_common_iface_mac),
 1277                                 OCE_MBX_VER_V0);
 1278                                 
 1279         fwcmd->params.req.if_id = (uint16_t) if_id;
 1280         bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
 1281 
 1282         mbx.u0.s.embedded = 1;
 1283         mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
 1284         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1285         rc = oce_mbox_post(sc, &mbx, NULL);
 1286         if (!rc)
 1287                 rc = fwcmd->hdr.u0.rsp.status;
 1288         if (rc) {
 1289                 device_printf(sc->dev,
 1290                               "%s failed - cmd status: %d addi status: %d\n",
 1291                               __FUNCTION__, rc,
 1292                               fwcmd->hdr.u0.rsp.additional_status);
 1293                 goto error;
 1294         }
 1295         *pmac_id = fwcmd->params.rsp.pmac_id;
 1296 error:
 1297         return rc;
 1298 }
 1299 
 1300 
 1301 int
 1302 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
 1303 {
 1304         struct oce_mbx mbx;
 1305         struct mbx_del_common_iface_mac *fwcmd;
 1306         int rc = 0;
 1307 
 1308         bzero(&mbx, sizeof(struct oce_mbx));
 1309 
 1310         fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
 1311         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1312                                 MBX_SUBSYSTEM_COMMON,
 1313                                 OPCODE_COMMON_DEL_IFACE_MAC,
 1314                                 MBX_TIMEOUT_SEC,
 1315                                 sizeof(struct mbx_del_common_iface_mac),
 1316                                 OCE_MBX_VER_V0);
 1317 
 1318         fwcmd->params.req.if_id = (uint16_t)if_id;
 1319         fwcmd->params.req.pmac_id = pmac_id;
 1320 
 1321         mbx.u0.s.embedded = 1;
 1322         mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
 1323         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1324 
 1325         rc = oce_mbox_post(sc, &mbx, NULL);
 1326         if (!rc)
 1327                 rc = fwcmd->hdr.u0.rsp.status;
 1328         if (rc)
 1329                 device_printf(sc->dev,
 1330                               "%s failed - cmd status: %d addi status: %d\n",
 1331                               __FUNCTION__, rc,
 1332                               fwcmd->hdr.u0.rsp.additional_status);
 1333         return rc;
 1334 }
 1335 
 1336 
 1337 
 1338 int
 1339 oce_mbox_check_native_mode(POCE_SOFTC sc)
 1340 {
 1341         struct oce_mbx mbx;
 1342         struct mbx_common_set_function_cap *fwcmd;
 1343         int rc = 0;
 1344 
 1345         bzero(&mbx, sizeof(struct oce_mbx));
 1346 
 1347         fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
 1348         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1349                                 MBX_SUBSYSTEM_COMMON,
 1350                                 OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
 1351                                 MBX_TIMEOUT_SEC,
 1352                                 sizeof(struct mbx_common_set_function_cap),
 1353                                 OCE_MBX_VER_V0);
 1354 
 1355         fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS | 
 1356                                                         CAP_BE3_NATIVE_ERX_API;
 1357 
 1358         fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
 1359 
 1360         mbx.u0.s.embedded = 1;
 1361         mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
 1362         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1363 
 1364         rc = oce_mbox_post(sc, &mbx, NULL);
 1365         if (!rc)
 1366                 rc = fwcmd->hdr.u0.rsp.status;
 1367         if (rc) {
 1368                 device_printf(sc->dev,
 1369                               "%s failed - cmd status: %d addi status: %d\n",
 1370                               __FUNCTION__, rc,
 1371                               fwcmd->hdr.u0.rsp.additional_status);
 1372                 goto error;
 1373         }
 1374         sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
 1375                         & CAP_BE3_NATIVE_ERX_API;
 1376 
 1377 error:
 1378         return 0;
 1379 }
 1380 
 1381 
 1382 
 1383 int
 1384 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
 1385                 uint8_t loopback_type, uint8_t enable)
 1386 {
 1387         struct oce_mbx mbx;
 1388         struct mbx_lowlevel_set_loopback_mode *fwcmd;
 1389         int rc = 0;
 1390 
 1391 
 1392         bzero(&mbx, sizeof(struct oce_mbx));
 1393 
 1394         fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
 1395         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1396                                 MBX_SUBSYSTEM_LOWLEVEL,
 1397                                 OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
 1398                                 MBX_TIMEOUT_SEC,
 1399                                 sizeof(struct mbx_lowlevel_set_loopback_mode),
 1400                                 OCE_MBX_VER_V0);
 1401 
 1402         fwcmd->params.req.src_port = port_num;
 1403         fwcmd->params.req.dest_port = port_num;
 1404         fwcmd->params.req.loopback_type = loopback_type;
 1405         fwcmd->params.req.loopback_state = enable;
 1406 
 1407         mbx.u0.s.embedded = 1;
 1408         mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
 1409         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1410 
 1411         rc = oce_mbox_post(sc, &mbx, NULL);
 1412         if (!rc)
 1413                 rc = fwcmd->hdr.u0.rsp.status;
 1414         if (rc)
 1415                 device_printf(sc->dev,
 1416                               "%s failed - cmd status: %d addi status: %d\n",
 1417                               __FUNCTION__, rc,
 1418                               fwcmd->hdr.u0.rsp.additional_status);
 1419 
 1420         return rc;
 1421 
 1422 }
 1423 
 1424 int
 1425 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
 1426         uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
 1427         uint64_t pattern)
 1428 {
 1429         
 1430         struct oce_mbx mbx;
 1431         struct mbx_lowlevel_test_loopback_mode *fwcmd;
 1432         int rc = 0;
 1433 
 1434 
 1435         bzero(&mbx, sizeof(struct oce_mbx));
 1436 
 1437         fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
 1438         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1439                                 MBX_SUBSYSTEM_LOWLEVEL,
 1440                                 OPCODE_LOWLEVEL_TEST_LOOPBACK,
 1441                                 MBX_TIMEOUT_SEC,
 1442                                 sizeof(struct mbx_lowlevel_test_loopback_mode),
 1443                                 OCE_MBX_VER_V0);
 1444 
 1445         fwcmd->params.req.pattern = pattern;
 1446         fwcmd->params.req.src_port = port_num;
 1447         fwcmd->params.req.dest_port = port_num;
 1448         fwcmd->params.req.pkt_size = pkt_size;
 1449         fwcmd->params.req.num_pkts = num_pkts;
 1450         fwcmd->params.req.loopback_type = loopback_type;
 1451 
 1452         mbx.u0.s.embedded = 1;
 1453         mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
 1454         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1455 
 1456         rc = oce_mbox_post(sc, &mbx, NULL);
 1457         if (!rc)
 1458                 rc = fwcmd->hdr.u0.rsp.status;
 1459         if (rc)
 1460                 device_printf(sc->dev,
 1461                               "%s failed - cmd status: %d addi status: %d\n",
 1462                               __FUNCTION__, rc,
 1463                               fwcmd->hdr.u0.rsp.additional_status);
 1464         
 1465         return rc;
 1466 }
 1467 
 1468 int
 1469 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
 1470                                 POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
 1471 {
 1472 
 1473         struct oce_mbx mbx;
 1474         struct oce_mq_sge *sgl = NULL;
 1475         struct mbx_common_read_write_flashrom *fwcmd = NULL;
 1476         int rc = 0, payload_len = 0;
 1477 
 1478         bzero(&mbx, sizeof(struct oce_mbx));
 1479         fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
 1480         payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
 1481 
 1482         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1483                                 MBX_SUBSYSTEM_COMMON,
 1484                                 OPCODE_COMMON_WRITE_FLASHROM,
 1485                                 LONG_TIMEOUT,
 1486                                 payload_len,
 1487                                 OCE_MBX_VER_V0);
 1488 
 1489         fwcmd->flash_op_type = LE_32(optype);
 1490         fwcmd->flash_op_code = LE_32(opcode);
 1491         fwcmd->data_buffer_size = LE_32(num_bytes);
 1492 
 1493         mbx.u0.s.embedded  = 0; /*Non embeded*/
 1494         mbx.payload_length = payload_len;
 1495         mbx.u0.s.sge_count = 1;
 1496 
 1497         sgl = &mbx.payload.u0.u1.sgl[0];
 1498         sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
 1499         sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
 1500         sgl->length = payload_len;
 1501 
 1502         /* post the command */
 1503         rc = oce_mbox_post(sc, &mbx, NULL);
 1504         if (!rc)
 1505                 rc = fwcmd->hdr.u0.rsp.status;
 1506         if (rc)
 1507                 device_printf(sc->dev,
 1508                               "%s failed - cmd status: %d addi status: %d\n",
 1509                               __FUNCTION__, rc,
 1510                               fwcmd->hdr.u0.rsp.additional_status);
 1511         
 1512         return rc;
 1513 
 1514 }
 1515 
 1516 int
 1517 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
 1518                                 uint32_t offset, uint32_t optype)
 1519 {
 1520 
 1521         int rc = 0, payload_len = 0;
 1522         struct oce_mbx mbx;
 1523         struct mbx_common_read_write_flashrom *fwcmd;
 1524 
 1525         bzero(&mbx, sizeof(struct oce_mbx));
 1526 
 1527         fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
 1528 
 1529         /* Firmware requires extra 4 bytes with this ioctl. Since there
 1530            is enough room in the mbx payload it should be good enough
 1531            Reference: Bug 14853
 1532         */
 1533         payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
 1534 
 1535         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1536                                 MBX_SUBSYSTEM_COMMON,
 1537                                 OPCODE_COMMON_READ_FLASHROM,
 1538                                 MBX_TIMEOUT_SEC,
 1539                                 payload_len,
 1540                                 OCE_MBX_VER_V0);
 1541 
 1542         fwcmd->flash_op_type = optype;
 1543         fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
 1544         fwcmd->data_offset = offset;
 1545         fwcmd->data_buffer_size = 0x4;
 1546 
 1547         mbx.u0.s.embedded  = 1;
 1548         mbx.payload_length = payload_len;
 1549 
 1550         /* post the command */
 1551         rc = oce_mbox_post(sc, &mbx, NULL);
 1552         if (!rc)
 1553                 rc = fwcmd->hdr.u0.rsp.status;
 1554         if (rc) {
 1555                 device_printf(sc->dev,
 1556                               "%s failed - cmd status: %d addi status: %d\n",
 1557                               __FUNCTION__, rc,
 1558                               fwcmd->hdr.u0.rsp.additional_status);
 1559                 goto error;
 1560         }
 1561         bcopy(fwcmd->data_buffer, flash_crc, 4);
 1562 error:
 1563         return rc;
 1564 }
 1565 
 1566 int
 1567 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
 1568 {
 1569 
 1570         struct oce_mbx mbx;
 1571         struct mbx_common_phy_info *fwcmd;
 1572         int rc = 0;
 1573 
 1574         bzero(&mbx, sizeof(struct oce_mbx));
 1575 
 1576         fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
 1577         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1578                                 MBX_SUBSYSTEM_COMMON,
 1579                                 OPCODE_COMMON_GET_PHY_CONFIG,
 1580                                 MBX_TIMEOUT_SEC,
 1581                                 sizeof(struct mbx_common_phy_info),
 1582                                 OCE_MBX_VER_V0);
 1583 
 1584         mbx.u0.s.embedded = 1;
 1585         mbx.payload_length = sizeof(struct  mbx_common_phy_info);
 1586 
 1587         /* now post the command */
 1588         rc = oce_mbox_post(sc, &mbx, NULL);
 1589         if (!rc)
 1590                 rc = fwcmd->hdr.u0.rsp.status;
 1591         if (rc) {
 1592                 device_printf(sc->dev,
 1593                               "%s failed - cmd status: %d addi status: %d\n",
 1594                               __FUNCTION__, rc,
 1595                               fwcmd->hdr.u0.rsp.additional_status);
 1596                 goto error;
 1597         }
 1598         phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
 1599         phy_info->interface_type =
 1600                         HOST_16(fwcmd->params.rsp.phy_info.interface_type);
 1601         phy_info->auto_speeds_supported =
 1602                 HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
 1603         phy_info->fixed_speeds_supported =
 1604                 HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
 1605         phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
 1606 error:
 1607         return rc;
 1608 
 1609 }
 1610 
 1611 
 1612 int
 1613 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
 1614                         uint32_t data_offset, POCE_DMA_MEM pdma_mem,
 1615                         uint32_t *written_data, uint32_t *additional_status)
 1616 {
 1617 
 1618         struct oce_mbx mbx;
 1619         struct mbx_lancer_common_write_object *fwcmd = NULL;
 1620         int rc = 0, payload_len = 0;
 1621 
 1622         bzero(&mbx, sizeof(struct oce_mbx));
 1623         payload_len = sizeof(struct mbx_lancer_common_write_object);
 1624 
 1625         mbx.u0.s.embedded  = 1;/* Embedded */
 1626         mbx.payload_length = payload_len;
 1627         fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
 1628 
 1629         /* initialize the ioctl header */
 1630         mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
 1631                                 MBX_SUBSYSTEM_COMMON,
 1632                                 OPCODE_COMMON_WRITE_OBJECT,
 1633                                 LONG_TIMEOUT,
 1634                                 payload_len,
 1635                                 OCE_MBX_VER_V0);
 1636 
 1637         fwcmd->params.req.write_length = data_size;
 1638         if (data_size == 0)
 1639                 fwcmd->params.req.eof = 1;
 1640         else
 1641                 fwcmd->params.req.eof = 0;
 1642 
 1643         strcpy(fwcmd->params.req.object_name, "/prg");
 1644         fwcmd->params.req.descriptor_count = 1;
 1645         fwcmd->params.req.write_offset = data_offset;
 1646         fwcmd->params.req.buffer_length = data_size;
 1647         fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
 1648         fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
 1649 
 1650         /* post the command */
 1651         rc = oce_mbox_post(sc, &mbx, NULL);
 1652         if (!rc)
 1653                 rc = fwcmd->params.rsp.status;
 1654         if (rc) {
 1655                 device_printf(sc->dev,
 1656                               "%s failed - cmd status: %d addi status: %d\n",
 1657                               __FUNCTION__, rc,
 1658                               fwcmd->params.rsp.additional_status);
 1659                 goto error;
 1660         }
 1661         *written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
 1662         *additional_status = fwcmd->params.rsp.additional_status;
 1663 error:
 1664         return rc;
 1665 
 1666 }
 1667 
 1668 
 1669 
 1670 int
 1671 oce_mbox_create_rq(struct oce_rq *rq)
 1672 {
 1673 
 1674         struct oce_mbx mbx;
 1675         struct mbx_create_nic_rq *fwcmd;
 1676         POCE_SOFTC sc = rq->parent;
 1677         int rc, num_pages = 0;
 1678 
 1679         if (rq->qstate == QCREATED)
 1680                 return 0;
 1681 
 1682         bzero(&mbx, sizeof(struct oce_mbx));
 1683 
 1684         fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
 1685         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1686                                 MBX_SUBSYSTEM_NIC,
 1687                                 NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
 1688                                 sizeof(struct mbx_create_nic_rq),
 1689                                 OCE_MBX_VER_V0);
 1690 
 1691         /* oce_page_list will also prepare pages */
 1692         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
 1693         
 1694         if (IS_XE201(sc)) {
 1695                 fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
 1696                 fwcmd->params.req.page_size = 1;
 1697                 fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
 1698         } else
 1699                 fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
 1700         fwcmd->params.req.num_pages = num_pages;
 1701         fwcmd->params.req.cq_id = rq->cq->cq_id;
 1702         fwcmd->params.req.if_id = sc->if_id;
 1703         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
 1704         fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
 1705         
 1706         mbx.u0.s.embedded = 1;
 1707         mbx.payload_length = sizeof(struct mbx_create_nic_rq);
 1708         
 1709         rc = oce_mbox_post(sc, &mbx, NULL);
 1710         if (!rc)
 1711                 rc = fwcmd->hdr.u0.rsp.status;
 1712         if (rc) {
 1713                 device_printf(sc->dev,
 1714                               "%s failed - cmd status: %d addi status: %d\n",
 1715                               __FUNCTION__, rc,
 1716                               fwcmd->hdr.u0.rsp.additional_status);
 1717                 goto error;
 1718         }
 1719         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
 1720         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
 1721 error:
 1722         return rc;
 1723 
 1724 }
 1725 
 1726 
 1727 
 1728 int
 1729 oce_mbox_create_wq(struct oce_wq *wq)
 1730 {
 1731         struct oce_mbx mbx;
 1732         struct mbx_create_nic_wq *fwcmd;
 1733         POCE_SOFTC sc = wq->parent;
 1734         int rc = 0, version, num_pages;
 1735 
 1736         bzero(&mbx, sizeof(struct oce_mbx));
 1737 
 1738         fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
 1739         if (IS_XE201(sc))
 1740                 version = OCE_MBX_VER_V1;
 1741         else if(IS_BE(sc))
 1742                 IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2) 
 1743                                          : (version = OCE_MBX_VER_V0);
 1744         else
 1745                 version = OCE_MBX_VER_V2;
 1746 
 1747         if (version > OCE_MBX_VER_V0)
 1748                 fwcmd->params.req.if_id = sc->if_id;
 1749 
 1750         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1751                                 MBX_SUBSYSTEM_NIC,
 1752                                 NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
 1753                                 sizeof(struct mbx_create_nic_wq),
 1754                                 version);
 1755 
 1756         num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
 1757 
 1758         fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
 1759         fwcmd->params.req.num_pages = num_pages;
 1760         fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
 1761         fwcmd->params.req.cq_id = wq->cq->cq_id;
 1762         fwcmd->params.req.ulp_num = 1;
 1763 
 1764         mbx.u0.s.embedded = 1;
 1765         mbx.payload_length = sizeof(struct mbx_create_nic_wq);
 1766 
 1767         rc = oce_mbox_post(sc, &mbx, NULL);
 1768         if (!rc)
 1769                 rc = fwcmd->hdr.u0.rsp.status;
 1770         if (rc) {
 1771                 device_printf(sc->dev,
 1772                               "%s failed - cmd status: %d addi status: %d\n",
 1773                               __FUNCTION__, rc,
 1774                               fwcmd->hdr.u0.rsp.additional_status);
 1775                 goto error;
 1776         }
 1777         wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
 1778         if (version == OCE_MBX_VER_V2)
 1779                 wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
 1780         else
 1781                 wq->db_offset = PD_TXULP_DB;
 1782 error:
 1783         return rc;
 1784 
 1785 }
 1786 
 1787 
 1788 
 1789 int
 1790 oce_mbox_create_eq(struct oce_eq *eq)
 1791 {
 1792         struct oce_mbx mbx;
 1793         struct mbx_create_common_eq *fwcmd;
 1794         POCE_SOFTC sc = eq->parent;
 1795         int rc = 0;
 1796         uint32_t num_pages;
 1797 
 1798         bzero(&mbx, sizeof(struct oce_mbx));
 1799 
 1800         fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
 1801 
 1802         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1803                                 MBX_SUBSYSTEM_COMMON,
 1804                                 OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
 1805                                 sizeof(struct mbx_create_common_eq),
 1806                                 OCE_MBX_VER_V0);
 1807 
 1808         num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
 1809         fwcmd->params.req.ctx.num_pages = num_pages;
 1810         fwcmd->params.req.ctx.valid = 1;
 1811         fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
 1812         fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
 1813         fwcmd->params.req.ctx.armed = 0;
 1814         fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
 1815 
 1816 
 1817         mbx.u0.s.embedded = 1;
 1818         mbx.payload_length = sizeof(struct mbx_create_common_eq);
 1819 
 1820         rc = oce_mbox_post(sc, &mbx, NULL);
 1821         if (!rc)
 1822                 rc = fwcmd->hdr.u0.rsp.status;
 1823         if (rc) {
 1824                 device_printf(sc->dev,
 1825                               "%s failed - cmd status: %d addi status: %d\n",
 1826                               __FUNCTION__, rc,
 1827                               fwcmd->hdr.u0.rsp.additional_status);
 1828                 goto error;
 1829         }
 1830         eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
 1831 error:
 1832         return rc;
 1833 }
 1834 
 1835 
 1836 
 1837 int
 1838 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
 1839 {
 1840         struct oce_mbx mbx;
 1841         struct mbx_create_common_cq *fwcmd;
 1842         POCE_SOFTC sc = cq->parent;
 1843         uint8_t version;
 1844         oce_cq_ctx_t *ctx;
 1845         uint32_t num_pages, page_size;
 1846         int rc = 0;
 1847 
 1848         
 1849         bzero(&mbx, sizeof(struct oce_mbx));
 1850 
 1851         fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
 1852 
 1853         if (IS_XE201(sc))
 1854                 version = OCE_MBX_VER_V2;
 1855         else
 1856                 version = OCE_MBX_VER_V0;
 1857 
 1858         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1859                                 MBX_SUBSYSTEM_COMMON,
 1860                                 OPCODE_COMMON_CREATE_CQ,
 1861                                 MBX_TIMEOUT_SEC,
 1862                                 sizeof(struct mbx_create_common_cq),
 1863                                 version);
 1864 
 1865         ctx = &fwcmd->params.req.cq_ctx;
 1866 
 1867         num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
 1868         page_size =  1;  /* 1 for 4K */
 1869 
 1870         if (version == OCE_MBX_VER_V2) {
 1871                 ctx->v2.num_pages = LE_16(num_pages);
 1872                 ctx->v2.page_size = page_size;
 1873                 ctx->v2.eventable = is_eventable;
 1874                 ctx->v2.valid = 1;
 1875                 ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
 1876                 ctx->v2.nodelay = cq->cq_cfg.nodelay;
 1877                 ctx->v2.coalesce_wm = ncoalesce;
 1878                 ctx->v2.armed = 0;
 1879                 ctx->v2.eq_id = cq->eq->eq_id;
 1880                 if (ctx->v2.count == 3) {
 1881                         if ((u_int)cq->cq_cfg.q_len > (4*1024)-1)
 1882                                 ctx->v2.cqe_count = (4*1024)-1;
 1883                         else
 1884                                 ctx->v2.cqe_count = cq->cq_cfg.q_len;
 1885                 }
 1886         } else {
 1887                 ctx->v0.num_pages = LE_16(num_pages);
 1888                 ctx->v0.eventable = is_eventable;
 1889                 ctx->v0.valid = 1;
 1890                 ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
 1891                 ctx->v0.nodelay = cq->cq_cfg.nodelay;
 1892                 ctx->v0.coalesce_wm = ncoalesce;
 1893                 ctx->v0.armed = 0;
 1894                 ctx->v0.eq_id = cq->eq->eq_id;
 1895         }
 1896 
 1897         mbx.u0.s.embedded = 1;
 1898         mbx.payload_length = sizeof(struct mbx_create_common_cq);
 1899 
 1900         rc = oce_mbox_post(sc, &mbx, NULL);
 1901         if (!rc)
 1902                 rc = fwcmd->hdr.u0.rsp.status;
 1903         if (rc) {
 1904                 device_printf(sc->dev,
 1905                               "%s failed - cmd status: %d addi status: %d\n",
 1906                               __FUNCTION__, rc,
 1907                               fwcmd->hdr.u0.rsp.additional_status);
 1908                 goto error;
 1909         }
 1910         cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
 1911 error:
 1912         return rc;
 1913 
 1914 }
 1915 
 1916 int 
 1917 oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
 1918 {
 1919         int rc = 0;
 1920         struct oce_mbx mbx;
 1921         struct mbx_read_common_transrecv_data *fwcmd;
 1922         struct oce_mq_sge *sgl;
 1923         OCE_DMA_MEM dma;
 1924 
 1925         /* Allocate DMA mem*/
 1926         if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
 1927                                 &dma, 0))
 1928                 return ENOMEM;
 1929 
 1930         fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
 1931         bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
 1932 
 1933         bzero(&mbx, sizeof(struct oce_mbx));
 1934         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1935                         MBX_SUBSYSTEM_COMMON,
 1936                         OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
 1937                         MBX_TIMEOUT_SEC,
 1938                         sizeof(struct mbx_read_common_transrecv_data),
 1939                         OCE_MBX_VER_V0);
 1940 
 1941         /* fill rest of mbx */
 1942         mbx.u0.s.embedded = 0;
 1943         mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
 1944         mbx.u0.s.sge_count = 1;
 1945         sgl = &mbx.payload.u0.u1.sgl[0];
 1946         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
 1947         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
 1948         sgl->length = htole32(mbx.payload_length);
 1949         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 1950 
 1951         fwcmd->params.req.port = LE_32(sc->port_id);
 1952         fwcmd->params.req.page_num = LE_32(page_num);
 1953 
 1954         /* command post */
 1955         rc = oce_mbox_post(sc, &mbx, NULL);
 1956         if (!rc)
 1957                 rc = fwcmd->hdr.u0.rsp.status;
 1958         if (rc) {
 1959                 device_printf(sc->dev,
 1960                               "%s failed - cmd status: %d addi status: %d\n",
 1961                               __FUNCTION__, rc,
 1962                               fwcmd->hdr.u0.rsp.additional_status);
 1963                 goto error;
 1964         }
 1965         if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
 1966         {
 1967                 bcopy((char *)fwcmd->params.rsp.page_data, 
 1968                       &sfp_vpd_dump_buffer[0], 
 1969                       TRANSCEIVER_A0_SIZE);
 1970         }
 1971 
 1972         if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
 1973         {
 1974                 bcopy((char *)fwcmd->params.rsp.page_data, 
 1975                       &sfp_vpd_dump_buffer[TRANSCEIVER_A0_SIZE],
 1976                       TRANSCEIVER_A2_SIZE);
 1977         }
 1978 error:
 1979         oce_dma_free(sc, &dma);
 1980         return rc;
 1981 }
 1982 
 1983 void
 1984 oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
 1985                                 int num)
 1986 {
 1987         struct oce_mbx mbx;
 1988         struct mbx_modify_common_eq_delay *fwcmd;
 1989         int rc = 0;
 1990         int i = 0;
 1991 
 1992         bzero(&mbx, sizeof(struct oce_mbx));
 1993 
 1994         /* Initialize MODIFY_EQ_DELAY ioctl header */
 1995         fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
 1996         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 1997                                 MBX_SUBSYSTEM_COMMON,
 1998                                 OPCODE_COMMON_MODIFY_EQ_DELAY,
 1999                                 MBX_TIMEOUT_SEC,
 2000                                 sizeof(struct mbx_modify_common_eq_delay),
 2001                                 OCE_MBX_VER_V0);
 2002         /* fill rest of mbx */
 2003         mbx.u0.s.embedded = 1;
 2004         mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
 2005         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 2006 
 2007         fwcmd->params.req.num_eq = num;
 2008         for (i = 0; i < num; i++) {
 2009                 fwcmd->params.req.delay[i].eq_id = 
 2010                                         htole32(set_eqd[i].eq_id);
 2011                 fwcmd->params.req.delay[i].phase = 0;
 2012                 fwcmd->params.req.delay[i].dm =
 2013                 htole32(set_eqd[i].delay_multiplier);
 2014         }
 2015         
 2016 
 2017         /* command post */
 2018         rc = oce_mbox_post(sc, &mbx, NULL);
 2019 
 2020         if (!rc)
 2021                 rc = fwcmd->hdr.u0.rsp.status;
 2022         if (rc)
 2023                 device_printf(sc->dev,
 2024                               "%s failed - cmd status: %d addi status: %d\n",
 2025                               __FUNCTION__, rc,
 2026                               fwcmd->hdr.u0.rsp.additional_status);
 2027 }
 2028 
 2029 int
 2030 oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
 2031 {
 2032         struct oce_mbx mbx;
 2033         struct mbx_common_get_profile_config *fwcmd;
 2034         int rc = 0;
 2035         int version = 0;
 2036         struct oce_mq_sge *sgl;
 2037         OCE_DMA_MEM dma;
 2038         uint32_t desc_count = 0;
 2039         struct oce_nic_resc_desc *nic_desc = NULL;
 2040         int i;
 2041         boolean_t nic_desc_valid = FALSE;
 2042 
 2043         if (IS_BE2(sc))
 2044                 return -1;
 2045 
 2046         /* Allocate DMA mem*/
 2047         if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
 2048                           &dma, 0))
 2049                 return ENOMEM;
 2050 
 2051         /* Initialize MODIFY_EQ_DELAY ioctl header */
 2052         fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
 2053         bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
 2054 
 2055         if (!IS_XE201(sc))
 2056                 version = OCE_MBX_VER_V1;
 2057         else
 2058                 version = OCE_MBX_VER_V0;
 2059 
 2060         bzero(&mbx, sizeof(struct oce_mbx));
 2061         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 2062                                 MBX_SUBSYSTEM_COMMON,
 2063                                 OPCODE_COMMON_GET_PROFILE_CONFIG,
 2064                                 MBX_TIMEOUT_SEC,
 2065                                 sizeof(struct mbx_common_get_profile_config),
 2066                                 version);
 2067         /* fill rest of mbx */
 2068         mbx.u0.s.embedded = 0;
 2069         mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
 2070         mbx.u0.s.sge_count = 1;
 2071         sgl = &mbx.payload.u0.u1.sgl[0];
 2072         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
 2073         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
 2074         sgl->length = htole32(mbx.payload_length);
 2075         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 2076 
 2077         fwcmd->params.req.type = ACTIVE_PROFILE;
 2078 
 2079         /* command post */
 2080         rc = oce_mbox_post(sc, &mbx, NULL);
 2081         if (!rc)
 2082                 rc = fwcmd->hdr.u0.rsp.status;
 2083         if (rc) {
 2084                 device_printf(sc->dev,
 2085                               "%s failed - cmd status: %d addi status: %d\n",
 2086                               __FUNCTION__, rc,
 2087                               fwcmd->hdr.u0.rsp.additional_status);
 2088                 goto error;
 2089         }
 2090 
 2091         nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
 2092         desc_count = HOST_32(fwcmd->params.rsp.desc_count);
 2093         for (i = 0; i < desc_count; i++) {
 2094                 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 
 2095                     (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
 2096                         nic_desc_valid = TRUE;
 2097                         break;
 2098                 }
 2099                 nic_desc = (struct oce_nic_resc_desc *) \
 2100                                 ((char *)nic_desc + nic_desc->desc_len);
 2101         }
 2102         if (!nic_desc_valid) {
 2103                 rc = -1;
 2104                 goto error;
 2105         }
 2106         else { 
 2107                 sc->max_vlans = HOST_16(nic_desc->vlan_count);
 2108                 sc->nwqs = HOST_16(nic_desc->txq_count);
 2109                 if (sc->nwqs)
 2110                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
 2111                 else
 2112                         sc->nwqs = OCE_MAX_WQ;
 2113 
 2114                 sc->nrssqs = HOST_16(nic_desc->rssq_count);
 2115                 if (sc->nrssqs)
 2116                         sc->nrssqs = MIN(sc->nrssqs, max_rss);
 2117                 else
 2118                         sc->nrssqs = max_rss;
 2119                 sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
 2120 
 2121         }
 2122 error:
 2123         oce_dma_free(sc, &dma);
 2124         return rc;
 2125 
 2126 }
 2127 
 2128 int
 2129 oce_get_func_config(POCE_SOFTC sc)
 2130 {
 2131         struct oce_mbx mbx;
 2132         struct mbx_common_get_func_config *fwcmd;
 2133         int rc = 0;
 2134         int version = 0;
 2135         struct oce_mq_sge *sgl;
 2136         OCE_DMA_MEM dma;
 2137         uint32_t desc_count = 0;
 2138         struct oce_nic_resc_desc *nic_desc = NULL;
 2139         int i;
 2140         boolean_t nic_desc_valid = FALSE;
 2141         uint32_t max_rss = 0;
 2142         
 2143         if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
 2144                 max_rss = OCE_LEGACY_MODE_RSS;
 2145         else
 2146                 max_rss = OCE_MAX_RSS;
 2147 
 2148         /* Allocate DMA mem*/
 2149         if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
 2150                           &dma, 0))
 2151                 return ENOMEM;
 2152 
 2153         /* Initialize MODIFY_EQ_DELAY ioctl header */
 2154         fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
 2155         bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
 2156 
 2157         if (IS_SH(sc))
 2158                 version = OCE_MBX_VER_V1;
 2159         else
 2160                 version = OCE_MBX_VER_V0;
 2161 
 2162         bzero(&mbx, sizeof(struct oce_mbx));
 2163         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 2164                                 MBX_SUBSYSTEM_COMMON,
 2165                                 OPCODE_COMMON_GET_FUNCTION_CONFIG,
 2166                                 MBX_TIMEOUT_SEC,
 2167                                 sizeof(struct mbx_common_get_func_config),
 2168                                 version);
 2169         /* fill rest of mbx */
 2170         mbx.u0.s.embedded = 0;
 2171         mbx.payload_length = sizeof(struct mbx_common_get_func_config);
 2172         mbx.u0.s.sge_count = 1;
 2173         sgl = &mbx.payload.u0.u1.sgl[0];
 2174         sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
 2175         sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
 2176         sgl->length = htole32(mbx.payload_length);
 2177         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
 2178 
 2179         /* command post */
 2180         rc = oce_mbox_post(sc, &mbx, NULL);
 2181         if (!rc)
 2182                 rc = fwcmd->hdr.u0.rsp.status;
 2183         if (rc) {
 2184                 device_printf(sc->dev,
 2185                               "%s failed - cmd status: %d addi status: %d\n",
 2186                               __FUNCTION__, rc,
 2187                               fwcmd->hdr.u0.rsp.additional_status);
 2188                 goto error;
 2189         }
 2190 
 2191         nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
 2192         desc_count = HOST_32(fwcmd->params.rsp.desc_count);
 2193         for (i = 0; i < desc_count; i++) {
 2194                 if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || 
 2195                     (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
 2196                         nic_desc_valid = TRUE;
 2197                         break;
 2198                 }
 2199                 nic_desc = (struct oce_nic_resc_desc *) \
 2200                                 ((char *)nic_desc + nic_desc->desc_len);
 2201         }
 2202         if (!nic_desc_valid) {
 2203                 rc = -1;
 2204                 goto error;
 2205         }
 2206         else {
 2207                 sc->max_vlans = nic_desc->vlan_count;
 2208                 sc->nwqs = HOST_32(nic_desc->txq_count);
 2209                 if (sc->nwqs)
 2210                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
 2211                 else
 2212                         sc->nwqs = OCE_MAX_WQ;
 2213 
 2214                 sc->nrssqs = HOST_32(nic_desc->rssq_count);
 2215                 if (sc->nrssqs)
 2216                         sc->nrssqs = MIN(sc->nrssqs, max_rss);
 2217                 else
 2218                         sc->nrssqs = max_rss;
 2219                 sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
 2220         }
 2221 error:
 2222         oce_dma_free(sc, &dma);
 2223         return rc;
 2224 
 2225 }
 2226 
 2227 /* hw lro functions */
 2228 
 2229 int
 2230 oce_mbox_nic_query_lro_capabilities(POCE_SOFTC sc, uint32_t *lro_rq_cnt, uint32_t *lro_flags)
 2231 {
 2232         struct oce_mbx mbx;
 2233         struct mbx_nic_query_lro_capabilities *fwcmd;
 2234         int rc = 0;
 2235 
 2236         bzero(&mbx, sizeof(struct oce_mbx));
 2237 
 2238         fwcmd = (struct mbx_nic_query_lro_capabilities *)&mbx.payload;
 2239         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 2240                                 MBX_SUBSYSTEM_NIC,
 2241                                 0x20,MBX_TIMEOUT_SEC,
 2242                                 sizeof(struct mbx_nic_query_lro_capabilities),
 2243                                 OCE_MBX_VER_V0);
 2244 
 2245         mbx.u0.s.embedded = 1;
 2246         mbx.payload_length = sizeof(struct mbx_nic_query_lro_capabilities);
 2247 
 2248         rc = oce_mbox_post(sc, &mbx, NULL);
 2249         if (!rc)
 2250                 rc = fwcmd->hdr.u0.rsp.status;
 2251         if (rc) {
 2252                 device_printf(sc->dev,
 2253                               "%s failed - cmd status: %d addi status: %d\n",
 2254                               __FUNCTION__, rc,
 2255                               fwcmd->hdr.u0.rsp.additional_status);
 2256 
 2257                 return rc;
 2258         }
 2259         if(lro_flags)
 2260                 *lro_flags = HOST_32(fwcmd->params.rsp.lro_flags);
 2261 
 2262         if(lro_rq_cnt)
 2263                 *lro_rq_cnt = HOST_16(fwcmd->params.rsp.lro_rq_cnt);
 2264 
 2265         return rc;
 2266 }
 2267 
 2268 int
 2269 oce_mbox_nic_set_iface_lro_config(POCE_SOFTC sc, int enable)
 2270 {
 2271         struct oce_mbx mbx;
 2272         struct mbx_nic_set_iface_lro_config *fwcmd;
 2273         int rc = 0;
 2274 
 2275         bzero(&mbx, sizeof(struct oce_mbx));
 2276 
 2277         fwcmd = (struct mbx_nic_set_iface_lro_config *)&mbx.payload;
 2278         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 2279                                 MBX_SUBSYSTEM_NIC,
 2280                                 0x26,MBX_TIMEOUT_SEC,
 2281                                 sizeof(struct mbx_nic_set_iface_lro_config),
 2282                                 OCE_MBX_VER_V0);
 2283 
 2284         mbx.u0.s.embedded = 1;
 2285         mbx.payload_length = sizeof(struct mbx_nic_set_iface_lro_config);
 2286 
 2287         fwcmd->params.req.iface_id = sc->if_id;
 2288         fwcmd->params.req.lro_flags = 0;
 2289 
 2290         if(enable) {
 2291                 fwcmd->params.req.lro_flags = LRO_FLAGS_HASH_MODE | LRO_FLAGS_RSS_MODE;
 2292                 fwcmd->params.req.lro_flags |= LRO_FLAGS_CLSC_IPV4 | LRO_FLAGS_CLSC_IPV6;
 2293 
 2294                 fwcmd->params.req.max_clsc_byte_cnt = 64*1024; /* min = 2974, max = 0xfa59 */
 2295                 fwcmd->params.req.max_clsc_seg_cnt = 43; /* min = 2, max = 64 */
 2296                 fwcmd->params.req.max_clsc_usec_delay = 18; /* min = 1, max = 256 */
 2297                 fwcmd->params.req.min_clsc_frame_byte_cnt = 0; /* min = 1, max = 9014 */
 2298         }
 2299 
 2300         rc = oce_mbox_post(sc, &mbx, NULL);
 2301         if (!rc)
 2302                 rc = fwcmd->hdr.u0.rsp.status;
 2303         if (rc) {
 2304                 device_printf(sc->dev,
 2305                               "%s failed - cmd status: %d addi status: %d\n",
 2306                               __FUNCTION__, rc,
 2307                               fwcmd->hdr.u0.rsp.additional_status);
 2308 
 2309                 return rc;
 2310         }
 2311         return rc;
 2312 }
 2313 
 2314 int
 2315 oce_mbox_create_rq_v2(struct oce_rq *rq)
 2316 {
 2317         struct oce_mbx mbx;
 2318         struct mbx_create_nic_rq_v2 *fwcmd;
 2319         POCE_SOFTC sc = rq->parent;
 2320         int rc = 0, num_pages = 0;
 2321 
 2322         if (rq->qstate == QCREATED)
 2323                 return 0;
 2324 
 2325         bzero(&mbx, sizeof(struct oce_mbx));
 2326 
 2327         fwcmd = (struct mbx_create_nic_rq_v2 *)&mbx.payload;
 2328         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 2329                                 MBX_SUBSYSTEM_NIC,
 2330                                 0x08, MBX_TIMEOUT_SEC,
 2331                                 sizeof(struct mbx_create_nic_rq_v2),
 2332                                 OCE_MBX_VER_V2);
 2333 
 2334         /* oce_page_list will also prepare pages */
 2335         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
 2336 
 2337         fwcmd->params.req.cq_id = rq->cq->cq_id;
 2338         fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
 2339         fwcmd->params.req.num_pages = num_pages;
 2340 
 2341         fwcmd->params.req.if_id = sc->if_id;
 2342 
 2343         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
 2344         fwcmd->params.req.page_size = 1;
 2345         if(rq->cfg.is_rss_queue) {
 2346                 fwcmd->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
 2347         }else {
 2348                 device_printf(sc->dev,
 2349                         "non rss lro queue should not be created \n");
 2350                 goto error;
 2351         }
 2352         mbx.u0.s.embedded = 1;
 2353         mbx.payload_length = sizeof(struct mbx_create_nic_rq_v2);
 2354 
 2355         rc = oce_mbox_post(sc, &mbx, NULL);
 2356         if (!rc)
 2357                 rc = fwcmd->hdr.u0.rsp.status;
 2358         if (rc) {
 2359                 device_printf(sc->dev,
 2360                               "%s failed - cmd status: %d addi status: %d\n",
 2361                               __FUNCTION__, rc,
 2362                               fwcmd->hdr.u0.rsp.additional_status);
 2363                 goto error;
 2364         }
 2365         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
 2366         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
 2367 
 2368 error:
 2369         return rc;
 2370 }
 2371 

Cache object: ae9e2642da6f4dbb02328e72063fbb33


[ 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.