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;
123 uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
124 struct hwrm_short_input short_input = {0};
126 /* TODO: DMASYNC in here. */
127 req->seq_id = htole16(softc->hwrm_cmd_seq++);
128 memset(resp, 0, PAGE_SIZE);
130 if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
131 msg_len > BNXT_HWRM_MAX_REQ_LEN) {
132 void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
133 uint16_t max_msg_len;
135 /* Set boundary for maximum extended request length for short
136 * cmd format. If passed up from device use the max supported
137 * internal req length.
140 max_msg_len = softc->hwrm_max_ext_req_len;
143 memcpy(short_cmd_req, req, msg_len);
144 if (msg_len < max_msg_len)
145 memset((uint8_t *) short_cmd_req + msg_len, 0,
146 max_msg_len - msg_len);
148 short_input.req_type = req->req_type;
149 short_input.signature =
150 htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
151 short_input.size = htole16(msg_len);
152 short_input.req_addr =
153 htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
155 data = (uint32_t *)&short_input;
156 msg_len = sizeof(short_input);
158 /* Sync memory write before updating doorbell */
161 max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
164 /* Write request msg to hwrm channel */
165 for (i = 0; i < msg_len; i += 4) {
166 bus_space_write_4(softc->hwrm_bar.tag,
167 softc->hwrm_bar.handle,
172 /* Clear to the end of the request buffer */
173 for (i = msg_len; i < max_req_len; i += 4)
174 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
177 /* Ring channel doorbell */
178 bus_space_write_4(softc->hwrm_bar.tag,
179 softc->hwrm_bar.handle,
182 /* Check if response len is updated */
183 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
184 if (resp->resp_len && resp->resp_len <= 4096)
188 if (i >= softc->hwrm_cmd_timeo) {
189 device_printf(softc->dev,
190 "Timeout sending %s: (timeout: %u) seq: %d\n",
191 GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
192 le16toh(req->seq_id));
195 /* Last byte of resp contains the valid key */
196 valid = (uint8_t *)resp + resp->resp_len - 1;
197 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
198 if (*valid == HWRM_RESP_VALID_KEY)
202 if (i >= softc->hwrm_cmd_timeo) {
203 device_printf(softc->dev, "Timeout sending %s: "
204 "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
205 GET_HWRM_REQ_TYPE(req->req_type),
206 softc->hwrm_cmd_timeo, le16toh(req->req_type),
207 le16toh(req->seq_id), msg_len,
212 err = le16toh(resp->error_code);
214 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
215 if (err != HWRM_ERR_CODE_FAIL) {
216 device_printf(softc->dev,
217 "%s command returned %s error.\n",
218 GET_HWRM_REQ_TYPE(req->req_type),
219 GET_HWRM_ERROR_CODE(err));
221 return bnxt_hwrm_err_map(err);
228 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
232 BNXT_HWRM_LOCK(softc);
233 rc = _hwrm_send_message(softc, msg, msg_len);
234 BNXT_HWRM_UNLOCK(softc);
239 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
242 struct hwrm_queue_qportcfg_input req = {0};
243 struct hwrm_queue_qportcfg_output *resp =
244 (void *)softc->hwrm_cmd_resp.idi_vaddr;
248 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
250 BNXT_HWRM_LOCK(softc);
251 rc = _hwrm_send_message(softc, &req, sizeof(req));
255 if (!resp->max_configurable_queues) {
259 softc->max_tc = resp->max_configurable_queues;
260 softc->max_lltc = resp->max_configurable_lossless_queues;
261 if (softc->max_tc > BNXT_MAX_COS_QUEUE)
262 softc->max_tc = BNXT_MAX_COS_QUEUE;
264 /* Currently no RDMA support */
267 qptr = &resp->queue_id0;
268 for (i = 0, j = 0; i < softc->max_tc; i++) {
269 softc->q_info[j].id = *qptr;
270 softc->q_ids[i] = *qptr++;
271 softc->q_info[j].profile = *qptr++;
272 softc->tc_to_qidx[j] = j;
273 if (!BNXT_CNPQ(softc->q_info[j].profile) ||
274 (no_rdma && BNXT_PF(softc)))
277 softc->max_q = softc->max_tc;
278 softc->max_tc = max_t(uint32_t, j, 1);
280 if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG)
283 if (softc->max_lltc > softc->max_tc)
284 softc->max_lltc = softc->max_tc;
287 BNXT_HWRM_UNLOCK(softc);
291 int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
293 struct hwrm_func_backing_store_qcaps_input req = {0};
294 struct hwrm_func_backing_store_qcaps_output *resp =
295 (void *)softc->hwrm_cmd_resp.idi_vaddr;
298 if (softc->hwrm_spec_code < 0x10902 || BNXT_VF(softc) || softc->ctx_mem)
301 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
302 BNXT_HWRM_LOCK(softc);
303 rc = _hwrm_send_message(softc, &req, sizeof(req));
305 struct bnxt_ctx_pg_info *ctx_pg;
306 struct bnxt_ctx_mem_info *ctx;
309 ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
314 ctx_pg = malloc(sizeof(*ctx_pg) * (softc->max_q + 1),
315 M_DEVBUF, M_NOWAIT | M_ZERO);
321 for (i = 0; i < softc->max_q + 1; i++, ctx_pg++)
322 ctx->tqm_mem[i] = ctx_pg;
324 softc->ctx_mem = ctx;
325 ctx->qp_max_entries = le32toh(resp->qp_max_entries);
326 ctx->qp_min_qp1_entries = le16toh(resp->qp_min_qp1_entries);
327 ctx->qp_max_l2_entries = le16toh(resp->qp_max_l2_entries);
328 ctx->qp_entry_size = le16toh(resp->qp_entry_size);
329 ctx->srq_max_l2_entries = le16toh(resp->srq_max_l2_entries);
330 ctx->srq_max_entries = le32toh(resp->srq_max_entries);
331 ctx->srq_entry_size = le16toh(resp->srq_entry_size);
332 ctx->cq_max_l2_entries = le16toh(resp->cq_max_l2_entries);
333 ctx->cq_max_entries = le32toh(resp->cq_max_entries);
334 ctx->cq_entry_size = le16toh(resp->cq_entry_size);
335 ctx->vnic_max_vnic_entries =
336 le16toh(resp->vnic_max_vnic_entries);
337 ctx->vnic_max_ring_table_entries =
338 le16toh(resp->vnic_max_ring_table_entries);
339 ctx->vnic_entry_size = le16toh(resp->vnic_entry_size);
340 ctx->stat_max_entries = le32toh(resp->stat_max_entries);
341 ctx->stat_entry_size = le16toh(resp->stat_entry_size);
342 ctx->tqm_entry_size = le16toh(resp->tqm_entry_size);
343 ctx->tqm_min_entries_per_ring =
344 le32toh(resp->tqm_min_entries_per_ring);
345 ctx->tqm_max_entries_per_ring =
346 le32toh(resp->tqm_max_entries_per_ring);
347 ctx->tqm_entries_multiple = resp->tqm_entries_multiple;
348 if (!ctx->tqm_entries_multiple)
349 ctx->tqm_entries_multiple = 1;
350 ctx->mrav_max_entries = le32toh(resp->mrav_max_entries);
351 ctx->mrav_entry_size = le16toh(resp->mrav_entry_size);
352 ctx->tim_entry_size = le16toh(resp->tim_entry_size);
353 ctx->tim_max_entries = le32toh(resp->tim_max_entries);
354 ctx->ctx_kind_initializer = resp->ctx_kind_initializer;
359 BNXT_HWRM_UNLOCK(softc);
363 #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES \
364 (HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP | \
365 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ | \
366 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ | \
367 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC | \
368 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
370 static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
375 if (BNXT_PAGE_SHIFT == 13)
377 else if (BNXT_PAGE_SIZE == 16)
381 if (rmem->depth >= 1) {
382 if (rmem->depth == 2)
383 *pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
385 *pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
386 *pg_dir = htole64(rmem->pg_tbl.idi_paddr);
388 *pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
392 int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
394 struct hwrm_func_backing_store_cfg_input req = {0};
395 struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
396 struct bnxt_ctx_pg_info *ctx_pg;
397 uint32_t *num_entries, req_len = sizeof(req);
406 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
407 req.enables = htole32(enables);
409 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
410 ctx_pg = &ctx->qp_mem;
411 req.qp_num_entries = htole32(ctx_pg->entries);
412 req.qp_num_qp1_entries = htole16(ctx->qp_min_qp1_entries);
413 req.qp_num_l2_entries = htole16(ctx->qp_max_l2_entries);
414 req.qp_entry_size = htole16(ctx->qp_entry_size);
415 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
416 &req.qpc_pg_size_qpc_lvl,
419 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
420 ctx_pg = &ctx->srq_mem;
421 req.srq_num_entries = htole32(ctx_pg->entries);
422 req.srq_num_l2_entries = htole16(ctx->srq_max_l2_entries);
423 req.srq_entry_size = htole16(ctx->srq_entry_size);
424 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
425 &req.srq_pg_size_srq_lvl,
428 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
429 ctx_pg = &ctx->cq_mem;
430 req.cq_num_entries = htole32(ctx_pg->entries);
431 req.cq_num_l2_entries = htole16(ctx->cq_max_l2_entries);
432 req.cq_entry_size = htole16(ctx->cq_entry_size);
433 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, &req.cq_pg_size_cq_lvl,
436 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
437 ctx_pg = &ctx->mrav_mem;
438 req.mrav_num_entries = htole32(ctx_pg->entries);
439 req.mrav_entry_size = htole16(ctx->mrav_entry_size);
440 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
441 &req.mrav_pg_size_mrav_lvl,
444 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
445 ctx_pg = &ctx->tim_mem;
446 req.tim_num_entries = htole32(ctx_pg->entries);
447 req.tim_entry_size = htole16(ctx->tim_entry_size);
448 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
449 &req.tim_pg_size_tim_lvl,
452 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
453 ctx_pg = &ctx->vnic_mem;
454 req.vnic_num_vnic_entries =
455 htole16(ctx->vnic_max_vnic_entries);
456 req.vnic_num_ring_table_entries =
457 htole16(ctx->vnic_max_ring_table_entries);
458 req.vnic_entry_size = htole16(ctx->vnic_entry_size);
459 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
460 &req.vnic_pg_size_vnic_lvl,
463 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
464 ctx_pg = &ctx->stat_mem;
465 req.stat_num_entries = htole32(ctx->stat_max_entries);
466 req.stat_entry_size = htole16(ctx->stat_entry_size);
467 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
468 &req.stat_pg_size_stat_lvl,
471 for (i = 0, num_entries = &req.tqm_sp_num_entries,
472 pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
473 pg_dir = &req.tqm_sp_page_dir,
474 ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP;
475 i < 9; i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
476 if (!(enables & ena))
479 req.tqm_entry_size = htole16(ctx->tqm_entry_size);
480 ctx_pg = ctx->tqm_mem[i];
481 *num_entries = htole32(ctx_pg->entries);
482 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
485 if (req_len > softc->hwrm_max_ext_req_len)
486 req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN;
488 rc = hwrm_send_message(softc, &req, req_len);
494 int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
496 struct hwrm_func_resource_qcaps_output *resp =
497 (void *)softc->hwrm_cmd_resp.idi_vaddr;
498 struct hwrm_func_resource_qcaps_input req = {0};
499 struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
502 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
503 req.fid = htole16(0xffff);
505 BNXT_HWRM_LOCK(softc);
506 rc = _hwrm_send_message(softc, &req, sizeof(req));
509 goto hwrm_func_resc_qcaps_exit;
512 hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
514 goto hwrm_func_resc_qcaps_exit;
516 hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
517 hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
518 hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
519 hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
520 hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
521 hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
522 hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
523 hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
524 hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
525 hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
526 hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
527 hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
528 hw_resc->min_vnics = le16toh(resp->min_vnics);
529 hw_resc->max_vnics = le16toh(resp->max_vnics);
530 hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
531 hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
533 if (BNXT_CHIP_P5(softc)) {
534 hw_resc->max_nqs = le16toh(resp->max_msix);
535 hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
538 hwrm_func_resc_qcaps_exit:
539 BNXT_HWRM_UNLOCK(softc);
544 bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len,
545 void *resp, uint32_t resp_len, uint32_t app_timeout)
548 void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr;
549 struct input *input = req;
552 input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
553 BNXT_HWRM_LOCK(softc);
554 old_timeo = softc->hwrm_cmd_timeo;
555 if (input->req_type == HWRM_NVM_INSTALL_UPDATE)
556 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
558 softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo);
559 rc = _hwrm_send_message(softc, req, req_len);
560 softc->hwrm_cmd_timeo = old_timeo;
562 device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n",
563 __FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc);
567 memcpy(resp, output, resp_len);
569 BNXT_HWRM_UNLOCK(softc);
575 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
577 struct hwrm_ver_get_input req = {0};
578 struct hwrm_ver_get_output *resp =
579 (void *)softc->hwrm_cmd_resp.idi_vaddr;
581 const char nastr[] = "<not installed>";
582 const char naver[] = "<N/A>";
583 uint32_t dev_caps_cfg;
584 uint16_t fw_maj, fw_min, fw_bld, fw_rsv, len;
586 softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
587 softc->hwrm_cmd_timeo = 1000;
588 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
590 req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
591 req.hwrm_intf_min = HWRM_VERSION_MINOR;
592 req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
594 BNXT_HWRM_LOCK(softc);
595 rc = _hwrm_send_message(softc, &req, sizeof(req));
599 snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
600 resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
601 softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b;
602 softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b;
603 softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b;
604 snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
605 resp->hwrm_fw_major, resp->hwrm_fw_minor, resp->hwrm_fw_build);
606 strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
608 strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
611 softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
612 resp->hwrm_intf_min_8b << 8 |
613 resp->hwrm_intf_upd_8b;
614 if (resp->hwrm_intf_maj_8b < 1) {
615 device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
616 "than 1.0.0.\n", resp->hwrm_intf_maj_8b,
617 resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
618 device_printf(softc->dev, "Please update firmware with HWRM "
619 "interface 1.0.0 or newer.\n");
621 if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
622 resp->mgmt_fw_build == 0) {
623 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
624 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
627 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
628 "%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor,
629 resp->mgmt_fw_build);
630 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
633 if (resp->netctrl_fw_major == 0 && resp->netctrl_fw_minor == 0 &&
634 resp->netctrl_fw_build == 0) {
635 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
637 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
641 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
642 "%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor,
643 resp->netctrl_fw_build);
644 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
647 if (resp->roce_fw_major == 0 && resp->roce_fw_minor == 0 &&
648 resp->roce_fw_build == 0) {
649 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
650 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
653 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
654 "%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor,
655 resp->roce_fw_build);
656 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
660 fw_maj = le32toh(resp->hwrm_fw_major);
661 if (softc->hwrm_spec_code > 0x10803 && fw_maj) {
662 fw_min = le16toh(resp->hwrm_fw_minor);
663 fw_bld = le16toh(resp->hwrm_fw_build);
664 fw_rsv = le16toh(resp->hwrm_fw_patch);
665 len = FW_VER_STR_LEN;
667 fw_maj = resp->hwrm_fw_maj_8b;
668 fw_min = resp->hwrm_fw_min_8b;
669 fw_bld = resp->hwrm_fw_bld_8b;
670 fw_rsv = resp->hwrm_fw_rsvd_8b;
671 len = BC_HWRM_STR_LEN;
674 snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d",
675 fw_maj, fw_min, fw_bld, fw_rsv);
677 if (strlen(resp->active_pkg_name)) {
678 int fw_ver_len = strlen (softc->ver_info->fw_ver_str);
680 snprintf(softc->ver_info->fw_ver_str + fw_ver_len,
681 FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
682 resp->active_pkg_name);
685 softc->ver_info->chip_num = le16toh(resp->chip_num);
686 softc->ver_info->chip_rev = resp->chip_rev;
687 softc->ver_info->chip_metal = resp->chip_metal;
688 softc->ver_info->chip_bond_id = resp->chip_bond_id;
689 softc->ver_info->chip_type = resp->chip_platform_type;
691 if (resp->hwrm_intf_maj_8b >= 1) {
692 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
693 softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
695 #define DFLT_HWRM_CMD_TIMEOUT 500
696 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
697 if (!softc->hwrm_cmd_timeo)
698 softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
700 dev_caps_cfg = le32toh(resp->dev_caps_cfg);
701 if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
702 (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
703 softc->flags |= BNXT_FLAG_SHORT_CMD;
706 BNXT_HWRM_UNLOCK(softc);
711 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
713 struct hwrm_func_drv_rgtr_input req = {0};
715 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
717 req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
718 HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
719 req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
721 req.ver_maj = __FreeBSD_version / 100000;
722 req.ver_min = (__FreeBSD_version / 1000) % 100;
723 req.ver_upd = (__FreeBSD_version / 100) % 10;
725 return hwrm_send_message(softc, &req, sizeof(req));
729 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
731 struct hwrm_func_drv_unrgtr_input req = {0};
733 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
734 if (shutdown == true)
736 HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
737 return hwrm_send_message(softc, &req, sizeof(req));
741 _is_valid_ether_addr(uint8_t *addr)
743 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
745 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
752 get_random_ether_addr(uint8_t *addr)
754 uint8_t temp[ETHER_ADDR_LEN];
756 arc4rand(&temp, sizeof(temp), 0);
759 bcopy(temp, addr, sizeof(temp));
763 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
766 struct hwrm_func_qcaps_input req = {0};
767 struct hwrm_func_qcaps_output *resp =
768 (void *)softc->hwrm_cmd_resp.idi_vaddr;
769 struct bnxt_func_info *func = &softc->func;
771 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
772 req.fid = htole16(0xffff);
774 BNXT_HWRM_LOCK(softc);
775 rc = _hwrm_send_message(softc, &req, sizeof(req));
780 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
781 softc->flags |= BNXT_FLAG_WOL_CAP;
783 func->fw_fid = le16toh(resp->fid);
784 memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
785 func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
786 func->max_cp_rings = le16toh(resp->max_cmpl_rings);
787 func->max_tx_rings = le16toh(resp->max_tx_rings);
788 func->max_rx_rings = le16toh(resp->max_rx_rings);
789 func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
790 if (!func->max_hw_ring_grps)
791 func->max_hw_ring_grps = func->max_tx_rings;
792 func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
793 func->max_vnics = le16toh(resp->max_vnics);
794 func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
795 if (BNXT_PF(softc)) {
796 struct bnxt_pf_info *pf = &softc->pf;
798 pf->port_id = le16toh(resp->port_id);
799 pf->first_vf_id = le16toh(resp->first_vf_id);
800 pf->max_vfs = le16toh(resp->max_vfs);
801 pf->max_encap_records = le32toh(resp->max_encap_records);
802 pf->max_decap_records = le32toh(resp->max_decap_records);
803 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
804 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
805 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
806 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
808 if (!_is_valid_ether_addr(func->mac_addr)) {
809 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
810 get_random_ether_addr(func->mac_addr);
814 BNXT_HWRM_UNLOCK(softc);
819 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
821 struct hwrm_func_qcfg_input req = {0};
822 struct hwrm_func_qcfg_output *resp =
823 (void *)softc->hwrm_cmd_resp.idi_vaddr;
824 struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
827 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
828 req.fid = htole16(0xffff);
829 BNXT_HWRM_LOCK(softc);
830 rc = _hwrm_send_message(softc, &req, sizeof(req));
834 fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
835 fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
836 fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
837 fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
839 BNXT_HWRM_UNLOCK(softc);
844 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
846 struct hwrm_func_reset_input req = {0};
848 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
851 return hwrm_send_message(softc, &req, sizeof(req));
855 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
856 struct hwrm_port_phy_cfg_input *req)
858 uint8_t autoneg = softc->link_info.autoneg;
859 uint16_t fw_link_speed = softc->link_info.req_link_speed;
861 if (autoneg & BNXT_AUTONEG_SPEED) {
863 HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
866 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
868 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
870 req->force_link_speed = htole16(fw_link_speed);
871 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
874 /* tell chimp that the setting takes effect immediately */
875 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
879 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
880 struct hwrm_port_phy_cfg_input *req)
882 struct bnxt_link_info *link_info = &softc->link_info;
884 if (link_info->flow_ctrl.autoneg) {
886 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
887 if (link_info->flow_ctrl.rx)
889 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
890 if (link_info->flow_ctrl.tx)
892 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
894 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
896 if (link_info->flow_ctrl.rx)
898 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
899 if (link_info->flow_ctrl.tx)
901 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
903 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
904 req->auto_pause = req->force_pause;
906 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
910 /* JFV this needs interface connection */
912 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
914 /* struct ethtool_eee *eee = &softc->eee; */
915 bool eee_enabled = false;
920 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
922 if (eee->tx_lpi_enabled)
923 flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
925 req->flags |= htole32(flags);
926 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
927 req->eee_link_speed_mask = htole16(eee_speeds);
928 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
932 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
937 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
938 bool set_eee, bool set_link)
940 struct hwrm_port_phy_cfg_input req = {0};
943 if (softc->flags & BNXT_FLAG_NPAR)
946 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
949 bnxt_hwrm_set_pause_common(softc, &req);
951 if (softc->link_info.flow_ctrl.autoneg)
956 bnxt_hwrm_set_link_common(softc, &req);
959 bnxt_hwrm_set_eee(softc, &req);
961 BNXT_HWRM_LOCK(softc);
962 rc = _hwrm_send_message(softc, &req, sizeof(req));
966 /* since changing of 'force pause' setting doesn't
967 * trigger any link change event, the driver needs to
968 * update the current pause result upon successfully i
969 * return of the phy_cfg command */
970 if (!softc->link_info.flow_ctrl.autoneg)
971 bnxt_report_link(softc);
974 BNXT_HWRM_UNLOCK(softc);
979 bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
981 struct hwrm_vnic_plcmodes_cfg_input req = {0};
983 if (!BNXT_CHIP_P5(softc))
986 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
989 * TBD -- Explore these flags
990 * 1. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4
991 * 2. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6
992 * 3. req.jumbo_thresh
993 * 4. req.hds_threshold
995 req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
996 req.vnic_id = htole16(vnic->id);
998 return hwrm_send_message(softc, &req, sizeof(req));
1002 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1004 struct hwrm_vnic_cfg_input req = {0};
1006 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
1008 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1009 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
1010 if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
1011 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
1012 if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
1013 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
1014 if (BNXT_CHIP_P5 (softc)) {
1015 req.default_rx_ring_id =
1016 htole16(softc->rx_rings[0].phys_id);
1017 req.default_cmpl_ring_id =
1018 htole16(softc->rx_cp_rings[0].ring.phys_id);
1020 htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
1021 HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
1022 req.vnic_id = htole16(vnic->id);
1024 req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
1025 HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
1026 req.vnic_id = htole16(vnic->id);
1027 req.dflt_ring_grp = htole16(vnic->def_ring_grp);
1029 req.rss_rule = htole16(vnic->rss_id);
1030 req.cos_rule = htole16(vnic->cos_rule);
1031 req.lb_rule = htole16(vnic->lb_rule);
1032 req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
1033 req.mru = htole16(vnic->mru);
1035 return hwrm_send_message(softc, &req, sizeof(req));
1039 bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1041 struct hwrm_vnic_free_input req = {0};
1044 if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE)
1047 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
1049 req.vnic_id = htole32(vnic->id);
1051 BNXT_HWRM_LOCK(softc);
1052 rc = _hwrm_send_message(softc, &req, sizeof(req));
1057 BNXT_HWRM_UNLOCK(softc);
1062 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1064 struct hwrm_vnic_alloc_input req = {0};
1065 struct hwrm_vnic_alloc_output *resp =
1066 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1069 if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
1070 device_printf(softc->dev,
1071 "Attempt to re-allocate vnic %04x\n", vnic->id);
1075 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
1077 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1078 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
1080 BNXT_HWRM_LOCK(softc);
1081 rc = _hwrm_send_message(softc, &req, sizeof(req));
1085 vnic->id = le32toh(resp->vnic_id);
1088 BNXT_HWRM_UNLOCK(softc);
1093 bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t ctx_id)
1095 struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
1098 if (ctx_id == (uint16_t)HWRM_NA_SIGNATURE)
1101 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
1102 req.rss_cos_lb_ctx_id = htole16(ctx_id);
1103 BNXT_HWRM_LOCK(softc);
1104 rc = _hwrm_send_message(softc, &req, sizeof(req));
1109 BNXT_HWRM_UNLOCK(softc);
1114 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
1116 struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
1117 struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
1118 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1121 if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
1122 device_printf(softc->dev,
1123 "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
1127 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
1129 BNXT_HWRM_LOCK(softc);
1130 rc = _hwrm_send_message(softc, &req, sizeof(req));
1134 *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
1137 BNXT_HWRM_UNLOCK(softc);
1142 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1144 struct hwrm_ring_grp_alloc_input req = {0};
1145 struct hwrm_ring_grp_alloc_output *resp;
1148 if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
1149 device_printf(softc->dev,
1150 "Attempt to re-allocate ring group %04x\n", grp->grp_id);
1154 if (BNXT_CHIP_P5 (softc))
1157 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1158 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
1159 req.cr = htole16(grp->cp_ring_id);
1160 req.rr = htole16(grp->rx_ring_id);
1161 req.ar = htole16(grp->ag_ring_id);
1162 req.sc = htole16(grp->stats_ctx);
1164 BNXT_HWRM_LOCK(softc);
1165 rc = _hwrm_send_message(softc, &req, sizeof(req));
1169 grp->grp_id = le32toh(resp->ring_group_id);
1172 BNXT_HWRM_UNLOCK(softc);
1177 bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1179 struct hwrm_ring_grp_free_input req = {0};
1182 if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE)
1185 if (BNXT_CHIP_P5 (softc))
1188 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
1190 req.ring_group_id = htole32(grp->grp_id);
1192 BNXT_HWRM_LOCK(softc);
1193 rc = _hwrm_send_message(softc, &req, sizeof(req));
1198 BNXT_HWRM_UNLOCK(softc);
1202 int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t ring_type,
1203 struct bnxt_ring *ring, int cmpl_ring_id)
1205 struct hwrm_ring_free_input req = {0};
1206 struct hwrm_ring_free_output *resp;
1208 uint16_t error_code;
1210 if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE)
1213 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1214 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
1215 req.cmpl_ring = htole16(cmpl_ring_id);
1216 req.ring_type = ring_type;
1217 req.ring_id = htole16(ring->phys_id);
1219 BNXT_HWRM_LOCK(softc);
1220 rc = _hwrm_send_message(softc, &req, sizeof(req));
1221 error_code = le16toh(resp->error_code);
1223 if (rc || error_code) {
1224 device_printf(softc->dev, "hwrm_ring_free type %d failed. "
1225 "rc:%x err:%x\n", ring_type, rc, error_code);
1230 BNXT_HWRM_UNLOCK(softc);
1235 * Ring allocation message to the firmware
1238 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
1239 struct bnxt_ring *ring)
1241 struct hwrm_ring_alloc_input req = {0};
1242 struct hwrm_ring_alloc_output *resp;
1243 uint16_t idx = ring->idx;
1244 struct bnxt_cp_ring *cp_ring;
1247 if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1248 device_printf(softc->dev,
1249 "Attempt to re-allocate ring %04x\n", ring->phys_id);
1253 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1254 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
1255 req.enables = htole32(0);
1256 req.fbo = htole32(0);
1257 req.ring_type = type;
1258 req.page_tbl_addr = htole64(ring->paddr);
1259 req.logical_id = htole16(ring->id);
1260 req.length = htole32(ring->ring_size);
1263 case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
1264 cp_ring = &softc->tx_cp_rings[idx];
1266 req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
1267 /* queue_id - what CoS queue the TX ring is associated with */
1268 req.queue_id = htole16(softc->q_info[0].id);
1270 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1271 req.enables |= htole32(
1272 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1274 case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
1275 if (!BNXT_CHIP_P5(softc))
1278 cp_ring = &softc->rx_cp_rings[idx];
1280 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1281 req.rx_buf_size = htole16(softc->rx_buf_size);
1282 req.enables |= htole32(
1283 HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1284 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1286 case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
1287 if (!BNXT_CHIP_P5(softc)) {
1288 req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
1292 cp_ring = &softc->rx_cp_rings[idx];
1294 req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
1295 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1296 req.rx_buf_size = htole16(softc->rx_buf_size);
1297 req.enables |= htole32(
1298 HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
1299 HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1300 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1302 case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
1303 if (!BNXT_CHIP_P5(softc)) {
1304 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1308 req.cq_handle = htole64(ring->id);
1309 req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
1310 req.enables |= htole32(
1311 HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
1313 case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
1314 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1317 printf("hwrm alloc invalid ring type %d\n", type);
1321 BNXT_HWRM_LOCK(softc);
1322 rc = _hwrm_send_message(softc, &req, sizeof(req));
1326 ring->phys_id = le16toh(resp->ring_id);
1329 BNXT_HWRM_UNLOCK(softc);
1334 bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
1336 struct hwrm_stat_ctx_free_input req = {0};
1339 if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE)
1342 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
1344 req.stat_ctx_id = htole16(cpr->stats_ctx_id);
1345 BNXT_HWRM_LOCK(softc);
1346 rc = _hwrm_send_message(softc, &req, sizeof(req));
1351 BNXT_HWRM_UNLOCK(softc);
1357 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
1360 struct hwrm_stat_ctx_alloc_input req = {0};
1361 struct hwrm_stat_ctx_alloc_output *resp;
1364 if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
1365 device_printf(softc->dev,
1366 "Attempt to re-allocate stats ctx %08x\n",
1371 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1372 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
1374 req.update_period_ms = htole32(1000);
1375 req.stats_dma_addr = htole64(paddr);
1376 if (BNXT_CHIP_P5(softc))
1377 req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
1379 req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
1381 BNXT_HWRM_LOCK(softc);
1382 rc = _hwrm_send_message(softc, &req, sizeof(req));
1386 cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
1389 BNXT_HWRM_UNLOCK(softc);
1395 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
1397 struct hwrm_port_qstats_input req = {0};
1400 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
1402 req.port_id = htole16(softc->pf.port_id);
1403 req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
1404 req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
1406 BNXT_HWRM_LOCK(softc);
1407 rc = _hwrm_send_message(softc, &req, sizeof(req));
1408 BNXT_HWRM_UNLOCK(softc);
1414 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
1415 struct bnxt_vnic_info *vnic)
1417 struct hwrm_cfa_l2_set_rx_mask_input req = {0};
1418 uint32_t mask = vnic->rx_mask;
1420 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
1422 req.vnic_id = htole32(vnic->id);
1423 req.mask = htole32(mask);
1424 req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
1425 req.num_mc_entries = htole32(vnic->mc_list_count);
1426 return hwrm_send_message(softc, &req, sizeof(req));
1430 bnxt_hwrm_l2_filter_free(struct bnxt_softc *softc, uint64_t filter_id)
1432 struct hwrm_cfa_l2_filter_free_input req = {0};
1435 if (filter_id == -1)
1438 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
1440 req.l2_filter_id = htole64(filter_id);
1442 BNXT_HWRM_LOCK(softc);
1443 rc = _hwrm_send_message(softc, &req, sizeof(req));
1448 BNXT_HWRM_UNLOCK(softc);
1453 bnxt_hwrm_free_filter(struct bnxt_softc *softc)
1455 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1456 struct bnxt_vlan_tag *tag;
1459 rc = bnxt_hwrm_l2_filter_free(softc, softc->vnic_info.filter_id);
1463 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1464 rc = bnxt_hwrm_l2_filter_free(softc, tag->filter_id);
1467 tag->filter_id = -1;
1475 bnxt_hwrm_l2_filter_alloc(struct bnxt_softc *softc, uint16_t vlan_tag,
1476 uint64_t *filter_id)
1478 struct hwrm_cfa_l2_filter_alloc_input req = {0};
1479 struct hwrm_cfa_l2_filter_alloc_output *resp;
1480 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1481 uint32_t enables = 0;
1484 if (*filter_id != -1) {
1485 device_printf(softc->dev, "Attempt to re-allocate l2 ctx "
1486 "filter (fid: 0x%jx)\n", (uintmax_t)*filter_id);
1490 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1491 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
1493 req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
1494 enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
1495 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
1496 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
1498 if (vlan_tag != 0xffff) {
1500 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN |
1501 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK |
1502 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_NUM_VLANS;
1503 req.l2_ivlan_mask = 0xffff;
1504 req.l2_ivlan = vlan_tag;
1508 req.enables = htole32(enables);
1509 req.dst_id = htole16(vnic->id);
1510 memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
1512 memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
1514 BNXT_HWRM_LOCK(softc);
1515 rc = _hwrm_send_message(softc, &req, sizeof(req));
1519 *filter_id = le64toh(resp->l2_filter_id);
1521 BNXT_HWRM_UNLOCK(softc);
1526 bnxt_hwrm_set_filter(struct bnxt_softc *softc)
1528 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1529 struct bnxt_vlan_tag *tag;
1532 rc = bnxt_hwrm_l2_filter_alloc(softc, 0xffff, &vnic->filter_id);
1536 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1537 rc = bnxt_hwrm_l2_filter_alloc(softc, tag->tag,
1548 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
1551 struct hwrm_vnic_rss_cfg_input req = {0};
1553 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
1555 req.hash_type = htole32(hash_type);
1556 req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
1557 req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
1558 req.rss_ctx_idx = htole16(vnic->rss_id);
1559 req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
1560 if (BNXT_CHIP_P5(softc)) {
1561 req.vnic_id = htole16(vnic->id);
1562 req.ring_table_pair_index = 0x0;
1565 return hwrm_send_message(softc, &req, sizeof(req));
1569 bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
1571 struct hwrm_func_cfg_input req = {0};
1573 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1575 req.fid = htole16(0xffff);
1576 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
1577 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
1578 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
1579 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
1580 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
1581 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
1582 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
1583 req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
1584 req.num_rsscos_ctxs = htole16(0x8);
1585 req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
1586 req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1587 req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1588 req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
1589 req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
1591 return hwrm_send_message(softc, &req, sizeof(req));
1595 bnxt_cfg_async_cr(struct bnxt_softc *softc)
1598 struct hwrm_func_cfg_input req = {0};
1600 if (!BNXT_PF(softc))
1603 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1605 req.fid = htole16(0xffff);
1606 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
1607 if (BNXT_CHIP_P5(softc))
1608 req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id);
1610 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
1612 rc = hwrm_send_message(softc, &req, sizeof(req));
1618 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
1620 softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
1622 softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
1624 softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
1625 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
1627 softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
1628 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
1630 softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
1634 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
1636 struct hwrm_vnic_tpa_cfg_input req = {0};
1639 if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
1643 if (!(softc->flags & BNXT_FLAG_TPA))
1646 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
1648 if (softc->hw_lro.enable) {
1649 flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
1650 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
1651 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
1652 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
1654 if (softc->hw_lro.is_mode_gro)
1655 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
1657 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
1659 req.flags = htole32(flags);
1661 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
1662 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
1663 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
1665 req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
1666 req.max_aggs = htole16(softc->hw_lro.max_aggs);
1667 req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
1670 req.vnic_id = htole16(softc->vnic_info.id);
1672 return hwrm_send_message(softc, &req, sizeof(req));
1676 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
1677 uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
1678 uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
1681 struct hwrm_nvm_find_dir_entry_input req = {0};
1682 struct hwrm_nvm_find_dir_entry_output *resp =
1683 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1689 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
1691 req.enables = htole32(
1692 HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
1693 req.dir_idx = htole16(*index);
1695 req.dir_type = htole16(type);
1696 req.dir_ordinal = htole16(*ordinal);
1697 req.dir_ext = htole16(ext);
1698 req.opt_ordinal = search_opt;
1700 BNXT_HWRM_LOCK(softc);
1701 old_timeo = softc->hwrm_cmd_timeo;
1702 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1703 rc = _hwrm_send_message(softc, &req, sizeof(req));
1704 softc->hwrm_cmd_timeo = old_timeo;
1709 *item_length = le32toh(resp->dir_item_length);
1711 *data_length = le32toh(resp->dir_data_length);
1713 *fw_ver = le32toh(resp->fw_ver);
1714 *ordinal = le16toh(resp->dir_ordinal);
1716 *index = le16toh(resp->dir_idx);
1719 BNXT_HWRM_UNLOCK(softc);
1724 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1725 uint32_t length, struct iflib_dma_info *data)
1727 struct hwrm_nvm_read_input req = {0};
1731 if (length > data->idi_size) {
1735 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1736 req.host_dest_addr = htole64(data->idi_paddr);
1737 req.dir_idx = htole16(index);
1738 req.offset = htole32(offset);
1739 req.len = htole32(length);
1740 BNXT_HWRM_LOCK(softc);
1741 old_timeo = softc->hwrm_cmd_timeo;
1742 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1743 rc = _hwrm_send_message(softc, &req, sizeof(req));
1744 softc->hwrm_cmd_timeo = old_timeo;
1745 BNXT_HWRM_UNLOCK(softc);
1748 bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1757 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1758 void *data, bool cpyin, uint32_t length)
1760 struct hwrm_nvm_modify_input req = {0};
1761 struct iflib_dma_info dma_data;
1765 if (length == 0 || !data)
1767 rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1772 rc = copyin(data, dma_data.idi_vaddr, length);
1777 memcpy(dma_data.idi_vaddr, data, length);
1778 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1779 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1781 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1782 req.host_src_addr = htole64(dma_data.idi_paddr);
1783 req.dir_idx = htole16(index);
1784 req.offset = htole32(offset);
1785 req.len = htole32(length);
1786 BNXT_HWRM_LOCK(softc);
1787 old_timeo = softc->hwrm_cmd_timeo;
1788 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1789 rc = _hwrm_send_message(softc, &req, sizeof(req));
1790 softc->hwrm_cmd_timeo = old_timeo;
1791 BNXT_HWRM_UNLOCK(softc);
1794 iflib_dma_free(&dma_data);
1799 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1802 struct hwrm_fw_reset_input req = {0};
1803 struct hwrm_fw_reset_output *resp =
1804 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1809 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1810 req.embedded_proc_type = processor;
1811 req.selfrst_status = *selfreset;
1813 BNXT_HWRM_LOCK(softc);
1814 rc = _hwrm_send_message(softc, &req, sizeof(req));
1817 *selfreset = resp->selfrst_status;
1820 BNXT_HWRM_UNLOCK(softc);
1825 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1827 struct hwrm_fw_qstatus_input req = {0};
1828 struct hwrm_fw_qstatus_output *resp =
1829 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1834 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1835 req.embedded_proc_type = type;
1837 BNXT_HWRM_LOCK(softc);
1838 rc = _hwrm_send_message(softc, &req, sizeof(req));
1841 *selfreset = resp->selfrst_status;
1844 BNXT_HWRM_UNLOCK(softc);
1849 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1850 uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1851 uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1854 struct hwrm_nvm_write_input req = {0};
1855 struct hwrm_nvm_write_output *resp =
1856 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1857 struct iflib_dma_info dma_data;
1862 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1867 rc = copyin(data, dma_data.idi_vaddr, data_length);
1872 memcpy(dma_data.idi_vaddr, data, data_length);
1873 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1874 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1877 dma_data.idi_paddr = 0;
1879 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1881 req.host_src_addr = htole64(dma_data.idi_paddr);
1882 req.dir_type = htole16(type);
1883 req.dir_ordinal = htole16(ordinal);
1884 req.dir_ext = htole16(ext);
1885 req.dir_attr = htole16(attr);
1886 req.dir_data_length = htole32(data_length);
1887 req.option = htole16(option);
1890 htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1893 req.dir_item_length = htole32(*item_length);
1895 BNXT_HWRM_LOCK(softc);
1896 old_timeo = softc->hwrm_cmd_timeo;
1897 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1898 rc = _hwrm_send_message(softc, &req, sizeof(req));
1899 softc->hwrm_cmd_timeo = old_timeo;
1903 *item_length = le32toh(resp->dir_item_length);
1905 *index = le16toh(resp->dir_idx);
1908 BNXT_HWRM_UNLOCK(softc);
1911 iflib_dma_free(&dma_data);
1916 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1918 struct hwrm_nvm_erase_dir_entry_input req = {0};
1922 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1923 req.dir_idx = htole16(index);
1924 BNXT_HWRM_LOCK(softc);
1925 old_timeo = softc->hwrm_cmd_timeo;
1926 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1927 rc = _hwrm_send_message(softc, &req, sizeof(req));
1928 softc->hwrm_cmd_timeo = old_timeo;
1929 BNXT_HWRM_UNLOCK(softc);
1934 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1935 uint32_t *entry_length)
1937 struct hwrm_nvm_get_dir_info_input req = {0};
1938 struct hwrm_nvm_get_dir_info_output *resp =
1939 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1943 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1945 BNXT_HWRM_LOCK(softc);
1946 old_timeo = softc->hwrm_cmd_timeo;
1947 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1948 rc = _hwrm_send_message(softc, &req, sizeof(req));
1949 softc->hwrm_cmd_timeo = old_timeo;
1954 *entries = le32toh(resp->entries);
1956 *entry_length = le32toh(resp->entry_length);
1959 BNXT_HWRM_UNLOCK(softc);
1964 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1965 uint32_t *entry_length, struct iflib_dma_info *dma_data)
1967 struct hwrm_nvm_get_dir_entries_input req = {0};
1976 entry_length = &ent_len;
1978 rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1981 if (*entries * *entry_length > dma_data->idi_size) {
1987 * TODO: There's a race condition here that could blow up DMA memory...
1988 * we need to allocate the max size, not the currently in use
1989 * size. The command should totally have a max size here.
1991 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1992 req.host_dest_addr = htole64(dma_data->idi_paddr);
1993 BNXT_HWRM_LOCK(softc);
1994 old_timeo = softc->hwrm_cmd_timeo;
1995 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1996 rc = _hwrm_send_message(softc, &req, sizeof(req));
1997 softc->hwrm_cmd_timeo = old_timeo;
1998 BNXT_HWRM_UNLOCK(softc);
2001 bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
2002 BUS_DMASYNC_POSTWRITE);
2009 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
2010 uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
2011 uint32_t *reserved_size, uint32_t *available_size)
2013 struct hwrm_nvm_get_dev_info_input req = {0};
2014 struct hwrm_nvm_get_dev_info_output *resp =
2015 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2019 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
2021 BNXT_HWRM_LOCK(softc);
2022 old_timeo = softc->hwrm_cmd_timeo;
2023 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2024 rc = _hwrm_send_message(softc, &req, sizeof(req));
2025 softc->hwrm_cmd_timeo = old_timeo;
2030 *mfg_id = le16toh(resp->manufacturer_id);
2032 *device_id = le16toh(resp->device_id);
2034 *sector_size = le32toh(resp->sector_size);
2036 *nvram_size = le32toh(resp->nvram_size);
2038 *reserved_size = le32toh(resp->reserved_size);
2040 *available_size = le32toh(resp->available_size);
2043 BNXT_HWRM_UNLOCK(softc);
2048 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
2049 uint32_t install_type, uint64_t *installed_items, uint8_t *result,
2050 uint8_t *problem_item, uint8_t *reset_required)
2052 struct hwrm_nvm_install_update_input req = {0};
2053 struct hwrm_nvm_install_update_output *resp =
2054 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2058 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
2059 req.install_type = htole32(install_type);
2061 BNXT_HWRM_LOCK(softc);
2062 old_timeo = softc->hwrm_cmd_timeo;
2063 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2064 rc = _hwrm_send_message(softc, &req, sizeof(req));
2065 softc->hwrm_cmd_timeo = old_timeo;
2069 if (installed_items)
2070 *installed_items = le32toh(resp->installed_items);
2072 *result = resp->result;
2074 *problem_item = resp->problem_item;
2076 *reset_required = resp->reset_required;
2079 BNXT_HWRM_UNLOCK(softc);
2084 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
2085 uint16_t ordinal, uint16_t ext)
2087 struct hwrm_nvm_verify_update_input req = {0};
2091 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
2093 req.dir_type = htole16(type);
2094 req.dir_ordinal = htole16(ordinal);
2095 req.dir_ext = htole16(ext);
2097 BNXT_HWRM_LOCK(softc);
2098 old_timeo = softc->hwrm_cmd_timeo;
2099 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2100 rc = _hwrm_send_message(softc, &req, sizeof(req));
2101 softc->hwrm_cmd_timeo = old_timeo;
2102 BNXT_HWRM_UNLOCK(softc);
2107 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
2108 uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
2109 uint16_t *millisecond, uint16_t *zone)
2111 struct hwrm_fw_get_time_input req = {0};
2112 struct hwrm_fw_get_time_output *resp =
2113 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2116 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
2118 BNXT_HWRM_LOCK(softc);
2119 rc = _hwrm_send_message(softc, &req, sizeof(req));
2124 *year = le16toh(resp->year);
2126 *month = resp->month;
2132 *minute = resp->minute;
2134 *second = resp->second;
2136 *millisecond = le16toh(resp->millisecond);
2138 *zone = le16toh(resp->zone);
2141 BNXT_HWRM_UNLOCK(softc);
2146 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
2147 uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
2148 uint16_t millisecond, uint16_t zone)
2150 struct hwrm_fw_set_time_input req = {0};
2152 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
2154 req.year = htole16(year);
2158 req.minute = minute;
2159 req.second = second;
2160 req.millisecond = htole16(millisecond);
2161 req.zone = htole16(zone);
2162 return hwrm_send_message(softc, &req, sizeof(req));
2166 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
2168 struct bnxt_link_info *link_info = &softc->link_info;
2169 struct hwrm_port_phy_qcfg_input req = {0};
2170 struct hwrm_port_phy_qcfg_output *resp =
2171 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2174 BNXT_HWRM_LOCK(softc);
2175 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
2177 rc = _hwrm_send_message(softc, &req, sizeof(req));
2181 link_info->phy_link_status = resp->link;
2182 link_info->duplex = resp->duplex_cfg;
2183 link_info->auto_mode = resp->auto_mode;
2186 * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
2187 * the advertisement of pause is enabled.
2188 * 1. When the auto_mode is not set to none and this flag is set to 1,
2189 * then the auto_pause bits on this port are being advertised and
2190 * autoneg pause results are being interpreted.
2191 * 2. When the auto_mode is not set to none and this flag is set to 0,
2192 * the pause is forced as indicated in force_pause, and also
2193 * advertised as auto_pause bits, but the autoneg results are not
2194 * interpreted since the pause configuration is being forced.
2195 * 3. When the auto_mode is set to none and this flag is set to 1,
2196 * auto_pause bits should be ignored and should be set to 0.
2199 link_info->flow_ctrl.autoneg = false;
2200 link_info->flow_ctrl.tx = false;
2201 link_info->flow_ctrl.rx = false;
2203 if ((resp->auto_mode) &&
2204 (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
2205 link_info->flow_ctrl.autoneg = true;
2208 if (link_info->flow_ctrl.autoneg) {
2209 if (resp->auto_pause & BNXT_PAUSE_TX)
2210 link_info->flow_ctrl.tx = true;
2211 if (resp->auto_pause & BNXT_PAUSE_RX)
2212 link_info->flow_ctrl.rx = true;
2214 if (resp->force_pause & BNXT_PAUSE_TX)
2215 link_info->flow_ctrl.tx = true;
2216 if (resp->force_pause & BNXT_PAUSE_RX)
2217 link_info->flow_ctrl.rx = true;
2220 link_info->duplex_setting = resp->duplex_cfg;
2221 if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
2222 link_info->link_speed = le16toh(resp->link_speed);
2224 link_info->link_speed = 0;
2225 link_info->force_link_speed = le16toh(resp->force_link_speed);
2226 link_info->auto_link_speed = le16toh(resp->auto_link_speed);
2227 link_info->support_speeds = le16toh(resp->support_speeds);
2228 link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
2229 link_info->preemphasis = le32toh(resp->preemphasis);
2230 link_info->phy_ver[0] = resp->phy_maj;
2231 link_info->phy_ver[1] = resp->phy_min;
2232 link_info->phy_ver[2] = resp->phy_bld;
2233 snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
2234 "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
2235 link_info->phy_ver[2]);
2236 strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
2238 strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
2240 link_info->media_type = resp->media_type;
2241 link_info->phy_type = resp->phy_type;
2242 link_info->transceiver = resp->xcvr_pkg_type;
2243 link_info->phy_addr = resp->eee_config_phy_addr &
2244 HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
2247 BNXT_HWRM_UNLOCK(softc);
2252 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
2254 struct hwrm_wol_filter_qcfg_input req = {0};
2255 struct hwrm_wol_filter_qcfg_output *resp =
2256 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2257 uint16_t next_handle = 0;
2260 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
2261 req.port_id = htole16(softc->pf.port_id);
2262 req.handle = htole16(handle);
2263 rc = hwrm_send_message(softc, &req, sizeof(req));
2265 next_handle = le16toh(resp->next_handle);
2266 if (next_handle != 0) {
2267 if (resp->wol_type ==
2268 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
2270 softc->wol_filter_id = resp->wol_filter_id;
2278 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
2280 struct hwrm_wol_filter_alloc_input req = {0};
2281 struct hwrm_wol_filter_alloc_output *resp =
2282 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2285 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
2286 req.port_id = htole16(softc->pf.port_id);
2287 req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
2289 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
2290 memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
2291 rc = hwrm_send_message(softc, &req, sizeof(req));
2293 softc->wol_filter_id = resp->wol_filter_id;
2299 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
2301 struct hwrm_wol_filter_free_input req = {0};
2303 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
2304 req.port_id = htole16(softc->pf.port_id);
2306 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
2307 req.wol_filter_id = softc->wol_filter_id;
2308 return hwrm_send_message(softc, &req, sizeof(req));
2311 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
2312 uint32_t buf_tmrs, uint16_t flags,
2313 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
2315 req->flags = htole16(flags);
2316 req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
2317 req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
2318 req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
2319 req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
2320 /* Minimum time between 2 interrupts set to buf_tmr x 2 */
2321 req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
2322 req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
2323 req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
2326 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
2329 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
2331 uint16_t max_buf, max_buf_irq;
2332 uint16_t buf_tmr, buf_tmr_irq;
2335 bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
2336 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2337 bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
2338 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2340 /* Each rx completion (2 records) should be DMAed immediately.
2341 * DMA 1/4 of the completion buffers at a time.
2343 max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
2344 /* max_buf must not be zero */
2345 max_buf = clamp_t(uint16_t, max_buf, 1, 63);
2346 max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
2347 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
2348 /* buf timer set to 1/4 of interrupt timer */
2349 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2350 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
2351 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2353 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2355 /* RING_IDLE generates more IRQs for lower latency. Enable it only
2356 * if coal_usecs is less than 25 us.
2358 if (softc->rx_coal_usecs < 25)
2359 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
2361 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2362 buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
2364 /* max_buf must not be zero */
2365 max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
2366 max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
2367 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
2368 /* buf timer set to 1/4 of interrupt timer */
2369 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2370 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
2371 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2372 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2373 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2374 buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
2376 for (i = 0; i < softc->nrxqsets; i++) {
2381 * Check if Tx also needs to be done
2382 * So far, Tx processing has been done in softirq contest
2386 req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
2388 rc = hwrm_send_message(softc, req, sizeof(*req));
2395 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
2398 struct hwrm_func_drv_rgtr_input req = {0};
2399 bitstr_t *async_events_bmap;
2403 #define BNXT_MAX_NUM_ASYNC_EVENTS 256
2404 async_events_bmap = bit_alloc(BNXT_MAX_NUM_ASYNC_EVENTS, M_DEVBUF,
2406 events = (uint32_t *)async_events_bmap;
2408 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
2411 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
2413 memset(async_events_bmap, 0, sizeof(BNXT_MAX_NUM_ASYNC_EVENTS / 8));
2415 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
2416 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
2417 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
2418 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
2419 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
2421 if (bmap && bmap_size) {
2422 for (i = 0; i < bmap_size; i++) {
2423 if (bit_test(bmap, i))
2424 bit_set(async_events_bmap, i);
2428 for (i = 0; i < 8; i++)
2429 req.async_event_fwd[i] |= htole32(events[i]);
2431 free(async_events_bmap, M_DEVBUF);
2433 return hwrm_send_message(softc, &req, sizeof(req));
2436 void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type,
2437 uint32_t ring_id, uint32_t *prod, uint32_t *cons)
2439 hwrm_dbg_ring_info_get_input_t req = {0};
2440 hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
2443 *prod = *cons = 0xffffffff;
2444 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET);
2445 req.ring_type = le32toh(ring_type);
2446 req.fw_ring_id = le32toh(ring_id);
2447 rc = hwrm_send_message(softc, &req, sizeof(req));
2449 *prod = resp->producer_index;
2450 *cons = resp->consumer_index;