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/bnxt/bnxt_hwrm.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  * Broadcom NetXtreme-C/E network driver.
    3  *
    4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
    5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
   17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   26  * THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/12.0/sys/dev/bnxt/bnxt_hwrm.c 333870 2018-05-19 05:57:26Z mmacy $");
   31 
   32 #include <sys/endian.h>
   33 #include <sys/bitstring.h>
   34 
   35 #include "bnxt.h"
   36 #include "bnxt_hwrm.h"
   37 #include "hsi_struct_def.h"
   38 
   39 static int bnxt_hwrm_err_map(uint16_t err);
   40 static inline int _is_valid_ether_addr(uint8_t *);
   41 static inline void get_random_ether_addr(uint8_t *);
   42 static void     bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
   43                     struct hwrm_port_phy_cfg_input *req);
   44 static void     bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
   45                     struct hwrm_port_phy_cfg_input *req);
   46 static void     bnxt_hwrm_set_eee(struct bnxt_softc *softc,
   47                     struct hwrm_port_phy_cfg_input *req);
   48 static int      _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
   49 static int      hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
   50 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
   51 
   52 /* NVRam stuff has a five minute timeout */
   53 #define BNXT_NVM_TIMEO  (5 * 60 * 1000)
   54 
   55 static int
   56 bnxt_hwrm_err_map(uint16_t err)
   57 {
   58         int rc;
   59 
   60         switch (err) {
   61         case HWRM_ERR_CODE_SUCCESS:
   62                 return 0;
   63         case HWRM_ERR_CODE_INVALID_PARAMS:
   64         case HWRM_ERR_CODE_INVALID_FLAGS:
   65         case HWRM_ERR_CODE_INVALID_ENABLES:
   66                 return EINVAL;
   67         case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
   68                 return EACCES;
   69         case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
   70                 return ENOMEM;
   71         case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
   72                 return ENOSYS;
   73         case HWRM_ERR_CODE_FAIL:
   74                 return EIO;
   75         case HWRM_ERR_CODE_HWRM_ERROR:
   76         case HWRM_ERR_CODE_UNKNOWN_ERR:
   77         default:
   78                 return EDOOFUS;
   79         }
   80 
   81         return rc;
   82 }
   83 
   84 int
   85 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
   86 {
   87         int rc;
   88 
   89         rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
   90             BUS_DMA_NOWAIT);
   91         return rc;
   92 }
   93 
   94 void
   95 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
   96 {
   97         if (softc->hwrm_cmd_resp.idi_vaddr)
   98                 iflib_dma_free(&softc->hwrm_cmd_resp);
   99         softc->hwrm_cmd_resp.idi_vaddr = NULL;
  100         return;
  101 }
  102 
  103 static void
  104 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
  105     uint16_t req_type)
  106 {
  107         struct input *req = request;
  108 
  109         req->req_type = htole16(req_type);
  110         req->cmpl_ring = 0xffff;
  111         req->target_id = 0xffff;
  112         req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
  113 }
  114 
  115 static int
  116 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
  117 {
  118         struct input *req = msg;
  119         struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
  120         uint32_t *data = msg;
  121         int i;
  122         uint16_t cp_ring_id;
  123         uint8_t *valid;
  124         uint16_t err;
  125         uint16_t max_req_len = HWRM_MAX_REQ_LEN;
  126         struct hwrm_short_input short_input = {0};
  127 
  128         /* TODO: DMASYNC in here. */
  129         req->seq_id = htole16(softc->hwrm_cmd_seq++);
  130         memset(resp, 0, PAGE_SIZE);
  131         cp_ring_id = le16toh(req->cmpl_ring);
  132 
  133         if (softc->flags & BNXT_FLAG_SHORT_CMD) {
  134                 void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
  135 
  136                 memcpy(short_cmd_req, req, msg_len);
  137                 memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len-
  138                     msg_len);
  139 
  140                 short_input.req_type = req->req_type;
  141                 short_input.signature =
  142                     htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
  143                 short_input.size = htole16(msg_len);
  144                 short_input.req_addr =
  145                     htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
  146 
  147                 data = (uint32_t *)&short_input;
  148                 msg_len = sizeof(short_input);
  149 
  150                 /* Sync memory write before updating doorbell */
  151                 wmb();
  152 
  153                 max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
  154         }
  155 
  156         /* Write request msg to hwrm channel */
  157         for (i = 0; i < msg_len; i += 4) {
  158                 bus_space_write_4(softc->hwrm_bar.tag,
  159                                   softc->hwrm_bar.handle,
  160                                   i, *data);
  161                 data++;
  162         }
  163 
  164         /* Clear to the end of the request buffer */
  165         for (i = msg_len; i < max_req_len; i += 4)
  166                 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
  167                     i, 0);
  168 
  169         /* Ring channel doorbell */
  170         bus_space_write_4(softc->hwrm_bar.tag,
  171                           softc->hwrm_bar.handle,
  172                           0x100, htole32(1));
  173 
  174         /* Check if response len is updated */
  175         for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
  176                 if (resp->resp_len && resp->resp_len <= 4096)
  177                         break;
  178                 DELAY(1000);
  179         }
  180         if (i >= softc->hwrm_cmd_timeo) {
  181                 device_printf(softc->dev,
  182                     "Timeout sending %s: (timeout: %u) seq: %d\n",
  183                     GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
  184                     le16toh(req->seq_id));
  185                 return ETIMEDOUT;
  186         }
  187         /* Last byte of resp contains the valid key */
  188         valid = (uint8_t *)resp + resp->resp_len - 1;
  189         for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
  190                 if (*valid == HWRM_RESP_VALID_KEY)
  191                         break;
  192                 DELAY(1000);
  193         }
  194         if (i >= softc->hwrm_cmd_timeo) {
  195                 device_printf(softc->dev, "Timeout sending %s: "
  196                     "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
  197                     GET_HWRM_REQ_TYPE(req->req_type),
  198                     softc->hwrm_cmd_timeo, le16toh(req->req_type),
  199                     le16toh(req->seq_id), msg_len,
  200                     *valid);
  201                 return ETIMEDOUT;
  202         }
  203 
  204         err = le16toh(resp->error_code);
  205         if (err) {
  206                 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
  207                 if (err != HWRM_ERR_CODE_FAIL) {
  208                         device_printf(softc->dev,
  209                             "%s command returned %s error.\n",
  210                             GET_HWRM_REQ_TYPE(req->req_type),
  211                             GET_HWRM_ERROR_CODE(err));
  212                 }
  213                 return bnxt_hwrm_err_map(err);
  214         }
  215 
  216         return 0;
  217 }
  218 
  219 static int
  220 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
  221 {
  222         int rc;
  223 
  224         BNXT_HWRM_LOCK(softc);
  225         rc = _hwrm_send_message(softc, msg, msg_len);
  226         BNXT_HWRM_UNLOCK(softc);
  227         return rc;
  228 }
  229 
  230 int
  231 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
  232 {
  233         struct hwrm_queue_qportcfg_input req = {0};
  234         struct hwrm_queue_qportcfg_output *resp =
  235             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  236 
  237         int     rc = 0;
  238         uint8_t *qptr;
  239 
  240         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
  241 
  242         BNXT_HWRM_LOCK(softc);
  243         rc = _hwrm_send_message(softc, &req, sizeof(req));
  244         if (rc)
  245                 goto qportcfg_exit;
  246 
  247         if (!resp->max_configurable_queues) {
  248                 rc = -EINVAL;
  249                 goto qportcfg_exit;
  250         }
  251         softc->max_tc = resp->max_configurable_queues;
  252         if (softc->max_tc > BNXT_MAX_QUEUE)
  253                 softc->max_tc = BNXT_MAX_QUEUE;
  254 
  255         qptr = &resp->queue_id0;
  256         for (int i = 0; i < softc->max_tc; i++) {
  257                 softc->q_info[i].id = *qptr++;
  258                 softc->q_info[i].profile = *qptr++;
  259         }
  260 
  261 qportcfg_exit:
  262         BNXT_HWRM_UNLOCK(softc);
  263         return (rc);
  264 }
  265 
  266 
  267 int
  268 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
  269 {
  270         struct hwrm_ver_get_input       req = {0};
  271         struct hwrm_ver_get_output      *resp =
  272             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  273         int                             rc;
  274         const char nastr[] = "<not installed>";
  275         const char naver[] = "<N/A>";
  276         uint32_t dev_caps_cfg;
  277 
  278         softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
  279         softc->hwrm_cmd_timeo = 1000;
  280         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
  281 
  282         req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
  283         req.hwrm_intf_min = HWRM_VERSION_MINOR;
  284         req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
  285 
  286         BNXT_HWRM_LOCK(softc);
  287         rc = _hwrm_send_message(softc, &req, sizeof(req));
  288         if (rc)
  289                 goto fail;
  290 
  291         snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
  292             resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
  293         softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
  294         softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
  295         softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
  296         snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
  297             resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
  298         strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
  299             BNXT_VERSTR_SIZE);
  300         strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
  301             BNXT_NAME_SIZE);
  302 
  303         if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
  304             resp->mgmt_fw_bld == 0) {
  305                 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
  306                 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
  307         }
  308         else {
  309                 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
  310                     "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
  311                     resp->mgmt_fw_bld);
  312                 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
  313                     BNXT_NAME_SIZE);
  314         }
  315         if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
  316             resp->netctrl_fw_bld == 0) {
  317                 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
  318                     BNXT_VERSTR_SIZE);
  319                 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
  320                     BNXT_NAME_SIZE);
  321         }
  322         else {
  323                 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
  324                     "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
  325                     resp->netctrl_fw_bld);
  326                 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
  327                     BNXT_NAME_SIZE);
  328         }
  329         if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
  330             resp->roce_fw_bld == 0) {
  331                 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
  332                 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
  333         }
  334         else {
  335                 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
  336                     "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
  337                     resp->roce_fw_bld);
  338                 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
  339                     BNXT_NAME_SIZE);
  340         }
  341         softc->ver_info->chip_num = le16toh(resp->chip_num);
  342         softc->ver_info->chip_rev = resp->chip_rev;
  343         softc->ver_info->chip_metal = resp->chip_metal;
  344         softc->ver_info->chip_bond_id = resp->chip_bond_id;
  345         softc->ver_info->chip_type = resp->chip_platform_type;
  346 
  347         if (resp->max_req_win_len)
  348                 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
  349         if (resp->def_req_timeout)
  350                 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
  351 
  352         dev_caps_cfg = le32toh(resp->dev_caps_cfg);
  353         if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
  354             (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
  355                 softc->flags |= BNXT_FLAG_SHORT_CMD;
  356 
  357 fail:
  358         BNXT_HWRM_UNLOCK(softc);
  359         return rc;
  360 }
  361 
  362 int
  363 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
  364 {
  365         struct hwrm_func_drv_rgtr_input req = {0};
  366 
  367         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
  368 
  369         req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
  370             HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
  371         req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
  372 
  373         req.ver_maj = __FreeBSD_version / 100000;
  374         req.ver_min = (__FreeBSD_version / 1000) % 100;
  375         req.ver_upd = (__FreeBSD_version / 100) % 10;
  376 
  377         return hwrm_send_message(softc, &req, sizeof(req));
  378 }
  379 
  380 
  381 int
  382 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
  383 {
  384         struct hwrm_func_drv_unrgtr_input req = {0};
  385 
  386         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
  387         if (shutdown == true)
  388                 req.flags |=
  389                     HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
  390         return hwrm_send_message(softc, &req, sizeof(req));
  391 }
  392 
  393 
  394 static inline int
  395 _is_valid_ether_addr(uint8_t *addr)
  396 {
  397         char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
  398 
  399         if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
  400                 return (FALSE);
  401 
  402         return (TRUE);
  403 }
  404 
  405 static inline void
  406 get_random_ether_addr(uint8_t *addr)
  407 {
  408         uint8_t temp[ETHER_ADDR_LEN];
  409 
  410         arc4rand(&temp, sizeof(temp), 0);
  411         temp[0] &= 0xFE;
  412         temp[0] |= 0x02;
  413         bcopy(temp, addr, sizeof(temp));
  414 }
  415 
  416 int
  417 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
  418 {
  419         int rc = 0;
  420         struct hwrm_func_qcaps_input req = {0};
  421         struct hwrm_func_qcaps_output *resp =
  422             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  423         struct bnxt_func_info *func = &softc->func;
  424 
  425         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
  426         req.fid = htole16(0xffff);
  427 
  428         BNXT_HWRM_LOCK(softc);
  429         rc = _hwrm_send_message(softc, &req, sizeof(req));
  430         if (rc)
  431                 goto fail;
  432 
  433         if (resp->flags &
  434             htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
  435                 softc->flags |= BNXT_FLAG_WOL_CAP;
  436 
  437         func->fw_fid = le16toh(resp->fid);
  438         memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
  439         func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
  440         func->max_cp_rings = le16toh(resp->max_cmpl_rings);
  441         func->max_tx_rings = le16toh(resp->max_tx_rings);
  442         func->max_rx_rings = le16toh(resp->max_rx_rings);
  443         func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
  444         if (!func->max_hw_ring_grps)
  445                 func->max_hw_ring_grps = func->max_tx_rings;
  446         func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
  447         func->max_vnics = le16toh(resp->max_vnics);
  448         func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
  449         if (BNXT_PF(softc)) {
  450                 struct bnxt_pf_info *pf = &softc->pf;
  451 
  452                 pf->port_id = le16toh(resp->port_id);
  453                 pf->first_vf_id = le16toh(resp->first_vf_id);
  454                 pf->max_vfs = le16toh(resp->max_vfs);
  455                 pf->max_encap_records = le32toh(resp->max_encap_records);
  456                 pf->max_decap_records = le32toh(resp->max_decap_records);
  457                 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
  458                 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
  459                 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
  460                 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
  461         }
  462         if (!_is_valid_ether_addr(func->mac_addr)) {
  463                 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
  464                 get_random_ether_addr(func->mac_addr);
  465         }
  466 
  467 fail:
  468         BNXT_HWRM_UNLOCK(softc);
  469         return rc;
  470 }
  471 
  472 int 
  473 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
  474 {
  475         struct hwrm_func_qcfg_input req = {0};
  476         struct hwrm_func_qcfg_output *resp =
  477             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  478         struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
  479         int rc;
  480 
  481         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
  482         req.fid = htole16(0xffff);
  483         BNXT_HWRM_LOCK(softc);
  484         rc = _hwrm_send_message(softc, &req, sizeof(req));
  485         if (rc)
  486                 goto fail;
  487 
  488         fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
  489         fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
  490         fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
  491         fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
  492 fail:
  493         BNXT_HWRM_UNLOCK(softc);
  494         return rc;
  495 }
  496 
  497 int
  498 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
  499 {
  500         struct hwrm_func_reset_input req = {0};
  501 
  502         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
  503         req.enables = 0;
  504 
  505         return hwrm_send_message(softc, &req, sizeof(req));
  506 }
  507 
  508 static void
  509 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
  510     struct hwrm_port_phy_cfg_input *req)
  511 {
  512         uint8_t autoneg = softc->link_info.autoneg;
  513         uint16_t fw_link_speed = softc->link_info.req_link_speed;
  514 
  515         if (autoneg & BNXT_AUTONEG_SPEED) {
  516                 req->auto_mode |=
  517                     HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
  518 
  519                 req->enables |=
  520                     htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
  521                 req->flags |=
  522                     htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
  523         } else {
  524                 req->force_link_speed = htole16(fw_link_speed);
  525                 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
  526         }
  527 
  528         /* tell chimp that the setting takes effect immediately */
  529         req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
  530 }
  531 
  532 
  533 static void
  534 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
  535     struct hwrm_port_phy_cfg_input *req)
  536 {
  537         struct bnxt_link_info *link_info = &softc->link_info;
  538 
  539         if (link_info->flow_ctrl.autoneg) {
  540                 req->auto_pause =
  541                     HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
  542                 if (link_info->flow_ctrl.rx)
  543                         req->auto_pause |=
  544                             HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
  545                 if (link_info->flow_ctrl.tx)
  546                         req->auto_pause |=
  547                             HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
  548                 req->enables |=
  549                     htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
  550         } else {
  551                 if (link_info->flow_ctrl.rx)
  552                         req->force_pause |=
  553                             HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
  554                 if (link_info->flow_ctrl.tx)
  555                         req->force_pause |=
  556                             HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
  557                 req->enables |=
  558                         htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
  559         }
  560 }
  561 
  562 
  563 /* JFV this needs interface connection */
  564 static void
  565 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
  566 {
  567         /* struct ethtool_eee *eee = &softc->eee; */
  568         bool    eee_enabled = false;
  569 
  570         if (eee_enabled) {
  571 #if 0
  572                 uint16_t eee_speeds;
  573                 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
  574 
  575                 if (eee->tx_lpi_enabled)
  576                         flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
  577 
  578                 req->flags |= htole32(flags);
  579                 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
  580                 req->eee_link_speed_mask = htole16(eee_speeds);
  581                 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
  582 #endif
  583         } else {
  584                 req->flags |=
  585                     htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
  586         }
  587 }
  588 
  589 
  590 int
  591 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
  592     bool set_eee, bool set_link)
  593 {
  594         struct hwrm_port_phy_cfg_input req = {0};
  595         int rc;
  596 
  597         if (softc->flags & BNXT_FLAG_NPAR)
  598                 return ENOTSUP;
  599 
  600         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
  601         
  602         if (set_pause) {
  603                 bnxt_hwrm_set_pause_common(softc, &req);
  604 
  605                 if (softc->link_info.flow_ctrl.autoneg)
  606                         set_link = true;
  607         }
  608 
  609         if (set_link)
  610                 bnxt_hwrm_set_link_common(softc, &req);
  611         
  612         if (set_eee)
  613                 bnxt_hwrm_set_eee(softc, &req);
  614         
  615         BNXT_HWRM_LOCK(softc);
  616         rc = _hwrm_send_message(softc, &req, sizeof(req));
  617 
  618         if (!rc) {
  619                 if (set_pause) {
  620                         /* since changing of 'force pause' setting doesn't 
  621                          * trigger any link change event, the driver needs to
  622                          * update the current pause result upon successfully i
  623                          * return of the phy_cfg command */
  624                         if (!softc->link_info.flow_ctrl.autoneg) 
  625                                 bnxt_report_link(softc);
  626                 }
  627         }
  628         BNXT_HWRM_UNLOCK(softc);
  629         return rc;
  630 }
  631 
  632 int
  633 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
  634 {
  635         struct hwrm_vnic_cfg_input req = {0};
  636 
  637         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
  638 
  639         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
  640                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
  641         if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
  642                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
  643         if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
  644                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
  645         req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
  646             HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
  647             HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
  648         req.vnic_id = htole16(vnic->id);
  649         req.dflt_ring_grp = htole16(vnic->def_ring_grp);
  650         req.rss_rule = htole16(vnic->rss_id);
  651         req.cos_rule = htole16(vnic->cos_rule);
  652         req.lb_rule = htole16(vnic->lb_rule);
  653         req.mru = htole16(vnic->mru);
  654 
  655         return hwrm_send_message(softc, &req, sizeof(req));
  656 }
  657 
  658 int
  659 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
  660 {
  661         struct hwrm_vnic_alloc_input req = {0};
  662         struct hwrm_vnic_alloc_output *resp =
  663             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  664         int rc;
  665 
  666         if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
  667                 device_printf(softc->dev,
  668                     "Attempt to re-allocate vnic %04x\n", vnic->id);
  669                 return EDOOFUS;
  670         }
  671 
  672         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
  673 
  674         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
  675                 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
  676 
  677         BNXT_HWRM_LOCK(softc);
  678         rc = _hwrm_send_message(softc, &req, sizeof(req));
  679         if (rc)
  680                 goto fail;
  681 
  682         vnic->id = le32toh(resp->vnic_id);
  683 
  684 fail:
  685         BNXT_HWRM_UNLOCK(softc);
  686         return (rc);
  687 }
  688 
  689 int
  690 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
  691 {
  692         struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
  693         struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
  694             (void *)softc->hwrm_cmd_resp.idi_vaddr;
  695         int rc;
  696 
  697         if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
  698                 device_printf(softc->dev,
  699                     "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
  700                 return EDOOFUS;
  701         }
  702 
  703         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
  704 
  705         BNXT_HWRM_LOCK(softc);
  706         rc = _hwrm_send_message(softc, &req, sizeof(req));
  707         if (rc)
  708                 goto fail;
  709 
  710         *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
  711 
  712 fail:
  713         BNXT_HWRM_UNLOCK(softc);
  714         return (rc);
  715 }
  716 
  717 int
  718 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
  719 {
  720         struct hwrm_ring_grp_alloc_input req = {0};
  721         struct hwrm_ring_grp_alloc_output *resp;
  722         int rc = 0;
  723 
  724         if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
  725                 device_printf(softc->dev,
  726                     "Attempt to re-allocate ring group %04x\n", grp->grp_id);
  727                 return EDOOFUS;
  728         }
  729 
  730         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
  731         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
  732         req.cr = htole16(grp->cp_ring_id);
  733         req.rr = htole16(grp->rx_ring_id);
  734         req.ar = htole16(grp->ag_ring_id);
  735         req.sc = htole16(grp->stats_ctx);
  736 
  737         BNXT_HWRM_LOCK(softc);
  738         rc = _hwrm_send_message(softc, &req, sizeof(req));
  739         if (rc)
  740                 goto fail;
  741 
  742         grp->grp_id = le32toh(resp->ring_group_id);
  743 
  744 fail:
  745         BNXT_HWRM_UNLOCK(softc);
  746         return rc;
  747 }
  748 
  749 /*
  750  * Ring allocation message to the firmware
  751  */
  752 int
  753 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
  754     struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
  755     bool irq)
  756 {
  757         struct hwrm_ring_alloc_input req = {0};
  758         struct hwrm_ring_alloc_output *resp;
  759         int rc;
  760 
  761         if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
  762                 device_printf(softc->dev,
  763                     "Attempt to re-allocate ring %04x\n", ring->phys_id);
  764                 return EDOOFUS;
  765         }
  766 
  767         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
  768         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
  769         req.enables = htole32(0);
  770         req.fbo = htole32(0);
  771 
  772         if (stat_ctx_id != HWRM_NA_SIGNATURE) {
  773                 req.enables |= htole32(
  774                     HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
  775                 req.stat_ctx_id = htole32(stat_ctx_id);
  776         }
  777         req.ring_type = type;
  778         req.page_tbl_addr = htole64(ring->paddr);
  779         req.length = htole32(ring->ring_size);
  780         req.logical_id = htole16(ring->id);
  781         req.cmpl_ring_id = htole16(cmpl_ring_id);
  782         req.queue_id = htole16(softc->q_info[0].id);
  783 #if 0
  784         /* MODE_POLL appears to crash the firmware */
  785         if (irq)
  786                 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
  787         else
  788                 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
  789 #else
  790         req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
  791 #endif
  792         BNXT_HWRM_LOCK(softc);
  793         rc = _hwrm_send_message(softc, &req, sizeof(req));
  794         if (rc)
  795                 goto fail;
  796 
  797         ring->phys_id = le16toh(resp->ring_id);
  798 
  799 fail:
  800         BNXT_HWRM_UNLOCK(softc);
  801         return rc;
  802 }
  803 
  804 int
  805 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
  806     uint64_t paddr)
  807 {
  808         struct hwrm_stat_ctx_alloc_input req = {0};
  809         struct hwrm_stat_ctx_alloc_output *resp;
  810         int rc = 0;
  811 
  812         if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
  813                 device_printf(softc->dev,
  814                     "Attempt to re-allocate stats ctx %08x\n",
  815                     cpr->stats_ctx_id);
  816                 return EDOOFUS;
  817         }
  818 
  819         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
  820         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
  821 
  822         req.update_period_ms = htole32(1000);
  823         req.stats_dma_addr = htole64(paddr);
  824 
  825         BNXT_HWRM_LOCK(softc);
  826         rc = _hwrm_send_message(softc, &req, sizeof(req));
  827         if (rc)
  828                 goto fail;
  829 
  830         cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
  831 
  832 fail:
  833         BNXT_HWRM_UNLOCK(softc);
  834 
  835         return rc;
  836 }
  837 
  838 int
  839 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
  840 {
  841         struct hwrm_port_qstats_input req = {0};
  842         int rc = 0;
  843 
  844         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
  845 
  846         req.port_id = htole16(softc->pf.port_id);
  847         req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
  848         req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
  849 
  850         BNXT_HWRM_LOCK(softc);
  851         rc = _hwrm_send_message(softc, &req, sizeof(req));
  852         BNXT_HWRM_UNLOCK(softc);
  853 
  854         return rc;
  855 }
  856 
  857 int
  858 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
  859     struct bnxt_vnic_info *vnic)
  860 {
  861         struct hwrm_cfa_l2_set_rx_mask_input req = {0};
  862         struct bnxt_vlan_tag *tag;
  863         uint32_t *tags;
  864         uint32_t num_vlan_tags = 0;;
  865         uint32_t i;
  866         uint32_t mask = vnic->rx_mask;
  867         int rc;
  868 
  869         SLIST_FOREACH(tag, &vnic->vlan_tags, next)
  870                 num_vlan_tags++;
  871 
  872         if (num_vlan_tags) {
  873                 if (!(mask &
  874                     HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
  875                         if (!vnic->vlan_only)
  876                                 mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
  877                         else
  878                                 mask |=
  879                                     HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
  880                 }
  881                 if (vnic->vlan_tag_list.idi_vaddr) {
  882                         iflib_dma_free(&vnic->vlan_tag_list);
  883                         vnic->vlan_tag_list.idi_vaddr = NULL;
  884                 }
  885                 rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
  886                     &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
  887                 if (rc)
  888                         return rc;
  889                 tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
  890 
  891                 i = 0;
  892                 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
  893                         tags[i] = htole32((tag->tpid << 16) | tag->tag);
  894                         i++;
  895                 }
  896         }
  897         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
  898 
  899         req.vnic_id = htole32(vnic->id);
  900         req.mask = htole32(mask);
  901         req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
  902         req.num_mc_entries = htole32(vnic->mc_list_count);
  903         req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
  904         req.num_vlan_tags = htole32(num_vlan_tags);
  905         return hwrm_send_message(softc, &req, sizeof(req));
  906 }
  907 
  908 
  909 int
  910 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
  911 {
  912         struct hwrm_cfa_l2_filter_alloc_input   req = {0};
  913         struct hwrm_cfa_l2_filter_alloc_output  *resp;
  914         uint32_t enables = 0;
  915         int rc = 0;
  916 
  917         if (vnic->filter_id != -1) {
  918                 device_printf(softc->dev,
  919                     "Attempt to re-allocate l2 ctx filter\n");
  920                 return EDOOFUS;
  921         }
  922 
  923         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
  924         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
  925 
  926         req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
  927         enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
  928             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
  929             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
  930         req.enables = htole32(enables);
  931         req.dst_id = htole16(vnic->id);
  932         memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
  933             ETHER_ADDR_LEN);
  934         memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
  935 
  936         BNXT_HWRM_LOCK(softc);
  937         rc = _hwrm_send_message(softc, &req, sizeof(req));
  938         if (rc)
  939                 goto fail;
  940 
  941         vnic->filter_id = le64toh(resp->l2_filter_id);
  942         vnic->flow_id = le64toh(resp->flow_id);
  943 
  944 fail:
  945         BNXT_HWRM_UNLOCK(softc);
  946         return (rc);
  947 }
  948 
  949 int
  950 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
  951     uint32_t hash_type)
  952 {
  953         struct hwrm_vnic_rss_cfg_input  req = {0};
  954 
  955         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
  956 
  957         req.hash_type = htole32(hash_type);
  958         req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
  959         req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
  960         req.rss_ctx_idx = htole16(vnic->rss_id);
  961 
  962         return hwrm_send_message(softc, &req, sizeof(req));
  963 }
  964 
  965 int
  966 bnxt_cfg_async_cr(struct bnxt_softc *softc)
  967 {
  968         int rc = 0;
  969         
  970         if (BNXT_PF(softc)) {
  971                 struct hwrm_func_cfg_input req = {0};
  972 
  973                 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
  974 
  975                 req.fid = htole16(0xffff);
  976                 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
  977                 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
  978 
  979                 rc = hwrm_send_message(softc, &req, sizeof(req));
  980         }
  981         else {
  982                 struct hwrm_func_vf_cfg_input req = {0};
  983 
  984                 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
  985 
  986                 req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
  987                 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
  988 
  989                 rc = hwrm_send_message(softc, &req, sizeof(req));
  990         }
  991         return rc;
  992 }
  993 
  994 void
  995 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
  996 {
  997         softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
  998 
  999         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
 1000 
 1001         softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
 1002                 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
 1003 
 1004         softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
 1005                 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
 1006 
 1007         softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
 1008 }
 1009 
 1010 int
 1011 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
 1012 {
 1013         struct hwrm_vnic_tpa_cfg_input req = {0};
 1014         uint32_t flags;
 1015 
 1016         if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
 1017                 return 0;
 1018         }
 1019 
 1020         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
 1021 
 1022         if (softc->hw_lro.enable) {
 1023                 flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
 1024                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
 1025                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
 1026                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
 1027                 
 1028                 if (softc->hw_lro.is_mode_gro)
 1029                         flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
 1030                 else
 1031                         flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
 1032                         
 1033                 req.flags = htole32(flags);
 1034 
 1035                 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
 1036                                 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
 1037                                 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
 1038 
 1039                 req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
 1040                 req.max_aggs = htole16(softc->hw_lro.max_aggs);
 1041                 req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
 1042         }
 1043 
 1044         req.vnic_id = htole16(softc->vnic_info.id);
 1045 
 1046         return hwrm_send_message(softc, &req, sizeof(req));
 1047 }
 1048 
 1049 int
 1050 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
 1051     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
 1052     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
 1053     uint32_t *fw_ver)
 1054 {
 1055         struct hwrm_nvm_find_dir_entry_input req = {0};
 1056         struct hwrm_nvm_find_dir_entry_output *resp =
 1057             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1058         int     rc = 0;
 1059         uint32_t old_timeo;
 1060 
 1061         MPASS(ordinal);
 1062 
 1063         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
 1064         if (use_index) {
 1065                 req.enables = htole32(
 1066                     HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
 1067                 req.dir_idx = htole16(*index);
 1068         }
 1069         req.dir_type = htole16(type);
 1070         req.dir_ordinal = htole16(*ordinal);
 1071         req.dir_ext = htole16(ext);
 1072         req.opt_ordinal = search_opt;
 1073 
 1074         BNXT_HWRM_LOCK(softc);
 1075         old_timeo = softc->hwrm_cmd_timeo;
 1076         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1077         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1078         softc->hwrm_cmd_timeo = old_timeo;
 1079         if (rc)
 1080                 goto exit;
 1081 
 1082         if (item_length)
 1083                 *item_length = le32toh(resp->dir_item_length);
 1084         if (data_length)
 1085                 *data_length = le32toh(resp->dir_data_length);
 1086         if (fw_ver)
 1087                 *fw_ver = le32toh(resp->fw_ver);
 1088         *ordinal = le16toh(resp->dir_ordinal);
 1089         if (index)
 1090                 *index = le16toh(resp->dir_idx);
 1091 
 1092 exit:
 1093         BNXT_HWRM_UNLOCK(softc);
 1094         return (rc);
 1095 }
 1096 
 1097 int
 1098 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
 1099     uint32_t length, struct iflib_dma_info *data)
 1100 {
 1101         struct hwrm_nvm_read_input req = {0};
 1102         int rc;
 1103         uint32_t old_timeo;
 1104 
 1105         if (length > data->idi_size) {
 1106                 rc = EINVAL;
 1107                 goto exit;
 1108         }
 1109         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
 1110         req.host_dest_addr = htole64(data->idi_paddr);
 1111         req.dir_idx = htole16(index);
 1112         req.offset = htole32(offset);
 1113         req.len = htole32(length);
 1114         BNXT_HWRM_LOCK(softc);
 1115         old_timeo = softc->hwrm_cmd_timeo;
 1116         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1117         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1118         softc->hwrm_cmd_timeo = old_timeo;
 1119         BNXT_HWRM_UNLOCK(softc);
 1120         if (rc)
 1121                 goto exit;
 1122         bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
 1123 
 1124         goto exit;
 1125 
 1126 exit:
 1127         return rc;
 1128 }
 1129 
 1130 int
 1131 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
 1132     void *data, bool cpyin, uint32_t length)
 1133 {
 1134         struct hwrm_nvm_modify_input req = {0};
 1135         struct iflib_dma_info dma_data;
 1136         int rc;
 1137         uint32_t old_timeo;
 1138 
 1139         if (length == 0 || !data)
 1140                 return EINVAL;
 1141         rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
 1142             BUS_DMA_NOWAIT);
 1143         if (rc)
 1144                 return ENOMEM;
 1145         if (cpyin) {
 1146                 rc = copyin(data, dma_data.idi_vaddr, length);
 1147                 if (rc)
 1148                         goto exit;
 1149         }
 1150         else
 1151                 memcpy(dma_data.idi_vaddr, data, length);
 1152         bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
 1153             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1154 
 1155         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
 1156         req.host_src_addr = htole64(dma_data.idi_paddr);
 1157         req.dir_idx = htole16(index);
 1158         req.offset = htole32(offset);
 1159         req.len = htole32(length);
 1160         BNXT_HWRM_LOCK(softc);
 1161         old_timeo = softc->hwrm_cmd_timeo;
 1162         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1163         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1164         softc->hwrm_cmd_timeo = old_timeo;
 1165         BNXT_HWRM_UNLOCK(softc);
 1166 
 1167 exit:
 1168         iflib_dma_free(&dma_data);
 1169         return rc;
 1170 }
 1171 
 1172 int
 1173 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
 1174     uint8_t *selfreset)
 1175 {
 1176         struct hwrm_fw_reset_input req = {0};
 1177         struct hwrm_fw_reset_output *resp =
 1178             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1179         int rc;
 1180 
 1181         MPASS(selfreset);
 1182 
 1183         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
 1184         req.embedded_proc_type = processor;
 1185         req.selfrst_status = *selfreset;
 1186 
 1187         BNXT_HWRM_LOCK(softc);
 1188         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1189         if (rc)
 1190                 goto exit;
 1191         *selfreset = resp->selfrst_status;
 1192 
 1193 exit:
 1194         BNXT_HWRM_UNLOCK(softc);
 1195         return rc;
 1196 }
 1197 
 1198 int
 1199 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
 1200 {
 1201         struct hwrm_fw_qstatus_input req = {0};
 1202         struct hwrm_fw_qstatus_output *resp =
 1203             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1204         int rc;
 1205 
 1206         MPASS(selfreset);
 1207 
 1208         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
 1209         req.embedded_proc_type = type;
 1210 
 1211         BNXT_HWRM_LOCK(softc);
 1212         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1213         if (rc)
 1214                 goto exit;
 1215         *selfreset = resp->selfrst_status;
 1216 
 1217 exit:
 1218         BNXT_HWRM_UNLOCK(softc);
 1219         return rc;
 1220 }
 1221 
 1222 int
 1223 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
 1224     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
 1225     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
 1226     uint16_t *index)
 1227 {
 1228         struct hwrm_nvm_write_input req = {0};
 1229         struct hwrm_nvm_write_output *resp =
 1230             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1231         struct iflib_dma_info dma_data;
 1232         int rc;
 1233         uint32_t old_timeo;
 1234 
 1235         if (data_length) {
 1236                 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
 1237                     BUS_DMA_NOWAIT);
 1238                 if (rc)
 1239                         return ENOMEM;
 1240                 if (cpyin) {
 1241                         rc = copyin(data, dma_data.idi_vaddr, data_length);
 1242                         if (rc)
 1243                                 goto early_exit;
 1244                 }
 1245                 else
 1246                         memcpy(dma_data.idi_vaddr, data, data_length);
 1247                 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
 1248                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1249         }
 1250         else
 1251                 dma_data.idi_paddr = 0;
 1252 
 1253         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
 1254 
 1255         req.host_src_addr = htole64(dma_data.idi_paddr);
 1256         req.dir_type = htole16(type);
 1257         req.dir_ordinal = htole16(ordinal);
 1258         req.dir_ext = htole16(ext);
 1259         req.dir_attr = htole16(attr);
 1260         req.dir_data_length = htole32(data_length);
 1261         req.option = htole16(option);
 1262         if (keep) {
 1263                 req.flags =
 1264                     htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
 1265         }
 1266         if (item_length)
 1267                 req.dir_item_length = htole32(*item_length);
 1268 
 1269         BNXT_HWRM_LOCK(softc);
 1270         old_timeo = softc->hwrm_cmd_timeo;
 1271         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1272         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1273         softc->hwrm_cmd_timeo = old_timeo;
 1274         if (rc)
 1275                 goto exit;
 1276         if (item_length)
 1277                 *item_length = le32toh(resp->dir_item_length);
 1278         if (index)
 1279                 *index = le16toh(resp->dir_idx);
 1280 
 1281 exit:
 1282         BNXT_HWRM_UNLOCK(softc);
 1283 early_exit:
 1284         if (data_length)
 1285                 iflib_dma_free(&dma_data);
 1286         return rc;
 1287 }
 1288 
 1289 int
 1290 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
 1291 {
 1292         struct hwrm_nvm_erase_dir_entry_input req = {0};
 1293         uint32_t old_timeo;
 1294         int rc;
 1295 
 1296         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
 1297         req.dir_idx = htole16(index);
 1298         BNXT_HWRM_LOCK(softc);
 1299         old_timeo = softc->hwrm_cmd_timeo;
 1300         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1301         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1302         softc->hwrm_cmd_timeo = old_timeo;
 1303         BNXT_HWRM_UNLOCK(softc);
 1304         return rc;
 1305 }
 1306 
 1307 int
 1308 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
 1309     uint32_t *entry_length)
 1310 {
 1311         struct hwrm_nvm_get_dir_info_input req = {0};
 1312         struct hwrm_nvm_get_dir_info_output *resp =
 1313             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1314         int rc;
 1315         uint32_t old_timeo;
 1316 
 1317         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
 1318 
 1319         BNXT_HWRM_LOCK(softc);
 1320         old_timeo = softc->hwrm_cmd_timeo;
 1321         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1322         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1323         softc->hwrm_cmd_timeo = old_timeo;
 1324         if (rc)
 1325                 goto exit;
 1326 
 1327         if (entries)
 1328                 *entries = le32toh(resp->entries);
 1329         if (entry_length)
 1330                 *entry_length = le32toh(resp->entry_length);
 1331 
 1332 exit:
 1333         BNXT_HWRM_UNLOCK(softc);
 1334         return rc;
 1335 }
 1336 
 1337 int
 1338 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
 1339     uint32_t *entry_length, struct iflib_dma_info *dma_data)
 1340 {
 1341         struct hwrm_nvm_get_dir_entries_input req = {0};
 1342         uint32_t ent;
 1343         uint32_t ent_len;
 1344         int rc;
 1345         uint32_t old_timeo;
 1346 
 1347         if (!entries)
 1348                 entries = &ent;
 1349         if (!entry_length)
 1350                 entry_length = &ent_len;
 1351 
 1352         rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
 1353         if (rc)
 1354                 goto exit;
 1355         if (*entries * *entry_length > dma_data->idi_size) {
 1356                 rc = EINVAL;
 1357                 goto exit;
 1358         }
 1359 
 1360         /*
 1361          * TODO: There's a race condition here that could blow up DMA memory...
 1362          *       we need to allocate the max size, not the currently in use
 1363          *       size.  The command should totally have a max size here.
 1364          */
 1365         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
 1366         req.host_dest_addr = htole64(dma_data->idi_paddr);
 1367         BNXT_HWRM_LOCK(softc);
 1368         old_timeo = softc->hwrm_cmd_timeo;
 1369         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1370         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1371         softc->hwrm_cmd_timeo = old_timeo;
 1372         BNXT_HWRM_UNLOCK(softc);
 1373         if (rc)
 1374                 goto exit;
 1375         bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
 1376             BUS_DMASYNC_POSTWRITE);
 1377 
 1378 exit:
 1379         return rc;
 1380 }
 1381 
 1382 int
 1383 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
 1384     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
 1385     uint32_t *reserved_size, uint32_t *available_size)
 1386 {
 1387         struct hwrm_nvm_get_dev_info_input req = {0};
 1388         struct hwrm_nvm_get_dev_info_output *resp =
 1389             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1390         int rc;
 1391         uint32_t old_timeo;
 1392 
 1393         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
 1394 
 1395         BNXT_HWRM_LOCK(softc);
 1396         old_timeo = softc->hwrm_cmd_timeo;
 1397         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1398         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1399         softc->hwrm_cmd_timeo = old_timeo;
 1400         if (rc)
 1401                 goto exit;
 1402 
 1403         if (mfg_id)
 1404                 *mfg_id = le16toh(resp->manufacturer_id);
 1405         if (device_id)
 1406                 *device_id = le16toh(resp->device_id);
 1407         if (sector_size)
 1408                 *sector_size = le32toh(resp->sector_size);
 1409         if (nvram_size)
 1410                 *nvram_size = le32toh(resp->nvram_size);
 1411         if (reserved_size)
 1412                 *reserved_size = le32toh(resp->reserved_size);
 1413         if (available_size)
 1414                 *available_size = le32toh(resp->available_size);
 1415 
 1416 exit:
 1417         BNXT_HWRM_UNLOCK(softc);
 1418         return rc;
 1419 }
 1420 
 1421 int
 1422 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
 1423     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
 1424     uint8_t *problem_item, uint8_t *reset_required)
 1425 {
 1426         struct hwrm_nvm_install_update_input req = {0};
 1427         struct hwrm_nvm_install_update_output *resp =
 1428             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1429         int rc;
 1430         uint32_t old_timeo;
 1431 
 1432         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
 1433         req.install_type = htole32(install_type);
 1434 
 1435         BNXT_HWRM_LOCK(softc);
 1436         old_timeo = softc->hwrm_cmd_timeo;
 1437         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1438         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1439         softc->hwrm_cmd_timeo = old_timeo;
 1440         if (rc)
 1441                 goto exit;
 1442 
 1443         if (installed_items)
 1444                 *installed_items = le32toh(resp->installed_items);
 1445         if (result)
 1446                 *result = resp->result;
 1447         if (problem_item)
 1448                 *problem_item = resp->problem_item;
 1449         if (reset_required)
 1450                 *reset_required = resp->reset_required;
 1451 
 1452 exit:
 1453         BNXT_HWRM_UNLOCK(softc);
 1454         return rc;
 1455 }
 1456 
 1457 int
 1458 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
 1459     uint16_t ordinal, uint16_t ext)
 1460 {
 1461         struct hwrm_nvm_verify_update_input req = {0};
 1462         uint32_t old_timeo;
 1463         int rc;
 1464 
 1465         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
 1466 
 1467         req.dir_type = htole16(type);
 1468         req.dir_ordinal = htole16(ordinal);
 1469         req.dir_ext = htole16(ext);
 1470 
 1471         BNXT_HWRM_LOCK(softc);
 1472         old_timeo = softc->hwrm_cmd_timeo;
 1473         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
 1474         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1475         softc->hwrm_cmd_timeo = old_timeo;
 1476         BNXT_HWRM_UNLOCK(softc);
 1477         return rc;
 1478 }
 1479 
 1480 int
 1481 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
 1482     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
 1483     uint16_t *millisecond, uint16_t *zone)
 1484 {
 1485         struct hwrm_fw_get_time_input req = {0};
 1486         struct hwrm_fw_get_time_output *resp =
 1487             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1488         int rc;
 1489 
 1490         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
 1491 
 1492         BNXT_HWRM_LOCK(softc);
 1493         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1494         if (rc)
 1495                 goto exit;
 1496 
 1497         if (year)
 1498                 *year = le16toh(resp->year);
 1499         if (month)
 1500                 *month = resp->month;
 1501         if (day)
 1502                 *day = resp->day;
 1503         if (hour)
 1504                 *hour = resp->hour;
 1505         if (minute)
 1506                 *minute = resp->minute;
 1507         if (second)
 1508                 *second = resp->second;
 1509         if (millisecond)
 1510                 *millisecond = le16toh(resp->millisecond);
 1511         if (zone)
 1512                 *zone = le16toh(resp->zone);
 1513 
 1514 exit:
 1515         BNXT_HWRM_UNLOCK(softc);
 1516         return rc;
 1517 }
 1518 
 1519 int
 1520 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
 1521     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
 1522     uint16_t millisecond, uint16_t zone)
 1523 {
 1524         struct hwrm_fw_set_time_input req = {0};
 1525 
 1526         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
 1527 
 1528         req.year = htole16(year);
 1529         req.month = month;
 1530         req.day = day;
 1531         req.hour = hour;
 1532         req.minute = minute;
 1533         req.second = second;
 1534         req.millisecond = htole16(millisecond);
 1535         req.zone = htole16(zone);
 1536         return hwrm_send_message(softc, &req, sizeof(req));
 1537 }
 1538 
 1539 int
 1540 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
 1541 {
 1542         struct bnxt_link_info *link_info = &softc->link_info;
 1543         struct hwrm_port_phy_qcfg_input req = {0};
 1544         struct hwrm_port_phy_qcfg_output *resp =
 1545             (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1546         int rc = 0;
 1547 
 1548         BNXT_HWRM_LOCK(softc);
 1549         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
 1550 
 1551         rc = _hwrm_send_message(softc, &req, sizeof(req));
 1552         if (rc)
 1553                 goto exit;
 1554 
 1555         link_info->phy_link_status = resp->link;
 1556         link_info->duplex =  resp->duplex_cfg;
 1557         link_info->auto_mode = resp->auto_mode;
 1558 
 1559         /*
 1560          * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1, 
 1561          * the advertisement of pause is enabled.
 1562          * 1. When the auto_mode is not set to none and this flag is set to 1,
 1563          *    then the auto_pause bits on this port are being advertised and
 1564          *    autoneg pause results are being interpreted.
 1565          * 2. When the auto_mode is not set to none and this flag is set to 0,
 1566          *    the pause is forced as indicated in force_pause, and also 
 1567          *    advertised as auto_pause bits, but the autoneg results are not 
 1568          *    interpreted since the pause configuration is being forced.
 1569          * 3. When the auto_mode is set to none and this flag is set to 1,
 1570          *    auto_pause bits should be ignored and should be set to 0.
 1571          */
 1572         
 1573         link_info->flow_ctrl.autoneg = false;
 1574         link_info->flow_ctrl.tx = false;
 1575         link_info->flow_ctrl.rx = false;
 1576 
 1577         if ((resp->auto_mode) && 
 1578             (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
 1579                         link_info->flow_ctrl.autoneg = true;
 1580         }
 1581 
 1582         if (link_info->flow_ctrl.autoneg) {
 1583                 if (resp->auto_pause & BNXT_PAUSE_TX)
 1584                         link_info->flow_ctrl.tx = true;
 1585                 if (resp->auto_pause & BNXT_PAUSE_RX)
 1586                         link_info->flow_ctrl.rx = true;
 1587         } else {
 1588                 if (resp->force_pause & BNXT_PAUSE_TX)
 1589                         link_info->flow_ctrl.tx = true;
 1590                 if (resp->force_pause & BNXT_PAUSE_RX)
 1591                         link_info->flow_ctrl.rx = true;
 1592         }
 1593 
 1594         link_info->duplex_setting = resp->duplex_cfg;
 1595         if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
 1596                 link_info->link_speed = le16toh(resp->link_speed);
 1597         else
 1598                 link_info->link_speed = 0;
 1599         link_info->force_link_speed = le16toh(resp->force_link_speed);
 1600         link_info->auto_link_speed = le16toh(resp->auto_link_speed);
 1601         link_info->support_speeds = le16toh(resp->support_speeds);
 1602         link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
 1603         link_info->preemphasis = le32toh(resp->preemphasis);
 1604         link_info->phy_ver[0] = resp->phy_maj;
 1605         link_info->phy_ver[1] = resp->phy_min;
 1606         link_info->phy_ver[2] = resp->phy_bld;
 1607         snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
 1608             "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
 1609             link_info->phy_ver[2]);
 1610         strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
 1611             BNXT_NAME_SIZE);
 1612         strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
 1613             BNXT_NAME_SIZE);
 1614         link_info->media_type = resp->media_type;
 1615         link_info->phy_type = resp->phy_type;
 1616         link_info->transceiver = resp->xcvr_pkg_type;
 1617         link_info->phy_addr = resp->eee_config_phy_addr &
 1618             HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
 1619 
 1620 exit:
 1621         BNXT_HWRM_UNLOCK(softc);
 1622         return rc;
 1623 }
 1624 
 1625 uint16_t
 1626 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
 1627 {
 1628         struct hwrm_wol_filter_qcfg_input req = {0};
 1629         struct hwrm_wol_filter_qcfg_output *resp =
 1630                         (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1631         uint16_t next_handle = 0;
 1632         int rc;
 1633 
 1634         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
 1635         req.port_id = htole16(softc->pf.port_id);
 1636         req.handle = htole16(handle);
 1637         rc = hwrm_send_message(softc, &req, sizeof(req));
 1638         if (!rc) {
 1639                 next_handle = le16toh(resp->next_handle);
 1640                 if (next_handle != 0) {
 1641                         if (resp->wol_type ==
 1642                                 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
 1643                                 softc->wol = 1;
 1644                                 softc->wol_filter_id = resp->wol_filter_id;
 1645                         }
 1646                 }
 1647         }
 1648         return next_handle;
 1649 }
 1650 
 1651 int
 1652 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
 1653 {
 1654         struct hwrm_wol_filter_alloc_input req = {0};
 1655         struct hwrm_wol_filter_alloc_output *resp =
 1656                 (void *)softc->hwrm_cmd_resp.idi_vaddr;
 1657         int rc;
 1658 
 1659         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
 1660         req.port_id = htole16(softc->pf.port_id);
 1661         req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
 1662         req.enables =
 1663                 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
 1664         memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
 1665         rc = hwrm_send_message(softc, &req, sizeof(req));
 1666         if (!rc)
 1667                 softc->wol_filter_id = resp->wol_filter_id;
 1668 
 1669         return rc;
 1670 }
 1671 
 1672 int
 1673 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
 1674 {
 1675         struct hwrm_wol_filter_free_input req = {0};
 1676 
 1677         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
 1678         req.port_id = htole16(softc->pf.port_id);
 1679         req.enables =
 1680                 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
 1681         req.wol_filter_id = softc->wol_filter_id;
 1682         return hwrm_send_message(softc, &req, sizeof(req));
 1683 }
 1684 
 1685 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
 1686         uint32_t buf_tmrs, uint16_t flags,
 1687         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
 1688 {
 1689         req->flags = htole16(flags);
 1690         req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
 1691         req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
 1692         req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
 1693         req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
 1694         /* Minimum time between 2 interrupts set to buf_tmr x 2 */
 1695         req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
 1696         req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
 1697         req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
 1698 }
 1699 
 1700 
 1701 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
 1702 {
 1703         int i, rc = 0;
 1704         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
 1705                                                            req_tx = {0}, *req;
 1706         uint16_t max_buf, max_buf_irq;
 1707         uint16_t buf_tmr, buf_tmr_irq;
 1708         uint32_t flags;
 1709 
 1710         bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
 1711                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
 1712         bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
 1713                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
 1714 
 1715         /* Each rx completion (2 records) should be DMAed immediately.
 1716          * DMA 1/4 of the completion buffers at a time.
 1717          */
 1718         max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
 1719         /* max_buf must not be zero */
 1720         max_buf = clamp_t(uint16_t, max_buf, 1, 63);
 1721         max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
 1722         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
 1723         /* buf timer set to 1/4 of interrupt timer */
 1724         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
 1725         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
 1726         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
 1727 
 1728         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
 1729 
 1730         /* RING_IDLE generates more IRQs for lower latency.  Enable it only
 1731          * if coal_usecs is less than 25 us.
 1732          */
 1733         if (softc->rx_coal_usecs < 25)
 1734                 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
 1735 
 1736         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
 1737                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
 1738 
 1739         /* max_buf must not be zero */
 1740         max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
 1741         max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
 1742         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
 1743         /* buf timer set to 1/4 of interrupt timer */
 1744         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
 1745         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
 1746         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
 1747         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
 1748         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
 1749                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
 1750 
 1751         for (i = 0; i < softc->nrxqsets; i++) {
 1752 
 1753                 
 1754                 req = &req_rx;
 1755                 /*
 1756                  * TBD:
 1757                  *      Check if Tx also needs to be done
 1758                  *      So far, Tx processing has been done in softirq contest
 1759                  *
 1760                  * req = &req_tx;
 1761                  */
 1762                 req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
 1763 
 1764                 rc = hwrm_send_message(softc, req, sizeof(*req));
 1765                 if (rc)
 1766                         break;
 1767         }
 1768         return rc;
 1769 }
 1770 
 1771 
 1772 
 1773 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
 1774                                      int bmap_size)
 1775 {
 1776         struct hwrm_func_drv_rgtr_input req = {0};
 1777         bitstr_t *async_events_bmap;
 1778         uint32_t *events;
 1779         int i;
 1780 
 1781         async_events_bmap = bit_alloc(256, M_DEVBUF, M_WAITOK|M_ZERO);
 1782         events = (uint32_t *)async_events_bmap;
 1783 
 1784         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
 1785 
 1786         req.enables =
 1787                 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
 1788 
 1789         memset(async_events_bmap, 0, sizeof(256 / 8));
 1790 
 1791         bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
 1792         bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
 1793         bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
 1794         bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
 1795         bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
 1796 
 1797         if (bmap && bmap_size) {
 1798                 for (i = 0; i < bmap_size; i++) {
 1799                         if (bit_test(bmap, i))
 1800                                 bit_set(async_events_bmap, i);
 1801                 }
 1802         }
 1803 
 1804         for (i = 0; i < 8; i++)
 1805                 req.async_event_fwd[i] |= htole32(events[i]);
 1806 
 1807         free(async_events_bmap, M_DEVBUF);
 1808 
 1809         return hwrm_send_message(softc, &req, sizeof(req));
 1810 }

Cache object: b2725c0b8913f5a9d57c27101cc122ca


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