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>
35 #include "bnxt_hwrm.h"
36 #include "hsi_struct_def.h"
38 static int bnxt_hwrm_err_map(uint16_t err);
39 static inline int _is_valid_ether_addr(uint8_t *);
40 static inline void get_random_ether_addr(uint8_t *);
41 static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
42 struct hwrm_port_phy_cfg_input *req);
43 static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
44 struct hwrm_port_phy_cfg_input *req);
45 static void bnxt_hwrm_set_eee(struct bnxt_softc *softc,
46 struct hwrm_port_phy_cfg_input *req);
47 static int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
48 static int hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
49 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
51 /* NVRam stuff has a five minute timeout */
52 #define BNXT_NVM_TIMEO (5 * 60 * 1000)
55 bnxt_hwrm_err_map(uint16_t err)
60 case HWRM_ERR_CODE_SUCCESS:
62 case HWRM_ERR_CODE_INVALID_PARAMS:
63 case HWRM_ERR_CODE_INVALID_FLAGS:
64 case HWRM_ERR_CODE_INVALID_ENABLES:
66 case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
68 case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
70 case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
72 case HWRM_ERR_CODE_FAIL:
74 case HWRM_ERR_CODE_HWRM_ERROR:
75 case HWRM_ERR_CODE_UNKNOWN_ERR:
84 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
88 rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
94 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
96 if (softc->hwrm_cmd_resp.idi_vaddr)
97 iflib_dma_free(&softc->hwrm_cmd_resp);
98 softc->hwrm_cmd_resp.idi_vaddr = NULL;
103 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
106 struct input *req = request;
108 req->req_type = htole16(req_type);
109 req->cmpl_ring = 0xffff;
110 req->target_id = 0xffff;
111 req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
115 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
117 struct input *req = msg;
118 struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
119 uint32_t *data = msg;
125 /* TODO: DMASYNC in here. */
126 req->seq_id = htole16(softc->hwrm_cmd_seq++);
127 memset(resp, 0, PAGE_SIZE);
128 cp_ring_id = le16toh(req->cmpl_ring);
130 /* Write request msg to hwrm channel */
131 for (i = 0; i < msg_len; i += 4) {
132 bus_space_write_4(softc->hwrm_bar.tag,
133 softc->hwrm_bar.handle,
138 /* Clear to the end of the request buffer */
139 for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
140 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
143 /* Ring channel doorbell */
144 bus_space_write_4(softc->hwrm_bar.tag,
145 softc->hwrm_bar.handle,
148 /* Check if response len is updated */
149 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
150 if (resp->resp_len && resp->resp_len <= 4096)
154 if (i >= softc->hwrm_cmd_timeo) {
155 device_printf(softc->dev,
156 "Timeout sending %s: (timeout: %u) seq: %d\n",
157 GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
158 le16toh(req->seq_id));
161 /* Last byte of resp contains the valid key */
162 valid = (uint8_t *)resp + resp->resp_len - 1;
163 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
164 if (*valid == HWRM_RESP_VALID_KEY)
168 if (i >= softc->hwrm_cmd_timeo) {
169 device_printf(softc->dev, "Timeout sending %s: "
170 "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
171 GET_HWRM_REQ_TYPE(req->req_type),
172 softc->hwrm_cmd_timeo, le16toh(req->req_type),
173 le16toh(req->seq_id), msg_len,
178 err = le16toh(resp->error_code);
180 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
181 if (err != HWRM_ERR_CODE_FAIL) {
182 device_printf(softc->dev,
183 "%s command returned %s error.\n",
184 GET_HWRM_REQ_TYPE(req->req_type),
185 GET_HWRM_ERROR_CODE(err));
187 return bnxt_hwrm_err_map(err);
194 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
198 BNXT_HWRM_LOCK(softc);
199 rc = _hwrm_send_message(softc, msg, msg_len);
200 BNXT_HWRM_UNLOCK(softc);
205 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
207 struct hwrm_queue_qportcfg_input req = {0};
208 struct hwrm_queue_qportcfg_output *resp =
209 (void *)softc->hwrm_cmd_resp.idi_vaddr;
214 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
216 BNXT_HWRM_LOCK(softc);
217 rc = _hwrm_send_message(softc, &req, sizeof(req));
221 if (!resp->max_configurable_queues) {
225 softc->max_tc = resp->max_configurable_queues;
226 if (softc->max_tc > BNXT_MAX_QUEUE)
227 softc->max_tc = BNXT_MAX_QUEUE;
229 qptr = &resp->queue_id0;
230 for (int i = 0; i < softc->max_tc; i++) {
231 softc->q_info[i].id = *qptr++;
232 softc->q_info[i].profile = *qptr++;
236 BNXT_HWRM_UNLOCK(softc);
242 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
244 struct hwrm_ver_get_input req = {0};
245 struct hwrm_ver_get_output *resp =
246 (void *)softc->hwrm_cmd_resp.idi_vaddr;
248 const char nastr[] = "<not installed>";
249 const char naver[] = "<N/A>";
251 softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
252 softc->hwrm_cmd_timeo = 1000;
253 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
255 req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
256 req.hwrm_intf_min = HWRM_VERSION_MINOR;
257 req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
259 BNXT_HWRM_LOCK(softc);
260 rc = _hwrm_send_message(softc, &req, sizeof(req));
264 snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
265 resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
266 softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
267 softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
268 softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
269 snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
270 resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
271 strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
273 strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
276 if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
277 resp->mgmt_fw_bld == 0) {
278 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
279 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
282 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
283 "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
285 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
288 if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
289 resp->netctrl_fw_bld == 0) {
290 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
292 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
296 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
297 "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
298 resp->netctrl_fw_bld);
299 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
302 if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
303 resp->roce_fw_bld == 0) {
304 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
305 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
308 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
309 "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
311 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
314 softc->ver_info->chip_num = le16toh(resp->chip_num);
315 softc->ver_info->chip_rev = resp->chip_rev;
316 softc->ver_info->chip_metal = resp->chip_metal;
317 softc->ver_info->chip_bond_id = resp->chip_bond_id;
318 softc->ver_info->chip_type = resp->chip_platform_type;
320 if (resp->max_req_win_len)
321 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
322 if (resp->def_req_timeout)
323 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
326 BNXT_HWRM_UNLOCK(softc);
331 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
333 struct hwrm_func_drv_rgtr_input req = {0};
335 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
337 req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
338 HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
339 req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
341 req.ver_maj = __FreeBSD_version / 100000;
342 req.ver_min = (__FreeBSD_version / 1000) % 100;
343 req.ver_upd = (__FreeBSD_version / 100) % 10;
345 return hwrm_send_message(softc, &req, sizeof(req));
350 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
352 struct hwrm_func_drv_unrgtr_input req = {0};
354 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
355 if (shutdown == true)
357 HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
358 return hwrm_send_message(softc, &req, sizeof(req));
363 _is_valid_ether_addr(uint8_t *addr)
365 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
367 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
374 get_random_ether_addr(uint8_t *addr)
376 uint8_t temp[ETHER_ADDR_LEN];
378 arc4rand(&temp, sizeof(temp), 0);
381 bcopy(temp, addr, sizeof(temp));
385 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
388 struct hwrm_func_qcaps_input req = {0};
389 struct hwrm_func_qcaps_output *resp =
390 (void *)softc->hwrm_cmd_resp.idi_vaddr;
391 struct bnxt_func_info *func = &softc->func;
393 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
394 req.fid = htole16(0xffff);
396 BNXT_HWRM_LOCK(softc);
397 rc = _hwrm_send_message(softc, &req, sizeof(req));
402 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
403 softc->flags |= BNXT_FLAG_WOL_CAP;
405 func->fw_fid = le16toh(resp->fid);
406 memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
407 func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
408 func->max_cp_rings = le16toh(resp->max_cmpl_rings);
409 func->max_tx_rings = le16toh(resp->max_tx_rings);
410 func->max_rx_rings = le16toh(resp->max_rx_rings);
411 func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
412 if (!func->max_hw_ring_grps)
413 func->max_hw_ring_grps = func->max_tx_rings;
414 func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
415 func->max_vnics = le16toh(resp->max_vnics);
416 func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
417 if (BNXT_PF(softc)) {
418 struct bnxt_pf_info *pf = &softc->pf;
420 pf->port_id = le16toh(resp->port_id);
421 pf->first_vf_id = le16toh(resp->first_vf_id);
422 pf->max_vfs = le16toh(resp->max_vfs);
423 pf->max_encap_records = le32toh(resp->max_encap_records);
424 pf->max_decap_records = le32toh(resp->max_decap_records);
425 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
426 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
427 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
428 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
430 if (!_is_valid_ether_addr(func->mac_addr)) {
431 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
432 get_random_ether_addr(func->mac_addr);
436 BNXT_HWRM_UNLOCK(softc);
441 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
443 struct hwrm_func_reset_input req = {0};
445 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
448 return hwrm_send_message(softc, &req, sizeof(req));
452 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
453 struct hwrm_port_phy_cfg_input *req)
455 uint8_t autoneg = softc->link_info.autoneg;
456 uint16_t fw_link_speed = softc->link_info.req_link_speed;
458 if (autoneg & BNXT_AUTONEG_SPEED) {
460 HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
463 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
465 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
467 req->force_link_speed = htole16(fw_link_speed);
468 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
471 /* tell chimp that the setting takes effect immediately */
472 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
477 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
478 struct hwrm_port_phy_cfg_input *req)
480 if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
482 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
483 if (softc->link_info.req_flow_ctrl &
484 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
486 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
487 if (softc->link_info.req_flow_ctrl &
488 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
490 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
492 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
494 if (softc->link_info.req_flow_ctrl &
495 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
497 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
498 if (softc->link_info.req_flow_ctrl &
499 HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
501 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
503 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
504 req->auto_pause = req->force_pause;
505 req->enables |= htole32(
506 HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
511 /* JFV this needs interface connection */
513 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
515 /* struct ethtool_eee *eee = &softc->eee; */
516 bool eee_enabled = false;
521 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
523 if (eee->tx_lpi_enabled)
524 flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
526 req->flags |= htole32(flags);
527 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
528 req->eee_link_speed_mask = htole16(eee_speeds);
529 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
533 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
539 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
542 struct hwrm_port_phy_cfg_input req = {0};
544 if (softc->flags & BNXT_FLAG_NPAR)
547 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
549 bnxt_hwrm_set_pause_common(softc, &req);
551 bnxt_hwrm_set_link_common(softc, &req);
553 bnxt_hwrm_set_eee(softc, &req);
554 return hwrm_send_message(softc, &req, sizeof(req));
559 bnxt_hwrm_set_pause(struct bnxt_softc *softc)
561 struct hwrm_port_phy_cfg_input req = {0};
564 if (softc->flags & BNXT_FLAG_NPAR)
567 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
568 bnxt_hwrm_set_pause_common(softc, &req);
570 if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)
571 bnxt_hwrm_set_link_common(softc, &req);
573 BNXT_HWRM_LOCK(softc);
574 rc = _hwrm_send_message(softc, &req, sizeof(req));
575 if (!rc && !(softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
576 /* since changing of pause setting doesn't trigger any link
577 * change event, the driver needs to update the current pause
578 * result upon successfully return of the phy_cfg command */
579 softc->link_info.pause =
580 softc->link_info.force_pause = softc->link_info.req_flow_ctrl;
581 softc->link_info.auto_pause = 0;
582 bnxt_report_link(softc);
584 BNXT_HWRM_UNLOCK(softc);
589 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
591 struct hwrm_vnic_cfg_input req = {0};
592 struct hwrm_vnic_cfg_output *resp;
594 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
595 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
597 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
598 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
599 if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
600 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
601 if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
602 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
603 req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
604 HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
605 HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
606 req.vnic_id = htole16(vnic->id);
607 req.dflt_ring_grp = htole16(vnic->def_ring_grp);
608 req.rss_rule = htole16(vnic->rss_id);
609 req.cos_rule = htole16(vnic->cos_rule);
610 req.lb_rule = htole16(vnic->lb_rule);
611 req.mru = htole16(vnic->mru);
613 return hwrm_send_message(softc, &req, sizeof(req));
617 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
619 struct hwrm_vnic_alloc_input req = {0};
620 struct hwrm_vnic_alloc_output *resp =
621 (void *)softc->hwrm_cmd_resp.idi_vaddr;
624 if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
625 device_printf(softc->dev,
626 "Attempt to re-allocate vnic %04x\n", vnic->id);
630 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
632 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
633 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
635 BNXT_HWRM_LOCK(softc);
636 rc = _hwrm_send_message(softc, &req, sizeof(req));
640 vnic->id = le32toh(resp->vnic_id);
643 BNXT_HWRM_UNLOCK(softc);
648 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
650 struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
651 struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
652 (void *)softc->hwrm_cmd_resp.idi_vaddr;
655 if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
656 device_printf(softc->dev,
657 "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
661 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
663 BNXT_HWRM_LOCK(softc);
664 rc = _hwrm_send_message(softc, &req, sizeof(req));
668 *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
671 BNXT_HWRM_UNLOCK(softc);
676 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
678 struct hwrm_ring_grp_alloc_input req = {0};
679 struct hwrm_ring_grp_alloc_output *resp;
682 if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
683 device_printf(softc->dev,
684 "Attempt to re-allocate ring group %04x\n", grp->grp_id);
688 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
689 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
690 req.cr = htole16(grp->cp_ring_id);
691 req.rr = htole16(grp->rx_ring_id);
692 req.ar = htole16(grp->ag_ring_id);
693 req.sc = htole16(grp->stats_ctx);
695 BNXT_HWRM_LOCK(softc);
696 rc = _hwrm_send_message(softc, &req, sizeof(req));
700 grp->grp_id = le32toh(resp->ring_group_id);
703 BNXT_HWRM_UNLOCK(softc);
708 * Ring allocation message to the firmware
711 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
712 struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
715 struct hwrm_ring_alloc_input req = {0};
716 struct hwrm_ring_alloc_output *resp;
719 if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
720 device_printf(softc->dev,
721 "Attempt to re-allocate ring %04x\n", ring->phys_id);
725 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
726 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
727 req.enables = htole32(0);
728 req.fbo = htole32(0);
730 if (stat_ctx_id != HWRM_NA_SIGNATURE) {
731 req.enables |= htole32(
732 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
733 req.stat_ctx_id = htole32(stat_ctx_id);
735 req.ring_type = type;
736 req.page_tbl_addr = htole64(ring->paddr);
737 req.length = htole32(ring->ring_size);
738 req.logical_id = htole16(ring->id);
739 req.cmpl_ring_id = htole16(cmpl_ring_id);
740 req.queue_id = htole16(softc->q_info[0].id);
742 /* MODE_POLL appears to crash the firmware */
744 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
746 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
748 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
750 BNXT_HWRM_LOCK(softc);
751 rc = _hwrm_send_message(softc, &req, sizeof(req));
755 ring->phys_id = le16toh(resp->ring_id);
758 BNXT_HWRM_UNLOCK(softc);
763 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
766 struct hwrm_stat_ctx_alloc_input req = {0};
767 struct hwrm_stat_ctx_alloc_output *resp;
770 if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
771 device_printf(softc->dev,
772 "Attempt to re-allocate stats ctx %08x\n",
777 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
778 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
780 req.update_period_ms = htole32(1000);
781 req.stats_dma_addr = htole64(paddr);
783 BNXT_HWRM_LOCK(softc);
784 rc = _hwrm_send_message(softc, &req, sizeof(req));
788 cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
791 BNXT_HWRM_UNLOCK(softc);
797 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
798 struct bnxt_vnic_info *vnic)
800 struct hwrm_cfa_l2_set_rx_mask_input req = {0};
801 struct bnxt_vlan_tag *tag;
803 uint32_t num_vlan_tags = 0;;
805 uint32_t mask = vnic->rx_mask;
808 SLIST_FOREACH(tag, &vnic->vlan_tags, next)
813 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
814 if (!vnic->vlan_only)
815 mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
818 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
820 if (vnic->vlan_tag_list.idi_vaddr) {
821 iflib_dma_free(&vnic->vlan_tag_list);
822 vnic->vlan_tag_list.idi_vaddr = NULL;
824 rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
825 &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
828 tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
831 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
832 tags[i] = htole32((tag->tpid << 16) | tag->tag);
836 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
838 req.vnic_id = htole32(vnic->id);
839 req.mask = htole32(mask);
840 req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
841 req.num_mc_entries = htole32(vnic->mc_list_count);
842 req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
843 req.num_vlan_tags = htole32(num_vlan_tags);
844 return hwrm_send_message(softc, &req, sizeof(req));
849 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
851 struct hwrm_cfa_l2_filter_alloc_input req = {0};
852 struct hwrm_cfa_l2_filter_alloc_output *resp;
853 uint32_t enables = 0;
856 if (vnic->filter_id != -1) {
857 device_printf(softc->dev,
858 "Attempt to re-allocate l2 ctx filter\n");
862 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
863 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
865 req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
866 enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
867 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
868 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
869 req.enables = htole32(enables);
870 req.dst_id = htole16(vnic->id);
871 memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
873 memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
875 BNXT_HWRM_LOCK(softc);
876 rc = _hwrm_send_message(softc, &req, sizeof(req));
880 vnic->filter_id = le64toh(resp->l2_filter_id);
881 vnic->flow_id = le64toh(resp->flow_id);
884 BNXT_HWRM_UNLOCK(softc);
889 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
892 struct hwrm_vnic_rss_cfg_input req = {0};
893 struct hwrm_vnic_rss_cfg_output *resp;
895 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
896 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
898 req.hash_type = htole32(hash_type);
899 req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
900 req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
901 req.rss_ctx_idx = htole16(vnic->rss_id);
903 return hwrm_send_message(softc, &req, sizeof(req));
907 bnxt_hwrm_func_cfg(struct bnxt_softc *softc)
909 struct hwrm_func_cfg_input req = {0};
911 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
914 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
916 req.async_event_cr = softc->def_cp_ring.ring.phys_id;
918 return hwrm_send_message(softc, &req, sizeof(req));
922 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
925 struct hwrm_vnic_tpa_cfg_input req = {0};
927 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
929 req.flags = htole32(flags);
930 req.vnic_id = htole16(vnic->id);
931 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
932 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
933 /* HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER | */
934 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
935 /* TODO: Calculate this based on ring size? */
936 req.max_agg_segs = htole16(3);
937 /* Base this in the allocated TPA start size... */
938 req.max_aggs = htole16(2);
940 * TODO: max_agg_timer?
941 * req.mag_agg_timer = htole32(XXX);
943 req.min_agg_len = htole32(0);
945 return hwrm_send_message(softc, &req, sizeof(req));
949 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
950 uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
951 uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
954 struct hwrm_nvm_find_dir_entry_input req = {0};
955 struct hwrm_nvm_find_dir_entry_output *resp =
956 (void *)softc->hwrm_cmd_resp.idi_vaddr;
962 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
964 req.enables = htole32(
965 HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
966 req.dir_idx = htole16(*index);
968 req.dir_type = htole16(type);
969 req.dir_ordinal = htole16(*ordinal);
970 req.dir_ext = htole16(ext);
971 req.opt_ordinal = search_opt;
973 BNXT_HWRM_LOCK(softc);
974 old_timeo = softc->hwrm_cmd_timeo;
975 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
976 rc = _hwrm_send_message(softc, &req, sizeof(req));
977 softc->hwrm_cmd_timeo = old_timeo;
982 *item_length = le32toh(resp->dir_item_length);
984 *data_length = le32toh(resp->dir_data_length);
986 *fw_ver = le32toh(resp->fw_ver);
987 *ordinal = le16toh(resp->dir_ordinal);
989 *index = le16toh(resp->dir_idx);
992 BNXT_HWRM_UNLOCK(softc);
997 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
998 uint32_t length, struct iflib_dma_info *data)
1000 struct hwrm_nvm_read_input req = {0};
1004 if (length > data->idi_size) {
1008 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1009 req.host_dest_addr = htole64(data->idi_paddr);
1010 req.dir_idx = htole16(index);
1011 req.offset = htole32(offset);
1012 req.len = htole32(length);
1013 BNXT_HWRM_LOCK(softc);
1014 old_timeo = softc->hwrm_cmd_timeo;
1015 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1016 rc = _hwrm_send_message(softc, &req, sizeof(req));
1017 softc->hwrm_cmd_timeo = old_timeo;
1018 BNXT_HWRM_UNLOCK(softc);
1021 bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1030 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1031 void *data, bool cpyin, uint32_t length)
1033 struct hwrm_nvm_modify_input req = {0};
1034 struct iflib_dma_info dma_data;
1038 if (length == 0 || !data)
1040 rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1045 rc = copyin(data, dma_data.idi_vaddr, length);
1050 memcpy(dma_data.idi_vaddr, data, length);
1051 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1052 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1054 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1055 req.host_src_addr = htole64(dma_data.idi_paddr);
1056 req.dir_idx = htole16(index);
1057 req.offset = htole32(offset);
1058 req.len = htole32(length);
1059 BNXT_HWRM_LOCK(softc);
1060 old_timeo = softc->hwrm_cmd_timeo;
1061 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1062 rc = _hwrm_send_message(softc, &req, sizeof(req));
1063 softc->hwrm_cmd_timeo = old_timeo;
1064 BNXT_HWRM_UNLOCK(softc);
1067 iflib_dma_free(&dma_data);
1072 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1075 struct hwrm_fw_reset_input req = {0};
1076 struct hwrm_fw_reset_output *resp =
1077 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1082 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1083 req.embedded_proc_type = processor;
1084 req.selfrst_status = *selfreset;
1086 BNXT_HWRM_LOCK(softc);
1087 rc = _hwrm_send_message(softc, &req, sizeof(req));
1090 *selfreset = resp->selfrst_status;
1093 BNXT_HWRM_UNLOCK(softc);
1098 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1100 struct hwrm_fw_qstatus_input req = {0};
1101 struct hwrm_fw_qstatus_output *resp =
1102 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1107 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1108 req.embedded_proc_type = type;
1110 BNXT_HWRM_LOCK(softc);
1111 rc = _hwrm_send_message(softc, &req, sizeof(req));
1114 *selfreset = resp->selfrst_status;
1117 BNXT_HWRM_UNLOCK(softc);
1122 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1123 uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1124 uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1127 struct hwrm_nvm_write_input req = {0};
1128 struct hwrm_nvm_write_output *resp =
1129 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1130 struct iflib_dma_info dma_data;
1135 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1140 rc = copyin(data, dma_data.idi_vaddr, data_length);
1145 memcpy(dma_data.idi_vaddr, data, data_length);
1146 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1147 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1150 dma_data.idi_paddr = 0;
1152 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1154 req.host_src_addr = htole64(dma_data.idi_paddr);
1155 req.dir_type = htole16(type);
1156 req.dir_ordinal = htole16(ordinal);
1157 req.dir_ext = htole16(ext);
1158 req.dir_attr = htole16(attr);
1159 req.dir_data_length = htole32(data_length);
1160 req.option = htole16(option);
1163 htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1166 req.dir_item_length = htole32(*item_length);
1168 BNXT_HWRM_LOCK(softc);
1169 old_timeo = softc->hwrm_cmd_timeo;
1170 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1171 rc = _hwrm_send_message(softc, &req, sizeof(req));
1172 softc->hwrm_cmd_timeo = old_timeo;
1176 *item_length = le32toh(resp->dir_item_length);
1178 *index = le16toh(resp->dir_idx);
1181 BNXT_HWRM_UNLOCK(softc);
1184 iflib_dma_free(&dma_data);
1189 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1191 struct hwrm_nvm_erase_dir_entry_input req = {0};
1195 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1196 req.dir_idx = htole16(index);
1197 BNXT_HWRM_LOCK(softc);
1198 old_timeo = softc->hwrm_cmd_timeo;
1199 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1200 rc = _hwrm_send_message(softc, &req, sizeof(req));
1201 softc->hwrm_cmd_timeo = old_timeo;
1202 BNXT_HWRM_UNLOCK(softc);
1207 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1208 uint32_t *entry_length)
1210 struct hwrm_nvm_get_dir_info_input req = {0};
1211 struct hwrm_nvm_get_dir_info_output *resp =
1212 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1216 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1218 BNXT_HWRM_LOCK(softc);
1219 old_timeo = softc->hwrm_cmd_timeo;
1220 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1221 rc = _hwrm_send_message(softc, &req, sizeof(req));
1222 softc->hwrm_cmd_timeo = old_timeo;
1227 *entries = le32toh(resp->entries);
1229 *entry_length = le32toh(resp->entry_length);
1232 BNXT_HWRM_UNLOCK(softc);
1237 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1238 uint32_t *entry_length, struct iflib_dma_info *dma_data)
1240 struct hwrm_nvm_get_dir_entries_input req = {0};
1249 entry_length = &ent_len;
1251 rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1254 if (*entries * *entry_length > dma_data->idi_size) {
1260 * TODO: There's a race condition here that could blow up DMA memory...
1261 * we need to allocate the max size, not the currently in use
1262 * size. The command should totally have a max size here.
1264 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1265 req.host_dest_addr = htole64(dma_data->idi_paddr);
1266 BNXT_HWRM_LOCK(softc);
1267 old_timeo = softc->hwrm_cmd_timeo;
1268 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1269 rc = _hwrm_send_message(softc, &req, sizeof(req));
1270 softc->hwrm_cmd_timeo = old_timeo;
1271 BNXT_HWRM_UNLOCK(softc);
1274 bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
1275 BUS_DMASYNC_POSTWRITE);
1282 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
1283 uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
1284 uint32_t *reserved_size, uint32_t *available_size)
1286 struct hwrm_nvm_get_dev_info_input req = {0};
1287 struct hwrm_nvm_get_dev_info_output *resp =
1288 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1292 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
1294 BNXT_HWRM_LOCK(softc);
1295 old_timeo = softc->hwrm_cmd_timeo;
1296 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1297 rc = _hwrm_send_message(softc, &req, sizeof(req));
1298 softc->hwrm_cmd_timeo = old_timeo;
1303 *mfg_id = le16toh(resp->manufacturer_id);
1305 *device_id = le16toh(resp->device_id);
1307 *sector_size = le32toh(resp->sector_size);
1309 *nvram_size = le32toh(resp->nvram_size);
1311 *reserved_size = le32toh(resp->reserved_size);
1313 *available_size = le32toh(resp->available_size);
1316 BNXT_HWRM_UNLOCK(softc);
1321 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
1322 uint32_t install_type, uint64_t *installed_items, uint8_t *result,
1323 uint8_t *problem_item, uint8_t *reset_required)
1325 struct hwrm_nvm_install_update_input req = {0};
1326 struct hwrm_nvm_install_update_output *resp =
1327 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1331 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
1332 req.install_type = htole32(install_type);
1334 BNXT_HWRM_LOCK(softc);
1335 old_timeo = softc->hwrm_cmd_timeo;
1336 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1337 rc = _hwrm_send_message(softc, &req, sizeof(req));
1338 softc->hwrm_cmd_timeo = old_timeo;
1342 if (installed_items)
1343 *installed_items = le32toh(resp->installed_items);
1345 *result = resp->result;
1347 *problem_item = resp->problem_item;
1349 *reset_required = resp->reset_required;
1352 BNXT_HWRM_UNLOCK(softc);
1357 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
1358 uint16_t ordinal, uint16_t ext)
1360 struct hwrm_nvm_verify_update_input req = {0};
1364 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
1366 req.dir_type = htole16(type);
1367 req.dir_ordinal = htole16(ordinal);
1368 req.dir_ext = htole16(ext);
1370 BNXT_HWRM_LOCK(softc);
1371 old_timeo = softc->hwrm_cmd_timeo;
1372 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1373 rc = _hwrm_send_message(softc, &req, sizeof(req));
1374 softc->hwrm_cmd_timeo = old_timeo;
1375 BNXT_HWRM_UNLOCK(softc);
1380 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
1381 uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
1382 uint16_t *millisecond, uint16_t *zone)
1384 struct hwrm_fw_get_time_input req = {0};
1385 struct hwrm_fw_get_time_output *resp =
1386 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1389 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
1391 BNXT_HWRM_LOCK(softc);
1392 rc = _hwrm_send_message(softc, &req, sizeof(req));
1397 *year = le16toh(resp->year);
1399 *month = resp->month;
1405 *minute = resp->minute;
1407 *second = resp->second;
1409 *millisecond = le16toh(resp->millisecond);
1411 *zone = le16toh(resp->zone);
1414 BNXT_HWRM_UNLOCK(softc);
1419 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
1420 uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
1421 uint16_t millisecond, uint16_t zone)
1423 struct hwrm_fw_set_time_input req = {0};
1425 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
1427 req.year = htole16(year);
1431 req.minute = minute;
1432 req.second = second;
1433 req.millisecond = htole16(millisecond);
1434 req.zone = htole16(zone);
1435 return hwrm_send_message(softc, &req, sizeof(req));
1439 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
1441 struct bnxt_link_info *link_info = &softc->link_info;
1442 struct hwrm_port_phy_qcfg_input req = {0};
1443 struct hwrm_port_phy_qcfg_output *resp =
1444 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1447 BNXT_HWRM_LOCK(softc);
1448 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
1450 rc = _hwrm_send_message(softc, &req, sizeof(req));
1454 link_info->phy_link_status = resp->link;
1455 link_info->duplex = resp->duplex;
1456 link_info->pause = resp->pause;
1457 link_info->auto_mode = resp->auto_mode;
1458 link_info->auto_pause = resp->auto_pause;
1459 link_info->force_pause = resp->force_pause;
1460 link_info->duplex_setting = resp->duplex;
1461 if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
1462 link_info->link_speed = le16toh(resp->link_speed);
1464 link_info->link_speed = 0;
1465 link_info->force_link_speed = le16toh(resp->force_link_speed);
1466 link_info->auto_link_speed = le16toh(resp->auto_link_speed);
1467 link_info->support_speeds = le16toh(resp->support_speeds);
1468 link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
1469 link_info->preemphasis = le32toh(resp->preemphasis);
1470 link_info->phy_ver[0] = resp->phy_maj;
1471 link_info->phy_ver[1] = resp->phy_min;
1472 link_info->phy_ver[2] = resp->phy_bld;
1473 snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
1474 "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
1475 link_info->phy_ver[2]);
1476 strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
1478 strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
1480 link_info->media_type = resp->media_type;
1481 link_info->phy_type = resp->phy_type;
1482 link_info->transceiver = resp->xcvr_pkg_type;
1483 link_info->phy_addr = resp->eee_config_phy_addr &
1484 HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
1487 BNXT_HWRM_UNLOCK(softc);
1492 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
1494 struct hwrm_wol_filter_qcfg_input req = {0};
1495 struct hwrm_wol_filter_qcfg_output *resp =
1496 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1497 uint16_t next_handle = 0;
1500 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
1501 req.port_id = htole16(softc->pf.port_id);
1502 req.handle = htole16(handle);
1503 rc = hwrm_send_message(softc, &req, sizeof(req));
1505 next_handle = le16toh(resp->next_handle);
1506 if (next_handle != 0) {
1507 if (resp->wol_type ==
1508 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
1510 softc->wol_filter_id = resp->wol_filter_id;
1518 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
1520 struct hwrm_wol_filter_alloc_input req = {0};
1521 struct hwrm_wol_filter_alloc_output *resp =
1522 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1525 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
1526 req.port_id = htole16(softc->pf.port_id);
1527 req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
1529 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
1530 memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
1531 rc = hwrm_send_message(softc, &req, sizeof(req));
1533 softc->wol_filter_id = resp->wol_filter_id;
1539 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
1541 struct hwrm_wol_filter_free_input req = {0};
1543 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
1544 req.port_id = htole16(softc->pf.port_id);
1546 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
1547 req.wol_filter_id = softc->wol_filter_id;
1548 return hwrm_send_message(softc, &req, sizeof(req));