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;
125 uint16_t max_req_len = HWRM_MAX_REQ_LEN;
126 struct hwrm_short_input short_input = {0};
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);
133 if (softc->flags & BNXT_FLAG_SHORT_CMD) {
134 void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
136 memcpy(short_cmd_req, req, msg_len);
137 memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len-
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);
147 data = (uint32_t *)&short_input;
148 msg_len = sizeof(short_input);
150 /* Sync memory write before updating doorbell */
153 max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
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,
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,
169 /* Ring channel doorbell */
170 bus_space_write_4(softc->hwrm_bar.tag,
171 softc->hwrm_bar.handle,
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)
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));
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)
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,
204 err = le16toh(resp->error_code);
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));
213 return bnxt_hwrm_err_map(err);
220 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
224 BNXT_HWRM_LOCK(softc);
225 rc = _hwrm_send_message(softc, msg, msg_len);
226 BNXT_HWRM_UNLOCK(softc);
231 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
233 struct hwrm_queue_qportcfg_input req = {0};
234 struct hwrm_queue_qportcfg_output *resp =
235 (void *)softc->hwrm_cmd_resp.idi_vaddr;
240 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
242 BNXT_HWRM_LOCK(softc);
243 rc = _hwrm_send_message(softc, &req, sizeof(req));
247 if (!resp->max_configurable_queues) {
251 softc->max_tc = resp->max_configurable_queues;
252 if (softc->max_tc > BNXT_MAX_QUEUE)
253 softc->max_tc = BNXT_MAX_QUEUE;
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++;
262 BNXT_HWRM_UNLOCK(softc);
267 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
269 struct hwrm_ver_get_input req = {0};
270 struct hwrm_ver_get_output *resp =
271 (void *)softc->hwrm_cmd_resp.idi_vaddr;
273 const char nastr[] = "<not installed>";
274 const char naver[] = "<N/A>";
275 uint32_t dev_caps_cfg;
277 softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
278 softc->hwrm_cmd_timeo = 1000;
279 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
281 req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
282 req.hwrm_intf_min = HWRM_VERSION_MINOR;
283 req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
285 BNXT_HWRM_LOCK(softc);
286 rc = _hwrm_send_message(softc, &req, sizeof(req));
290 snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
291 resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
292 softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
293 softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
294 softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
295 snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
296 resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
297 strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
299 strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
302 if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
303 resp->mgmt_fw_bld == 0) {
304 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
305 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
308 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
309 "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
311 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
314 if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
315 resp->netctrl_fw_bld == 0) {
316 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
318 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
322 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
323 "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
324 resp->netctrl_fw_bld);
325 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
328 if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
329 resp->roce_fw_bld == 0) {
330 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
331 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
334 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
335 "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
337 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
340 softc->ver_info->chip_num = le16toh(resp->chip_num);
341 softc->ver_info->chip_rev = resp->chip_rev;
342 softc->ver_info->chip_metal = resp->chip_metal;
343 softc->ver_info->chip_bond_id = resp->chip_bond_id;
344 softc->ver_info->chip_type = resp->chip_platform_type;
346 if (resp->max_req_win_len)
347 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
348 if (resp->def_req_timeout)
349 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
351 dev_caps_cfg = le32toh(resp->dev_caps_cfg);
352 if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
353 (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
354 softc->flags |= BNXT_FLAG_SHORT_CMD;
357 BNXT_HWRM_UNLOCK(softc);
362 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
364 struct hwrm_func_drv_rgtr_input req = {0};
366 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
368 req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
369 HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
370 req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
372 req.ver_maj = __FreeBSD_version / 100000;
373 req.ver_min = (__FreeBSD_version / 1000) % 100;
374 req.ver_upd = (__FreeBSD_version / 100) % 10;
376 return hwrm_send_message(softc, &req, sizeof(req));
380 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
382 struct hwrm_func_drv_unrgtr_input req = {0};
384 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
385 if (shutdown == true)
387 HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
388 return hwrm_send_message(softc, &req, sizeof(req));
392 _is_valid_ether_addr(uint8_t *addr)
394 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
396 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
403 get_random_ether_addr(uint8_t *addr)
405 uint8_t temp[ETHER_ADDR_LEN];
407 arc4rand(&temp, sizeof(temp), 0);
410 bcopy(temp, addr, sizeof(temp));
414 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
417 struct hwrm_func_qcaps_input req = {0};
418 struct hwrm_func_qcaps_output *resp =
419 (void *)softc->hwrm_cmd_resp.idi_vaddr;
420 struct bnxt_func_info *func = &softc->func;
422 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
423 req.fid = htole16(0xffff);
425 BNXT_HWRM_LOCK(softc);
426 rc = _hwrm_send_message(softc, &req, sizeof(req));
431 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
432 softc->flags |= BNXT_FLAG_WOL_CAP;
434 func->fw_fid = le16toh(resp->fid);
435 memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
436 func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
437 func->max_cp_rings = le16toh(resp->max_cmpl_rings);
438 func->max_tx_rings = le16toh(resp->max_tx_rings);
439 func->max_rx_rings = le16toh(resp->max_rx_rings);
440 func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
441 if (!func->max_hw_ring_grps)
442 func->max_hw_ring_grps = func->max_tx_rings;
443 func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
444 func->max_vnics = le16toh(resp->max_vnics);
445 func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
446 if (BNXT_PF(softc)) {
447 struct bnxt_pf_info *pf = &softc->pf;
449 pf->port_id = le16toh(resp->port_id);
450 pf->first_vf_id = le16toh(resp->first_vf_id);
451 pf->max_vfs = le16toh(resp->max_vfs);
452 pf->max_encap_records = le32toh(resp->max_encap_records);
453 pf->max_decap_records = le32toh(resp->max_decap_records);
454 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
455 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
456 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
457 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
459 if (!_is_valid_ether_addr(func->mac_addr)) {
460 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
461 get_random_ether_addr(func->mac_addr);
465 BNXT_HWRM_UNLOCK(softc);
470 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
472 struct hwrm_func_qcfg_input req = {0};
473 struct hwrm_func_qcfg_output *resp =
474 (void *)softc->hwrm_cmd_resp.idi_vaddr;
475 struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
478 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
479 req.fid = htole16(0xffff);
480 BNXT_HWRM_LOCK(softc);
481 rc = _hwrm_send_message(softc, &req, sizeof(req));
485 fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
486 fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
487 fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
488 fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
490 BNXT_HWRM_UNLOCK(softc);
495 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
497 struct hwrm_func_reset_input req = {0};
499 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
502 return hwrm_send_message(softc, &req, sizeof(req));
506 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
507 struct hwrm_port_phy_cfg_input *req)
509 uint8_t autoneg = softc->link_info.autoneg;
510 uint16_t fw_link_speed = softc->link_info.req_link_speed;
512 if (autoneg & BNXT_AUTONEG_SPEED) {
514 HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
517 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
519 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
521 req->force_link_speed = htole16(fw_link_speed);
522 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
525 /* tell chimp that the setting takes effect immediately */
526 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
530 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
531 struct hwrm_port_phy_cfg_input *req)
533 struct bnxt_link_info *link_info = &softc->link_info;
535 if (link_info->flow_ctrl.autoneg) {
537 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
538 if (link_info->flow_ctrl.rx)
540 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
541 if (link_info->flow_ctrl.tx)
543 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
545 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
547 if (link_info->flow_ctrl.rx)
549 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
550 if (link_info->flow_ctrl.tx)
552 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
554 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
558 /* JFV this needs interface connection */
560 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
562 /* struct ethtool_eee *eee = &softc->eee; */
563 bool eee_enabled = false;
568 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
570 if (eee->tx_lpi_enabled)
571 flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
573 req->flags |= htole32(flags);
574 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
575 req->eee_link_speed_mask = htole16(eee_speeds);
576 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
580 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
585 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
586 bool set_eee, bool set_link)
588 struct hwrm_port_phy_cfg_input req = {0};
591 if (softc->flags & BNXT_FLAG_NPAR)
594 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
597 bnxt_hwrm_set_pause_common(softc, &req);
599 if (softc->link_info.flow_ctrl.autoneg)
604 bnxt_hwrm_set_link_common(softc, &req);
607 bnxt_hwrm_set_eee(softc, &req);
609 BNXT_HWRM_LOCK(softc);
610 rc = _hwrm_send_message(softc, &req, sizeof(req));
614 /* since changing of 'force pause' setting doesn't
615 * trigger any link change event, the driver needs to
616 * update the current pause result upon successfully i
617 * return of the phy_cfg command */
618 if (!softc->link_info.flow_ctrl.autoneg)
619 bnxt_report_link(softc);
622 BNXT_HWRM_UNLOCK(softc);
627 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
629 struct hwrm_vnic_cfg_input req = {0};
631 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
633 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
634 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
635 if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
636 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
637 if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
638 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
639 req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
640 HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
641 HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
642 req.vnic_id = htole16(vnic->id);
643 req.dflt_ring_grp = htole16(vnic->def_ring_grp);
644 req.rss_rule = htole16(vnic->rss_id);
645 req.cos_rule = htole16(vnic->cos_rule);
646 req.lb_rule = htole16(vnic->lb_rule);
647 req.mru = htole16(vnic->mru);
649 return hwrm_send_message(softc, &req, sizeof(req));
653 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
655 struct hwrm_vnic_alloc_input req = {0};
656 struct hwrm_vnic_alloc_output *resp =
657 (void *)softc->hwrm_cmd_resp.idi_vaddr;
660 if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
661 device_printf(softc->dev,
662 "Attempt to re-allocate vnic %04x\n", vnic->id);
666 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
668 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
669 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
671 BNXT_HWRM_LOCK(softc);
672 rc = _hwrm_send_message(softc, &req, sizeof(req));
676 vnic->id = le32toh(resp->vnic_id);
679 BNXT_HWRM_UNLOCK(softc);
684 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
686 struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
687 struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
688 (void *)softc->hwrm_cmd_resp.idi_vaddr;
691 if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
692 device_printf(softc->dev,
693 "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
697 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
699 BNXT_HWRM_LOCK(softc);
700 rc = _hwrm_send_message(softc, &req, sizeof(req));
704 *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
707 BNXT_HWRM_UNLOCK(softc);
712 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
714 struct hwrm_ring_grp_alloc_input req = {0};
715 struct hwrm_ring_grp_alloc_output *resp;
718 if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
719 device_printf(softc->dev,
720 "Attempt to re-allocate ring group %04x\n", grp->grp_id);
724 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
725 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
726 req.cr = htole16(grp->cp_ring_id);
727 req.rr = htole16(grp->rx_ring_id);
728 req.ar = htole16(grp->ag_ring_id);
729 req.sc = htole16(grp->stats_ctx);
731 BNXT_HWRM_LOCK(softc);
732 rc = _hwrm_send_message(softc, &req, sizeof(req));
736 grp->grp_id = le32toh(resp->ring_group_id);
739 BNXT_HWRM_UNLOCK(softc);
744 * Ring allocation message to the firmware
747 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
748 struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
751 struct hwrm_ring_alloc_input req = {0};
752 struct hwrm_ring_alloc_output *resp;
755 if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
756 device_printf(softc->dev,
757 "Attempt to re-allocate ring %04x\n", ring->phys_id);
761 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
762 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
763 req.enables = htole32(0);
764 req.fbo = htole32(0);
766 if (stat_ctx_id != HWRM_NA_SIGNATURE) {
767 req.enables |= htole32(
768 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
769 req.stat_ctx_id = htole32(stat_ctx_id);
771 req.ring_type = type;
772 req.page_tbl_addr = htole64(ring->paddr);
773 req.length = htole32(ring->ring_size);
774 req.logical_id = htole16(ring->id);
775 req.cmpl_ring_id = htole16(cmpl_ring_id);
776 req.queue_id = htole16(softc->q_info[0].id);
778 /* MODE_POLL appears to crash the firmware */
780 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
782 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
784 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
786 BNXT_HWRM_LOCK(softc);
787 rc = _hwrm_send_message(softc, &req, sizeof(req));
791 ring->phys_id = le16toh(resp->ring_id);
794 BNXT_HWRM_UNLOCK(softc);
799 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
802 struct hwrm_stat_ctx_alloc_input req = {0};
803 struct hwrm_stat_ctx_alloc_output *resp;
806 if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
807 device_printf(softc->dev,
808 "Attempt to re-allocate stats ctx %08x\n",
813 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
814 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
816 req.update_period_ms = htole32(1000);
817 req.stats_dma_addr = htole64(paddr);
819 BNXT_HWRM_LOCK(softc);
820 rc = _hwrm_send_message(softc, &req, sizeof(req));
824 cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
827 BNXT_HWRM_UNLOCK(softc);
833 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
835 struct hwrm_port_qstats_input req = {0};
838 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
840 req.port_id = htole16(softc->pf.port_id);
841 req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
842 req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
844 BNXT_HWRM_LOCK(softc);
845 rc = _hwrm_send_message(softc, &req, sizeof(req));
846 BNXT_HWRM_UNLOCK(softc);
852 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
853 struct bnxt_vnic_info *vnic)
855 struct hwrm_cfa_l2_set_rx_mask_input req = {0};
856 struct bnxt_vlan_tag *tag;
858 uint32_t num_vlan_tags = 0;
860 uint32_t mask = vnic->rx_mask;
863 SLIST_FOREACH(tag, &vnic->vlan_tags, next)
868 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
869 if (!vnic->vlan_only)
870 mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
873 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
875 if (vnic->vlan_tag_list.idi_vaddr) {
876 iflib_dma_free(&vnic->vlan_tag_list);
877 vnic->vlan_tag_list.idi_vaddr = NULL;
879 rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
880 &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
883 tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
886 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
887 tags[i] = htole32((tag->tpid << 16) | tag->tag);
891 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
893 req.vnic_id = htole32(vnic->id);
894 req.mask = htole32(mask);
895 req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
896 req.num_mc_entries = htole32(vnic->mc_list_count);
897 req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
898 req.num_vlan_tags = htole32(num_vlan_tags);
899 return hwrm_send_message(softc, &req, sizeof(req));
903 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
905 struct hwrm_cfa_l2_filter_alloc_input req = {0};
906 struct hwrm_cfa_l2_filter_alloc_output *resp;
907 uint32_t enables = 0;
910 if (vnic->filter_id != -1) {
911 device_printf(softc->dev,
912 "Attempt to re-allocate l2 ctx filter\n");
916 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
917 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
919 req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
920 enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
921 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
922 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
923 req.enables = htole32(enables);
924 req.dst_id = htole16(vnic->id);
925 memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
927 memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
929 BNXT_HWRM_LOCK(softc);
930 rc = _hwrm_send_message(softc, &req, sizeof(req));
934 vnic->filter_id = le64toh(resp->l2_filter_id);
935 vnic->flow_id = le64toh(resp->flow_id);
938 BNXT_HWRM_UNLOCK(softc);
943 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
946 struct hwrm_vnic_rss_cfg_input req = {0};
948 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
950 req.hash_type = htole32(hash_type);
951 req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
952 req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
953 req.rss_ctx_idx = htole16(vnic->rss_id);
955 return hwrm_send_message(softc, &req, sizeof(req));
959 bnxt_cfg_async_cr(struct bnxt_softc *softc)
963 if (BNXT_PF(softc)) {
964 struct hwrm_func_cfg_input req = {0};
966 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
968 req.fid = htole16(0xffff);
969 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
970 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
972 rc = hwrm_send_message(softc, &req, sizeof(req));
975 struct hwrm_func_vf_cfg_input req = {0};
977 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
979 req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
980 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
982 rc = hwrm_send_message(softc, &req, sizeof(req));
988 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
990 softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
992 softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
994 softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
995 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
997 softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
998 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
1000 softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
1004 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
1006 struct hwrm_vnic_tpa_cfg_input req = {0};
1009 if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
1013 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
1015 if (softc->hw_lro.enable) {
1016 flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
1017 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
1018 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
1019 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
1021 if (softc->hw_lro.is_mode_gro)
1022 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
1024 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
1026 req.flags = htole32(flags);
1028 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
1029 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
1030 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
1032 req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
1033 req.max_aggs = htole16(softc->hw_lro.max_aggs);
1034 req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
1037 req.vnic_id = htole16(softc->vnic_info.id);
1039 return hwrm_send_message(softc, &req, sizeof(req));
1043 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
1044 uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
1045 uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
1048 struct hwrm_nvm_find_dir_entry_input req = {0};
1049 struct hwrm_nvm_find_dir_entry_output *resp =
1050 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1056 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
1058 req.enables = htole32(
1059 HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
1060 req.dir_idx = htole16(*index);
1062 req.dir_type = htole16(type);
1063 req.dir_ordinal = htole16(*ordinal);
1064 req.dir_ext = htole16(ext);
1065 req.opt_ordinal = search_opt;
1067 BNXT_HWRM_LOCK(softc);
1068 old_timeo = softc->hwrm_cmd_timeo;
1069 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1070 rc = _hwrm_send_message(softc, &req, sizeof(req));
1071 softc->hwrm_cmd_timeo = old_timeo;
1076 *item_length = le32toh(resp->dir_item_length);
1078 *data_length = le32toh(resp->dir_data_length);
1080 *fw_ver = le32toh(resp->fw_ver);
1081 *ordinal = le16toh(resp->dir_ordinal);
1083 *index = le16toh(resp->dir_idx);
1086 BNXT_HWRM_UNLOCK(softc);
1091 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1092 uint32_t length, struct iflib_dma_info *data)
1094 struct hwrm_nvm_read_input req = {0};
1098 if (length > data->idi_size) {
1102 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1103 req.host_dest_addr = htole64(data->idi_paddr);
1104 req.dir_idx = htole16(index);
1105 req.offset = htole32(offset);
1106 req.len = htole32(length);
1107 BNXT_HWRM_LOCK(softc);
1108 old_timeo = softc->hwrm_cmd_timeo;
1109 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1110 rc = _hwrm_send_message(softc, &req, sizeof(req));
1111 softc->hwrm_cmd_timeo = old_timeo;
1112 BNXT_HWRM_UNLOCK(softc);
1115 bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1124 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1125 void *data, bool cpyin, uint32_t length)
1127 struct hwrm_nvm_modify_input req = {0};
1128 struct iflib_dma_info dma_data;
1132 if (length == 0 || !data)
1134 rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1139 rc = copyin(data, dma_data.idi_vaddr, length);
1144 memcpy(dma_data.idi_vaddr, data, length);
1145 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1146 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1148 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1149 req.host_src_addr = htole64(dma_data.idi_paddr);
1150 req.dir_idx = htole16(index);
1151 req.offset = htole32(offset);
1152 req.len = htole32(length);
1153 BNXT_HWRM_LOCK(softc);
1154 old_timeo = softc->hwrm_cmd_timeo;
1155 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1156 rc = _hwrm_send_message(softc, &req, sizeof(req));
1157 softc->hwrm_cmd_timeo = old_timeo;
1158 BNXT_HWRM_UNLOCK(softc);
1161 iflib_dma_free(&dma_data);
1166 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1169 struct hwrm_fw_reset_input req = {0};
1170 struct hwrm_fw_reset_output *resp =
1171 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1176 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1177 req.embedded_proc_type = processor;
1178 req.selfrst_status = *selfreset;
1180 BNXT_HWRM_LOCK(softc);
1181 rc = _hwrm_send_message(softc, &req, sizeof(req));
1184 *selfreset = resp->selfrst_status;
1187 BNXT_HWRM_UNLOCK(softc);
1192 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1194 struct hwrm_fw_qstatus_input req = {0};
1195 struct hwrm_fw_qstatus_output *resp =
1196 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1201 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1202 req.embedded_proc_type = type;
1204 BNXT_HWRM_LOCK(softc);
1205 rc = _hwrm_send_message(softc, &req, sizeof(req));
1208 *selfreset = resp->selfrst_status;
1211 BNXT_HWRM_UNLOCK(softc);
1216 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1217 uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1218 uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1221 struct hwrm_nvm_write_input req = {0};
1222 struct hwrm_nvm_write_output *resp =
1223 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1224 struct iflib_dma_info dma_data;
1229 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1234 rc = copyin(data, dma_data.idi_vaddr, data_length);
1239 memcpy(dma_data.idi_vaddr, data, data_length);
1240 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1241 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1244 dma_data.idi_paddr = 0;
1246 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1248 req.host_src_addr = htole64(dma_data.idi_paddr);
1249 req.dir_type = htole16(type);
1250 req.dir_ordinal = htole16(ordinal);
1251 req.dir_ext = htole16(ext);
1252 req.dir_attr = htole16(attr);
1253 req.dir_data_length = htole32(data_length);
1254 req.option = htole16(option);
1257 htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1260 req.dir_item_length = htole32(*item_length);
1262 BNXT_HWRM_LOCK(softc);
1263 old_timeo = softc->hwrm_cmd_timeo;
1264 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1265 rc = _hwrm_send_message(softc, &req, sizeof(req));
1266 softc->hwrm_cmd_timeo = old_timeo;
1270 *item_length = le32toh(resp->dir_item_length);
1272 *index = le16toh(resp->dir_idx);
1275 BNXT_HWRM_UNLOCK(softc);
1278 iflib_dma_free(&dma_data);
1283 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1285 struct hwrm_nvm_erase_dir_entry_input req = {0};
1289 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1290 req.dir_idx = htole16(index);
1291 BNXT_HWRM_LOCK(softc);
1292 old_timeo = softc->hwrm_cmd_timeo;
1293 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1294 rc = _hwrm_send_message(softc, &req, sizeof(req));
1295 softc->hwrm_cmd_timeo = old_timeo;
1296 BNXT_HWRM_UNLOCK(softc);
1301 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1302 uint32_t *entry_length)
1304 struct hwrm_nvm_get_dir_info_input req = {0};
1305 struct hwrm_nvm_get_dir_info_output *resp =
1306 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1310 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1312 BNXT_HWRM_LOCK(softc);
1313 old_timeo = softc->hwrm_cmd_timeo;
1314 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1315 rc = _hwrm_send_message(softc, &req, sizeof(req));
1316 softc->hwrm_cmd_timeo = old_timeo;
1321 *entries = le32toh(resp->entries);
1323 *entry_length = le32toh(resp->entry_length);
1326 BNXT_HWRM_UNLOCK(softc);
1331 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1332 uint32_t *entry_length, struct iflib_dma_info *dma_data)
1334 struct hwrm_nvm_get_dir_entries_input req = {0};
1343 entry_length = &ent_len;
1345 rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1348 if (*entries * *entry_length > dma_data->idi_size) {
1354 * TODO: There's a race condition here that could blow up DMA memory...
1355 * we need to allocate the max size, not the currently in use
1356 * size. The command should totally have a max size here.
1358 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1359 req.host_dest_addr = htole64(dma_data->idi_paddr);
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;
1365 BNXT_HWRM_UNLOCK(softc);
1368 bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
1369 BUS_DMASYNC_POSTWRITE);
1376 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
1377 uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
1378 uint32_t *reserved_size, uint32_t *available_size)
1380 struct hwrm_nvm_get_dev_info_input req = {0};
1381 struct hwrm_nvm_get_dev_info_output *resp =
1382 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1386 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
1388 BNXT_HWRM_LOCK(softc);
1389 old_timeo = softc->hwrm_cmd_timeo;
1390 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1391 rc = _hwrm_send_message(softc, &req, sizeof(req));
1392 softc->hwrm_cmd_timeo = old_timeo;
1397 *mfg_id = le16toh(resp->manufacturer_id);
1399 *device_id = le16toh(resp->device_id);
1401 *sector_size = le32toh(resp->sector_size);
1403 *nvram_size = le32toh(resp->nvram_size);
1405 *reserved_size = le32toh(resp->reserved_size);
1407 *available_size = le32toh(resp->available_size);
1410 BNXT_HWRM_UNLOCK(softc);
1415 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
1416 uint32_t install_type, uint64_t *installed_items, uint8_t *result,
1417 uint8_t *problem_item, uint8_t *reset_required)
1419 struct hwrm_nvm_install_update_input req = {0};
1420 struct hwrm_nvm_install_update_output *resp =
1421 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1425 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
1426 req.install_type = htole32(install_type);
1428 BNXT_HWRM_LOCK(softc);
1429 old_timeo = softc->hwrm_cmd_timeo;
1430 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1431 rc = _hwrm_send_message(softc, &req, sizeof(req));
1432 softc->hwrm_cmd_timeo = old_timeo;
1436 if (installed_items)
1437 *installed_items = le32toh(resp->installed_items);
1439 *result = resp->result;
1441 *problem_item = resp->problem_item;
1443 *reset_required = resp->reset_required;
1446 BNXT_HWRM_UNLOCK(softc);
1451 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
1452 uint16_t ordinal, uint16_t ext)
1454 struct hwrm_nvm_verify_update_input req = {0};
1458 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
1460 req.dir_type = htole16(type);
1461 req.dir_ordinal = htole16(ordinal);
1462 req.dir_ext = htole16(ext);
1464 BNXT_HWRM_LOCK(softc);
1465 old_timeo = softc->hwrm_cmd_timeo;
1466 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1467 rc = _hwrm_send_message(softc, &req, sizeof(req));
1468 softc->hwrm_cmd_timeo = old_timeo;
1469 BNXT_HWRM_UNLOCK(softc);
1474 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
1475 uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
1476 uint16_t *millisecond, uint16_t *zone)
1478 struct hwrm_fw_get_time_input req = {0};
1479 struct hwrm_fw_get_time_output *resp =
1480 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1483 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
1485 BNXT_HWRM_LOCK(softc);
1486 rc = _hwrm_send_message(softc, &req, sizeof(req));
1491 *year = le16toh(resp->year);
1493 *month = resp->month;
1499 *minute = resp->minute;
1501 *second = resp->second;
1503 *millisecond = le16toh(resp->millisecond);
1505 *zone = le16toh(resp->zone);
1508 BNXT_HWRM_UNLOCK(softc);
1513 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
1514 uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
1515 uint16_t millisecond, uint16_t zone)
1517 struct hwrm_fw_set_time_input req = {0};
1519 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
1521 req.year = htole16(year);
1525 req.minute = minute;
1526 req.second = second;
1527 req.millisecond = htole16(millisecond);
1528 req.zone = htole16(zone);
1529 return hwrm_send_message(softc, &req, sizeof(req));
1533 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
1535 struct bnxt_link_info *link_info = &softc->link_info;
1536 struct hwrm_port_phy_qcfg_input req = {0};
1537 struct hwrm_port_phy_qcfg_output *resp =
1538 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1541 BNXT_HWRM_LOCK(softc);
1542 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
1544 rc = _hwrm_send_message(softc, &req, sizeof(req));
1548 link_info->phy_link_status = resp->link;
1549 link_info->duplex = resp->duplex_cfg;
1550 link_info->auto_mode = resp->auto_mode;
1553 * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
1554 * the advertisement of pause is enabled.
1555 * 1. When the auto_mode is not set to none and this flag is set to 1,
1556 * then the auto_pause bits on this port are being advertised and
1557 * autoneg pause results are being interpreted.
1558 * 2. When the auto_mode is not set to none and this flag is set to 0,
1559 * the pause is forced as indicated in force_pause, and also
1560 * advertised as auto_pause bits, but the autoneg results are not
1561 * interpreted since the pause configuration is being forced.
1562 * 3. When the auto_mode is set to none and this flag is set to 1,
1563 * auto_pause bits should be ignored and should be set to 0.
1566 link_info->flow_ctrl.autoneg = false;
1567 link_info->flow_ctrl.tx = false;
1568 link_info->flow_ctrl.rx = false;
1570 if ((resp->auto_mode) &&
1571 (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
1572 link_info->flow_ctrl.autoneg = true;
1575 if (link_info->flow_ctrl.autoneg) {
1576 if (resp->auto_pause & BNXT_PAUSE_TX)
1577 link_info->flow_ctrl.tx = true;
1578 if (resp->auto_pause & BNXT_PAUSE_RX)
1579 link_info->flow_ctrl.rx = true;
1581 if (resp->force_pause & BNXT_PAUSE_TX)
1582 link_info->flow_ctrl.tx = true;
1583 if (resp->force_pause & BNXT_PAUSE_RX)
1584 link_info->flow_ctrl.rx = true;
1587 link_info->duplex_setting = resp->duplex_cfg;
1588 if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
1589 link_info->link_speed = le16toh(resp->link_speed);
1591 link_info->link_speed = 0;
1592 link_info->force_link_speed = le16toh(resp->force_link_speed);
1593 link_info->auto_link_speed = le16toh(resp->auto_link_speed);
1594 link_info->support_speeds = le16toh(resp->support_speeds);
1595 link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
1596 link_info->preemphasis = le32toh(resp->preemphasis);
1597 link_info->phy_ver[0] = resp->phy_maj;
1598 link_info->phy_ver[1] = resp->phy_min;
1599 link_info->phy_ver[2] = resp->phy_bld;
1600 snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
1601 "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
1602 link_info->phy_ver[2]);
1603 strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
1605 strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
1607 link_info->media_type = resp->media_type;
1608 link_info->phy_type = resp->phy_type;
1609 link_info->transceiver = resp->xcvr_pkg_type;
1610 link_info->phy_addr = resp->eee_config_phy_addr &
1611 HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
1614 BNXT_HWRM_UNLOCK(softc);
1619 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
1621 struct hwrm_wol_filter_qcfg_input req = {0};
1622 struct hwrm_wol_filter_qcfg_output *resp =
1623 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1624 uint16_t next_handle = 0;
1627 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
1628 req.port_id = htole16(softc->pf.port_id);
1629 req.handle = htole16(handle);
1630 rc = hwrm_send_message(softc, &req, sizeof(req));
1632 next_handle = le16toh(resp->next_handle);
1633 if (next_handle != 0) {
1634 if (resp->wol_type ==
1635 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
1637 softc->wol_filter_id = resp->wol_filter_id;
1645 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
1647 struct hwrm_wol_filter_alloc_input req = {0};
1648 struct hwrm_wol_filter_alloc_output *resp =
1649 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1652 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
1653 req.port_id = htole16(softc->pf.port_id);
1654 req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
1656 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
1657 memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
1658 rc = hwrm_send_message(softc, &req, sizeof(req));
1660 softc->wol_filter_id = resp->wol_filter_id;
1666 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
1668 struct hwrm_wol_filter_free_input req = {0};
1670 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
1671 req.port_id = htole16(softc->pf.port_id);
1673 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
1674 req.wol_filter_id = softc->wol_filter_id;
1675 return hwrm_send_message(softc, &req, sizeof(req));
1678 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
1679 uint32_t buf_tmrs, uint16_t flags,
1680 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
1682 req->flags = htole16(flags);
1683 req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
1684 req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
1685 req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
1686 req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
1687 /* Minimum time between 2 interrupts set to buf_tmr x 2 */
1688 req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
1689 req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
1690 req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
1693 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
1696 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
1698 uint16_t max_buf, max_buf_irq;
1699 uint16_t buf_tmr, buf_tmr_irq;
1702 bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
1703 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1704 bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
1705 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1707 /* Each rx completion (2 records) should be DMAed immediately.
1708 * DMA 1/4 of the completion buffers at a time.
1710 max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
1711 /* max_buf must not be zero */
1712 max_buf = clamp_t(uint16_t, max_buf, 1, 63);
1713 max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
1714 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
1715 /* buf timer set to 1/4 of interrupt timer */
1716 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1717 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
1718 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1720 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1722 /* RING_IDLE generates more IRQs for lower latency. Enable it only
1723 * if coal_usecs is less than 25 us.
1725 if (softc->rx_coal_usecs < 25)
1726 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
1728 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1729 buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
1731 /* max_buf must not be zero */
1732 max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
1733 max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
1734 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
1735 /* buf timer set to 1/4 of interrupt timer */
1736 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1737 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
1738 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1739 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1740 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1741 buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
1743 for (i = 0; i < softc->nrxqsets; i++) {
1748 * Check if Tx also needs to be done
1749 * So far, Tx processing has been done in softirq contest
1753 req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
1755 rc = hwrm_send_message(softc, req, sizeof(*req));
1762 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
1765 struct hwrm_func_drv_rgtr_input req = {0};
1766 bitstr_t *async_events_bmap;
1770 #define AE_BMAP_SZ_BITS 256
1771 async_events_bmap = bit_alloc(AE_BMAP_SZ_BITS, M_DEVBUF, M_WAITOK);
1773 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
1776 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1778 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
1779 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
1780 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
1781 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
1782 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
1784 if (bmap && bmap_size) {
1785 for (i = 0; i < bmap_size; i++) {
1786 if (bit_test(bmap, i))
1787 bit_set(async_events_bmap, i);
1791 #define AE_BMAP_SZ_WORDS (AE_BMAP_SZ_BITS / 8 / sizeof(uint32_t))
1792 events = (uint32_t *)async_events_bmap;
1793 for (i = 0; i < AE_BMAP_SZ_WORDS; i++)
1794 req.async_event_fwd[i] |= htole32(events[i]);
1795 #undef AE_BMAP_SZ_WORDS
1796 #undef AE_BMAP_SZ_BITS
1798 free(async_events_bmap, M_DEVBUF);
1800 return hwrm_send_message(softc, &req, sizeof(req));