2 * Broadcom NetXtreme-C/E network driver.
4 * Copyright (c) 2016 Broadcom, All Rights Reserved.
5 * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/endian.h>
33 #include <sys/bitstring.h>
36 #include "bnxt_hwrm.h"
37 #include "hsi_struct_def.h"
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);
52 /* NVRam stuff has a five minute timeout */
53 #define BNXT_NVM_TIMEO (5 * 60 * 1000)
56 bnxt_hwrm_err_map(uint16_t err)
61 case HWRM_ERR_CODE_SUCCESS:
63 case HWRM_ERR_CODE_INVALID_PARAMS:
64 case HWRM_ERR_CODE_INVALID_FLAGS:
65 case HWRM_ERR_CODE_INVALID_ENABLES:
67 case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
69 case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
71 case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
73 case HWRM_ERR_CODE_FAIL:
75 case HWRM_ERR_CODE_HWRM_ERROR:
76 case HWRM_ERR_CODE_UNKNOWN_ERR:
85 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
89 rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
95 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
97 if (softc->hwrm_cmd_resp.idi_vaddr)
98 iflib_dma_free(&softc->hwrm_cmd_resp);
99 softc->hwrm_cmd_resp.idi_vaddr = NULL;
104 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
107 struct input *req = request;
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);
116 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
118 struct input *req = msg;
119 struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
120 uint32_t *data = msg;
126 /* TODO: DMASYNC in here. */
127 req->seq_id = htole16(softc->hwrm_cmd_seq++);
128 memset(resp, 0, PAGE_SIZE);
129 cp_ring_id = le16toh(req->cmpl_ring);
131 /* Write request msg to hwrm channel */
132 for (i = 0; i < msg_len; i += 4) {
133 bus_space_write_4(softc->hwrm_bar.tag,
134 softc->hwrm_bar.handle,
139 /* Clear to the end of the request buffer */
140 for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
141 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
144 /* Ring channel doorbell */
145 bus_space_write_4(softc->hwrm_bar.tag,
146 softc->hwrm_bar.handle,
149 /* Check if response len is updated */
150 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
151 if (resp->resp_len && resp->resp_len <= 4096)
155 if (i >= softc->hwrm_cmd_timeo) {
156 device_printf(softc->dev,
157 "Timeout sending %s: (timeout: %u) seq: %d\n",
158 GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
159 le16toh(req->seq_id));
162 /* Last byte of resp contains the valid key */
163 valid = (uint8_t *)resp + resp->resp_len - 1;
164 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
165 if (*valid == HWRM_RESP_VALID_KEY)
169 if (i >= softc->hwrm_cmd_timeo) {
170 device_printf(softc->dev, "Timeout sending %s: "
171 "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
172 GET_HWRM_REQ_TYPE(req->req_type),
173 softc->hwrm_cmd_timeo, le16toh(req->req_type),
174 le16toh(req->seq_id), msg_len,
179 err = le16toh(resp->error_code);
181 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
182 if (err != HWRM_ERR_CODE_FAIL) {
183 device_printf(softc->dev,
184 "%s command returned %s error.\n",
185 GET_HWRM_REQ_TYPE(req->req_type),
186 GET_HWRM_ERROR_CODE(err));
188 return bnxt_hwrm_err_map(err);
195 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
199 BNXT_HWRM_LOCK(softc);
200 rc = _hwrm_send_message(softc, msg, msg_len);
201 BNXT_HWRM_UNLOCK(softc);
206 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
208 struct hwrm_queue_qportcfg_input req = {0};
209 struct hwrm_queue_qportcfg_output *resp =
210 (void *)softc->hwrm_cmd_resp.idi_vaddr;
215 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
217 BNXT_HWRM_LOCK(softc);
218 rc = _hwrm_send_message(softc, &req, sizeof(req));
222 if (!resp->max_configurable_queues) {
226 softc->max_tc = resp->max_configurable_queues;
227 if (softc->max_tc > BNXT_MAX_QUEUE)
228 softc->max_tc = BNXT_MAX_QUEUE;
230 qptr = &resp->queue_id0;
231 for (int i = 0; i < softc->max_tc; i++) {
232 softc->q_info[i].id = *qptr++;
233 softc->q_info[i].profile = *qptr++;
237 BNXT_HWRM_UNLOCK(softc);
243 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
245 struct hwrm_ver_get_input req = {0};
246 struct hwrm_ver_get_output *resp =
247 (void *)softc->hwrm_cmd_resp.idi_vaddr;
249 const char nastr[] = "<not installed>";
250 const char naver[] = "<N/A>";
252 softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
253 softc->hwrm_cmd_timeo = 1000;
254 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
256 req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
257 req.hwrm_intf_min = HWRM_VERSION_MINOR;
258 req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
260 BNXT_HWRM_LOCK(softc);
261 rc = _hwrm_send_message(softc, &req, sizeof(req));
265 snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
266 resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
267 softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
268 softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
269 softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
270 snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
271 resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
272 strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
274 strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
277 if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
278 resp->mgmt_fw_bld == 0) {
279 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
280 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
283 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
284 "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
286 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
289 if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
290 resp->netctrl_fw_bld == 0) {
291 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
293 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
297 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
298 "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
299 resp->netctrl_fw_bld);
300 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
303 if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
304 resp->roce_fw_bld == 0) {
305 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
306 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
309 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
310 "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
312 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
315 softc->ver_info->chip_num = le16toh(resp->chip_num);
316 softc->ver_info->chip_rev = resp->chip_rev;
317 softc->ver_info->chip_metal = resp->chip_metal;
318 softc->ver_info->chip_bond_id = resp->chip_bond_id;
319 softc->ver_info->chip_type = resp->chip_platform_type;
321 if (resp->max_req_win_len)
322 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
323 if (resp->def_req_timeout)
324 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
327 BNXT_HWRM_UNLOCK(softc);
332 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
334 struct hwrm_func_drv_rgtr_input req = {0};
336 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
338 req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
339 HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
340 req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
342 req.ver_maj = __FreeBSD_version / 100000;
343 req.ver_min = (__FreeBSD_version / 1000) % 100;
344 req.ver_upd = (__FreeBSD_version / 100) % 10;
346 return hwrm_send_message(softc, &req, sizeof(req));
351 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
353 struct hwrm_func_drv_unrgtr_input req = {0};
355 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
356 if (shutdown == true)
358 HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
359 return hwrm_send_message(softc, &req, sizeof(req));
364 _is_valid_ether_addr(uint8_t *addr)
366 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
368 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
375 get_random_ether_addr(uint8_t *addr)
377 uint8_t temp[ETHER_ADDR_LEN];
379 arc4rand(&temp, sizeof(temp), 0);
382 bcopy(temp, addr, sizeof(temp));
386 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
389 struct hwrm_func_qcaps_input req = {0};
390 struct hwrm_func_qcaps_output *resp =
391 (void *)softc->hwrm_cmd_resp.idi_vaddr;
392 struct bnxt_func_info *func = &softc->func;
394 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
395 req.fid = htole16(0xffff);
397 BNXT_HWRM_LOCK(softc);
398 rc = _hwrm_send_message(softc, &req, sizeof(req));
403 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
404 softc->flags |= BNXT_FLAG_WOL_CAP;
406 func->fw_fid = le16toh(resp->fid);
407 memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
408 func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
409 func->max_cp_rings = le16toh(resp->max_cmpl_rings);
410 func->max_tx_rings = le16toh(resp->max_tx_rings);
411 func->max_rx_rings = le16toh(resp->max_rx_rings);
412 func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
413 if (!func->max_hw_ring_grps)
414 func->max_hw_ring_grps = func->max_tx_rings;
415 func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
416 func->max_vnics = le16toh(resp->max_vnics);
417 func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
418 if (BNXT_PF(softc)) {
419 struct bnxt_pf_info *pf = &softc->pf;
421 pf->port_id = le16toh(resp->port_id);
422 pf->first_vf_id = le16toh(resp->first_vf_id);
423 pf->max_vfs = le16toh(resp->max_vfs);
424 pf->max_encap_records = le32toh(resp->max_encap_records);
425 pf->max_decap_records = le32toh(resp->max_decap_records);
426 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
427 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
428 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
429 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
431 if (!_is_valid_ether_addr(func->mac_addr)) {
432 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
433 get_random_ether_addr(func->mac_addr);
437 BNXT_HWRM_UNLOCK(softc);
442 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
444 struct hwrm_func_qcfg_input req = {0};
445 struct hwrm_func_qcfg_output *resp =
446 (void *)softc->hwrm_cmd_resp.idi_vaddr;
447 struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
450 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
451 req.fid = htole16(0xffff);
452 BNXT_HWRM_LOCK(softc);
453 rc = _hwrm_send_message(softc, &req, sizeof(req));
457 fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
458 fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
459 fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
460 fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
462 BNXT_HWRM_UNLOCK(softc);
467 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
469 struct hwrm_func_reset_input req = {0};
471 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
474 return hwrm_send_message(softc, &req, sizeof(req));
478 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
479 struct hwrm_port_phy_cfg_input *req)
481 uint8_t autoneg = softc->link_info.autoneg;
482 uint16_t fw_link_speed = softc->link_info.req_link_speed;
484 if (autoneg & BNXT_AUTONEG_SPEED) {
486 HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
489 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
491 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
493 req->force_link_speed = htole16(fw_link_speed);
494 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
497 /* tell chimp that the setting takes effect immediately */
498 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
503 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
504 struct hwrm_port_phy_cfg_input *req)
506 if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
508 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
509 if (softc->link_info.req_flow_ctrl &
510 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
512 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
513 if (softc->link_info.req_flow_ctrl &
514 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
516 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
518 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
520 if (softc->link_info.req_flow_ctrl &
521 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
523 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
524 if (softc->link_info.req_flow_ctrl &
525 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
527 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
529 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
530 req->auto_pause = req->force_pause;
531 req->enables |= htole32(
532 HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
537 /* JFV this needs interface connection */
539 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
541 /* struct ethtool_eee *eee = &softc->eee; */
542 bool eee_enabled = false;
547 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
549 if (eee->tx_lpi_enabled)
550 flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
552 req->flags |= htole32(flags);
553 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
554 req->eee_link_speed_mask = htole16(eee_speeds);
555 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
559 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
565 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
568 struct hwrm_port_phy_cfg_input req = {0};
570 if (softc->flags & BNXT_FLAG_NPAR)
573 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
575 bnxt_hwrm_set_pause_common(softc, &req);
577 bnxt_hwrm_set_link_common(softc, &req);
579 bnxt_hwrm_set_eee(softc, &req);
580 return hwrm_send_message(softc, &req, sizeof(req));
585 bnxt_hwrm_set_pause(struct bnxt_softc *softc)
587 struct hwrm_port_phy_cfg_input req = {0};
590 if (softc->flags & BNXT_FLAG_NPAR)
593 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
594 bnxt_hwrm_set_pause_common(softc, &req);
596 if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)
597 bnxt_hwrm_set_link_common(softc, &req);
599 BNXT_HWRM_LOCK(softc);
600 rc = _hwrm_send_message(softc, &req, sizeof(req));
601 if (!rc && !(softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
602 /* since changing of pause setting doesn't trigger any link
603 * change event, the driver needs to update the current pause
604 * result upon successfully return of the phy_cfg command */
605 softc->link_info.pause =
606 softc->link_info.force_pause = softc->link_info.req_flow_ctrl;
607 softc->link_info.auto_pause = 0;
608 bnxt_report_link(softc);
610 BNXT_HWRM_UNLOCK(softc);
615 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
617 struct hwrm_vnic_cfg_input req = {0};
618 struct hwrm_vnic_cfg_output *resp;
620 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
621 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
623 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
624 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
625 if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
626 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
627 if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
628 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
629 req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
630 HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
631 HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
632 req.vnic_id = htole16(vnic->id);
633 req.dflt_ring_grp = htole16(vnic->def_ring_grp);
634 req.rss_rule = htole16(vnic->rss_id);
635 req.cos_rule = htole16(vnic->cos_rule);
636 req.lb_rule = htole16(vnic->lb_rule);
637 req.mru = htole16(vnic->mru);
639 return hwrm_send_message(softc, &req, sizeof(req));
643 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
645 struct hwrm_vnic_alloc_input req = {0};
646 struct hwrm_vnic_alloc_output *resp =
647 (void *)softc->hwrm_cmd_resp.idi_vaddr;
650 if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
651 device_printf(softc->dev,
652 "Attempt to re-allocate vnic %04x\n", vnic->id);
656 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
658 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
659 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
661 BNXT_HWRM_LOCK(softc);
662 rc = _hwrm_send_message(softc, &req, sizeof(req));
666 vnic->id = le32toh(resp->vnic_id);
669 BNXT_HWRM_UNLOCK(softc);
674 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
676 struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
677 struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
678 (void *)softc->hwrm_cmd_resp.idi_vaddr;
681 if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
682 device_printf(softc->dev,
683 "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
687 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
689 BNXT_HWRM_LOCK(softc);
690 rc = _hwrm_send_message(softc, &req, sizeof(req));
694 *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
697 BNXT_HWRM_UNLOCK(softc);
702 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
704 struct hwrm_ring_grp_alloc_input req = {0};
705 struct hwrm_ring_grp_alloc_output *resp;
708 if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
709 device_printf(softc->dev,
710 "Attempt to re-allocate ring group %04x\n", grp->grp_id);
714 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
715 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
716 req.cr = htole16(grp->cp_ring_id);
717 req.rr = htole16(grp->rx_ring_id);
718 req.ar = htole16(grp->ag_ring_id);
719 req.sc = htole16(grp->stats_ctx);
721 BNXT_HWRM_LOCK(softc);
722 rc = _hwrm_send_message(softc, &req, sizeof(req));
726 grp->grp_id = le32toh(resp->ring_group_id);
729 BNXT_HWRM_UNLOCK(softc);
734 * Ring allocation message to the firmware
737 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
738 struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
741 struct hwrm_ring_alloc_input req = {0};
742 struct hwrm_ring_alloc_output *resp;
745 if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
746 device_printf(softc->dev,
747 "Attempt to re-allocate ring %04x\n", ring->phys_id);
751 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
752 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
753 req.enables = htole32(0);
754 req.fbo = htole32(0);
756 if (stat_ctx_id != HWRM_NA_SIGNATURE) {
757 req.enables |= htole32(
758 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
759 req.stat_ctx_id = htole32(stat_ctx_id);
761 req.ring_type = type;
762 req.page_tbl_addr = htole64(ring->paddr);
763 req.length = htole32(ring->ring_size);
764 req.logical_id = htole16(ring->id);
765 req.cmpl_ring_id = htole16(cmpl_ring_id);
766 req.queue_id = htole16(softc->q_info[0].id);
768 /* MODE_POLL appears to crash the firmware */
770 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
772 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
774 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
776 BNXT_HWRM_LOCK(softc);
777 rc = _hwrm_send_message(softc, &req, sizeof(req));
781 ring->phys_id = le16toh(resp->ring_id);
784 BNXT_HWRM_UNLOCK(softc);
789 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
792 struct hwrm_stat_ctx_alloc_input req = {0};
793 struct hwrm_stat_ctx_alloc_output *resp;
796 if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
797 device_printf(softc->dev,
798 "Attempt to re-allocate stats ctx %08x\n",
803 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
804 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
806 req.update_period_ms = htole32(1000);
807 req.stats_dma_addr = htole64(paddr);
809 BNXT_HWRM_LOCK(softc);
810 rc = _hwrm_send_message(softc, &req, sizeof(req));
814 cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
817 BNXT_HWRM_UNLOCK(softc);
823 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
824 struct bnxt_vnic_info *vnic)
826 struct hwrm_cfa_l2_set_rx_mask_input req = {0};
827 struct bnxt_vlan_tag *tag;
829 uint32_t num_vlan_tags = 0;;
831 uint32_t mask = vnic->rx_mask;
834 SLIST_FOREACH(tag, &vnic->vlan_tags, next)
839 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
840 if (!vnic->vlan_only)
841 mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
844 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
846 if (vnic->vlan_tag_list.idi_vaddr) {
847 iflib_dma_free(&vnic->vlan_tag_list);
848 vnic->vlan_tag_list.idi_vaddr = NULL;
850 rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
851 &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
854 tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
857 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
858 tags[i] = htole32((tag->tpid << 16) | tag->tag);
862 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
864 req.vnic_id = htole32(vnic->id);
865 req.mask = htole32(mask);
866 req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
867 req.num_mc_entries = htole32(vnic->mc_list_count);
868 req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
869 req.num_vlan_tags = htole32(num_vlan_tags);
870 return hwrm_send_message(softc, &req, sizeof(req));
875 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
877 struct hwrm_cfa_l2_filter_alloc_input req = {0};
878 struct hwrm_cfa_l2_filter_alloc_output *resp;
879 uint32_t enables = 0;
882 if (vnic->filter_id != -1) {
883 device_printf(softc->dev,
884 "Attempt to re-allocate l2 ctx filter\n");
888 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
889 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
891 req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
892 enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
893 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
894 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
895 req.enables = htole32(enables);
896 req.dst_id = htole16(vnic->id);
897 memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
899 memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
901 BNXT_HWRM_LOCK(softc);
902 rc = _hwrm_send_message(softc, &req, sizeof(req));
906 vnic->filter_id = le64toh(resp->l2_filter_id);
907 vnic->flow_id = le64toh(resp->flow_id);
910 BNXT_HWRM_UNLOCK(softc);
915 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
918 struct hwrm_vnic_rss_cfg_input req = {0};
919 struct hwrm_vnic_rss_cfg_output *resp;
921 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
922 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
924 req.hash_type = htole32(hash_type);
925 req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
926 req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
927 req.rss_ctx_idx = htole16(vnic->rss_id);
929 return hwrm_send_message(softc, &req, sizeof(req));
933 bnxt_hwrm_func_cfg(struct bnxt_softc *softc)
935 struct hwrm_func_cfg_input req = {0};
937 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
940 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
942 req.async_event_cr = softc->def_cp_ring.ring.phys_id;
944 return hwrm_send_message(softc, &req, sizeof(req));
948 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
951 struct hwrm_vnic_tpa_cfg_input req = {0};
953 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
955 req.flags = htole32(flags);
956 req.vnic_id = htole16(vnic->id);
957 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
958 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
959 /* HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER | */
960 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
961 /* TODO: Calculate this based on ring size? */
962 req.max_agg_segs = htole16(3);
963 /* Base this in the allocated TPA start size... */
964 req.max_aggs = htole16(7);
966 * TODO: max_agg_timer?
967 * req.mag_agg_timer = htole32(XXX);
969 req.min_agg_len = htole32(0);
971 return hwrm_send_message(softc, &req, sizeof(req));
975 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
976 uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
977 uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
980 struct hwrm_nvm_find_dir_entry_input req = {0};
981 struct hwrm_nvm_find_dir_entry_output *resp =
982 (void *)softc->hwrm_cmd_resp.idi_vaddr;
988 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
990 req.enables = htole32(
991 HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
992 req.dir_idx = htole16(*index);
994 req.dir_type = htole16(type);
995 req.dir_ordinal = htole16(*ordinal);
996 req.dir_ext = htole16(ext);
997 req.opt_ordinal = search_opt;
999 BNXT_HWRM_LOCK(softc);
1000 old_timeo = softc->hwrm_cmd_timeo;
1001 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1002 rc = _hwrm_send_message(softc, &req, sizeof(req));
1003 softc->hwrm_cmd_timeo = old_timeo;
1008 *item_length = le32toh(resp->dir_item_length);
1010 *data_length = le32toh(resp->dir_data_length);
1012 *fw_ver = le32toh(resp->fw_ver);
1013 *ordinal = le16toh(resp->dir_ordinal);
1015 *index = le16toh(resp->dir_idx);
1018 BNXT_HWRM_UNLOCK(softc);
1023 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1024 uint32_t length, struct iflib_dma_info *data)
1026 struct hwrm_nvm_read_input req = {0};
1030 if (length > data->idi_size) {
1034 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1035 req.host_dest_addr = htole64(data->idi_paddr);
1036 req.dir_idx = htole16(index);
1037 req.offset = htole32(offset);
1038 req.len = htole32(length);
1039 BNXT_HWRM_LOCK(softc);
1040 old_timeo = softc->hwrm_cmd_timeo;
1041 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1042 rc = _hwrm_send_message(softc, &req, sizeof(req));
1043 softc->hwrm_cmd_timeo = old_timeo;
1044 BNXT_HWRM_UNLOCK(softc);
1047 bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1056 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1057 void *data, bool cpyin, uint32_t length)
1059 struct hwrm_nvm_modify_input req = {0};
1060 struct iflib_dma_info dma_data;
1064 if (length == 0 || !data)
1066 rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1071 rc = copyin(data, dma_data.idi_vaddr, length);
1076 memcpy(dma_data.idi_vaddr, data, length);
1077 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1078 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1080 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1081 req.host_src_addr = htole64(dma_data.idi_paddr);
1082 req.dir_idx = htole16(index);
1083 req.offset = htole32(offset);
1084 req.len = htole32(length);
1085 BNXT_HWRM_LOCK(softc);
1086 old_timeo = softc->hwrm_cmd_timeo;
1087 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1088 rc = _hwrm_send_message(softc, &req, sizeof(req));
1089 softc->hwrm_cmd_timeo = old_timeo;
1090 BNXT_HWRM_UNLOCK(softc);
1093 iflib_dma_free(&dma_data);
1098 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1101 struct hwrm_fw_reset_input req = {0};
1102 struct hwrm_fw_reset_output *resp =
1103 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1108 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1109 req.embedded_proc_type = processor;
1110 req.selfrst_status = *selfreset;
1112 BNXT_HWRM_LOCK(softc);
1113 rc = _hwrm_send_message(softc, &req, sizeof(req));
1116 *selfreset = resp->selfrst_status;
1119 BNXT_HWRM_UNLOCK(softc);
1124 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1126 struct hwrm_fw_qstatus_input req = {0};
1127 struct hwrm_fw_qstatus_output *resp =
1128 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1133 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1134 req.embedded_proc_type = type;
1136 BNXT_HWRM_LOCK(softc);
1137 rc = _hwrm_send_message(softc, &req, sizeof(req));
1140 *selfreset = resp->selfrst_status;
1143 BNXT_HWRM_UNLOCK(softc);
1148 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1149 uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1150 uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1153 struct hwrm_nvm_write_input req = {0};
1154 struct hwrm_nvm_write_output *resp =
1155 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1156 struct iflib_dma_info dma_data;
1161 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1166 rc = copyin(data, dma_data.idi_vaddr, data_length);
1171 memcpy(dma_data.idi_vaddr, data, data_length);
1172 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1173 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1176 dma_data.idi_paddr = 0;
1178 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1180 req.host_src_addr = htole64(dma_data.idi_paddr);
1181 req.dir_type = htole16(type);
1182 req.dir_ordinal = htole16(ordinal);
1183 req.dir_ext = htole16(ext);
1184 req.dir_attr = htole16(attr);
1185 req.dir_data_length = htole32(data_length);
1186 req.option = htole16(option);
1189 htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1192 req.dir_item_length = htole32(*item_length);
1194 BNXT_HWRM_LOCK(softc);
1195 old_timeo = softc->hwrm_cmd_timeo;
1196 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1197 rc = _hwrm_send_message(softc, &req, sizeof(req));
1198 softc->hwrm_cmd_timeo = old_timeo;
1202 *item_length = le32toh(resp->dir_item_length);
1204 *index = le16toh(resp->dir_idx);
1207 BNXT_HWRM_UNLOCK(softc);
1210 iflib_dma_free(&dma_data);
1215 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1217 struct hwrm_nvm_erase_dir_entry_input req = {0};
1221 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1222 req.dir_idx = htole16(index);
1223 BNXT_HWRM_LOCK(softc);
1224 old_timeo = softc->hwrm_cmd_timeo;
1225 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1226 rc = _hwrm_send_message(softc, &req, sizeof(req));
1227 softc->hwrm_cmd_timeo = old_timeo;
1228 BNXT_HWRM_UNLOCK(softc);
1233 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1234 uint32_t *entry_length)
1236 struct hwrm_nvm_get_dir_info_input req = {0};
1237 struct hwrm_nvm_get_dir_info_output *resp =
1238 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1242 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1244 BNXT_HWRM_LOCK(softc);
1245 old_timeo = softc->hwrm_cmd_timeo;
1246 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1247 rc = _hwrm_send_message(softc, &req, sizeof(req));
1248 softc->hwrm_cmd_timeo = old_timeo;
1253 *entries = le32toh(resp->entries);
1255 *entry_length = le32toh(resp->entry_length);
1258 BNXT_HWRM_UNLOCK(softc);
1263 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1264 uint32_t *entry_length, struct iflib_dma_info *dma_data)
1266 struct hwrm_nvm_get_dir_entries_input req = {0};
1275 entry_length = &ent_len;
1277 rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1280 if (*entries * *entry_length > dma_data->idi_size) {
1286 * TODO: There's a race condition here that could blow up DMA memory...
1287 * we need to allocate the max size, not the currently in use
1288 * size. The command should totally have a max size here.
1290 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1291 req.host_dest_addr = htole64(dma_data->idi_paddr);
1292 BNXT_HWRM_LOCK(softc);
1293 old_timeo = softc->hwrm_cmd_timeo;
1294 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1295 rc = _hwrm_send_message(softc, &req, sizeof(req));
1296 softc->hwrm_cmd_timeo = old_timeo;
1297 BNXT_HWRM_UNLOCK(softc);
1300 bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
1301 BUS_DMASYNC_POSTWRITE);
1308 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
1309 uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
1310 uint32_t *reserved_size, uint32_t *available_size)
1312 struct hwrm_nvm_get_dev_info_input req = {0};
1313 struct hwrm_nvm_get_dev_info_output *resp =
1314 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1318 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
1320 BNXT_HWRM_LOCK(softc);
1321 old_timeo = softc->hwrm_cmd_timeo;
1322 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1323 rc = _hwrm_send_message(softc, &req, sizeof(req));
1324 softc->hwrm_cmd_timeo = old_timeo;
1329 *mfg_id = le16toh(resp->manufacturer_id);
1331 *device_id = le16toh(resp->device_id);
1333 *sector_size = le32toh(resp->sector_size);
1335 *nvram_size = le32toh(resp->nvram_size);
1337 *reserved_size = le32toh(resp->reserved_size);
1339 *available_size = le32toh(resp->available_size);
1342 BNXT_HWRM_UNLOCK(softc);
1347 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
1348 uint32_t install_type, uint64_t *installed_items, uint8_t *result,
1349 uint8_t *problem_item, uint8_t *reset_required)
1351 struct hwrm_nvm_install_update_input req = {0};
1352 struct hwrm_nvm_install_update_output *resp =
1353 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1357 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
1358 req.install_type = htole32(install_type);
1360 BNXT_HWRM_LOCK(softc);
1361 old_timeo = softc->hwrm_cmd_timeo;
1362 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1363 rc = _hwrm_send_message(softc, &req, sizeof(req));
1364 softc->hwrm_cmd_timeo = old_timeo;
1368 if (installed_items)
1369 *installed_items = le32toh(resp->installed_items);
1371 *result = resp->result;
1373 *problem_item = resp->problem_item;
1375 *reset_required = resp->reset_required;
1378 BNXT_HWRM_UNLOCK(softc);
1383 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
1384 uint16_t ordinal, uint16_t ext)
1386 struct hwrm_nvm_verify_update_input req = {0};
1390 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
1392 req.dir_type = htole16(type);
1393 req.dir_ordinal = htole16(ordinal);
1394 req.dir_ext = htole16(ext);
1396 BNXT_HWRM_LOCK(softc);
1397 old_timeo = softc->hwrm_cmd_timeo;
1398 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1399 rc = _hwrm_send_message(softc, &req, sizeof(req));
1400 softc->hwrm_cmd_timeo = old_timeo;
1401 BNXT_HWRM_UNLOCK(softc);
1406 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
1407 uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
1408 uint16_t *millisecond, uint16_t *zone)
1410 struct hwrm_fw_get_time_input req = {0};
1411 struct hwrm_fw_get_time_output *resp =
1412 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1415 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
1417 BNXT_HWRM_LOCK(softc);
1418 rc = _hwrm_send_message(softc, &req, sizeof(req));
1423 *year = le16toh(resp->year);
1425 *month = resp->month;
1431 *minute = resp->minute;
1433 *second = resp->second;
1435 *millisecond = le16toh(resp->millisecond);
1437 *zone = le16toh(resp->zone);
1440 BNXT_HWRM_UNLOCK(softc);
1445 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
1446 uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
1447 uint16_t millisecond, uint16_t zone)
1449 struct hwrm_fw_set_time_input req = {0};
1451 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
1453 req.year = htole16(year);
1457 req.minute = minute;
1458 req.second = second;
1459 req.millisecond = htole16(millisecond);
1460 req.zone = htole16(zone);
1461 return hwrm_send_message(softc, &req, sizeof(req));
1465 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
1467 struct bnxt_link_info *link_info = &softc->link_info;
1468 struct hwrm_port_phy_qcfg_input req = {0};
1469 struct hwrm_port_phy_qcfg_output *resp =
1470 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1473 BNXT_HWRM_LOCK(softc);
1474 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
1476 rc = _hwrm_send_message(softc, &req, sizeof(req));
1480 link_info->phy_link_status = resp->link;
1481 link_info->duplex = resp->duplex;
1482 link_info->pause = resp->pause;
1483 link_info->auto_mode = resp->auto_mode;
1484 link_info->auto_pause = resp->auto_pause;
1485 link_info->force_pause = resp->force_pause;
1486 link_info->duplex_setting = resp->duplex;
1487 if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
1488 link_info->link_speed = le16toh(resp->link_speed);
1490 link_info->link_speed = 0;
1491 link_info->force_link_speed = le16toh(resp->force_link_speed);
1492 link_info->auto_link_speed = le16toh(resp->auto_link_speed);
1493 link_info->support_speeds = le16toh(resp->support_speeds);
1494 link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
1495 link_info->preemphasis = le32toh(resp->preemphasis);
1496 link_info->phy_ver[0] = resp->phy_maj;
1497 link_info->phy_ver[1] = resp->phy_min;
1498 link_info->phy_ver[2] = resp->phy_bld;
1499 snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
1500 "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
1501 link_info->phy_ver[2]);
1502 strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
1504 strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
1506 link_info->media_type = resp->media_type;
1507 link_info->phy_type = resp->phy_type;
1508 link_info->transceiver = resp->xcvr_pkg_type;
1509 link_info->phy_addr = resp->eee_config_phy_addr &
1510 HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
1513 BNXT_HWRM_UNLOCK(softc);
1518 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
1520 struct hwrm_wol_filter_qcfg_input req = {0};
1521 struct hwrm_wol_filter_qcfg_output *resp =
1522 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1523 uint16_t next_handle = 0;
1526 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
1527 req.port_id = htole16(softc->pf.port_id);
1528 req.handle = htole16(handle);
1529 rc = hwrm_send_message(softc, &req, sizeof(req));
1531 next_handle = le16toh(resp->next_handle);
1532 if (next_handle != 0) {
1533 if (resp->wol_type ==
1534 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
1536 softc->wol_filter_id = resp->wol_filter_id;
1544 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
1546 struct hwrm_wol_filter_alloc_input req = {0};
1547 struct hwrm_wol_filter_alloc_output *resp =
1548 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1551 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
1552 req.port_id = htole16(softc->pf.port_id);
1553 req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
1555 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
1556 memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
1557 rc = hwrm_send_message(softc, &req, sizeof(req));
1559 softc->wol_filter_id = resp->wol_filter_id;
1565 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
1567 struct hwrm_wol_filter_free_input req = {0};
1569 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
1570 req.port_id = htole16(softc->pf.port_id);
1572 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
1573 req.wol_filter_id = softc->wol_filter_id;
1574 return hwrm_send_message(softc, &req, sizeof(req));
1577 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
1578 uint32_t buf_tmrs, uint16_t flags,
1579 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
1581 req->flags = htole16(flags);
1582 req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
1583 req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
1584 req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
1585 req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
1586 /* Minimum time between 2 interrupts set to buf_tmr x 2 */
1587 req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
1588 req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
1589 req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
1593 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
1596 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
1598 uint16_t max_buf, max_buf_irq;
1599 uint16_t buf_tmr, buf_tmr_irq;
1602 bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
1603 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1604 bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
1605 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1607 /* Each rx completion (2 records) should be DMAed immediately.
1608 * DMA 1/4 of the completion buffers at a time.
1610 max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
1611 /* max_buf must not be zero */
1612 max_buf = clamp_t(uint16_t, max_buf, 1, 63);
1613 max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
1614 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
1615 /* buf timer set to 1/4 of interrupt timer */
1616 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1617 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
1618 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1620 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1622 /* RING_IDLE generates more IRQs for lower latency. Enable it only
1623 * if coal_usecs is less than 25 us.
1625 if (softc->rx_coal_usecs < 25)
1626 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
1628 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1629 buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
1631 /* max_buf must not be zero */
1632 max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
1633 max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
1634 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
1635 /* buf timer set to 1/4 of interrupt timer */
1636 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1637 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
1638 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1639 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1640 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1641 buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
1643 for (i = 0; i < softc->nrxqsets; i++) {
1649 * Check if Tx also needs to be done
1650 * So far, Tx processing has been done in softirq contest
1654 req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
1656 rc = hwrm_send_message(softc, req, sizeof(*req));
1665 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
1668 struct hwrm_func_drv_rgtr_input req = {0};
1669 bitstr_t *async_events_bmap;
1673 async_events_bmap = bit_alloc(256, M_DEVBUF, M_WAITOK|M_ZERO);
1674 events = (uint32_t *)async_events_bmap;
1676 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
1679 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1681 memset(async_events_bmap, 0, sizeof(256 / 8));
1683 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
1684 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
1685 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
1686 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
1687 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
1689 if (bmap && bmap_size) {
1690 for (i = 0; i < bmap_size; i++) {
1691 if (bit_test(bmap, i))
1692 bit_set(async_events_bmap, i);
1696 for (i = 0; i < 8; i++)
1697 req.async_event_fwd[i] |= htole32(events[i]);
1699 free(async_events_bmap, M_DEVBUF);
1701 return hwrm_send_message(softc, &req, sizeof(req));