1308696Sshurd/*- 2308696Sshurd * Broadcom NetXtreme-C/E network driver. 3308696Sshurd * 4308696Sshurd * Copyright (c) 2016 Broadcom, All Rights Reserved. 5308696Sshurd * The term Broadcom refers to Broadcom Limited and/or its subsidiaries 6308696Sshurd * 7308696Sshurd * Redistribution and use in source and binary forms, with or without 8308696Sshurd * modification, are permitted provided that the following conditions 9308696Sshurd * are met: 10308696Sshurd * 1. Redistributions of source code must retain the above copyright 11308696Sshurd * notice, this list of conditions and the following disclaimer. 12308696Sshurd * 2. Redistributions in binary form must reproduce the above copyright 13308696Sshurd * notice, this list of conditions and the following disclaimer in the 14308696Sshurd * documentation and/or other materials provided with the distribution. 15308696Sshurd * 16308696Sshurd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 17308696Sshurd * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18308696Sshurd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19308696Sshurd * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20308696Sshurd * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21308696Sshurd * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22308696Sshurd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23308696Sshurd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24308696Sshurd * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25308696Sshurd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26308696Sshurd * THE POSSIBILITY OF SUCH DAMAGE. 27308696Sshurd */ 28308696Sshurd 29308696Sshurd#include <sys/cdefs.h> 30308696Sshurd__FBSDID("$FreeBSD: stable/11/sys/dev/bnxt/bnxt_hwrm.c 334178 2018-05-24 18:53:29Z shurd $"); 31308696Sshurd 32308696Sshurd#include <sys/endian.h> 33333364Sshurd#include <sys/bitstring.h> 34308696Sshurd 35308696Sshurd#include "bnxt.h" 36308696Sshurd#include "bnxt_hwrm.h" 37308696Sshurd#include "hsi_struct_def.h" 38308696Sshurd 39308696Sshurdstatic int bnxt_hwrm_err_map(uint16_t err); 40308696Sshurdstatic inline int _is_valid_ether_addr(uint8_t *); 41308696Sshurdstatic inline void get_random_ether_addr(uint8_t *); 42308696Sshurdstatic void bnxt_hwrm_set_link_common(struct bnxt_softc *softc, 43308696Sshurd struct hwrm_port_phy_cfg_input *req); 44308696Sshurdstatic void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc, 45308696Sshurd struct hwrm_port_phy_cfg_input *req); 46308696Sshurdstatic void bnxt_hwrm_set_eee(struct bnxt_softc *softc, 47308696Sshurd struct hwrm_port_phy_cfg_input *req); 48308696Sshurdstatic int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t); 49308696Sshurdstatic int hwrm_send_message(struct bnxt_softc *, void *, uint32_t); 50308696Sshurdstatic void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t); 51308696Sshurd 52308696Sshurd/* NVRam stuff has a five minute timeout */ 53308696Sshurd#define BNXT_NVM_TIMEO (5 * 60 * 1000) 54308696Sshurd 55308696Sshurdstatic int 56308696Sshurdbnxt_hwrm_err_map(uint16_t err) 57308696Sshurd{ 58308696Sshurd int rc; 59308696Sshurd 60308696Sshurd switch (err) { 61308696Sshurd case HWRM_ERR_CODE_SUCCESS: 62308696Sshurd return 0; 63308696Sshurd case HWRM_ERR_CODE_INVALID_PARAMS: 64308696Sshurd case HWRM_ERR_CODE_INVALID_FLAGS: 65308696Sshurd case HWRM_ERR_CODE_INVALID_ENABLES: 66308696Sshurd return EINVAL; 67308696Sshurd case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED: 68308696Sshurd return EACCES; 69308696Sshurd case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR: 70308696Sshurd return ENOMEM; 71308696Sshurd case HWRM_ERR_CODE_CMD_NOT_SUPPORTED: 72308696Sshurd return ENOSYS; 73308696Sshurd case HWRM_ERR_CODE_FAIL: 74308696Sshurd return EIO; 75308696Sshurd case HWRM_ERR_CODE_HWRM_ERROR: 76308696Sshurd case HWRM_ERR_CODE_UNKNOWN_ERR: 77308696Sshurd default: 78308696Sshurd return EDOOFUS; 79308696Sshurd } 80308696Sshurd 81308696Sshurd return rc; 82308696Sshurd} 83308696Sshurd 84308696Sshurdint 85308696Sshurdbnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc) 86308696Sshurd{ 87308696Sshurd int rc; 88308696Sshurd 89308696Sshurd rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp, 90308696Sshurd BUS_DMA_NOWAIT); 91308696Sshurd return rc; 92308696Sshurd} 93308696Sshurd 94308696Sshurdvoid 95308696Sshurdbnxt_free_hwrm_dma_mem(struct bnxt_softc *softc) 96308696Sshurd{ 97308696Sshurd if (softc->hwrm_cmd_resp.idi_vaddr) 98308696Sshurd iflib_dma_free(&softc->hwrm_cmd_resp); 99308696Sshurd softc->hwrm_cmd_resp.idi_vaddr = NULL; 100308696Sshurd return; 101308696Sshurd} 102308696Sshurd 103308696Sshurdstatic void 104308696Sshurdbnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request, 105308696Sshurd uint16_t req_type) 106308696Sshurd{ 107308696Sshurd struct input *req = request; 108308696Sshurd 109308696Sshurd req->req_type = htole16(req_type); 110308696Sshurd req->cmpl_ring = 0xffff; 111308696Sshurd req->target_id = 0xffff; 112308696Sshurd req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr); 113308696Sshurd} 114308696Sshurd 115308696Sshurdstatic int 116308696Sshurd_hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) 117308696Sshurd{ 118308696Sshurd struct input *req = msg; 119308696Sshurd struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 120308696Sshurd uint32_t *data = msg; 121308696Sshurd int i; 122308696Sshurd uint16_t cp_ring_id; 123308696Sshurd uint8_t *valid; 124308696Sshurd uint16_t err; 125333364Sshurd uint16_t max_req_len = HWRM_MAX_REQ_LEN; 126333364Sshurd struct hwrm_short_input short_input = {0}; 127308696Sshurd 128308696Sshurd /* TODO: DMASYNC in here. */ 129308696Sshurd req->seq_id = htole16(softc->hwrm_cmd_seq++); 130308696Sshurd memset(resp, 0, PAGE_SIZE); 131308696Sshurd cp_ring_id = le16toh(req->cmpl_ring); 132308696Sshurd 133333364Sshurd if (softc->flags & BNXT_FLAG_SHORT_CMD) { 134333364Sshurd void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr; 135333364Sshurd 136333364Sshurd memcpy(short_cmd_req, req, msg_len); 137333364Sshurd memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len- 138333364Sshurd msg_len); 139333364Sshurd 140333364Sshurd short_input.req_type = req->req_type; 141333364Sshurd short_input.signature = 142333364Sshurd htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD); 143333364Sshurd short_input.size = htole16(msg_len); 144333364Sshurd short_input.req_addr = 145333364Sshurd htole64(softc->hwrm_short_cmd_req_addr.idi_paddr); 146333364Sshurd 147333364Sshurd data = (uint32_t *)&short_input; 148333364Sshurd msg_len = sizeof(short_input); 149333364Sshurd 150333364Sshurd /* Sync memory write before updating doorbell */ 151333364Sshurd wmb(); 152333364Sshurd 153333364Sshurd max_req_len = BNXT_HWRM_SHORT_REQ_LEN; 154333364Sshurd } 155333364Sshurd 156308696Sshurd /* Write request msg to hwrm channel */ 157308696Sshurd for (i = 0; i < msg_len; i += 4) { 158308696Sshurd bus_space_write_4(softc->hwrm_bar.tag, 159308696Sshurd softc->hwrm_bar.handle, 160308696Sshurd i, *data); 161308696Sshurd data++; 162308696Sshurd } 163308696Sshurd 164308696Sshurd /* Clear to the end of the request buffer */ 165333364Sshurd for (i = msg_len; i < max_req_len; i += 4) 166308696Sshurd bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle, 167308696Sshurd i, 0); 168308696Sshurd 169308696Sshurd /* Ring channel doorbell */ 170308696Sshurd bus_space_write_4(softc->hwrm_bar.tag, 171308696Sshurd softc->hwrm_bar.handle, 172308696Sshurd 0x100, htole32(1)); 173308696Sshurd 174308696Sshurd /* Check if response len is updated */ 175308696Sshurd for (i = 0; i < softc->hwrm_cmd_timeo; i++) { 176308696Sshurd if (resp->resp_len && resp->resp_len <= 4096) 177308696Sshurd break; 178308696Sshurd DELAY(1000); 179308696Sshurd } 180308696Sshurd if (i >= softc->hwrm_cmd_timeo) { 181308696Sshurd device_printf(softc->dev, 182308696Sshurd "Timeout sending %s: (timeout: %u) seq: %d\n", 183308696Sshurd GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo, 184308696Sshurd le16toh(req->seq_id)); 185308696Sshurd return ETIMEDOUT; 186308696Sshurd } 187308696Sshurd /* Last byte of resp contains the valid key */ 188308696Sshurd valid = (uint8_t *)resp + resp->resp_len - 1; 189308696Sshurd for (i = 0; i < softc->hwrm_cmd_timeo; i++) { 190308696Sshurd if (*valid == HWRM_RESP_VALID_KEY) 191308696Sshurd break; 192308696Sshurd DELAY(1000); 193308696Sshurd } 194308696Sshurd if (i >= softc->hwrm_cmd_timeo) { 195308696Sshurd device_printf(softc->dev, "Timeout sending %s: " 196308696Sshurd "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n", 197308696Sshurd GET_HWRM_REQ_TYPE(req->req_type), 198308696Sshurd softc->hwrm_cmd_timeo, le16toh(req->req_type), 199308696Sshurd le16toh(req->seq_id), msg_len, 200308696Sshurd *valid); 201308696Sshurd return ETIMEDOUT; 202308696Sshurd } 203308696Sshurd 204308696Sshurd err = le16toh(resp->error_code); 205308696Sshurd if (err) { 206308696Sshurd /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */ 207308696Sshurd if (err != HWRM_ERR_CODE_FAIL) { 208308696Sshurd device_printf(softc->dev, 209308696Sshurd "%s command returned %s error.\n", 210308696Sshurd GET_HWRM_REQ_TYPE(req->req_type), 211308696Sshurd GET_HWRM_ERROR_CODE(err)); 212308696Sshurd } 213308696Sshurd return bnxt_hwrm_err_map(err); 214308696Sshurd } 215308696Sshurd 216308696Sshurd return 0; 217308696Sshurd} 218308696Sshurd 219308696Sshurdstatic int 220308696Sshurdhwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) 221308696Sshurd{ 222308696Sshurd int rc; 223308696Sshurd 224308696Sshurd BNXT_HWRM_LOCK(softc); 225308696Sshurd rc = _hwrm_send_message(softc, msg, msg_len); 226308696Sshurd BNXT_HWRM_UNLOCK(softc); 227308696Sshurd return rc; 228308696Sshurd} 229308696Sshurd 230308696Sshurdint 231308696Sshurdbnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc) 232308696Sshurd{ 233308696Sshurd struct hwrm_queue_qportcfg_input req = {0}; 234308696Sshurd struct hwrm_queue_qportcfg_output *resp = 235308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 236308696Sshurd 237308696Sshurd int rc = 0; 238308696Sshurd uint8_t *qptr; 239308696Sshurd 240308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG); 241308696Sshurd 242308696Sshurd BNXT_HWRM_LOCK(softc); 243308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 244308696Sshurd if (rc) 245308696Sshurd goto qportcfg_exit; 246308696Sshurd 247308696Sshurd if (!resp->max_configurable_queues) { 248308696Sshurd rc = -EINVAL; 249308696Sshurd goto qportcfg_exit; 250308696Sshurd } 251308696Sshurd softc->max_tc = resp->max_configurable_queues; 252308696Sshurd if (softc->max_tc > BNXT_MAX_QUEUE) 253308696Sshurd softc->max_tc = BNXT_MAX_QUEUE; 254308696Sshurd 255308696Sshurd qptr = &resp->queue_id0; 256308696Sshurd for (int i = 0; i < softc->max_tc; i++) { 257308696Sshurd softc->q_info[i].id = *qptr++; 258308696Sshurd softc->q_info[i].profile = *qptr++; 259308696Sshurd } 260308696Sshurd 261308696Sshurdqportcfg_exit: 262308696Sshurd BNXT_HWRM_UNLOCK(softc); 263308696Sshurd return (rc); 264308696Sshurd} 265308696Sshurd 266308696Sshurd 267308696Sshurdint 268308696Sshurdbnxt_hwrm_ver_get(struct bnxt_softc *softc) 269308696Sshurd{ 270308696Sshurd struct hwrm_ver_get_input req = {0}; 271308696Sshurd struct hwrm_ver_get_output *resp = 272308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 273308696Sshurd int rc; 274308696Sshurd const char nastr[] = "<not installed>"; 275308696Sshurd const char naver[] = "<N/A>"; 276333364Sshurd uint32_t dev_caps_cfg; 277308696Sshurd 278308696Sshurd softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN; 279308696Sshurd softc->hwrm_cmd_timeo = 1000; 280308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET); 281308696Sshurd 282308696Sshurd req.hwrm_intf_maj = HWRM_VERSION_MAJOR; 283308696Sshurd req.hwrm_intf_min = HWRM_VERSION_MINOR; 284308696Sshurd req.hwrm_intf_upd = HWRM_VERSION_UPDATE; 285308696Sshurd 286308696Sshurd BNXT_HWRM_LOCK(softc); 287308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 288308696Sshurd if (rc) 289308696Sshurd goto fail; 290308696Sshurd 291308696Sshurd snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d", 292308696Sshurd resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd); 293308696Sshurd softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj; 294308696Sshurd softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min; 295308696Sshurd softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd; 296308696Sshurd snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d", 297308696Sshurd resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld); 298308696Sshurd strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR, 299308696Sshurd BNXT_VERSTR_SIZE); 300308696Sshurd strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name, 301308696Sshurd BNXT_NAME_SIZE); 302308696Sshurd 303308696Sshurd if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 && 304308696Sshurd resp->mgmt_fw_bld == 0) { 305308696Sshurd strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE); 306308696Sshurd strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE); 307308696Sshurd } 308308696Sshurd else { 309308696Sshurd snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE, 310308696Sshurd "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min, 311308696Sshurd resp->mgmt_fw_bld); 312308696Sshurd strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name, 313308696Sshurd BNXT_NAME_SIZE); 314308696Sshurd } 315308696Sshurd if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 && 316308696Sshurd resp->netctrl_fw_bld == 0) { 317308696Sshurd strlcpy(softc->ver_info->netctrl_fw_ver, naver, 318308696Sshurd BNXT_VERSTR_SIZE); 319308696Sshurd strlcpy(softc->ver_info->netctrl_fw_name, nastr, 320308696Sshurd BNXT_NAME_SIZE); 321308696Sshurd } 322308696Sshurd else { 323308696Sshurd snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE, 324308696Sshurd "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min, 325308696Sshurd resp->netctrl_fw_bld); 326308696Sshurd strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name, 327308696Sshurd BNXT_NAME_SIZE); 328308696Sshurd } 329308696Sshurd if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 && 330308696Sshurd resp->roce_fw_bld == 0) { 331308696Sshurd strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE); 332308696Sshurd strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE); 333308696Sshurd } 334308696Sshurd else { 335308696Sshurd snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE, 336308696Sshurd "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min, 337308696Sshurd resp->roce_fw_bld); 338308696Sshurd strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name, 339308696Sshurd BNXT_NAME_SIZE); 340308696Sshurd } 341308696Sshurd softc->ver_info->chip_num = le16toh(resp->chip_num); 342308696Sshurd softc->ver_info->chip_rev = resp->chip_rev; 343308696Sshurd softc->ver_info->chip_metal = resp->chip_metal; 344308696Sshurd softc->ver_info->chip_bond_id = resp->chip_bond_id; 345308696Sshurd softc->ver_info->chip_type = resp->chip_platform_type; 346308696Sshurd 347308696Sshurd if (resp->max_req_win_len) 348308696Sshurd softc->hwrm_max_req_len = le16toh(resp->max_req_win_len); 349308696Sshurd if (resp->def_req_timeout) 350308696Sshurd softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout); 351308696Sshurd 352333364Sshurd dev_caps_cfg = le32toh(resp->dev_caps_cfg); 353333364Sshurd if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) && 354333364Sshurd (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED)) 355333364Sshurd softc->flags |= BNXT_FLAG_SHORT_CMD; 356333364Sshurd 357308696Sshurdfail: 358308696Sshurd BNXT_HWRM_UNLOCK(softc); 359308696Sshurd return rc; 360308696Sshurd} 361308696Sshurd 362308696Sshurdint 363308696Sshurdbnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc) 364308696Sshurd{ 365308696Sshurd struct hwrm_func_drv_rgtr_input req = {0}; 366308696Sshurd 367308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR); 368308696Sshurd 369308696Sshurd req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER | 370308696Sshurd HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE); 371308696Sshurd req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD); 372308696Sshurd 373308696Sshurd req.ver_maj = __FreeBSD_version / 100000; 374308696Sshurd req.ver_min = (__FreeBSD_version / 1000) % 100; 375308696Sshurd req.ver_upd = (__FreeBSD_version / 100) % 10; 376308696Sshurd 377308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 378308696Sshurd} 379308696Sshurd 380308696Sshurd 381308696Sshurdint 382308696Sshurdbnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown) 383308696Sshurd{ 384308696Sshurd struct hwrm_func_drv_unrgtr_input req = {0}; 385308696Sshurd 386308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR); 387308696Sshurd if (shutdown == true) 388308696Sshurd req.flags |= 389308696Sshurd HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN; 390308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 391308696Sshurd} 392308696Sshurd 393308696Sshurd 394308696Sshurdstatic inline int 395308696Sshurd_is_valid_ether_addr(uint8_t *addr) 396308696Sshurd{ 397308696Sshurd char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; 398308696Sshurd 399308696Sshurd if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) 400308696Sshurd return (FALSE); 401308696Sshurd 402308696Sshurd return (TRUE); 403308696Sshurd} 404308696Sshurd 405308696Sshurdstatic inline void 406308696Sshurdget_random_ether_addr(uint8_t *addr) 407308696Sshurd{ 408308696Sshurd uint8_t temp[ETHER_ADDR_LEN]; 409308696Sshurd 410308696Sshurd arc4rand(&temp, sizeof(temp), 0); 411308696Sshurd temp[0] &= 0xFE; 412308696Sshurd temp[0] |= 0x02; 413308696Sshurd bcopy(temp, addr, sizeof(temp)); 414308696Sshurd} 415308696Sshurd 416308696Sshurdint 417308696Sshurdbnxt_hwrm_func_qcaps(struct bnxt_softc *softc) 418308696Sshurd{ 419308696Sshurd int rc = 0; 420308696Sshurd struct hwrm_func_qcaps_input req = {0}; 421308696Sshurd struct hwrm_func_qcaps_output *resp = 422308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 423308696Sshurd struct bnxt_func_info *func = &softc->func; 424308696Sshurd 425308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS); 426308696Sshurd req.fid = htole16(0xffff); 427308696Sshurd 428308696Sshurd BNXT_HWRM_LOCK(softc); 429308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 430308696Sshurd if (rc) 431308696Sshurd goto fail; 432308696Sshurd 433333364Sshurd if (resp->flags & 434333364Sshurd htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED)) 435333364Sshurd softc->flags |= BNXT_FLAG_WOL_CAP; 436333364Sshurd 437308696Sshurd func->fw_fid = le16toh(resp->fid); 438308696Sshurd memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN); 439308696Sshurd func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx); 440308696Sshurd func->max_cp_rings = le16toh(resp->max_cmpl_rings); 441308696Sshurd func->max_tx_rings = le16toh(resp->max_tx_rings); 442308696Sshurd func->max_rx_rings = le16toh(resp->max_rx_rings); 443308696Sshurd func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps); 444308696Sshurd if (!func->max_hw_ring_grps) 445308696Sshurd func->max_hw_ring_grps = func->max_tx_rings; 446308696Sshurd func->max_l2_ctxs = le16toh(resp->max_l2_ctxs); 447308696Sshurd func->max_vnics = le16toh(resp->max_vnics); 448308696Sshurd func->max_stat_ctxs = le16toh(resp->max_stat_ctx); 449308696Sshurd if (BNXT_PF(softc)) { 450308696Sshurd struct bnxt_pf_info *pf = &softc->pf; 451308696Sshurd 452308696Sshurd pf->port_id = le16toh(resp->port_id); 453308696Sshurd pf->first_vf_id = le16toh(resp->first_vf_id); 454308696Sshurd pf->max_vfs = le16toh(resp->max_vfs); 455308696Sshurd pf->max_encap_records = le32toh(resp->max_encap_records); 456308696Sshurd pf->max_decap_records = le32toh(resp->max_decap_records); 457308696Sshurd pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows); 458308696Sshurd pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows); 459308696Sshurd pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows); 460308696Sshurd pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows); 461308696Sshurd } 462308696Sshurd if (!_is_valid_ether_addr(func->mac_addr)) { 463309377Sshurd device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n"); 464308696Sshurd get_random_ether_addr(func->mac_addr); 465308696Sshurd } 466308696Sshurd 467308696Sshurdfail: 468308696Sshurd BNXT_HWRM_UNLOCK(softc); 469308696Sshurd return rc; 470308696Sshurd} 471308696Sshurd 472333364Sshurdint 473333364Sshurdbnxt_hwrm_func_qcfg(struct bnxt_softc *softc) 474333364Sshurd{ 475333364Sshurd struct hwrm_func_qcfg_input req = {0}; 476333364Sshurd struct hwrm_func_qcfg_output *resp = 477333364Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 478333364Sshurd struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg; 479333364Sshurd int rc; 480333364Sshurd 481333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG); 482333364Sshurd req.fid = htole16(0xffff); 483333364Sshurd BNXT_HWRM_LOCK(softc); 484333364Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 485333364Sshurd if (rc) 486333364Sshurd goto fail; 487333364Sshurd 488333364Sshurd fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings); 489333364Sshurd fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings); 490333364Sshurd fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings); 491333364Sshurd fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics); 492333364Sshurdfail: 493333364Sshurd BNXT_HWRM_UNLOCK(softc); 494333364Sshurd return rc; 495333364Sshurd} 496333364Sshurd 497308696Sshurdint 498308696Sshurdbnxt_hwrm_func_reset(struct bnxt_softc *softc) 499308696Sshurd{ 500308696Sshurd struct hwrm_func_reset_input req = {0}; 501308696Sshurd 502308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET); 503308696Sshurd req.enables = 0; 504308696Sshurd 505308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 506308696Sshurd} 507308696Sshurd 508308696Sshurdstatic void 509308696Sshurdbnxt_hwrm_set_link_common(struct bnxt_softc *softc, 510308696Sshurd struct hwrm_port_phy_cfg_input *req) 511308696Sshurd{ 512308696Sshurd uint8_t autoneg = softc->link_info.autoneg; 513308696Sshurd uint16_t fw_link_speed = softc->link_info.req_link_speed; 514308696Sshurd 515308696Sshurd if (autoneg & BNXT_AUTONEG_SPEED) { 516308696Sshurd req->auto_mode |= 517308696Sshurd HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS; 518308696Sshurd 519308696Sshurd req->enables |= 520308696Sshurd htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE); 521308696Sshurd req->flags |= 522308696Sshurd htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG); 523308696Sshurd } else { 524308696Sshurd req->force_link_speed = htole16(fw_link_speed); 525308696Sshurd req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE); 526308696Sshurd } 527308696Sshurd 528308696Sshurd /* tell chimp that the setting takes effect immediately */ 529308696Sshurd req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY); 530308696Sshurd} 531308696Sshurd 532308696Sshurd 533308696Sshurdstatic void 534308696Sshurdbnxt_hwrm_set_pause_common(struct bnxt_softc *softc, 535308696Sshurd struct hwrm_port_phy_cfg_input *req) 536308696Sshurd{ 537333364Sshurd struct bnxt_link_info *link_info = &softc->link_info; 538333364Sshurd 539333364Sshurd if (link_info->flow_ctrl.autoneg) { 540308696Sshurd req->auto_pause = 541308696Sshurd HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE; 542333364Sshurd if (link_info->flow_ctrl.rx) 543308696Sshurd req->auto_pause |= 544308696Sshurd HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX; 545333364Sshurd if (link_info->flow_ctrl.tx) 546308696Sshurd req->auto_pause |= 547333364Sshurd HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX; 548308696Sshurd req->enables |= 549308696Sshurd htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE); 550308696Sshurd } else { 551333364Sshurd if (link_info->flow_ctrl.rx) 552308696Sshurd req->force_pause |= 553308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX; 554333364Sshurd if (link_info->flow_ctrl.tx) 555308696Sshurd req->force_pause |= 556308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX; 557308696Sshurd req->enables |= 558308696Sshurd htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE); 559308696Sshurd } 560308696Sshurd} 561308696Sshurd 562308696Sshurd 563308696Sshurd/* JFV this needs interface connection */ 564308696Sshurdstatic void 565308696Sshurdbnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req) 566308696Sshurd{ 567308696Sshurd /* struct ethtool_eee *eee = &softc->eee; */ 568308696Sshurd bool eee_enabled = false; 569308696Sshurd 570308696Sshurd if (eee_enabled) { 571308696Sshurd#if 0 572308696Sshurd uint16_t eee_speeds; 573308696Sshurd uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE; 574308696Sshurd 575308696Sshurd if (eee->tx_lpi_enabled) 576308696Sshurd flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI; 577308696Sshurd 578308696Sshurd req->flags |= htole32(flags); 579308696Sshurd eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised); 580308696Sshurd req->eee_link_speed_mask = htole16(eee_speeds); 581308696Sshurd req->tx_lpi_timer = htole32(eee->tx_lpi_timer); 582308696Sshurd#endif 583308696Sshurd } else { 584308696Sshurd req->flags |= 585308696Sshurd htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE); 586308696Sshurd } 587308696Sshurd} 588308696Sshurd 589308696Sshurd 590308696Sshurdint 591308696Sshurdbnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause, 592333364Sshurd bool set_eee, bool set_link) 593308696Sshurd{ 594308696Sshurd struct hwrm_port_phy_cfg_input req = {0}; 595333364Sshurd int rc; 596308696Sshurd 597308696Sshurd if (softc->flags & BNXT_FLAG_NPAR) 598308696Sshurd return ENOTSUP; 599308696Sshurd 600308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG); 601333364Sshurd 602333364Sshurd if (set_pause) { 603308696Sshurd bnxt_hwrm_set_pause_common(softc, &req); 604308696Sshurd 605333364Sshurd if (softc->link_info.flow_ctrl.autoneg) 606333364Sshurd set_link = true; 607333364Sshurd } 608333364Sshurd 609333364Sshurd if (set_link) 610333364Sshurd bnxt_hwrm_set_link_common(softc, &req); 611333364Sshurd 612308696Sshurd if (set_eee) 613308696Sshurd bnxt_hwrm_set_eee(softc, &req); 614333364Sshurd 615308696Sshurd BNXT_HWRM_LOCK(softc); 616308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 617333364Sshurd 618333364Sshurd if (!rc) { 619333364Sshurd if (set_pause) { 620333364Sshurd /* since changing of 'force pause' setting doesn't 621333364Sshurd * trigger any link change event, the driver needs to 622333364Sshurd * update the current pause result upon successfully i 623333364Sshurd * return of the phy_cfg command */ 624333364Sshurd if (!softc->link_info.flow_ctrl.autoneg) 625333364Sshurd bnxt_report_link(softc); 626333364Sshurd } 627308696Sshurd } 628308696Sshurd BNXT_HWRM_UNLOCK(softc); 629308696Sshurd return rc; 630308696Sshurd} 631308696Sshurd 632308696Sshurdint 633308696Sshurdbnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) 634308696Sshurd{ 635308696Sshurd struct hwrm_vnic_cfg_input req = {0}; 636308696Sshurd struct hwrm_vnic_cfg_output *resp; 637308696Sshurd 638308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 639308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG); 640308696Sshurd 641308696Sshurd if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT) 642308696Sshurd req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT); 643308696Sshurd if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL) 644308696Sshurd req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE); 645308696Sshurd if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP) 646308696Sshurd req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE); 647308696Sshurd req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP | 648308696Sshurd HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE | 649308696Sshurd HWRM_VNIC_CFG_INPUT_ENABLES_MRU); 650308696Sshurd req.vnic_id = htole16(vnic->id); 651308696Sshurd req.dflt_ring_grp = htole16(vnic->def_ring_grp); 652308696Sshurd req.rss_rule = htole16(vnic->rss_id); 653308696Sshurd req.cos_rule = htole16(vnic->cos_rule); 654308696Sshurd req.lb_rule = htole16(vnic->lb_rule); 655308696Sshurd req.mru = htole16(vnic->mru); 656308696Sshurd 657308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 658308696Sshurd} 659308696Sshurd 660308696Sshurdint 661308696Sshurdbnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) 662308696Sshurd{ 663308696Sshurd struct hwrm_vnic_alloc_input req = {0}; 664308696Sshurd struct hwrm_vnic_alloc_output *resp = 665308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 666308696Sshurd int rc; 667308696Sshurd 668308696Sshurd if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) { 669308696Sshurd device_printf(softc->dev, 670308696Sshurd "Attempt to re-allocate vnic %04x\n", vnic->id); 671308696Sshurd return EDOOFUS; 672308696Sshurd } 673308696Sshurd 674308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC); 675308696Sshurd 676308696Sshurd if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT) 677308696Sshurd req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT); 678308696Sshurd 679308696Sshurd BNXT_HWRM_LOCK(softc); 680308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 681308696Sshurd if (rc) 682308696Sshurd goto fail; 683308696Sshurd 684308696Sshurd vnic->id = le32toh(resp->vnic_id); 685308696Sshurd 686308696Sshurdfail: 687308696Sshurd BNXT_HWRM_UNLOCK(softc); 688308696Sshurd return (rc); 689308696Sshurd} 690308696Sshurd 691308696Sshurdint 692308696Sshurdbnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id) 693308696Sshurd{ 694308696Sshurd struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0}; 695308696Sshurd struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp = 696308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 697308696Sshurd int rc; 698308696Sshurd 699308696Sshurd if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) { 700308696Sshurd device_printf(softc->dev, 701308696Sshurd "Attempt to re-allocate vnic ctx %04x\n", *ctx_id); 702308696Sshurd return EDOOFUS; 703308696Sshurd } 704308696Sshurd 705308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC); 706308696Sshurd 707308696Sshurd BNXT_HWRM_LOCK(softc); 708308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 709308696Sshurd if (rc) 710308696Sshurd goto fail; 711308696Sshurd 712308696Sshurd *ctx_id = le32toh(resp->rss_cos_lb_ctx_id); 713308696Sshurd 714308696Sshurdfail: 715308696Sshurd BNXT_HWRM_UNLOCK(softc); 716308696Sshurd return (rc); 717308696Sshurd} 718308696Sshurd 719308696Sshurdint 720308696Sshurdbnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp) 721308696Sshurd{ 722308696Sshurd struct hwrm_ring_grp_alloc_input req = {0}; 723308696Sshurd struct hwrm_ring_grp_alloc_output *resp; 724308696Sshurd int rc = 0; 725308696Sshurd 726308696Sshurd if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) { 727308696Sshurd device_printf(softc->dev, 728308696Sshurd "Attempt to re-allocate ring group %04x\n", grp->grp_id); 729308696Sshurd return EDOOFUS; 730308696Sshurd } 731308696Sshurd 732308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 733308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC); 734308696Sshurd req.cr = htole16(grp->cp_ring_id); 735308696Sshurd req.rr = htole16(grp->rx_ring_id); 736308696Sshurd req.ar = htole16(grp->ag_ring_id); 737308696Sshurd req.sc = htole16(grp->stats_ctx); 738308696Sshurd 739308696Sshurd BNXT_HWRM_LOCK(softc); 740308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 741308696Sshurd if (rc) 742308696Sshurd goto fail; 743308696Sshurd 744308696Sshurd grp->grp_id = le32toh(resp->ring_group_id); 745308696Sshurd 746308696Sshurdfail: 747308696Sshurd BNXT_HWRM_UNLOCK(softc); 748308696Sshurd return rc; 749308696Sshurd} 750308696Sshurd 751308696Sshurd/* 752308696Sshurd * Ring allocation message to the firmware 753308696Sshurd */ 754308696Sshurdint 755308696Sshurdbnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, 756308696Sshurd struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id, 757308696Sshurd bool irq) 758308696Sshurd{ 759308696Sshurd struct hwrm_ring_alloc_input req = {0}; 760308696Sshurd struct hwrm_ring_alloc_output *resp; 761308696Sshurd int rc; 762308696Sshurd 763308696Sshurd if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) { 764308696Sshurd device_printf(softc->dev, 765308696Sshurd "Attempt to re-allocate ring %04x\n", ring->phys_id); 766308696Sshurd return EDOOFUS; 767308696Sshurd } 768308696Sshurd 769308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 770308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC); 771308696Sshurd req.enables = htole32(0); 772308696Sshurd req.fbo = htole32(0); 773308696Sshurd 774308696Sshurd if (stat_ctx_id != HWRM_NA_SIGNATURE) { 775308696Sshurd req.enables |= htole32( 776308696Sshurd HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID); 777308696Sshurd req.stat_ctx_id = htole32(stat_ctx_id); 778308696Sshurd } 779308696Sshurd req.ring_type = type; 780308696Sshurd req.page_tbl_addr = htole64(ring->paddr); 781308696Sshurd req.length = htole32(ring->ring_size); 782308696Sshurd req.logical_id = htole16(ring->id); 783308696Sshurd req.cmpl_ring_id = htole16(cmpl_ring_id); 784308696Sshurd req.queue_id = htole16(softc->q_info[0].id); 785308696Sshurd#if 0 786308696Sshurd /* MODE_POLL appears to crash the firmware */ 787308696Sshurd if (irq) 788308696Sshurd req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; 789308696Sshurd else 790308696Sshurd req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL; 791308696Sshurd#else 792308696Sshurd req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; 793308696Sshurd#endif 794308696Sshurd BNXT_HWRM_LOCK(softc); 795308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 796308696Sshurd if (rc) 797308696Sshurd goto fail; 798308696Sshurd 799308696Sshurd ring->phys_id = le16toh(resp->ring_id); 800308696Sshurd 801308696Sshurdfail: 802308696Sshurd BNXT_HWRM_UNLOCK(softc); 803308696Sshurd return rc; 804308696Sshurd} 805308696Sshurd 806308696Sshurdint 807308696Sshurdbnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr, 808308696Sshurd uint64_t paddr) 809308696Sshurd{ 810308696Sshurd struct hwrm_stat_ctx_alloc_input req = {0}; 811308696Sshurd struct hwrm_stat_ctx_alloc_output *resp; 812308696Sshurd int rc = 0; 813308696Sshurd 814308696Sshurd if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) { 815308696Sshurd device_printf(softc->dev, 816308696Sshurd "Attempt to re-allocate stats ctx %08x\n", 817308696Sshurd cpr->stats_ctx_id); 818308696Sshurd return EDOOFUS; 819308696Sshurd } 820308696Sshurd 821308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 822308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC); 823308696Sshurd 824308696Sshurd req.update_period_ms = htole32(1000); 825308696Sshurd req.stats_dma_addr = htole64(paddr); 826308696Sshurd 827308696Sshurd BNXT_HWRM_LOCK(softc); 828308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 829308696Sshurd if (rc) 830308696Sshurd goto fail; 831308696Sshurd 832308696Sshurd cpr->stats_ctx_id = le32toh(resp->stat_ctx_id); 833308696Sshurd 834308696Sshurdfail: 835308696Sshurd BNXT_HWRM_UNLOCK(softc); 836308696Sshurd 837308696Sshurd return rc; 838308696Sshurd} 839308696Sshurd 840308696Sshurdint 841333364Sshurdbnxt_hwrm_port_qstats(struct bnxt_softc *softc) 842333364Sshurd{ 843333364Sshurd struct hwrm_port_qstats_input req = {0}; 844333364Sshurd int rc = 0; 845333364Sshurd 846333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS); 847333364Sshurd 848333364Sshurd req.port_id = htole16(softc->pf.port_id); 849333364Sshurd req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr); 850333364Sshurd req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr); 851333364Sshurd 852333364Sshurd BNXT_HWRM_LOCK(softc); 853333364Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 854333364Sshurd BNXT_HWRM_UNLOCK(softc); 855333364Sshurd 856333364Sshurd return rc; 857333364Sshurd} 858333364Sshurd 859333364Sshurdint 860308696Sshurdbnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc, 861308696Sshurd struct bnxt_vnic_info *vnic) 862308696Sshurd{ 863308696Sshurd struct hwrm_cfa_l2_set_rx_mask_input req = {0}; 864308696Sshurd struct bnxt_vlan_tag *tag; 865308696Sshurd uint32_t *tags; 866308696Sshurd uint32_t num_vlan_tags = 0;; 867308696Sshurd uint32_t i; 868308696Sshurd uint32_t mask = vnic->rx_mask; 869308696Sshurd int rc; 870308696Sshurd 871308696Sshurd SLIST_FOREACH(tag, &vnic->vlan_tags, next) 872308696Sshurd num_vlan_tags++; 873308696Sshurd 874308696Sshurd if (num_vlan_tags) { 875308696Sshurd if (!(mask & 876308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) { 877308696Sshurd if (!vnic->vlan_only) 878308696Sshurd mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN; 879308696Sshurd else 880308696Sshurd mask |= 881308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY; 882308696Sshurd } 883308696Sshurd if (vnic->vlan_tag_list.idi_vaddr) { 884308696Sshurd iflib_dma_free(&vnic->vlan_tag_list); 885308696Sshurd vnic->vlan_tag_list.idi_vaddr = NULL; 886308696Sshurd } 887308696Sshurd rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags, 888308696Sshurd &vnic->vlan_tag_list, BUS_DMA_NOWAIT); 889308696Sshurd if (rc) 890308696Sshurd return rc; 891308696Sshurd tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr; 892308696Sshurd 893308696Sshurd i = 0; 894308696Sshurd SLIST_FOREACH(tag, &vnic->vlan_tags, next) { 895308696Sshurd tags[i] = htole32((tag->tpid << 16) | tag->tag); 896308696Sshurd i++; 897308696Sshurd } 898308696Sshurd } 899308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK); 900308696Sshurd 901308696Sshurd req.vnic_id = htole32(vnic->id); 902308696Sshurd req.mask = htole32(mask); 903308696Sshurd req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr); 904308696Sshurd req.num_mc_entries = htole32(vnic->mc_list_count); 905308696Sshurd req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr); 906308696Sshurd req.num_vlan_tags = htole32(num_vlan_tags); 907308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 908308696Sshurd} 909308696Sshurd 910308696Sshurd 911308696Sshurdint 912308696Sshurdbnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) 913308696Sshurd{ 914308696Sshurd struct hwrm_cfa_l2_filter_alloc_input req = {0}; 915308696Sshurd struct hwrm_cfa_l2_filter_alloc_output *resp; 916308696Sshurd uint32_t enables = 0; 917308696Sshurd int rc = 0; 918308696Sshurd 919308696Sshurd if (vnic->filter_id != -1) { 920308696Sshurd device_printf(softc->dev, 921308696Sshurd "Attempt to re-allocate l2 ctx filter\n"); 922308696Sshurd return EDOOFUS; 923308696Sshurd } 924308696Sshurd 925308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 926308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC); 927308696Sshurd 928308696Sshurd req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX); 929308696Sshurd enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR 930308696Sshurd | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK 931308696Sshurd | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID; 932308696Sshurd req.enables = htole32(enables); 933308696Sshurd req.dst_id = htole16(vnic->id); 934308696Sshurd memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)), 935308696Sshurd ETHER_ADDR_LEN); 936308696Sshurd memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask)); 937308696Sshurd 938308696Sshurd BNXT_HWRM_LOCK(softc); 939308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 940308696Sshurd if (rc) 941308696Sshurd goto fail; 942308696Sshurd 943308696Sshurd vnic->filter_id = le64toh(resp->l2_filter_id); 944308696Sshurd vnic->flow_id = le64toh(resp->flow_id); 945308696Sshurd 946308696Sshurdfail: 947308696Sshurd BNXT_HWRM_UNLOCK(softc); 948308696Sshurd return (rc); 949308696Sshurd} 950308696Sshurd 951308696Sshurdint 952308696Sshurdbnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic, 953308696Sshurd uint32_t hash_type) 954308696Sshurd{ 955308696Sshurd struct hwrm_vnic_rss_cfg_input req = {0}; 956308696Sshurd struct hwrm_vnic_rss_cfg_output *resp; 957308696Sshurd 958308696Sshurd resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; 959308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG); 960308696Sshurd 961308696Sshurd req.hash_type = htole32(hash_type); 962308696Sshurd req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr); 963308696Sshurd req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr); 964308696Sshurd req.rss_ctx_idx = htole16(vnic->rss_id); 965308696Sshurd 966308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 967308696Sshurd} 968308696Sshurd 969308696Sshurdint 970333364Sshurdbnxt_cfg_async_cr(struct bnxt_softc *softc) 971308696Sshurd{ 972333364Sshurd int rc = 0; 973333364Sshurd 974333364Sshurd if (BNXT_PF(softc)) { 975333364Sshurd struct hwrm_func_cfg_input req = {0}; 976308696Sshurd 977333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG); 978308696Sshurd 979333364Sshurd req.fid = htole16(0xffff); 980333364Sshurd req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); 981333364Sshurd req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id); 982308696Sshurd 983333364Sshurd rc = hwrm_send_message(softc, &req, sizeof(req)); 984333364Sshurd } 985333364Sshurd else { 986333364Sshurd struct hwrm_func_vf_cfg_input req = {0}; 987308696Sshurd 988333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG); 989333364Sshurd 990333364Sshurd req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); 991333364Sshurd req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id); 992333364Sshurd 993333364Sshurd rc = hwrm_send_message(softc, &req, sizeof(req)); 994333364Sshurd } 995333364Sshurd return rc; 996308696Sshurd} 997308696Sshurd 998333364Sshurdvoid 999333364Sshurdbnxt_validate_hw_lro_settings(struct bnxt_softc *softc) 1000333364Sshurd{ 1001333364Sshurd softc->hw_lro.enable = min(softc->hw_lro.enable, 1); 1002333364Sshurd 1003333364Sshurd softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1); 1004333364Sshurd 1005333364Sshurd softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs, 1006333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX); 1007333364Sshurd 1008333364Sshurd softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs, 1009333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX); 1010333364Sshurd 1011333364Sshurd softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU); 1012333364Sshurd} 1013333364Sshurd 1014308696Sshurdint 1015333364Sshurdbnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc) 1016308696Sshurd{ 1017308696Sshurd struct hwrm_vnic_tpa_cfg_input req = {0}; 1018333364Sshurd uint32_t flags; 1019308696Sshurd 1020334178Sshurd if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) { 1021334178Sshurd return 0; 1022334178Sshurd } 1023334178Sshurd 1024308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG); 1025308696Sshurd 1026333364Sshurd if (softc->hw_lro.enable) { 1027333364Sshurd flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA | 1028333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA | 1029333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN | 1030333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ; 1031333364Sshurd 1032333364Sshurd if (softc->hw_lro.is_mode_gro) 1033333364Sshurd flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO; 1034333364Sshurd else 1035333364Sshurd flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE; 1036333364Sshurd 1037333364Sshurd req.flags = htole32(flags); 1038308696Sshurd 1039333364Sshurd req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS | 1040333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS | 1041333364Sshurd HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN); 1042333364Sshurd 1043333364Sshurd req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs); 1044333364Sshurd req.max_aggs = htole16(softc->hw_lro.max_aggs); 1045333364Sshurd req.min_agg_len = htole32(softc->hw_lro.min_agg_len); 1046333364Sshurd } 1047333364Sshurd 1048333364Sshurd req.vnic_id = htole16(softc->vnic_info.id); 1049333364Sshurd 1050308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 1051308696Sshurd} 1052308696Sshurd 1053308696Sshurdint 1054308696Sshurdbnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type, 1055308696Sshurd uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index, 1056308696Sshurd uint8_t search_opt, uint32_t *data_length, uint32_t *item_length, 1057308696Sshurd uint32_t *fw_ver) 1058308696Sshurd{ 1059308696Sshurd struct hwrm_nvm_find_dir_entry_input req = {0}; 1060308696Sshurd struct hwrm_nvm_find_dir_entry_output *resp = 1061308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1062308696Sshurd int rc = 0; 1063308696Sshurd uint32_t old_timeo; 1064308696Sshurd 1065308696Sshurd MPASS(ordinal); 1066308696Sshurd 1067308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY); 1068308696Sshurd if (use_index) { 1069308696Sshurd req.enables = htole32( 1070308696Sshurd HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID); 1071308696Sshurd req.dir_idx = htole16(*index); 1072308696Sshurd } 1073308696Sshurd req.dir_type = htole16(type); 1074308696Sshurd req.dir_ordinal = htole16(*ordinal); 1075308696Sshurd req.dir_ext = htole16(ext); 1076308696Sshurd req.opt_ordinal = search_opt; 1077308696Sshurd 1078308696Sshurd BNXT_HWRM_LOCK(softc); 1079308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1080308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1081308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1082308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1083308696Sshurd if (rc) 1084308696Sshurd goto exit; 1085308696Sshurd 1086308696Sshurd if (item_length) 1087308696Sshurd *item_length = le32toh(resp->dir_item_length); 1088308696Sshurd if (data_length) 1089308696Sshurd *data_length = le32toh(resp->dir_data_length); 1090308696Sshurd if (fw_ver) 1091308696Sshurd *fw_ver = le32toh(resp->fw_ver); 1092308696Sshurd *ordinal = le16toh(resp->dir_ordinal); 1093308696Sshurd if (index) 1094308696Sshurd *index = le16toh(resp->dir_idx); 1095308696Sshurd 1096308696Sshurdexit: 1097308696Sshurd BNXT_HWRM_UNLOCK(softc); 1098308696Sshurd return (rc); 1099308696Sshurd} 1100308696Sshurd 1101308696Sshurdint 1102308696Sshurdbnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset, 1103308696Sshurd uint32_t length, struct iflib_dma_info *data) 1104308696Sshurd{ 1105308696Sshurd struct hwrm_nvm_read_input req = {0}; 1106308696Sshurd int rc; 1107308696Sshurd uint32_t old_timeo; 1108308696Sshurd 1109308696Sshurd if (length > data->idi_size) { 1110308696Sshurd rc = EINVAL; 1111308696Sshurd goto exit; 1112308696Sshurd } 1113308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ); 1114308696Sshurd req.host_dest_addr = htole64(data->idi_paddr); 1115308696Sshurd req.dir_idx = htole16(index); 1116308696Sshurd req.offset = htole32(offset); 1117308696Sshurd req.len = htole32(length); 1118308696Sshurd BNXT_HWRM_LOCK(softc); 1119308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1120308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1121308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1122308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1123308696Sshurd BNXT_HWRM_UNLOCK(softc); 1124308696Sshurd if (rc) 1125308696Sshurd goto exit; 1126308696Sshurd bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD); 1127308696Sshurd 1128308696Sshurd goto exit; 1129308696Sshurd 1130308696Sshurdexit: 1131308696Sshurd return rc; 1132308696Sshurd} 1133308696Sshurd 1134308696Sshurdint 1135308696Sshurdbnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset, 1136308696Sshurd void *data, bool cpyin, uint32_t length) 1137308696Sshurd{ 1138308696Sshurd struct hwrm_nvm_modify_input req = {0}; 1139308696Sshurd struct iflib_dma_info dma_data; 1140308696Sshurd int rc; 1141308696Sshurd uint32_t old_timeo; 1142308696Sshurd 1143308696Sshurd if (length == 0 || !data) 1144308696Sshurd return EINVAL; 1145308696Sshurd rc = iflib_dma_alloc(softc->ctx, length, &dma_data, 1146308696Sshurd BUS_DMA_NOWAIT); 1147308696Sshurd if (rc) 1148308696Sshurd return ENOMEM; 1149308696Sshurd if (cpyin) { 1150308696Sshurd rc = copyin(data, dma_data.idi_vaddr, length); 1151308696Sshurd if (rc) 1152308696Sshurd goto exit; 1153308696Sshurd } 1154308696Sshurd else 1155308696Sshurd memcpy(dma_data.idi_vaddr, data, length); 1156308696Sshurd bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map, 1157308696Sshurd BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1158308696Sshurd 1159308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY); 1160308696Sshurd req.host_src_addr = htole64(dma_data.idi_paddr); 1161308696Sshurd req.dir_idx = htole16(index); 1162308696Sshurd req.offset = htole32(offset); 1163308696Sshurd req.len = htole32(length); 1164308696Sshurd BNXT_HWRM_LOCK(softc); 1165308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1166308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1167308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1168308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1169308696Sshurd BNXT_HWRM_UNLOCK(softc); 1170308696Sshurd 1171308696Sshurdexit: 1172308696Sshurd iflib_dma_free(&dma_data); 1173308696Sshurd return rc; 1174308696Sshurd} 1175308696Sshurd 1176308696Sshurdint 1177308696Sshurdbnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor, 1178308696Sshurd uint8_t *selfreset) 1179308696Sshurd{ 1180308696Sshurd struct hwrm_fw_reset_input req = {0}; 1181308696Sshurd struct hwrm_fw_reset_output *resp = 1182308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1183308696Sshurd int rc; 1184308696Sshurd 1185308696Sshurd MPASS(selfreset); 1186308696Sshurd 1187308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET); 1188308696Sshurd req.embedded_proc_type = processor; 1189308696Sshurd req.selfrst_status = *selfreset; 1190308696Sshurd 1191308696Sshurd BNXT_HWRM_LOCK(softc); 1192308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1193308696Sshurd if (rc) 1194308696Sshurd goto exit; 1195308696Sshurd *selfreset = resp->selfrst_status; 1196308696Sshurd 1197308696Sshurdexit: 1198308696Sshurd BNXT_HWRM_UNLOCK(softc); 1199308696Sshurd return rc; 1200308696Sshurd} 1201308696Sshurd 1202308696Sshurdint 1203308696Sshurdbnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset) 1204308696Sshurd{ 1205308696Sshurd struct hwrm_fw_qstatus_input req = {0}; 1206308696Sshurd struct hwrm_fw_qstatus_output *resp = 1207308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1208308696Sshurd int rc; 1209308696Sshurd 1210308696Sshurd MPASS(selfreset); 1211308696Sshurd 1212308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS); 1213308696Sshurd req.embedded_proc_type = type; 1214308696Sshurd 1215308696Sshurd BNXT_HWRM_LOCK(softc); 1216308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1217308696Sshurd if (rc) 1218308696Sshurd goto exit; 1219308696Sshurd *selfreset = resp->selfrst_status; 1220308696Sshurd 1221308696Sshurdexit: 1222308696Sshurd BNXT_HWRM_UNLOCK(softc); 1223308696Sshurd return rc; 1224308696Sshurd} 1225308696Sshurd 1226308696Sshurdint 1227308696Sshurdbnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin, 1228308696Sshurd uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr, 1229308696Sshurd uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length, 1230308696Sshurd uint16_t *index) 1231308696Sshurd{ 1232308696Sshurd struct hwrm_nvm_write_input req = {0}; 1233308696Sshurd struct hwrm_nvm_write_output *resp = 1234308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1235308696Sshurd struct iflib_dma_info dma_data; 1236308696Sshurd int rc; 1237308696Sshurd uint32_t old_timeo; 1238308696Sshurd 1239308696Sshurd if (data_length) { 1240308696Sshurd rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data, 1241308696Sshurd BUS_DMA_NOWAIT); 1242308696Sshurd if (rc) 1243308696Sshurd return ENOMEM; 1244308696Sshurd if (cpyin) { 1245308696Sshurd rc = copyin(data, dma_data.idi_vaddr, data_length); 1246308696Sshurd if (rc) 1247308696Sshurd goto early_exit; 1248308696Sshurd } 1249308696Sshurd else 1250308696Sshurd memcpy(dma_data.idi_vaddr, data, data_length); 1251308696Sshurd bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map, 1252308696Sshurd BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1253308696Sshurd } 1254308696Sshurd else 1255308696Sshurd dma_data.idi_paddr = 0; 1256308696Sshurd 1257308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE); 1258308696Sshurd 1259308696Sshurd req.host_src_addr = htole64(dma_data.idi_paddr); 1260308696Sshurd req.dir_type = htole16(type); 1261308696Sshurd req.dir_ordinal = htole16(ordinal); 1262308696Sshurd req.dir_ext = htole16(ext); 1263308696Sshurd req.dir_attr = htole16(attr); 1264308696Sshurd req.dir_data_length = htole32(data_length); 1265308696Sshurd req.option = htole16(option); 1266308696Sshurd if (keep) { 1267308696Sshurd req.flags = 1268308696Sshurd htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG); 1269308696Sshurd } 1270308696Sshurd if (item_length) 1271308696Sshurd req.dir_item_length = htole32(*item_length); 1272308696Sshurd 1273308696Sshurd BNXT_HWRM_LOCK(softc); 1274308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1275308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1276308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1277308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1278308696Sshurd if (rc) 1279308696Sshurd goto exit; 1280308696Sshurd if (item_length) 1281308696Sshurd *item_length = le32toh(resp->dir_item_length); 1282308696Sshurd if (index) 1283308696Sshurd *index = le16toh(resp->dir_idx); 1284308696Sshurd 1285308696Sshurdexit: 1286308696Sshurd BNXT_HWRM_UNLOCK(softc); 1287308696Sshurdearly_exit: 1288308696Sshurd if (data_length) 1289308696Sshurd iflib_dma_free(&dma_data); 1290308696Sshurd return rc; 1291308696Sshurd} 1292308696Sshurd 1293308696Sshurdint 1294308696Sshurdbnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index) 1295308696Sshurd{ 1296308696Sshurd struct hwrm_nvm_erase_dir_entry_input req = {0}; 1297308696Sshurd uint32_t old_timeo; 1298308696Sshurd int rc; 1299308696Sshurd 1300308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY); 1301308696Sshurd req.dir_idx = htole16(index); 1302308696Sshurd BNXT_HWRM_LOCK(softc); 1303308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1304308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1305308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1306308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1307308696Sshurd BNXT_HWRM_UNLOCK(softc); 1308308696Sshurd return rc; 1309308696Sshurd} 1310308696Sshurd 1311308696Sshurdint 1312308696Sshurdbnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries, 1313308696Sshurd uint32_t *entry_length) 1314308696Sshurd{ 1315308696Sshurd struct hwrm_nvm_get_dir_info_input req = {0}; 1316308696Sshurd struct hwrm_nvm_get_dir_info_output *resp = 1317308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1318308696Sshurd int rc; 1319308696Sshurd uint32_t old_timeo; 1320308696Sshurd 1321308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO); 1322308696Sshurd 1323308696Sshurd BNXT_HWRM_LOCK(softc); 1324308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1325308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1326308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1327308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1328308696Sshurd if (rc) 1329308696Sshurd goto exit; 1330308696Sshurd 1331308696Sshurd if (entries) 1332308696Sshurd *entries = le32toh(resp->entries); 1333308696Sshurd if (entry_length) 1334308696Sshurd *entry_length = le32toh(resp->entry_length); 1335308696Sshurd 1336308696Sshurdexit: 1337308696Sshurd BNXT_HWRM_UNLOCK(softc); 1338308696Sshurd return rc; 1339308696Sshurd} 1340308696Sshurd 1341308696Sshurdint 1342308696Sshurdbnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries, 1343308696Sshurd uint32_t *entry_length, struct iflib_dma_info *dma_data) 1344308696Sshurd{ 1345308696Sshurd struct hwrm_nvm_get_dir_entries_input req = {0}; 1346308696Sshurd uint32_t ent; 1347308696Sshurd uint32_t ent_len; 1348308696Sshurd int rc; 1349308696Sshurd uint32_t old_timeo; 1350308696Sshurd 1351308696Sshurd if (!entries) 1352308696Sshurd entries = &ent; 1353308696Sshurd if (!entry_length) 1354308696Sshurd entry_length = &ent_len; 1355308696Sshurd 1356308696Sshurd rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length); 1357308696Sshurd if (rc) 1358308696Sshurd goto exit; 1359308696Sshurd if (*entries * *entry_length > dma_data->idi_size) { 1360308696Sshurd rc = EINVAL; 1361308696Sshurd goto exit; 1362308696Sshurd } 1363308696Sshurd 1364308696Sshurd /* 1365308696Sshurd * TODO: There's a race condition here that could blow up DMA memory... 1366308696Sshurd * we need to allocate the max size, not the currently in use 1367308696Sshurd * size. The command should totally have a max size here. 1368308696Sshurd */ 1369308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES); 1370308696Sshurd req.host_dest_addr = htole64(dma_data->idi_paddr); 1371308696Sshurd BNXT_HWRM_LOCK(softc); 1372308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1373308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1374308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1375308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1376308696Sshurd BNXT_HWRM_UNLOCK(softc); 1377308696Sshurd if (rc) 1378308696Sshurd goto exit; 1379308696Sshurd bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map, 1380308696Sshurd BUS_DMASYNC_POSTWRITE); 1381308696Sshurd 1382308696Sshurdexit: 1383308696Sshurd return rc; 1384308696Sshurd} 1385308696Sshurd 1386308696Sshurdint 1387308696Sshurdbnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id, 1388308696Sshurd uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size, 1389308696Sshurd uint32_t *reserved_size, uint32_t *available_size) 1390308696Sshurd{ 1391308696Sshurd struct hwrm_nvm_get_dev_info_input req = {0}; 1392308696Sshurd struct hwrm_nvm_get_dev_info_output *resp = 1393308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1394308696Sshurd int rc; 1395308696Sshurd uint32_t old_timeo; 1396308696Sshurd 1397308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO); 1398308696Sshurd 1399308696Sshurd BNXT_HWRM_LOCK(softc); 1400308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1401308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1402308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1403308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1404308696Sshurd if (rc) 1405308696Sshurd goto exit; 1406308696Sshurd 1407308696Sshurd if (mfg_id) 1408308696Sshurd *mfg_id = le16toh(resp->manufacturer_id); 1409308696Sshurd if (device_id) 1410308696Sshurd *device_id = le16toh(resp->device_id); 1411308696Sshurd if (sector_size) 1412308696Sshurd *sector_size = le32toh(resp->sector_size); 1413308696Sshurd if (nvram_size) 1414308696Sshurd *nvram_size = le32toh(resp->nvram_size); 1415308696Sshurd if (reserved_size) 1416308696Sshurd *reserved_size = le32toh(resp->reserved_size); 1417308696Sshurd if (available_size) 1418308696Sshurd *available_size = le32toh(resp->available_size); 1419308696Sshurd 1420308696Sshurdexit: 1421308696Sshurd BNXT_HWRM_UNLOCK(softc); 1422308696Sshurd return rc; 1423308696Sshurd} 1424308696Sshurd 1425308696Sshurdint 1426308696Sshurdbnxt_hwrm_nvm_install_update(struct bnxt_softc *softc, 1427308696Sshurd uint32_t install_type, uint64_t *installed_items, uint8_t *result, 1428308696Sshurd uint8_t *problem_item, uint8_t *reset_required) 1429308696Sshurd{ 1430308696Sshurd struct hwrm_nvm_install_update_input req = {0}; 1431308696Sshurd struct hwrm_nvm_install_update_output *resp = 1432308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1433308696Sshurd int rc; 1434308696Sshurd uint32_t old_timeo; 1435308696Sshurd 1436308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE); 1437308696Sshurd req.install_type = htole32(install_type); 1438308696Sshurd 1439308696Sshurd BNXT_HWRM_LOCK(softc); 1440308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1441308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1442308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1443308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1444308696Sshurd if (rc) 1445308696Sshurd goto exit; 1446308696Sshurd 1447308696Sshurd if (installed_items) 1448308696Sshurd *installed_items = le32toh(resp->installed_items); 1449308696Sshurd if (result) 1450308696Sshurd *result = resp->result; 1451308696Sshurd if (problem_item) 1452308696Sshurd *problem_item = resp->problem_item; 1453308696Sshurd if (reset_required) 1454308696Sshurd *reset_required = resp->reset_required; 1455308696Sshurd 1456308696Sshurdexit: 1457308696Sshurd BNXT_HWRM_UNLOCK(softc); 1458308696Sshurd return rc; 1459308696Sshurd} 1460308696Sshurd 1461308696Sshurdint 1462308696Sshurdbnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type, 1463308696Sshurd uint16_t ordinal, uint16_t ext) 1464308696Sshurd{ 1465308696Sshurd struct hwrm_nvm_verify_update_input req = {0}; 1466308696Sshurd uint32_t old_timeo; 1467308696Sshurd int rc; 1468308696Sshurd 1469308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE); 1470308696Sshurd 1471308696Sshurd req.dir_type = htole16(type); 1472308696Sshurd req.dir_ordinal = htole16(ordinal); 1473308696Sshurd req.dir_ext = htole16(ext); 1474308696Sshurd 1475308696Sshurd BNXT_HWRM_LOCK(softc); 1476308696Sshurd old_timeo = softc->hwrm_cmd_timeo; 1477308696Sshurd softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; 1478308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1479308696Sshurd softc->hwrm_cmd_timeo = old_timeo; 1480308696Sshurd BNXT_HWRM_UNLOCK(softc); 1481308696Sshurd return rc; 1482308696Sshurd} 1483308696Sshurd 1484308696Sshurdint 1485308696Sshurdbnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month, 1486308696Sshurd uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second, 1487308696Sshurd uint16_t *millisecond, uint16_t *zone) 1488308696Sshurd{ 1489308696Sshurd struct hwrm_fw_get_time_input req = {0}; 1490308696Sshurd struct hwrm_fw_get_time_output *resp = 1491308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1492308696Sshurd int rc; 1493308696Sshurd 1494308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME); 1495308696Sshurd 1496308696Sshurd BNXT_HWRM_LOCK(softc); 1497308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1498308696Sshurd if (rc) 1499308696Sshurd goto exit; 1500308696Sshurd 1501308696Sshurd if (year) 1502308696Sshurd *year = le16toh(resp->year); 1503308696Sshurd if (month) 1504308696Sshurd *month = resp->month; 1505308696Sshurd if (day) 1506308696Sshurd *day = resp->day; 1507308696Sshurd if (hour) 1508308696Sshurd *hour = resp->hour; 1509308696Sshurd if (minute) 1510308696Sshurd *minute = resp->minute; 1511308696Sshurd if (second) 1512308696Sshurd *second = resp->second; 1513308696Sshurd if (millisecond) 1514308696Sshurd *millisecond = le16toh(resp->millisecond); 1515308696Sshurd if (zone) 1516308696Sshurd *zone = le16toh(resp->zone); 1517308696Sshurd 1518308696Sshurdexit: 1519308696Sshurd BNXT_HWRM_UNLOCK(softc); 1520308696Sshurd return rc; 1521308696Sshurd} 1522308696Sshurd 1523308696Sshurdint 1524308696Sshurdbnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month, 1525308696Sshurd uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, 1526308696Sshurd uint16_t millisecond, uint16_t zone) 1527308696Sshurd{ 1528308696Sshurd struct hwrm_fw_set_time_input req = {0}; 1529308696Sshurd 1530308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME); 1531308696Sshurd 1532308696Sshurd req.year = htole16(year); 1533308696Sshurd req.month = month; 1534308696Sshurd req.day = day; 1535308696Sshurd req.hour = hour; 1536308696Sshurd req.minute = minute; 1537308696Sshurd req.second = second; 1538308696Sshurd req.millisecond = htole16(millisecond); 1539308696Sshurd req.zone = htole16(zone); 1540308696Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 1541308696Sshurd} 1542308696Sshurd 1543308696Sshurdint 1544308696Sshurdbnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) 1545308696Sshurd{ 1546308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1547308696Sshurd struct hwrm_port_phy_qcfg_input req = {0}; 1548308696Sshurd struct hwrm_port_phy_qcfg_output *resp = 1549308696Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1550308696Sshurd int rc = 0; 1551308696Sshurd 1552308696Sshurd BNXT_HWRM_LOCK(softc); 1553308696Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG); 1554308696Sshurd 1555308696Sshurd rc = _hwrm_send_message(softc, &req, sizeof(req)); 1556308696Sshurd if (rc) 1557308696Sshurd goto exit; 1558308696Sshurd 1559308696Sshurd link_info->phy_link_status = resp->link; 1560333364Sshurd link_info->duplex = resp->duplex_cfg; 1561308696Sshurd link_info->auto_mode = resp->auto_mode; 1562333364Sshurd 1563333364Sshurd /* 1564333364Sshurd * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1, 1565333364Sshurd * the advertisement of pause is enabled. 1566333364Sshurd * 1. When the auto_mode is not set to none and this flag is set to 1, 1567333364Sshurd * then the auto_pause bits on this port are being advertised and 1568333364Sshurd * autoneg pause results are being interpreted. 1569333364Sshurd * 2. When the auto_mode is not set to none and this flag is set to 0, 1570333364Sshurd * the pause is forced as indicated in force_pause, and also 1571333364Sshurd * advertised as auto_pause bits, but the autoneg results are not 1572333364Sshurd * interpreted since the pause configuration is being forced. 1573333364Sshurd * 3. When the auto_mode is set to none and this flag is set to 1, 1574333364Sshurd * auto_pause bits should be ignored and should be set to 0. 1575333364Sshurd */ 1576333364Sshurd 1577333364Sshurd link_info->flow_ctrl.autoneg = false; 1578333364Sshurd link_info->flow_ctrl.tx = false; 1579333364Sshurd link_info->flow_ctrl.rx = false; 1580333364Sshurd 1581333364Sshurd if ((resp->auto_mode) && 1582333364Sshurd (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) { 1583333364Sshurd link_info->flow_ctrl.autoneg = true; 1584333364Sshurd } 1585333364Sshurd 1586333364Sshurd if (link_info->flow_ctrl.autoneg) { 1587333364Sshurd if (resp->auto_pause & BNXT_PAUSE_TX) 1588333364Sshurd link_info->flow_ctrl.tx = true; 1589333364Sshurd if (resp->auto_pause & BNXT_PAUSE_RX) 1590333364Sshurd link_info->flow_ctrl.rx = true; 1591333364Sshurd } else { 1592333364Sshurd if (resp->force_pause & BNXT_PAUSE_TX) 1593333364Sshurd link_info->flow_ctrl.tx = true; 1594333364Sshurd if (resp->force_pause & BNXT_PAUSE_RX) 1595333364Sshurd link_info->flow_ctrl.rx = true; 1596333364Sshurd } 1597333364Sshurd 1598333364Sshurd link_info->duplex_setting = resp->duplex_cfg; 1599308696Sshurd if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) 1600308696Sshurd link_info->link_speed = le16toh(resp->link_speed); 1601308696Sshurd else 1602308696Sshurd link_info->link_speed = 0; 1603308696Sshurd link_info->force_link_speed = le16toh(resp->force_link_speed); 1604308696Sshurd link_info->auto_link_speed = le16toh(resp->auto_link_speed); 1605308696Sshurd link_info->support_speeds = le16toh(resp->support_speeds); 1606308696Sshurd link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask); 1607308696Sshurd link_info->preemphasis = le32toh(resp->preemphasis); 1608308696Sshurd link_info->phy_ver[0] = resp->phy_maj; 1609308696Sshurd link_info->phy_ver[1] = resp->phy_min; 1610308696Sshurd link_info->phy_ver[2] = resp->phy_bld; 1611308696Sshurd snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver), 1612308696Sshurd "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1], 1613308696Sshurd link_info->phy_ver[2]); 1614308696Sshurd strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name, 1615308696Sshurd BNXT_NAME_SIZE); 1616308696Sshurd strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber, 1617308696Sshurd BNXT_NAME_SIZE); 1618308696Sshurd link_info->media_type = resp->media_type; 1619308696Sshurd link_info->phy_type = resp->phy_type; 1620308696Sshurd link_info->transceiver = resp->xcvr_pkg_type; 1621308696Sshurd link_info->phy_addr = resp->eee_config_phy_addr & 1622308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK; 1623308696Sshurd 1624308696Sshurdexit: 1625308696Sshurd BNXT_HWRM_UNLOCK(softc); 1626308696Sshurd return rc; 1627308696Sshurd} 1628333364Sshurd 1629333364Sshurduint16_t 1630333364Sshurdbnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle) 1631333364Sshurd{ 1632333364Sshurd struct hwrm_wol_filter_qcfg_input req = {0}; 1633333364Sshurd struct hwrm_wol_filter_qcfg_output *resp = 1634333364Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1635333364Sshurd uint16_t next_handle = 0; 1636333364Sshurd int rc; 1637333364Sshurd 1638333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG); 1639333364Sshurd req.port_id = htole16(softc->pf.port_id); 1640333364Sshurd req.handle = htole16(handle); 1641333364Sshurd rc = hwrm_send_message(softc, &req, sizeof(req)); 1642333364Sshurd if (!rc) { 1643333364Sshurd next_handle = le16toh(resp->next_handle); 1644333364Sshurd if (next_handle != 0) { 1645333364Sshurd if (resp->wol_type == 1646333364Sshurd HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) { 1647333364Sshurd softc->wol = 1; 1648333364Sshurd softc->wol_filter_id = resp->wol_filter_id; 1649333364Sshurd } 1650333364Sshurd } 1651333364Sshurd } 1652333364Sshurd return next_handle; 1653333364Sshurd} 1654333364Sshurd 1655333364Sshurdint 1656333364Sshurdbnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc) 1657333364Sshurd{ 1658333364Sshurd struct hwrm_wol_filter_alloc_input req = {0}; 1659333364Sshurd struct hwrm_wol_filter_alloc_output *resp = 1660333364Sshurd (void *)softc->hwrm_cmd_resp.idi_vaddr; 1661333364Sshurd int rc; 1662333364Sshurd 1663333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC); 1664333364Sshurd req.port_id = htole16(softc->pf.port_id); 1665333364Sshurd req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT; 1666333364Sshurd req.enables = 1667333364Sshurd htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS); 1668333364Sshurd memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN); 1669333364Sshurd rc = hwrm_send_message(softc, &req, sizeof(req)); 1670333364Sshurd if (!rc) 1671333364Sshurd softc->wol_filter_id = resp->wol_filter_id; 1672333364Sshurd 1673333364Sshurd return rc; 1674333364Sshurd} 1675333364Sshurd 1676333364Sshurdint 1677333364Sshurdbnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc) 1678333364Sshurd{ 1679333364Sshurd struct hwrm_wol_filter_free_input req = {0}; 1680333364Sshurd 1681333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE); 1682333364Sshurd req.port_id = htole16(softc->pf.port_id); 1683333364Sshurd req.enables = 1684333364Sshurd htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID); 1685333364Sshurd req.wol_filter_id = softc->wol_filter_id; 1686333364Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 1687333364Sshurd} 1688333364Sshurd 1689333364Sshurdstatic void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames, 1690333364Sshurd uint32_t buf_tmrs, uint16_t flags, 1691333364Sshurd struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req) 1692333364Sshurd{ 1693333364Sshurd req->flags = htole16(flags); 1694333364Sshurd req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames); 1695333364Sshurd req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16); 1696333364Sshurd req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs); 1697333364Sshurd req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16); 1698333364Sshurd /* Minimum time between 2 interrupts set to buf_tmr x 2 */ 1699333364Sshurd req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2); 1700333364Sshurd req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4); 1701333364Sshurd req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4); 1702333364Sshurd} 1703333364Sshurd 1704333364Sshurd 1705333364Sshurdint bnxt_hwrm_set_coal(struct bnxt_softc *softc) 1706333364Sshurd{ 1707333364Sshurd int i, rc = 0; 1708333364Sshurd struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0}, 1709333364Sshurd req_tx = {0}, *req; 1710333364Sshurd uint16_t max_buf, max_buf_irq; 1711333364Sshurd uint16_t buf_tmr, buf_tmr_irq; 1712333364Sshurd uint32_t flags; 1713333364Sshurd 1714333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req_rx, 1715333364Sshurd HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); 1716333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req_tx, 1717333364Sshurd HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS); 1718333364Sshurd 1719333364Sshurd /* Each rx completion (2 records) should be DMAed immediately. 1720333364Sshurd * DMA 1/4 of the completion buffers at a time. 1721333364Sshurd */ 1722333364Sshurd max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2); 1723333364Sshurd /* max_buf must not be zero */ 1724333364Sshurd max_buf = clamp_t(uint16_t, max_buf, 1, 63); 1725333364Sshurd max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63); 1726333364Sshurd buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs); 1727333364Sshurd /* buf timer set to 1/4 of interrupt timer */ 1728333364Sshurd buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); 1729333364Sshurd buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq); 1730333364Sshurd buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); 1731333364Sshurd 1732333364Sshurd flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; 1733333364Sshurd 1734333364Sshurd /* RING_IDLE generates more IRQs for lower latency. Enable it only 1735333364Sshurd * if coal_usecs is less than 25 us. 1736333364Sshurd */ 1737333364Sshurd if (softc->rx_coal_usecs < 25) 1738333364Sshurd flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE; 1739333364Sshurd 1740333364Sshurd bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, 1741333364Sshurd buf_tmr_irq << 16 | buf_tmr, flags, &req_rx); 1742333364Sshurd 1743333364Sshurd /* max_buf must not be zero */ 1744333364Sshurd max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63); 1745333364Sshurd max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63); 1746333364Sshurd buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs); 1747333364Sshurd /* buf timer set to 1/4 of interrupt timer */ 1748333364Sshurd buf_tmr = max_t(uint16_t, buf_tmr / 4, 1); 1749333364Sshurd buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq); 1750333364Sshurd buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1); 1751333364Sshurd flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET; 1752333364Sshurd bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf, 1753333364Sshurd buf_tmr_irq << 16 | buf_tmr, flags, &req_tx); 1754333364Sshurd 1755333364Sshurd for (i = 0; i < softc->nrxqsets; i++) { 1756333364Sshurd 1757333364Sshurd 1758333364Sshurd req = &req_rx; 1759333364Sshurd /* 1760333364Sshurd * TBD: 1761333364Sshurd * Check if Tx also needs to be done 1762333364Sshurd * So far, Tx processing has been done in softirq contest 1763333364Sshurd * 1764333364Sshurd * req = &req_tx; 1765333364Sshurd */ 1766333364Sshurd req->ring_id = htole16(softc->grp_info[i].cp_ring_id); 1767333364Sshurd 1768333364Sshurd rc = hwrm_send_message(softc, req, sizeof(*req)); 1769333364Sshurd if (rc) 1770333364Sshurd break; 1771333364Sshurd } 1772333364Sshurd return rc; 1773333364Sshurd} 1774333364Sshurd 1775333364Sshurd 1776333364Sshurd 1777333364Sshurdint bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap, 1778333364Sshurd int bmap_size) 1779333364Sshurd{ 1780333364Sshurd struct hwrm_func_drv_rgtr_input req = {0}; 1781333364Sshurd bitstr_t *async_events_bmap; 1782333364Sshurd uint32_t *events; 1783333364Sshurd int i; 1784333364Sshurd 1785333364Sshurd async_events_bmap = bit_alloc(256, M_DEVBUF, M_WAITOK|M_ZERO); 1786333364Sshurd events = (uint32_t *)async_events_bmap; 1787333364Sshurd 1788333364Sshurd bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR); 1789333364Sshurd 1790333364Sshurd req.enables = 1791333364Sshurd htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD); 1792333364Sshurd 1793333364Sshurd memset(async_events_bmap, 0, sizeof(256 / 8)); 1794333364Sshurd 1795333364Sshurd bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE); 1796333364Sshurd bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD); 1797333364Sshurd bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED); 1798333364Sshurd bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE); 1799333364Sshurd bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE); 1800333364Sshurd 1801333364Sshurd if (bmap && bmap_size) { 1802333364Sshurd for (i = 0; i < bmap_size; i++) { 1803333364Sshurd if (bit_test(bmap, i)) 1804333364Sshurd bit_set(async_events_bmap, i); 1805333364Sshurd } 1806333364Sshurd } 1807333364Sshurd 1808333364Sshurd for (i = 0; i < 8; i++) 1809333364Sshurd req.async_event_fwd[i] |= htole32(events[i]); 1810333364Sshurd 1811333364Sshurd free(async_events_bmap, M_DEVBUF); 1812333364Sshurd 1813333364Sshurd return hwrm_send_message(softc, &req, sizeof(req)); 1814333364Sshurd} 1815