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$"); 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 #define AE_BMAP_SZ_BITS 256 1782 async_events_bmap = bit_alloc(AE_BMAP_SZ_BITS, M_DEVBUF, M_WAITOK); 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 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE); 1790 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD); 1791 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED); 1792 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE); 1793 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE); 1794 1795 if (bmap && bmap_size) { 1796 for (i = 0; i < bmap_size; i++) { 1797 if (bit_test(bmap, i)) 1798 bit_set(async_events_bmap, i); 1799 } 1800 } 1801 1802 #define AE_BMAP_SZ_WORDS (AE_BMAP_SZ_BITS / 8 / sizeof(uint32_t)) 1803 events = (uint32_t *)async_events_bmap; 1804 for (i = 0; i < AE_BMAP_SZ_WORDS; i++) 1805 req.async_event_fwd[i] |= htole32(events[i]); 1806 #undef AE_BMAP_SZ_WORDS 1807 #undef AE_BMAP_SZ_BITS 1808 1809 free(async_events_bmap, M_DEVBUF); 1810 1811 return hwrm_send_message(softc, &req, sizeof(req)); 1812 } 1813