xref: /freebsd/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c (revision 7a7741af18d6c8a804cc643cb7ecda9d730c6aa6)
1 /*-
2  * Broadcom NetXtreme-C/E network driver.
3  *
4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #include <sys/endian.h>
31 #include <linux/pci.h>
32 
33 #include "bnxt.h"
34 #include "bnxt_hwrm.h"
35 #include "hsi_struct_def.h"
36 
37 static int bnxt_hwrm_err_map(uint16_t err);
38 static inline int _is_valid_ether_addr(uint8_t *);
39 static inline void get_random_ether_addr(uint8_t *);
40 static void	bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
41 		    struct hwrm_port_phy_cfg_input *req);
42 static void	bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
43 		    struct hwrm_port_phy_cfg_input *req);
44 static void	bnxt_hwrm_set_eee(struct bnxt_softc *softc,
45 		    struct hwrm_port_phy_cfg_input *req);
46 
47 /* NVRam stuff has a five minute timeout */
48 #define BNXT_NVM_TIMEO	(5 * 60 * 1000)
49 
50 #define BNXT_RX_STATS_PRI_ENTRY(counter, n)		\
51 	BNXT_RX_STATS_EXT_OFFSET(counter##_cos0)
52 
53 #define BNXT_TX_STATS_PRI_ENTRY(counter, n)		\
54 	 BNXT_TX_STATS_EXT_OFFSET(counter##_cos0)
55 
56 #define BNXT_RX_STATS_PRI_ENTRIES(counter)		\
57 	BNXT_RX_STATS_PRI_ENTRY(counter, 0),		\
58 	BNXT_RX_STATS_PRI_ENTRY(counter, 1),		\
59 	BNXT_RX_STATS_PRI_ENTRY(counter, 2),		\
60 	BNXT_RX_STATS_PRI_ENTRY(counter, 3),		\
61 	BNXT_RX_STATS_PRI_ENTRY(counter, 4),		\
62 	BNXT_RX_STATS_PRI_ENTRY(counter, 5),		\
63 	BNXT_RX_STATS_PRI_ENTRY(counter, 6),		\
64 	BNXT_RX_STATS_PRI_ENTRY(counter, 7)
65 
66 #define BNXT_TX_STATS_PRI_ENTRIES(counter)		\
67 	BNXT_TX_STATS_PRI_ENTRY(counter, 0),		\
68 	BNXT_TX_STATS_PRI_ENTRY(counter, 1),		\
69 	BNXT_TX_STATS_PRI_ENTRY(counter, 2),		\
70 	BNXT_TX_STATS_PRI_ENTRY(counter, 3),		\
71 	BNXT_TX_STATS_PRI_ENTRY(counter, 4),		\
72 	BNXT_TX_STATS_PRI_ENTRY(counter, 5),		\
73 	BNXT_TX_STATS_PRI_ENTRY(counter, 6),		\
74 	BNXT_TX_STATS_PRI_ENTRY(counter, 7)
75 
76 
77 long bnxt_rx_bytes_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_bytes)};
78 long bnxt_rx_pkts_pri_arr_base_off[] = {BNXT_RX_STATS_PRI_ENTRIES(rx_packets)};
79 long bnxt_tx_bytes_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_bytes)};
80 long bnxt_tx_pkts_pri_arr_base_off[] = {BNXT_TX_STATS_PRI_ENTRIES(tx_packets)};
81 
82 static int
83 bnxt_hwrm_err_map(uint16_t err)
84 {
85 	int rc;
86 
87 	switch (err) {
88 	case HWRM_ERR_CODE_SUCCESS:
89 		return 0;
90 	case HWRM_ERR_CODE_INVALID_PARAMS:
91 	case HWRM_ERR_CODE_INVALID_FLAGS:
92 	case HWRM_ERR_CODE_INVALID_ENABLES:
93 		return EINVAL;
94 	case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
95 		return EACCES;
96 	case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
97 		return ENOMEM;
98 	case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
99 		return ENOSYS;
100 	case HWRM_ERR_CODE_FAIL:
101 		return EIO;
102 	case HWRM_ERR_CODE_HWRM_ERROR:
103 	case HWRM_ERR_CODE_UNKNOWN_ERR:
104 	default:
105 		return EDOOFUS;
106 	}
107 
108 	return rc;
109 }
110 
111 int
112 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
113 {
114 	int rc;
115 
116 	rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
117 	    BUS_DMA_NOWAIT);
118 	return rc;
119 }
120 
121 void
122 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
123 {
124 	if (softc->hwrm_cmd_resp.idi_vaddr)
125 		iflib_dma_free(&softc->hwrm_cmd_resp);
126 	softc->hwrm_cmd_resp.idi_vaddr = NULL;
127 	return;
128 }
129 
130 void
131 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
132     uint16_t req_type)
133 {
134 	struct input *req = request;
135 
136 	req->req_type = htole16(req_type);
137 	req->cmpl_ring = 0xffff;
138 	req->target_id = 0xffff;
139 	req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
140 }
141 
142 int
143 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
144 {
145 	struct input *req = msg;
146 	struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
147 	uint32_t *data = msg;
148 	int i;
149 	uint8_t *valid;
150 	uint16_t err;
151 	uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
152 	struct hwrm_short_input short_input = {0};
153 
154 	/* TODO: DMASYNC in here. */
155 	req->seq_id = htole16(softc->hwrm_cmd_seq++);
156 	memset(resp, 0, PAGE_SIZE);
157 
158 	if (BNXT_NO_FW_ACCESS(softc) &&
159 	    (req->req_type != HWRM_FUNC_RESET && req->req_type != HWRM_VER_GET))
160 		return -EINVAL;
161 
162 	if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
163 	    msg_len > BNXT_HWRM_MAX_REQ_LEN) {
164 		void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
165                 uint16_t max_msg_len;
166 
167                 /* Set boundary for maximum extended request length for short
168                  * cmd format. If passed up from device use the max supported
169                  * internal req length.
170 		 */
171 
172 		max_msg_len = softc->hwrm_max_ext_req_len;
173 
174 
175 		memcpy(short_cmd_req, req, msg_len);
176                 if (msg_len < max_msg_len)
177 			memset((uint8_t *) short_cmd_req + msg_len, 0,
178 				max_msg_len - msg_len);
179 
180 		short_input.req_type = req->req_type;
181 		short_input.signature =
182 		    htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
183 		short_input.size = htole16(msg_len);
184 		short_input.req_addr =
185 		    htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
186 
187 		data = (uint32_t *)&short_input;
188 		msg_len = sizeof(short_input);
189 
190 		/* Sync memory write before updating doorbell */
191 		wmb();
192 
193 		max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
194 	}
195 
196 	/* Write request msg to hwrm channel */
197 	for (i = 0; i < msg_len; i += 4) {
198 		bus_space_write_4(softc->hwrm_bar.tag,
199 				  softc->hwrm_bar.handle,
200 				  i, *data);
201 		data++;
202 	}
203 
204 	/* Clear to the end of the request buffer */
205 	for (i = msg_len; i < max_req_len; i += 4)
206 		bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
207 		    i, 0);
208 
209 	/* Ring channel doorbell */
210 	bus_space_write_4(softc->hwrm_bar.tag,
211 			  softc->hwrm_bar.handle,
212 			  0x100, htole32(1));
213 
214 	/* Check if response len is updated */
215 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
216 		if (resp->resp_len && resp->resp_len <= 4096)
217 			break;
218 		DELAY(1000);
219 	}
220 	if (i >= softc->hwrm_cmd_timeo) {
221 		device_printf(softc->dev,
222 		    "Timeout sending %s: (timeout: %u) seq: %d\n",
223 		    GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
224 		    le16toh(req->seq_id));
225 		return ETIMEDOUT;
226 	}
227 	/* Last byte of resp contains the valid key */
228 	valid = (uint8_t *)resp + resp->resp_len - 1;
229 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
230 		if (*valid == HWRM_RESP_VALID_KEY)
231 			break;
232 		DELAY(1000);
233 	}
234 	if (i >= softc->hwrm_cmd_timeo) {
235 		device_printf(softc->dev, "Timeout sending %s: "
236 		    "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
237 		    GET_HWRM_REQ_TYPE(req->req_type),
238 		    softc->hwrm_cmd_timeo, le16toh(req->req_type),
239 		    le16toh(req->seq_id), msg_len,
240 		    *valid);
241 		return ETIMEDOUT;
242 	}
243 
244 	err = le16toh(resp->error_code);
245 	if (err) {
246 		/* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
247 		if (err != HWRM_ERR_CODE_FAIL) {
248 			device_printf(softc->dev,
249 			    "%s command returned %s error.\n",
250 			    GET_HWRM_REQ_TYPE(req->req_type),
251 			    GET_HWRM_ERROR_CODE(err));
252 		}
253 		return bnxt_hwrm_err_map(err);
254 	}
255 
256 	return 0;
257 }
258 
259 int
260 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
261 {
262 	int rc;
263 
264 	BNXT_HWRM_LOCK(softc);
265 	rc = _hwrm_send_message(softc, msg, msg_len);
266 	BNXT_HWRM_UNLOCK(softc);
267 	return rc;
268 }
269 
270 int
271 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc, uint32_t path_dir)
272 {
273 	int rc = 0;
274 	struct hwrm_queue_qportcfg_input req = {0};
275 	struct hwrm_queue_qportcfg_output *resp =
276 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
277 	uint8_t max_tc, max_lltc, *max_q;
278 	uint8_t queue_profile, queue_id;
279 	struct bnxt_queue_info *q_info;
280 	uint8_t i, j, *qptr, *q_ids;
281 	bool no_rdma;
282 
283 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
284 
285 	BNXT_HWRM_LOCK(softc);
286 	rc = _hwrm_send_message(softc, &req, sizeof(req));
287 	if (rc)
288 		goto qportcfg_exit;
289 
290 	if (!resp->max_configurable_queues) {
291 		rc = -EINVAL;
292 		goto qportcfg_exit;
293 	}
294 
295 	if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG) {
296 		softc->is_asym_q = true;
297 		/* bnxt_init_cosq_names(softc, path_dir); */
298 	} else {
299 		softc->is_asym_q = false;
300 		/* bnxt_free_stats_cosqnames_mem(softc); */
301 	}
302 
303 	max_tc = min_t(uint8_t, resp->max_configurable_queues, BNXT_MAX_QUEUE);
304 	max_lltc = resp->max_configurable_lossless_queues;
305 
306 	/*
307 	 * No RDMA support yet.
308 	 * no_rdma = !(softc->flags & BNXT_FLAG_ROCE_CAP);
309 	 */
310 	no_rdma = true;
311 	qptr = &resp->queue_id0;
312 
313 	if (path_dir == HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX) {
314 		q_info = softc->tx_q_info;
315 		q_ids = softc->tx_q_ids;
316 		max_q = &softc->tx_max_q;
317 	} else {
318 		q_info = softc->rx_q_info;
319 		q_ids = softc->rx_q_ids;
320 		max_q = &softc->rx_max_q;
321 	}
322 
323 	for (i = 0, j = 0; i < max_tc; i++) {
324 		queue_id = *qptr;
325 		qptr++;
326 
327 		queue_profile = *qptr;
328 		qptr++;
329 
330 		q_info[j].queue_id = queue_id;
331 		q_info[j].queue_profile = queue_profile;
332 		q_ids[i] = queue_id;
333 
334 		softc->tc_to_qidx[j] = j;
335 
336 		if (!BNXT_CNPQ(q_info[j].queue_profile) ||
337 		    (no_rdma && BNXT_PF(softc)))
338 			j++;
339 	}
340 	*max_q = max_tc;
341 	max_tc = max_t(uint8_t, j, 1);
342 	softc->max_tc = softc->max_tc ? min(softc->max_tc, max_tc) : max_tc;
343 	softc->max_lltc = softc->max_lltc ? min(softc->max_lltc, max_lltc) : max_lltc;
344 
345 	if (softc->max_lltc > softc->max_tc)
346 		softc->max_lltc = softc->max_tc;
347 
348 qportcfg_exit:
349 	BNXT_HWRM_UNLOCK(softc);
350 	return rc;
351 }
352 
353 static int bnxt_alloc_all_ctx_pg_info(struct bnxt_softc *softc)
354 {
355 	struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
356 	u16 type;
357 
358 	for (type = 0; type < BNXT_CTX_MAX; type++) {
359 		struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
360 		int n = 1;
361 
362 		if (!ctxm->max_entries || ctxm->pg_info)
363 			continue;
364 
365 		if (ctxm->instance_bmap)
366 			n = hweight32(ctxm->instance_bmap);
367 		ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL);
368 		if (!ctxm->pg_info)
369 			return -ENOMEM;
370 	}
371 	return 0;
372 }
373 
374 static void bnxt_init_ctx_initializer(struct bnxt_ctx_mem_type *ctxm,
375 				      u8 init_val, u8 init_offset,
376 				      bool init_mask_set)
377 {
378 	ctxm->init_value = init_val;
379 	ctxm->init_offset = BNXT_CTX_INIT_INVALID_OFFSET;
380 	if (init_mask_set)
381 		ctxm->init_offset = init_offset * 4;
382 	else
383 		ctxm->init_value = 0;
384 }
385 
386 int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
387 {
388 	struct hwrm_func_backing_store_qcaps_input req = {0};
389 	struct hwrm_func_backing_store_qcaps_output *resp =
390 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
391 	int rc;
392 
393 	if (softc->hwrm_spec_code < 0x10902 || softc->ctx_mem)
394 		return 0;
395 
396 	if (BNXT_VF(softc))
397 		return 0;
398 
399 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
400 	BNXT_HWRM_LOCK(softc);
401 	rc = _hwrm_send_message(softc, &req, sizeof(req));
402 	if (!rc) {
403 		struct bnxt_ctx_mem_type *ctxm;
404 		struct bnxt_ctx_mem_info *ctx;
405 		u8 init_val, init_idx = 0;
406 		u16 init_mask;
407 
408 		ctx = softc->ctx_mem;
409 		if (!ctx) {
410 			ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
411 			if (!ctx) {
412 				rc = -ENOMEM;
413 				goto ctx_err;
414 			}
415 			softc->ctx_mem = ctx;
416 		}
417 		init_val = resp->ctx_kind_initializer;
418 		init_mask = le16_to_cpu(resp->ctx_init_mask);
419 
420 		ctxm = &ctx->ctx_arr[BNXT_CTX_QP];
421 		ctxm->max_entries = le32_to_cpu(resp->qp_max_entries);
422 		ctxm->qp_qp1_entries = le16_to_cpu(resp->qp_min_qp1_entries);
423 		ctxm->qp_l2_entries = le16_to_cpu(resp->qp_max_l2_entries);
424 		ctxm->entry_size = le16_to_cpu(resp->qp_entry_size);
425 		bnxt_init_ctx_initializer(ctxm, init_val, resp->qp_init_offset,
426 					  (init_mask & (1 << init_idx++)) != 0);
427 
428 		ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ];
429 		ctxm->srq_l2_entries = le16_to_cpu(resp->srq_max_l2_entries);
430 		ctxm->max_entries = le32_to_cpu(resp->srq_max_entries);
431 		ctxm->entry_size = le16_to_cpu(resp->srq_entry_size);
432 		bnxt_init_ctx_initializer(ctxm, init_val, resp->srq_init_offset,
433 					  (init_mask & (1 << init_idx++)) != 0);
434 
435 		ctxm = &ctx->ctx_arr[BNXT_CTX_CQ];
436 		ctxm->cq_l2_entries = le16_to_cpu(resp->cq_max_l2_entries);
437 		ctxm->max_entries = le32_to_cpu(resp->cq_max_entries);
438 		ctxm->entry_size = le16_to_cpu(resp->cq_entry_size);
439 		bnxt_init_ctx_initializer(ctxm, init_val, resp->cq_init_offset,
440 					  (init_mask & (1 << init_idx++)) != 0);
441 
442 		ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC];
443 		ctxm->vnic_entries = le32_to_cpu(resp->vnic_max_vnic_entries);
444 		ctxm->max_entries = ctxm->vnic_entries +
445 			le16_to_cpu(resp->vnic_max_ring_table_entries);
446 		ctxm->entry_size = le16_to_cpu(resp->vnic_entry_size);
447 		bnxt_init_ctx_initializer(ctxm, init_val,
448 					  resp->vnic_init_offset,
449 					  (init_mask & (1 << init_idx++)) != 0);
450 
451 		ctxm = &ctx->ctx_arr[BNXT_CTX_STAT];
452 		ctxm->max_entries = le32_to_cpu(resp->stat_max_entries);
453 		ctxm->entry_size = le16_to_cpu(resp->stat_entry_size);
454 		bnxt_init_ctx_initializer(ctxm, init_val,
455 					  resp->stat_init_offset,
456 					  (init_mask & (1 << init_idx++)) != 0);
457 
458 		ctxm = &ctx->ctx_arr[BNXT_CTX_STQM];
459 		ctxm->entry_size = le16_to_cpu(resp->tqm_entry_size);
460 		ctxm->min_entries = le32_to_cpu(resp->tqm_min_entries_per_ring);
461 		ctxm->max_entries = le32_to_cpu(resp->tqm_max_entries_per_ring);
462 		ctxm->entry_multiple = resp->tqm_entries_multiple;
463 		if (!ctxm->entry_multiple)
464 			ctxm->entry_multiple = 1;
465 
466 		memcpy(&ctx->ctx_arr[BNXT_CTX_FTQM], ctxm, sizeof(*ctxm));
467 
468 		ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
469 		ctxm->max_entries = le32_to_cpu(resp->mrav_max_entries);
470 		ctxm->entry_size = le16_to_cpu(resp->mrav_entry_size);
471 		ctxm->mrav_num_entries_units =
472 			le16_to_cpu(resp->mrav_num_entries_units);
473 		bnxt_init_ctx_initializer(ctxm, init_val,
474 					  resp->mrav_init_offset,
475 					  (init_mask & (1 << init_idx++)) != 0);
476 
477 		ctxm = &ctx->ctx_arr[BNXT_CTX_TIM];
478 		ctxm->entry_size = le16_to_cpu(resp->tim_entry_size);
479 		ctxm->max_entries = le32_to_cpu(resp->tim_max_entries);
480 
481 		ctx->tqm_fp_rings_count = resp->tqm_fp_rings_count;
482 		if (!ctx->tqm_fp_rings_count)
483 			ctx->tqm_fp_rings_count = softc->tx_max_q;
484 		else if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_LEGACY_RINGS)
485 			ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_LEGACY_RINGS;
486 		if (ctx->tqm_fp_rings_count == BNXT_MAX_TQM_FP_LEGACY_RINGS &&
487 		    softc->hwrm_max_ext_req_len >= BNXT_BACKING_STORE_CFG_LEN) {
488 			ctx->tqm_fp_rings_count += resp->tqm_fp_rings_count_ext;
489 			if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_RINGS)
490 				ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_RINGS;
491 		}
492 		ctxm = &ctx->ctx_arr[BNXT_CTX_FTQM];
493 		memcpy(ctxm, &ctx->ctx_arr[BNXT_CTX_STQM], sizeof(*ctxm));
494 		ctxm->instance_bmap = (1 << ctx->tqm_fp_rings_count) - 1;
495 
496 		rc = bnxt_alloc_all_ctx_pg_info(softc);
497 	} else {
498 		rc = 0;
499 	}
500 ctx_err:
501 	BNXT_HWRM_UNLOCK(softc);
502 	return rc;
503 }
504 
505 #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES                 \
506         (HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP |                \
507          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ |               \
508          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ |                \
509          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC |              \
510          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
511 
512 static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
513 				  uint64_t *pg_dir)
514 {
515 	uint8_t pg_size = 0;
516 
517 	if (BNXT_PAGE_SHIFT == 13)
518 		pg_size = 1 << 4;
519 	else if (BNXT_PAGE_SIZE == 16)
520 		pg_size = 2 << 4;
521 
522 	*pg_attr = pg_size;
523 	if (rmem->depth >= 1) {
524 		if (rmem->depth == 2)
525 			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
526 		else
527 			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
528 		*pg_dir = htole64(rmem->pg_tbl.idi_paddr);
529 	} else {
530 		*pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
531 	}
532 }
533 
534 int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
535 {
536 	struct hwrm_func_backing_store_cfg_input req = {0};
537 	struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
538 	struct bnxt_ctx_pg_info *ctx_pg;
539 	struct bnxt_ctx_mem_type *ctxm;
540 	u32 req_len = sizeof(req);
541 	__le32 *num_entries;
542 	u32 ena, flags = 0;
543 	__le64 *pg_dir;
544 	u8 *pg_attr;
545 	int i;
546 
547 	if (!ctx)
548 		return 0;
549 
550 	if (req_len > softc->hwrm_max_ext_req_len)
551 		req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN;
552 
553 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
554 	req.enables = htole32(enables);
555 
556 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
557 		ctxm = &ctx->ctx_arr[BNXT_CTX_QP];
558 		ctx_pg = ctxm->pg_info;
559 		req.qp_num_entries = cpu_to_le32(ctx_pg->entries);
560 		req.qp_num_qp1_entries = cpu_to_le16(ctxm->qp_qp1_entries);
561 		req.qp_num_l2_entries = cpu_to_le16(ctxm->qp_l2_entries);
562 		req.qp_entry_size = cpu_to_le16(ctxm->entry_size);
563 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
564 				&req.qpc_pg_size_qpc_lvl,
565 				&req.qpc_page_dir);
566 	}
567 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
568 		ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ];
569 		ctx_pg = ctxm->pg_info;
570 		req.srq_num_entries = cpu_to_le32(ctx_pg->entries);
571 		req.srq_num_l2_entries = cpu_to_le16(ctxm->srq_l2_entries);
572 		req.srq_entry_size = cpu_to_le16(ctxm->entry_size);
573 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
574 				&req.srq_pg_size_srq_lvl,
575 				&req.srq_page_dir);
576 	}
577 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
578 		ctxm = &ctx->ctx_arr[BNXT_CTX_CQ];
579 		ctx_pg = ctxm->pg_info;
580 		req.cq_num_entries = cpu_to_le32(ctx_pg->entries);
581 		req.cq_num_l2_entries = cpu_to_le16(ctxm->cq_l2_entries);
582 		req.cq_entry_size = cpu_to_le16(ctxm->entry_size);
583 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
584 				      &req.cq_pg_size_cq_lvl,
585 				&req.cq_page_dir);
586 	}
587 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
588 		ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
589 		ctx_pg = ctxm->pg_info;
590 		req.mrav_num_entries = cpu_to_le32(ctx_pg->entries);
591 		if (ctxm->mrav_num_entries_units)
592 			flags |=
593 			HWRM_FUNC_BACKING_STORE_CFG_INPUT_FLAGS_MRAV_RESERVATION_SPLIT;
594 		req.mrav_entry_size = cpu_to_le16(ctxm->entry_size);
595 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
596 				&req.mrav_pg_size_mrav_lvl,
597 				&req.mrav_page_dir);
598 	}
599 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
600 		ctxm = &ctx->ctx_arr[BNXT_CTX_TIM];
601 		ctx_pg = ctxm->pg_info;
602 		req.tim_num_entries = cpu_to_le32(ctx_pg->entries);
603 		req.tim_entry_size = cpu_to_le16(ctxm->entry_size);
604 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
605 				&req.tim_pg_size_tim_lvl,
606 				&req.tim_page_dir);
607 	}
608 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
609 		ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC];
610 		ctx_pg = ctxm->pg_info;
611 		req.vnic_num_vnic_entries = cpu_to_le16(ctxm->vnic_entries);
612 		req.vnic_num_ring_table_entries =
613 			cpu_to_le16(ctxm->max_entries - ctxm->vnic_entries);
614 		req.vnic_entry_size = cpu_to_le16(ctxm->entry_size);
615 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
616 				&req.vnic_pg_size_vnic_lvl,
617 				&req.vnic_page_dir);
618 	}
619 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
620 		ctxm = &ctx->ctx_arr[BNXT_CTX_STAT];
621 		ctx_pg = ctxm->pg_info;
622 		req.stat_num_entries = cpu_to_le32(ctxm->max_entries);
623 		req.stat_entry_size = cpu_to_le16(ctxm->entry_size);
624 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
625 				&req.stat_pg_size_stat_lvl,
626 				&req.stat_page_dir);
627 	}
628 	ctxm = &ctx->ctx_arr[BNXT_CTX_STQM];
629 	for (i = 0, num_entries = &req.tqm_sp_num_entries,
630 			pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
631 			pg_dir = &req.tqm_sp_page_dir,
632 	     ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP,
633 	     ctx_pg = ctxm->pg_info;
634 	     i < BNXT_MAX_TQM_LEGACY_RINGS;
635 	     ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[i],
636 	     i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
637 		if (!(enables & ena))
638 			continue;
639 
640 		req.tqm_entry_size = cpu_to_le16(ctxm->entry_size);
641 		*num_entries = cpu_to_le32(ctx_pg->entries);
642 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
643 	}
644 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_RING8) {
645 		pg_attr = &req.tqm_ring8_pg_size_tqm_ring_lvl;
646 		pg_dir = &req.tqm_ring8_page_dir;
647 		ctx_pg = &ctx->ctx_arr[BNXT_CTX_FTQM].pg_info[8];
648 		req.tqm_ring8_num_entries = cpu_to_le32(ctx_pg->entries);
649 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
650 	}
651 	req.flags = cpu_to_le32(flags);
652 	return hwrm_send_message(softc, &req, sizeof(req));
653 }
654 
655 int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
656 {
657 	struct hwrm_func_resource_qcaps_output *resp =
658 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
659 	struct hwrm_func_resource_qcaps_input req = {0};
660 	struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
661 	int rc;
662 
663 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
664 	req.fid = htole16(0xffff);
665 
666 	BNXT_HWRM_LOCK(softc);
667 	rc = _hwrm_send_message(softc, &req, sizeof(req));
668 	if (rc) {
669 		rc = -EIO;
670 		goto hwrm_func_resc_qcaps_exit;
671 	}
672 
673 	hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
674 	if (!all)
675 		goto hwrm_func_resc_qcaps_exit;
676 
677 	hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
678 	hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
679 	hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
680 	hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
681 	hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
682 	hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
683 	hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
684 	hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
685 	hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
686 	hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
687 	hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
688 	hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
689 	hw_resc->min_vnics = le16toh(resp->min_vnics);
690 	hw_resc->max_vnics = le16toh(resp->max_vnics);
691 	hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
692 	hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
693 
694 	if (BNXT_CHIP_P5(softc)) {
695 		hw_resc->max_nqs = le16toh(resp->max_msix);
696 		hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
697 	}
698 
699 hwrm_func_resc_qcaps_exit:
700 	BNXT_HWRM_UNLOCK(softc);
701 	return rc;
702 }
703 
704 int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt_softc *softc,
705 					struct bnxt_ctx_mem_type *ctxm,
706 					bool last)
707 {
708 	struct hwrm_func_backing_store_cfg_v2_input req = {0};
709 	u32 instance_bmap = ctxm->instance_bmap;
710 	int i, j, rc = 0, n = 1;
711 	__le32 *p;
712 
713 	if (!(ctxm->flags & BNXT_CTX_MEM_TYPE_VALID) || !ctxm->pg_info)
714 		return 0;
715 
716 	if (instance_bmap)
717 		n = hweight32(ctxm->instance_bmap);
718 	else
719 		instance_bmap = 1;
720 
721 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG_V2);
722 
723 	req.type = cpu_to_le16(ctxm->type);
724 	req.entry_size = cpu_to_le16(ctxm->entry_size);
725 	for (i = 0, p = &req.split_entry_0; i < ctxm->split_entry_cnt; i++)
726 		p[i] = cpu_to_le32(ctxm->split[i]);
727 	for (i = 0, j = 0; j < n && !rc; i++) {
728 		struct bnxt_ctx_pg_info *ctx_pg;
729 
730 		if (!(instance_bmap & (1 << i)))
731 			continue;
732 		req.instance = cpu_to_le16(i);
733 		ctx_pg = &ctxm->pg_info[j++];
734 		if (!ctx_pg->entries)
735 			continue;
736 		req.num_entries = cpu_to_le32(ctx_pg->entries);
737 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
738 				      &req.page_size_pbl_level,
739 				      &req.page_dir);
740 		if (last && j == (n - 1))
741 			req.flags =
742 				cpu_to_le32(HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_FLAGS_BS_CFG_ALL_DONE);
743 		rc = hwrm_send_message(softc, &req, sizeof(req));
744 	}
745 	return rc;
746 }
747 
748 int
749 bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len,
750 		void *resp, uint32_t resp_len, uint32_t app_timeout)
751 {
752 	int rc = 0;
753 	void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr;
754 	struct input *input = req;
755 	uint32_t old_timeo;
756 
757 	input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
758 	BNXT_HWRM_LOCK(softc);
759 	old_timeo = softc->hwrm_cmd_timeo;
760 	if (input->req_type == HWRM_NVM_INSTALL_UPDATE)
761 		softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
762 	else
763 		softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo);
764 	rc = _hwrm_send_message(softc, req, req_len);
765 	softc->hwrm_cmd_timeo = old_timeo;
766 	if (rc) {
767 		device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n",
768 			      __FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc);
769 		goto fail;
770 	}
771 
772 	memcpy(resp, output, resp_len);
773 fail:
774 	BNXT_HWRM_UNLOCK(softc);
775 	return rc;
776 }
777 
778 
779 int
780 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
781 {
782 	struct hwrm_ver_get_input	req = {0};
783 	struct hwrm_ver_get_output	*resp =
784 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
785 	int				rc;
786 	const char nastr[] = "<not installed>";
787 	const char naver[] = "<N/A>";
788 	uint32_t dev_caps_cfg;
789 	uint16_t fw_maj, fw_min, fw_bld, fw_rsv, len;
790 
791 	softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
792 	softc->hwrm_cmd_timeo = 1000;
793 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
794 
795 	req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
796 	req.hwrm_intf_min = HWRM_VERSION_MINOR;
797 	req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
798 
799 	BNXT_HWRM_LOCK(softc);
800 	rc = _hwrm_send_message(softc, &req, sizeof(req));
801 	if (rc)
802 		goto fail;
803 
804 	snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
805 	    resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
806 	softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b;
807 	softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b;
808 	softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b;
809 	strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
810 	    BNXT_VERSTR_SIZE);
811 	strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
812 	    BNXT_NAME_SIZE);
813 
814 	 softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
815                              resp->hwrm_intf_min_8b << 8 |
816                              resp->hwrm_intf_upd_8b;
817 	if (resp->hwrm_intf_maj_8b < 1) {
818 		 device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
819 			       "than 1.0.0.\n", resp->hwrm_intf_maj_8b,
820 			       resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
821 		 device_printf(softc->dev, "Please update firmware with HWRM "
822 				"interface 1.0.0 or newer.\n");
823 	 }
824 	if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
825 	    resp->mgmt_fw_build == 0) {
826 		strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
827 		strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
828 	}
829 	else {
830 		snprintf(softc->ver_info->mgmt_fw_ver, FW_VER_STR_LEN,
831 		    "%d.%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor,
832 		    resp->mgmt_fw_build, resp->mgmt_fw_patch);
833 		strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
834 		    BNXT_NAME_SIZE);
835 	}
836 	if (resp->netctrl_fw_major == 0 && resp->netctrl_fw_minor == 0 &&
837 	    resp->netctrl_fw_build == 0) {
838 		strlcpy(softc->ver_info->netctrl_fw_ver, naver,
839 		    BNXT_VERSTR_SIZE);
840 		strlcpy(softc->ver_info->netctrl_fw_name, nastr,
841 		    BNXT_NAME_SIZE);
842 	}
843 	else {
844 		snprintf(softc->ver_info->netctrl_fw_ver, FW_VER_STR_LEN,
845 		    "%d.%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor,
846 		    resp->netctrl_fw_build, resp->netctrl_fw_patch);
847 		strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
848 		    BNXT_NAME_SIZE);
849 	}
850 	if (resp->roce_fw_major == 0 && resp->roce_fw_minor == 0 &&
851 	    resp->roce_fw_build == 0) {
852 		strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
853 		strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
854 	}
855 	else {
856 		snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
857 		    "%d.%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor,
858 		    resp->roce_fw_build, resp->roce_fw_patch);
859 		strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
860 		    BNXT_NAME_SIZE);
861 	}
862 
863 	fw_maj = le32toh(resp->hwrm_fw_major);
864 	if (softc->hwrm_spec_code > 0x10803 && fw_maj) {
865 		fw_min = le16toh(resp->hwrm_fw_minor);
866 		fw_bld = le16toh(resp->hwrm_fw_build);
867 		fw_rsv = le16toh(resp->hwrm_fw_patch);
868 		len = FW_VER_STR_LEN;
869 	} else {
870 		fw_maj = resp->hwrm_fw_maj_8b;
871 		fw_min = resp->hwrm_fw_min_8b;
872 		fw_bld = resp->hwrm_fw_bld_8b;
873 		fw_rsv = resp->hwrm_fw_rsvd_8b;
874 		len = BC_HWRM_STR_LEN;
875 	}
876 
877 	softc->ver_info->fw_ver_code = BNXT_FW_VER_CODE(fw_maj, fw_min, fw_bld, fw_rsv);
878 	snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d",
879 			fw_maj, fw_min, fw_bld, fw_rsv);
880 
881 	if (strlen(resp->active_pkg_name)) {
882 		int fw_ver_len = strlen (softc->ver_info->fw_ver_str);
883 
884 		snprintf(softc->ver_info->fw_ver_str + fw_ver_len,
885 				FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
886 				resp->active_pkg_name);
887 		softc->fw_cap |= BNXT_FW_CAP_PKG_VER;
888 	}
889 
890 	softc->ver_info->chip_num = le16toh(resp->chip_num);
891 	softc->ver_info->chip_rev = resp->chip_rev;
892 	softc->ver_info->chip_metal = resp->chip_metal;
893 	softc->ver_info->chip_bond_id = resp->chip_bond_id;
894 	softc->ver_info->chip_type = resp->chip_platform_type;
895 
896 	if (resp->hwrm_intf_maj_8b >= 1) {
897 		softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
898 		softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
899 	}
900 	softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
901 	if (!softc->hwrm_cmd_timeo)
902 		softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
903 
904 	dev_caps_cfg = le32toh(resp->dev_caps_cfg);
905 	if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
906 	    (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
907 		softc->flags |= BNXT_FLAG_SHORT_CMD;
908 
909 	if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
910 	    (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
911 		softc->fw_cap |= BNXT_FW_CAP_SHORT_CMD;
912 
913 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
914 		softc->fw_cap |= BNXT_FW_CAP_KONG_MB_CHNL;
915 
916 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED)
917 		softc->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE;
918 
919 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED)
920 		softc->fw_cap |= BNXT_FW_CAP_TRUSTED_VF;
921 
922 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED)
923 		softc->fw_cap |= BNXT_FW_CAP_CFA_ADV_FLOW;
924 
925 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_EEM_SUPPORTED)
926 		softc->fw_cap |= BNXT_FW_CAP_CFA_EEM;
927 
928 	if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_TRUFLOW_SUPPORTED)
929 		softc->fw_cap |= BNXT_FW_CAP_TRUFLOW_EN;
930 
931 fail:
932 	BNXT_HWRM_UNLOCK(softc);
933 	return rc;
934 }
935 
936 static const u16 bnxt_async_events_arr[] = {
937 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
938 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE,
939 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
940 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
941 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
942 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
943 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE,
944 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY,
945 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY,
946 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG,
947 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFAULT_VNIC_CHANGE,
948 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION,
949 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DEFERRED_RESPONSE,
950 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST,
951 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP,
952 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT,
953 	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE,
954 };
955 
956 int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *bp, unsigned long *bmap, int bmap_size,
957 			    bool async_only)
958 {
959 	DECLARE_BITMAP(async_events_bmap, 256);
960 	u32 *events = (u32 *)async_events_bmap;
961 	struct hwrm_func_drv_rgtr_output *resp =
962 		(void *)bp->hwrm_cmd_resp.idi_vaddr;
963 	struct hwrm_func_drv_rgtr_input req = {0};
964 	u32 flags = 0;
965 	int rc;
966 	int i;
967 
968 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR);
969 	req.ver_maj = HWRM_VERSION_MAJOR;
970 	req.ver_min = HWRM_VERSION_MINOR;
971 	req.ver_upd = HWRM_VERSION_UPDATE;
972 
973 	req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE |
974 				   HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
975 				   HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
976 
977 	if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET)
978 		flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT;
979 	if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
980 		flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT |
981 			 HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_MASTER_SUPPORT;
982 	if (bp->fw_cap & BNXT_FW_CAP_NPAR_1_2)
983 		flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_NPAR_1_2_SUPPORT;
984 	flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ASYM_QUEUE_CFG_SUPPORT;
985 	req.flags = htole32(flags);
986 	req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
987 
988 	if (BNXT_PF(bp)) {
989 		req.enables |=
990 			htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD);
991 	}
992 
993 	if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
994 		req.flags |= cpu_to_le32(HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FLOW_HANDLE_64BIT_MODE);
995 
996 	memset(async_events_bmap, 0, sizeof(async_events_bmap));
997 	for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++) {
998 		u16 event_id = bnxt_async_events_arr[i];
999 
1000 		if (event_id == HWRM_ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY &&
1001 		    !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) {
1002 			continue;
1003 		}
1004 		__set_bit(bnxt_async_events_arr[i], async_events_bmap);
1005 	}
1006 	if (bmap && bmap_size) {
1007 		for (i = 0; i < bmap_size; i++) {
1008 			if (test_bit(i, bmap))
1009 				__set_bit(i, async_events_bmap);
1010 		}
1011 	}
1012 	for (i = 0; i < 8; i++)
1013 		req.async_event_fwd[i] |= htole32(events[i]);
1014 
1015 	if (async_only)
1016 		req.enables =
1017 			htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1018 
1019 	rc = hwrm_send_message(bp, &req, sizeof(req));
1020 
1021 	if (!rc) {
1022 		if (resp->flags &
1023 		    le32toh(HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED))
1024 			bp->fw_cap |= BNXT_FW_CAP_IF_CHANGE;
1025 	}
1026 
1027 
1028 	return rc;
1029 }
1030 
1031 int
1032 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
1033 {
1034 	struct hwrm_func_drv_unrgtr_input req = {0};
1035 
1036 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
1037 	if (shutdown == true)
1038 		req.flags |=
1039 		    HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
1040 	return hwrm_send_message(softc, &req, sizeof(req));
1041 }
1042 
1043 static inline int
1044 _is_valid_ether_addr(uint8_t *addr)
1045 {
1046 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1047 
1048 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1049 		return (FALSE);
1050 
1051 	return (TRUE);
1052 }
1053 
1054 static inline void
1055 get_random_ether_addr(uint8_t *addr)
1056 {
1057 	uint8_t temp[ETHER_ADDR_LEN];
1058 
1059 	arc4rand(&temp, sizeof(temp), 0);
1060 	temp[0] &= 0xFE;
1061 	temp[0] |= 0x02;
1062 	bcopy(temp, addr, sizeof(temp));
1063 }
1064 
1065 int
1066 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
1067 {
1068 	int rc = 0;
1069 	struct hwrm_func_qcaps_input req = {0};
1070 	struct hwrm_func_qcaps_output *resp =
1071 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1072 	struct bnxt_func_info *func = &softc->func;
1073 	uint32_t flags, flags_ext, flags_ext2;
1074 
1075 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
1076 	req.fid = htole16(0xffff);
1077 
1078 	BNXT_HWRM_LOCK(softc);
1079 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1080 	if (rc)
1081 		goto fail;
1082 
1083 	flags = htole32(resp->flags);
1084 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED)
1085 		softc->flags |= BNXT_FLAG_WOL_CAP;
1086 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
1087 		softc->flags |= BNXT_FLAG_FW_CAP_EXT_STATS;
1088 
1089 	/* Enable RoCE only on Thor devices */
1090 	if (BNXT_CHIP_P5(softc)) {
1091 		if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V1_SUPPORTED)
1092 			softc->flags |= BNXT_FLAG_ROCEV1_CAP;
1093 		if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V2_SUPPORTED)
1094 			softc->flags |= BNXT_FLAG_ROCEV2_CAP;
1095 	}
1096 
1097 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_LINK_ADMIN_STATUS_SUPPORTED)
1098 		softc->fw_cap |= BNXT_FW_CAP_LINK_ADMIN;
1099 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ADMIN_PF_SUPPORTED)
1100 		softc->fw_cap |= BNXT_FW_CAP_ADMIN_PF;
1101 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_HOT_RESET_CAPABLE)
1102 		softc->fw_cap |= BNXT_FW_CAP_HOT_RESET;
1103 	if (flags &  HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE)
1104 		softc->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY;
1105 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PCIE_STATS_SUPPORTED)
1106 		softc->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED;
1107 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
1108 		softc->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED;
1109 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERR_RECOVER_RELOAD)
1110 		softc->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD;
1111 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_NOTIFY_VF_DEF_VNIC_CHNG_SUPPORTED)
1112 		softc->fw_cap |= BNXT_FW_CAP_VF_VNIC_NOTIFY;
1113 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_CRASHDUMP_CMD_SUPPORTED)
1114 		softc->fw_cap |= BNXT_FW_CAP_CRASHDUMP;
1115 	if (!(flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_VLAN_ACCELERATION_TX_DISABLED))
1116 		softc->fw_cap |= BNXT_FW_CAP_VLAN_TX_INSERT;
1117 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_DBG_QCAPS_CMD_SUPPORTED)
1118 		softc->fw_cap |= BNXT_FW_CAP_DBG_QCAPS;
1119 
1120 	flags_ext = htole32(resp->flags_ext);
1121 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_EXT_HW_STATS_SUPPORTED)
1122 		softc->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
1123 	if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_ECN_STATS_SUPPORTED))
1124 		softc->fw_cap |= BNXT_FW_CAP_ECN_STATS;
1125 
1126 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PPS_SUPPORTED)
1127 		softc->fw_cap |= BNXT_FW_CAP_PTP_PPS;
1128 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_PTM_SUPPORTED)
1129 		softc->fw_cap |= BNXT_FW_CAP_PTP_PTM;
1130 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_PTP_64BIT_RTC_SUPPORTED)
1131 		softc->fw_cap |= BNXT_FW_CAP_PTP_RTC;
1132 	if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_HOT_RESET_IF_SUPPORT))
1133 		softc->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF;
1134 	if (BNXT_PF(softc) && (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED))
1135 		softc->fw_cap |= BNXT_FW_CAP_LIVEPATCH;
1136 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_NPAR_1_2_SUPPORTED)
1137 		softc->fw_cap |= BNXT_FW_CAP_NPAR_1_2;
1138 	if (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_BS_V2_SUPPORTED)
1139 		softc->fw_cap |= BNXT_FW_CAP_BACKING_STORE_V2;
1140 	if (BNXT_PF(softc) &&
1141 	    (flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_VF_CFG_ASYNC_FOR_PF_SUPPORTED))
1142 		softc->fw_cap |= BNXT_FW_CAP_VF_CFG_FOR_PF;
1143 
1144 	flags_ext2 = htole32(resp->flags_ext2);
1145 	if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_RX_ALL_PKTS_TIMESTAMPS_SUPPORTED)
1146 		softc->fw_cap |= BNXT_FW_CAP_RX_ALL_PKT_TS;
1147 	if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_DBR_DROP_RECOVERY_SUPPORTED)
1148 		softc->fw_cap |= BNXT_FW_CAP_DBR_SUPPORTED;
1149 	if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_DBR_PACING_EXT_SUPPORTED ||
1150 	    flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_DBR_PACING_SUPPORTED)
1151 		softc->fw_cap |= BNXT_FW_CAP_DBR_PACING_SUPPORTED;
1152 
1153 	if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_GENERIC_STATS_SUPPORTED)
1154 		softc->fw_cap |= BNXT_FW_CAP_GENERIC_STATS;
1155 	func->fw_fid = le16toh(resp->fid);
1156 	memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
1157 	func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
1158 	func->max_cp_rings = le16toh(resp->max_cmpl_rings);
1159 	func->max_tx_rings = le16toh(resp->max_tx_rings);
1160 	func->max_rx_rings = le16toh(resp->max_rx_rings);
1161 	func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
1162 	if (!func->max_hw_ring_grps)
1163 		func->max_hw_ring_grps = func->max_tx_rings;
1164 	func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
1165 	func->max_vnics = le16toh(resp->max_vnics);
1166 	func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
1167 	if (BNXT_PF(softc)) {
1168 		struct bnxt_pf_info *pf = &softc->pf;
1169 
1170 		pf->port_id = le16toh(resp->port_id);
1171 		pf->first_vf_id = le16toh(resp->first_vf_id);
1172 		pf->max_vfs = le16toh(resp->max_vfs);
1173 		pf->max_encap_records = le32toh(resp->max_encap_records);
1174 		pf->max_decap_records = le32toh(resp->max_decap_records);
1175 		pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
1176 		pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
1177 		pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
1178 		pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
1179 	}
1180 	if (!_is_valid_ether_addr(func->mac_addr)) {
1181 		device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
1182 		get_random_ether_addr(func->mac_addr);
1183 	}
1184 
1185 fail:
1186 	BNXT_HWRM_UNLOCK(softc);
1187 	return rc;
1188 }
1189 
1190 int
1191 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
1192 {
1193 	struct hwrm_func_qcfg_input req = {0};
1194 	struct hwrm_func_qcfg_output *resp =
1195 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
1196 	struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
1197 	uint32_t min_db_offset = 0;
1198 	uint16_t flags;
1199 	int rc;
1200 
1201 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
1202 	req.fid = htole16(0xffff);
1203 	BNXT_HWRM_LOCK(softc);
1204 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1205 	if (rc)
1206 		goto end;
1207 
1208 	fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
1209 	fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
1210 	fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
1211 	fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
1212 
1213 	switch (resp->port_partition_type) {
1214 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0:
1215 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_2:
1216 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5:
1217 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0:
1218 		softc->port_partition_type = resp->port_partition_type;
1219 		break;
1220 	}
1221 
1222 	flags = le16toh(resp->flags);
1223 	if (flags & (HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED |
1224 		     HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_LLDP_AGENT_ENABLED)) {
1225 		softc->fw_cap |= BNXT_FW_CAP_LLDP_AGENT;
1226 		if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_FW_DCBX_AGENT_ENABLED)
1227 			softc->fw_cap |= BNXT_FW_CAP_DCBX_AGENT;
1228 	}
1229 	if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_HOST))
1230 		softc->flags |= BNXT_FLAG_MULTI_HOST;
1231 	if (BNXT_PF(softc) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_MULTI_ROOT))
1232 		softc->flags |= BNXT_FLAG_MULTI_ROOT;
1233 	if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_SECURE_MODE_ENABLED)
1234 		softc->fw_cap |= BNXT_FW_CAP_SECURE_MODE;
1235 	if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_RING_MONITOR_ENABLED)
1236 		softc->fw_cap |= BNXT_FW_CAP_RING_MONITOR;
1237 	if (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_ENABLE_RDMA_SRIOV)
1238 		softc->fw_cap |= BNXT_FW_CAP_ENABLE_RDMA_SRIOV;
1239 
1240 	if (softc->db_size)
1241 		goto end;
1242 
1243 	softc->legacy_db_size = le16_to_cpu(resp->legacy_l2_db_size_kb) * 1024;
1244 
1245 	if (BNXT_CHIP_P5(softc)) {
1246 		if (BNXT_PF(softc))
1247 		min_db_offset = DB_PF_OFFSET_P5;
1248 		else
1249 			min_db_offset = DB_VF_OFFSET_P5;
1250 	}
1251 
1252 	softc->db_size = roundup2(le16_to_cpu(resp->l2_doorbell_bar_size_kb) *
1253 			1024, PAGE_SIZE);
1254 	if (!softc->db_size || softc->db_size > pci_resource_len(softc->pdev, 2) ||
1255 			softc->db_size <= min_db_offset)
1256 		softc->db_size = pci_resource_len(softc->pdev, 2);
1257 
1258 	end:
1259 	BNXT_HWRM_UNLOCK(softc);
1260 	return rc;
1261 }
1262 
1263 int
1264 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
1265 {
1266 	struct hwrm_func_reset_input req = {0};
1267 
1268 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
1269 	req.enables = 0;
1270 
1271 	return hwrm_send_message(softc, &req, sizeof(req));
1272 }
1273 
1274 static void
1275 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
1276     struct hwrm_port_phy_cfg_input *req)
1277 {
1278 	struct bnxt_link_info *link_info = &softc->link_info;
1279 	uint8_t autoneg = softc->link_info.autoneg;
1280 	uint16_t fw_link_speed = softc->link_info.req_link_speed;
1281 
1282 	if (autoneg & BNXT_AUTONEG_SPEED) {
1283 		uint8_t phy_type = get_phy_type(softc);
1284 
1285 		if (phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET ||
1286 		    phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
1287 		    phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE) {
1288 
1289 			req->auto_mode |= htole32(HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK);
1290 			if (link_info->advertising) {
1291 				req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK);
1292 				req->auto_link_speed_mask = htole16(link_info->advertising);
1293 			}
1294 		} else {
1295 			req->auto_mode |= HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
1296 		}
1297 
1298 		req->enables |=
1299 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
1300 		req->flags |=
1301 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
1302 	} else {
1303 		req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
1304 
1305 		if (link_info->force_pam4_speed_set_by_user) {
1306 			req->force_pam4_link_speed = htole16(fw_link_speed);
1307 			req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED);
1308 			link_info->force_pam4_speed_set_by_user = false;
1309 		} else {
1310 			req->force_link_speed = htole16(fw_link_speed);
1311 		}
1312 	}
1313 
1314 	/* tell chimp that the setting takes effect immediately */
1315 	req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
1316 }
1317 
1318 static void
1319 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
1320     struct hwrm_port_phy_cfg_input *req)
1321 {
1322 	struct bnxt_link_info *link_info = &softc->link_info;
1323 
1324 	if (link_info->flow_ctrl.autoneg) {
1325 		req->auto_pause =
1326 		    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
1327 		if (link_info->flow_ctrl.rx)
1328 			req->auto_pause |=
1329 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
1330 		if (link_info->flow_ctrl.tx)
1331 			req->auto_pause |=
1332 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
1333 		req->enables |=
1334 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
1335 	} else {
1336 		if (link_info->flow_ctrl.rx)
1337 			req->force_pause |=
1338 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
1339 		if (link_info->flow_ctrl.tx)
1340 			req->force_pause |=
1341 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
1342 		req->enables |=
1343 			htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
1344 		req->auto_pause = req->force_pause;
1345 		req->enables |=
1346 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
1347 	}
1348 }
1349 
1350 /* JFV this needs interface connection */
1351 static void
1352 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
1353 {
1354 	/* struct ethtool_eee *eee = &softc->eee; */
1355 	bool	eee_enabled = false;
1356 
1357 	if (eee_enabled) {
1358 #if 0
1359 		uint16_t eee_speeds;
1360 		uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
1361 
1362 		if (eee->tx_lpi_enabled)
1363 			flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
1364 
1365 		req->flags |= htole32(flags);
1366 		eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
1367 		req->eee_link_speed_mask = htole16(eee_speeds);
1368 		req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
1369 #endif
1370 	} else {
1371 		req->flags |=
1372 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
1373 	}
1374 }
1375 
1376 int
1377 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
1378     bool set_eee, bool set_link)
1379 {
1380 	struct hwrm_port_phy_cfg_input req = {0};
1381 	int rc;
1382 
1383 	if (softc->flags & BNXT_FLAG_NPAR)
1384 		return ENOTSUP;
1385 
1386 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
1387 
1388 	if (set_pause) {
1389 		bnxt_hwrm_set_pause_common(softc, &req);
1390 
1391 		if (softc->link_info.flow_ctrl.autoneg)
1392 			set_link = true;
1393 	}
1394 
1395 	if (set_link)
1396 		bnxt_hwrm_set_link_common(softc, &req);
1397 
1398 	if (set_eee)
1399 		bnxt_hwrm_set_eee(softc, &req);
1400 
1401 	BNXT_HWRM_LOCK(softc);
1402 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1403 
1404 	if (!rc) {
1405 		if (set_pause) {
1406 			/* since changing of 'force pause' setting doesn't
1407 			 * trigger any link change event, the driver needs to
1408 			 * update the current pause result upon successfully i
1409 			 * return of the phy_cfg command */
1410 			if (!softc->link_info.flow_ctrl.autoneg)
1411 				bnxt_report_link(softc);
1412 		}
1413 	}
1414 	BNXT_HWRM_UNLOCK(softc);
1415 	return rc;
1416 }
1417 
1418 int
1419 bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1420 {
1421 	struct hwrm_vnic_plcmodes_cfg_input req = {0};
1422 
1423 	if (!BNXT_CHIP_P5(softc))
1424 		return 0;
1425 
1426 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
1427 
1428 	req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
1429 	req.vnic_id = htole16(vnic->id);
1430 
1431 	return hwrm_send_message(softc, &req, sizeof(req));
1432 }
1433 
1434 int
1435 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1436 {
1437 	struct hwrm_vnic_cfg_input req = {0};
1438 
1439 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
1440 
1441 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1442 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
1443 	if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
1444 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
1445 	if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
1446 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
1447 	if (BNXT_CHIP_P5 (softc)) {
1448 		req.default_rx_ring_id =
1449 			htole16(softc->rx_rings[0].phys_id);
1450 		req.default_cmpl_ring_id =
1451 			htole16(softc->rx_cp_rings[0].ring.phys_id);
1452 		req.enables |=
1453 			htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
1454 			    HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
1455 		req.vnic_id = htole16(vnic->id);
1456 	} else {
1457 		req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
1458 				HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
1459 		req.vnic_id = htole16(vnic->id);
1460 		req.dflt_ring_grp = htole16(vnic->def_ring_grp);
1461 	}
1462 	req.rss_rule = htole16(vnic->rss_id);
1463 	req.cos_rule = htole16(vnic->cos_rule);
1464 	req.lb_rule = htole16(vnic->lb_rule);
1465 	req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
1466 	req.mru = htole16(vnic->mru);
1467 
1468 	return hwrm_send_message(softc, &req, sizeof(req));
1469 }
1470 
1471 int
1472 bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1473 {
1474 	struct hwrm_vnic_free_input req = {0};
1475 	int rc = 0;
1476 
1477 	if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE)
1478 		return rc;
1479 
1480 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
1481 
1482 	req.vnic_id = htole32(vnic->id);
1483 
1484 	BNXT_HWRM_LOCK(softc);
1485 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1486 	if (rc)
1487 		goto fail;
1488 
1489 fail:
1490 	BNXT_HWRM_UNLOCK(softc);
1491 	return (rc);
1492 }
1493 
1494 int
1495 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1496 {
1497 	struct hwrm_vnic_alloc_input req = {0};
1498 	struct hwrm_vnic_alloc_output *resp =
1499 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1500 	int rc;
1501 
1502 	if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
1503 		device_printf(softc->dev,
1504 		    "Attempt to re-allocate vnic %04x\n", vnic->id);
1505 		return EDOOFUS;
1506 	}
1507 
1508 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
1509 
1510 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1511 		req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
1512 
1513 	BNXT_HWRM_LOCK(softc);
1514 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1515 	if (rc)
1516 		goto fail;
1517 
1518 	vnic->id = le32toh(resp->vnic_id);
1519 
1520 fail:
1521 	BNXT_HWRM_UNLOCK(softc);
1522 	return (rc);
1523 }
1524 
1525 int
1526 bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t ctx_id)
1527 {
1528 	struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
1529 	int rc = 0;
1530 
1531 	if (ctx_id == (uint16_t)HWRM_NA_SIGNATURE)
1532 		return rc;
1533 
1534 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
1535 	req.rss_cos_lb_ctx_id = htole16(ctx_id);
1536 	BNXT_HWRM_LOCK(softc);
1537 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1538 	if (rc)
1539 		goto fail;
1540 
1541 fail:
1542 	BNXT_HWRM_UNLOCK(softc);
1543 	return rc;
1544 }
1545 
1546 int
1547 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
1548 {
1549 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
1550 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
1551 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1552 	int rc;
1553 
1554 	if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
1555 		device_printf(softc->dev,
1556 		    "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
1557 		return EDOOFUS;
1558 	}
1559 
1560 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
1561 
1562 	BNXT_HWRM_LOCK(softc);
1563 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1564 	if (rc)
1565 		goto fail;
1566 
1567 	*ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
1568 
1569 fail:
1570 	BNXT_HWRM_UNLOCK(softc);
1571 	return (rc);
1572 }
1573 
1574 int
1575 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1576 {
1577 	struct hwrm_ring_grp_alloc_input req = {0};
1578 	struct hwrm_ring_grp_alloc_output *resp;
1579 	int rc = 0;
1580 
1581 	if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
1582 		device_printf(softc->dev,
1583 		    "Attempt to re-allocate ring group %04x\n", grp->grp_id);
1584 		return EDOOFUS;
1585 	}
1586 
1587 	if (BNXT_CHIP_P5 (softc))
1588 		return 0;
1589 
1590 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1591 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
1592 	req.cr = htole16(grp->cp_ring_id);
1593 	req.rr = htole16(grp->rx_ring_id);
1594 	req.ar = htole16(grp->ag_ring_id);
1595 	req.sc = htole16(grp->stats_ctx);
1596 
1597 	BNXT_HWRM_LOCK(softc);
1598 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1599 	if (rc)
1600 		goto fail;
1601 
1602 	grp->grp_id = le32toh(resp->ring_group_id);
1603 
1604 fail:
1605 	BNXT_HWRM_UNLOCK(softc);
1606 	return rc;
1607 }
1608 
1609 int
1610 bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1611 {
1612 	struct hwrm_ring_grp_free_input req = {0};
1613 	int rc = 0;
1614 
1615 	if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE)
1616 		return 0;
1617 
1618 	if (BNXT_CHIP_P5 (softc))
1619 		return 0;
1620 
1621 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
1622 
1623 	req.ring_group_id = htole32(grp->grp_id);
1624 
1625 	BNXT_HWRM_LOCK(softc);
1626 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1627 	if (rc)
1628 		goto fail;
1629 
1630 fail:
1631 	BNXT_HWRM_UNLOCK(softc);
1632 	return rc;
1633 }
1634 
1635 int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t ring_type,
1636 		struct bnxt_ring *ring, int cmpl_ring_id)
1637 {
1638         struct hwrm_ring_free_input req = {0};
1639 	struct hwrm_ring_free_output *resp;
1640 	int rc = 0;
1641         uint16_t error_code;
1642 
1643 	if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE)
1644 		return 0;
1645 
1646 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1647 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
1648 	req.cmpl_ring = htole16(cmpl_ring_id);
1649         req.ring_type = ring_type;
1650         req.ring_id = htole16(ring->phys_id);
1651 
1652 	BNXT_HWRM_LOCK(softc);
1653 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1654         error_code = le16toh(resp->error_code);
1655 
1656 	if (rc || error_code) {
1657 		device_printf(softc->dev, "hwrm_ring_free type %d failed. "
1658 				"rc:%x err:%x\n", ring_type, rc, error_code);
1659 		if (!rc)
1660 			rc = -EIO;
1661 	}
1662 
1663 	BNXT_HWRM_UNLOCK(softc);
1664 	return rc;
1665 }
1666 
1667 /*
1668  * Ring allocation message to the firmware
1669  */
1670 int
1671 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
1672                      struct bnxt_ring *ring)
1673 {
1674 	struct hwrm_ring_alloc_input req = {0};
1675 	struct hwrm_ring_alloc_output *resp;
1676 	uint16_t idx = ring->idx;
1677 	struct bnxt_cp_ring *cp_ring;
1678 	int rc;
1679 
1680 	if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1681 		device_printf(softc->dev,
1682 		    "Attempt to re-allocate ring %04x\n", ring->phys_id);
1683 		return EDOOFUS;
1684 	}
1685 
1686 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1687 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
1688 	req.enables = htole32(0);
1689 	req.fbo = htole32(0);
1690 	req.ring_type = type;
1691 	req.page_tbl_addr = htole64(ring->paddr);
1692 	req.logical_id = htole16(ring->id);
1693 	req.length = htole32(ring->ring_size);
1694 
1695 	switch (type) {
1696 	case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
1697 		cp_ring = &softc->tx_cp_rings[idx];
1698 
1699 		req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
1700 		/* queue_id - what CoS queue the TX ring is associated with */
1701 		req.queue_id = htole16(softc->tx_q_info[0].queue_id);
1702 
1703 		req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1704 		req.enables |= htole32(
1705 		    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1706 		break;
1707 	case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
1708 		if (!BNXT_CHIP_P5(softc))
1709 			break;
1710 
1711 		cp_ring = &softc->rx_cp_rings[idx];
1712 
1713 		req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1714 		req.rx_buf_size = htole16(softc->rx_buf_size);
1715 		req.enables |= htole32(
1716 			HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1717 			HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1718 		break;
1719 	case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
1720 		if (!BNXT_CHIP_P5(softc)) {
1721 			req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
1722 			break;
1723 		}
1724 
1725 		cp_ring = &softc->rx_cp_rings[idx];
1726 
1727 		req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
1728 		req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1729 		req.rx_buf_size = htole16(softc->rx_buf_size);
1730 		req.enables |= htole32(
1731 			HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
1732 			HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1733 			HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1734 		break;
1735 	case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
1736 		if (!BNXT_CHIP_P5(softc)) {
1737 			req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1738 			break;
1739 		}
1740 
1741                 req.cq_handle = htole64(ring->id);
1742 		req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
1743 		req.enables |= htole32(
1744 			HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
1745 		break;
1746 	case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
1747 		req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1748 		break;
1749 	default:
1750 		device_printf(softc->dev,
1751 			      "hwrm alloc invalid ring type %d\n", type);
1752 		return -1;
1753 	}
1754 
1755 	BNXT_HWRM_LOCK(softc);
1756 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1757 	if (rc)
1758 		goto fail;
1759 
1760 	ring->phys_id = le16toh(resp->ring_id);
1761 
1762 fail:
1763 	BNXT_HWRM_UNLOCK(softc);
1764 	return rc;
1765 }
1766 
1767 int
1768 bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
1769 {
1770 	struct hwrm_stat_ctx_free_input req = {0};
1771 	int rc = 0;
1772 
1773 	if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE)
1774 		return rc;
1775 
1776 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
1777 
1778 	req.stat_ctx_id = htole16(cpr->stats_ctx_id);
1779 	BNXT_HWRM_LOCK(softc);
1780 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1781 	if (rc)
1782 		goto fail;
1783 
1784 fail:
1785 	BNXT_HWRM_UNLOCK(softc);
1786 
1787 	return rc;
1788 }
1789 
1790 int
1791 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
1792     uint64_t paddr)
1793 {
1794 	struct hwrm_stat_ctx_alloc_input req = {0};
1795 	struct hwrm_stat_ctx_alloc_output *resp;
1796 	int rc = 0;
1797 
1798 	if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
1799 		device_printf(softc->dev,
1800 		    "Attempt to re-allocate stats ctx %08x\n",
1801 		    cpr->stats_ctx_id);
1802 		return EDOOFUS;
1803 	}
1804 
1805 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1806 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
1807 
1808 	req.update_period_ms = htole32(1000);
1809 	req.stats_dma_addr = htole64(paddr);
1810 	if (BNXT_CHIP_P5(softc))
1811 		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
1812 	else
1813 		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
1814 
1815 	BNXT_HWRM_LOCK(softc);
1816 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1817 	if (rc)
1818 		goto fail;
1819 
1820 	cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
1821 
1822 fail:
1823 	BNXT_HWRM_UNLOCK(softc);
1824 
1825 	return rc;
1826 }
1827 
1828 int
1829 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
1830 {
1831 	struct hwrm_port_qstats_input req = {0};
1832 	int rc = 0;
1833 
1834 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
1835 
1836 	req.port_id = htole16(softc->pf.port_id);
1837 	req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
1838 	req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
1839 
1840 	BNXT_HWRM_LOCK(softc);
1841 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1842 	BNXT_HWRM_UNLOCK(softc);
1843 
1844 	return rc;
1845 }
1846 static int bnxt_hwrm_pri2cos_idx(struct bnxt_softc *softc, uint32_t path_dir)
1847 {
1848 	struct hwrm_queue_pri2cos_qcfg_input req = {0};
1849 	struct hwrm_queue_pri2cos_qcfg_output *resp;
1850 	uint8_t *pri2cos_idx, *q_ids, max_q;
1851 	int rc, i, j;
1852 	uint8_t *pri2cos;
1853 
1854 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG);
1855 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1856 
1857 	req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN |
1858 			    path_dir);
1859 	rc = hwrm_send_message(softc, &req, sizeof(req));
1860 
1861 	if (rc)
1862 		return rc;
1863 
1864 	if (path_dir == HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX) {
1865 		pri2cos_idx = softc->tx_pri2cos_idx;
1866 		q_ids = softc->tx_q_ids;
1867 		max_q = softc->tx_max_q;
1868 	} else {
1869 		pri2cos_idx = softc->rx_pri2cos_idx;
1870 		q_ids = softc->rx_q_ids;
1871 		max_q = softc->rx_max_q;
1872 	}
1873 
1874 	pri2cos = &resp->pri0_cos_queue_id;
1875 
1876 	for (i = 0; i < BNXT_MAX_QUEUE; i++) {
1877 		uint8_t queue_id = pri2cos[i];
1878 		uint8_t queue_idx;
1879 
1880 		/* Per port queue IDs start from 0, 10, 20, etc */
1881 		queue_idx = queue_id % 10;
1882 		if (queue_idx > BNXT_MAX_QUEUE) {
1883 			softc->pri2cos_valid = false;
1884 			rc = -EINVAL;
1885 			return rc;
1886 		}
1887 
1888 		for (j = 0; j < max_q; j++) {
1889 			if (q_ids[j] == queue_id)
1890 				pri2cos_idx[i] = queue_idx;
1891 		}
1892 	}
1893 
1894 	softc->pri2cos_valid = true;
1895 
1896 	return rc;
1897 }
1898 
1899 int
1900 bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc)
1901 {
1902 	struct hwrm_port_qstats_ext_input req = {0};
1903 	struct hwrm_port_qstats_ext_output *resp;
1904 	int rc = 0, i;
1905 	uint32_t tx_stat_size;
1906 
1907 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS_EXT);
1908 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1909 
1910 	tx_stat_size = sizeof(struct tx_port_stats_ext);
1911 	req.port_id = htole16(softc->pf.port_id);
1912 	req.tx_stat_size = htole16(tx_stat_size);
1913 	req.rx_stat_size = htole16(sizeof(struct rx_port_stats_ext));
1914 	req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats_ext.idi_paddr);
1915 	req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats_ext.idi_paddr);
1916 
1917 	rc = hwrm_send_message(softc, &req, sizeof(req));
1918 
1919 	if (!rc) {
1920 		softc->fw_rx_stats_ext_size =
1921 			le16toh(resp->rx_stat_size) / 8;
1922 		if (BNXT_FW_MAJ(softc) < 220 &&
1923 		    softc->fw_rx_stats_ext_size > BNXT_RX_STATS_EXT_NUM_LEGACY)
1924 			softc->fw_rx_stats_ext_size = BNXT_RX_STATS_EXT_NUM_LEGACY;
1925 
1926 		softc->fw_tx_stats_ext_size = tx_stat_size ?
1927 			le16toh(resp->tx_stat_size) / 8 : 0;
1928 	} else {
1929 		softc->fw_rx_stats_ext_size = 0;
1930 		softc->fw_tx_stats_ext_size = 0;
1931 	}
1932 
1933 	if (softc->fw_tx_stats_ext_size <=
1934 	    offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) {
1935 		softc->pri2cos_valid = false;
1936 		return rc;
1937 	}
1938 
1939 	rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX);
1940 	if (rc)
1941 		return rc;
1942 
1943 	if (softc->is_asym_q) {
1944 		rc = bnxt_hwrm_pri2cos_idx(softc, HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX);
1945 		if (rc)
1946 			return rc;
1947 	} else {
1948 		memcpy(softc->rx_pri2cos_idx, softc->tx_pri2cos_idx, sizeof(softc->rx_pri2cos_idx));
1949 	}
1950 
1951 	u64 *rx_port_stats_ext = (u64 *)softc->hw_rx_port_stats_ext.idi_vaddr;
1952 	u64 *tx_port_stats_ext = (u64 *)softc->hw_tx_port_stats_ext.idi_vaddr;
1953 
1954 	if (softc->pri2cos_valid) {
1955 		for (i = 0; i < 8; i++) {
1956 			long n = bnxt_rx_bytes_pri_arr_base_off[i] +
1957 				 softc->rx_pri2cos_idx[i];
1958 
1959 			softc->rx_bytes_pri[i] = *(rx_port_stats_ext + n);
1960 		}
1961 		for (i = 0; i < 8; i++) {
1962 			long n = bnxt_rx_pkts_pri_arr_base_off[i] +
1963 				 softc->rx_pri2cos_idx[i];
1964 
1965 			softc->rx_packets_pri[i] = *(rx_port_stats_ext + n);
1966 		}
1967 		for (i = 0; i < 8; i++) {
1968 			long n = bnxt_tx_bytes_pri_arr_base_off[i] +
1969 				 softc->tx_pri2cos_idx[i];
1970 
1971 			softc->tx_bytes_pri[i] = *(tx_port_stats_ext + n);
1972 		}
1973 		for (i = 0; i < 8; i++) {
1974 			long n = bnxt_tx_pkts_pri_arr_base_off[i] +
1975 				 softc->tx_pri2cos_idx[i];
1976 
1977 			softc->tx_packets_pri[i] = *(tx_port_stats_ext + n);
1978 		}
1979 	}
1980 
1981 	return rc;
1982 }
1983 
1984 int
1985 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
1986     struct bnxt_vnic_info *vnic)
1987 {
1988 	struct hwrm_cfa_l2_set_rx_mask_input req = {0};
1989 	uint32_t mask = vnic->rx_mask;
1990 
1991 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
1992 
1993 	req.vnic_id = htole32(vnic->id);
1994 	req.mask = htole32(mask);
1995 	req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
1996 	req.num_mc_entries = htole32(vnic->mc_list_count);
1997 	return hwrm_send_message(softc, &req, sizeof(req));
1998 }
1999 
2000 int
2001 bnxt_hwrm_l2_filter_free(struct bnxt_softc *softc, uint64_t filter_id)
2002 {
2003 	struct hwrm_cfa_l2_filter_free_input	req = {0};
2004 	int rc = 0;
2005 
2006 	if (filter_id == -1)
2007 		return rc;
2008 
2009 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
2010 
2011 	req.l2_filter_id = htole64(filter_id);
2012 
2013 	BNXT_HWRM_LOCK(softc);
2014 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2015 	if (rc)
2016 		goto fail;
2017 
2018 fail:
2019 	BNXT_HWRM_UNLOCK(softc);
2020 	return (rc);
2021 }
2022 
2023 int
2024 bnxt_hwrm_free_filter(struct bnxt_softc *softc)
2025 {
2026 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
2027 	struct bnxt_vlan_tag *tag;
2028 	int rc = 0;
2029 
2030 	rc = bnxt_hwrm_l2_filter_free(softc, softc->vnic_info.filter_id);
2031 	if (rc)
2032 		goto end;
2033 
2034 	SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
2035 		rc = bnxt_hwrm_l2_filter_free(softc, tag->filter_id);
2036 		if (rc)
2037 			goto end;
2038 		tag->filter_id = -1;
2039 	}
2040 
2041 end:
2042 	return rc;
2043 }
2044 
2045 int
2046 bnxt_hwrm_l2_filter_alloc(struct bnxt_softc *softc, uint16_t vlan_tag,
2047 		uint64_t *filter_id)
2048 {
2049 	struct hwrm_cfa_l2_filter_alloc_input	req = {0};
2050 	struct hwrm_cfa_l2_filter_alloc_output	*resp;
2051 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
2052 	uint32_t enables = 0;
2053 	int rc = 0;
2054 
2055 	if (*filter_id != -1) {
2056 		device_printf(softc->dev, "Attempt to re-allocate l2 ctx "
2057 		    "filter (fid: 0x%jx)\n", (uintmax_t)*filter_id);
2058 		return EDOOFUS;
2059 	}
2060 
2061 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
2062 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
2063 
2064 	req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
2065 	enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
2066 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
2067 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
2068 
2069 	if (vlan_tag != 0xffff) {
2070 		enables |=
2071 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN |
2072 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK |
2073 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_NUM_VLANS;
2074 		req.l2_ivlan_mask = 0xffff;
2075 		req.l2_ivlan = vlan_tag;
2076 		req.num_vlans = 1;
2077 	}
2078 
2079 	req.enables = htole32(enables);
2080 	req.dst_id = htole16(vnic->id);
2081 	memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
2082 	    ETHER_ADDR_LEN);
2083 	memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
2084 
2085 	BNXT_HWRM_LOCK(softc);
2086 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2087 	if (rc)
2088 		goto fail;
2089 
2090 	*filter_id = le64toh(resp->l2_filter_id);
2091 fail:
2092 	BNXT_HWRM_UNLOCK(softc);
2093 	return (rc);
2094 }
2095 
2096 int
2097 bnxt_hwrm_set_filter(struct bnxt_softc *softc)
2098 {
2099 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
2100 	struct bnxt_vlan_tag *tag;
2101 	int rc = 0;
2102 
2103 	rc = bnxt_hwrm_l2_filter_alloc(softc, 0xffff, &vnic->filter_id);
2104 	if (rc)
2105 		goto end;
2106 
2107 	SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
2108 		rc = bnxt_hwrm_l2_filter_alloc(softc, tag->tag,
2109 				&tag->filter_id);
2110 		if (rc)
2111 			goto end;
2112 	}
2113 
2114 end:
2115 	return rc;
2116 }
2117 
2118 int
2119 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
2120     uint32_t hash_type)
2121 {
2122 	struct hwrm_vnic_rss_cfg_input	req = {0};
2123 
2124 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
2125 
2126 	req.hash_type = htole32(hash_type);
2127 	req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
2128 	req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
2129 	req.rss_ctx_idx = htole16(vnic->rss_id);
2130 	req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
2131 	if (BNXT_CHIP_P5(softc)) {
2132 		req.vnic_id = htole16(vnic->id);
2133 		req.ring_table_pair_index = 0x0;
2134 	}
2135 
2136 	return hwrm_send_message(softc, &req, sizeof(req));
2137 }
2138 
2139 int
2140 bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
2141 {
2142 	struct hwrm_func_cfg_input req = {0};
2143 
2144 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
2145 
2146 	req.fid = htole16(0xffff);
2147 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
2148 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
2149 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
2150 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
2151 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
2152 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
2153 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
2154 	req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
2155 	req.num_rsscos_ctxs = htole16(0x8);
2156 	req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
2157 	req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
2158 	req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
2159 	req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
2160 	req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
2161 
2162 	return hwrm_send_message(softc, &req, sizeof(req));
2163 }
2164 
2165 int
2166 bnxt_cfg_async_cr(struct bnxt_softc *softc)
2167 {
2168 	int rc = 0;
2169 	struct hwrm_func_cfg_input req = {0};
2170 
2171 	if (!BNXT_PF(softc))
2172 		return 0;
2173 
2174 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
2175 
2176 	req.fid = htole16(0xffff);
2177 	req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
2178 	if (BNXT_CHIP_P5(softc))
2179 		req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id);
2180 	else
2181 		req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
2182 
2183 	rc = hwrm_send_message(softc, &req, sizeof(req));
2184 
2185 	return rc;
2186 }
2187 
2188 void
2189 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
2190 {
2191 	softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
2192 
2193         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
2194 
2195 	softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
2196 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
2197 
2198 	softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
2199 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
2200 
2201 	softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
2202 }
2203 
2204 int
2205 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
2206 {
2207 	struct hwrm_vnic_tpa_cfg_input req = {0};
2208 	uint32_t flags;
2209 
2210 	if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
2211 		return 0;
2212 	}
2213 
2214 	if (!(softc->flags & BNXT_FLAG_TPA))
2215 		return 0;
2216 
2217 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
2218 
2219 	if (softc->hw_lro.enable) {
2220 		flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
2221 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
2222 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
2223 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
2224 
2225         	if (softc->hw_lro.is_mode_gro)
2226 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
2227 		else
2228 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
2229 
2230 		req.flags = htole32(flags);
2231 
2232 		req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
2233 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
2234 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
2235 
2236 		req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
2237 		req.max_aggs = htole16(softc->hw_lro.max_aggs);
2238 		req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
2239 	}
2240 
2241 	req.vnic_id = htole16(softc->vnic_info.id);
2242 
2243 	return hwrm_send_message(softc, &req, sizeof(req));
2244 }
2245 
2246 int
2247 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
2248     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
2249     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
2250     uint32_t *fw_ver)
2251 {
2252 	struct hwrm_nvm_find_dir_entry_input req = {0};
2253 	struct hwrm_nvm_find_dir_entry_output *resp =
2254 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2255 	int	rc = 0;
2256 	uint32_t old_timeo;
2257 
2258 	MPASS(ordinal);
2259 
2260 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
2261 	if (use_index) {
2262 		req.enables = htole32(
2263 		    HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
2264 		req.dir_idx = htole16(*index);
2265 	}
2266 	req.dir_type = htole16(type);
2267 	req.dir_ordinal = htole16(*ordinal);
2268 	req.dir_ext = htole16(ext);
2269 	req.opt_ordinal = search_opt;
2270 
2271 	BNXT_HWRM_LOCK(softc);
2272 	old_timeo = softc->hwrm_cmd_timeo;
2273 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2274 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2275 	softc->hwrm_cmd_timeo = old_timeo;
2276 	if (rc)
2277 		goto exit;
2278 
2279 	if (item_length)
2280 		*item_length = le32toh(resp->dir_item_length);
2281 	if (data_length)
2282 		*data_length = le32toh(resp->dir_data_length);
2283 	if (fw_ver)
2284 		*fw_ver = le32toh(resp->fw_ver);
2285 	*ordinal = le16toh(resp->dir_ordinal);
2286 	if (index)
2287 		*index = le16toh(resp->dir_idx);
2288 
2289 exit:
2290 	BNXT_HWRM_UNLOCK(softc);
2291 	return (rc);
2292 }
2293 
2294 int
2295 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
2296     uint32_t length, struct iflib_dma_info *data)
2297 {
2298 	struct hwrm_nvm_read_input req = {0};
2299 	int rc;
2300 	uint32_t old_timeo;
2301 
2302 	if (length > data->idi_size) {
2303 		rc = EINVAL;
2304 		goto exit;
2305 	}
2306 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
2307 	req.host_dest_addr = htole64(data->idi_paddr);
2308 	req.dir_idx = htole16(index);
2309 	req.offset = htole32(offset);
2310 	req.len = htole32(length);
2311 	BNXT_HWRM_LOCK(softc);
2312 	old_timeo = softc->hwrm_cmd_timeo;
2313 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2314 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2315 	softc->hwrm_cmd_timeo = old_timeo;
2316 	BNXT_HWRM_UNLOCK(softc);
2317 	if (rc)
2318 		goto exit;
2319 	bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
2320 
2321 	goto exit;
2322 
2323 exit:
2324 	return rc;
2325 }
2326 
2327 int
2328 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
2329     void *data, bool cpyin, uint32_t length)
2330 {
2331 	struct hwrm_nvm_modify_input req = {0};
2332 	struct iflib_dma_info dma_data;
2333 	int rc;
2334 	uint32_t old_timeo;
2335 
2336 	if (length == 0 || !data)
2337 		return EINVAL;
2338 	rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
2339 	    BUS_DMA_NOWAIT);
2340 	if (rc)
2341 		return ENOMEM;
2342 	if (cpyin) {
2343 		rc = copyin(data, dma_data.idi_vaddr, length);
2344 		if (rc)
2345 			goto exit;
2346 	}
2347 	else
2348 		memcpy(dma_data.idi_vaddr, data, length);
2349 	bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
2350 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2351 
2352 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
2353 	req.host_src_addr = htole64(dma_data.idi_paddr);
2354 	req.dir_idx = htole16(index);
2355 	req.offset = htole32(offset);
2356 	req.len = htole32(length);
2357 	BNXT_HWRM_LOCK(softc);
2358 	old_timeo = softc->hwrm_cmd_timeo;
2359 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2360 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2361 	softc->hwrm_cmd_timeo = old_timeo;
2362 	BNXT_HWRM_UNLOCK(softc);
2363 
2364 exit:
2365 	iflib_dma_free(&dma_data);
2366 	return rc;
2367 }
2368 
2369 int
2370 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
2371     uint8_t *selfreset)
2372 {
2373 	struct hwrm_fw_reset_input req = {0};
2374 	struct hwrm_fw_reset_output *resp =
2375 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2376 	int rc;
2377 
2378 	MPASS(selfreset);
2379 
2380 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
2381 	req.embedded_proc_type = processor;
2382 	req.selfrst_status = *selfreset;
2383 
2384 	BNXT_HWRM_LOCK(softc);
2385 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2386 	if (rc)
2387 		goto exit;
2388 	*selfreset = resp->selfrst_status;
2389 
2390 exit:
2391 	BNXT_HWRM_UNLOCK(softc);
2392 	return rc;
2393 }
2394 
2395 int
2396 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
2397 {
2398 	struct hwrm_fw_qstatus_input req = {0};
2399 	struct hwrm_fw_qstatus_output *resp =
2400 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2401 	int rc;
2402 
2403 	MPASS(selfreset);
2404 
2405 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
2406 	req.embedded_proc_type = type;
2407 
2408 	BNXT_HWRM_LOCK(softc);
2409 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2410 	if (rc)
2411 		goto exit;
2412 	*selfreset = resp->selfrst_status;
2413 
2414 exit:
2415 	BNXT_HWRM_UNLOCK(softc);
2416 	return rc;
2417 }
2418 
2419 int
2420 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
2421     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
2422     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
2423     uint16_t *index)
2424 {
2425 	struct hwrm_nvm_write_input req = {0};
2426 	struct hwrm_nvm_write_output *resp =
2427 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2428 	struct iflib_dma_info dma_data;
2429 	int rc;
2430 	uint32_t old_timeo;
2431 
2432 	if (data_length) {
2433 		rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
2434 		    BUS_DMA_NOWAIT);
2435 		if (rc)
2436 			return ENOMEM;
2437 		if (cpyin) {
2438 			rc = copyin(data, dma_data.idi_vaddr, data_length);
2439 			if (rc)
2440 				goto early_exit;
2441 		}
2442 		else
2443 			memcpy(dma_data.idi_vaddr, data, data_length);
2444 		bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
2445 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2446 	}
2447 	else
2448 		dma_data.idi_paddr = 0;
2449 
2450 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
2451 
2452 	req.host_src_addr = htole64(dma_data.idi_paddr);
2453 	req.dir_type = htole16(type);
2454 	req.dir_ordinal = htole16(ordinal);
2455 	req.dir_ext = htole16(ext);
2456 	req.dir_attr = htole16(attr);
2457 	req.dir_data_length = htole32(data_length);
2458 	req.option = htole16(option);
2459 	if (keep) {
2460 		req.flags =
2461 		    htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
2462 	}
2463 	if (item_length)
2464 		req.dir_item_length = htole32(*item_length);
2465 
2466 	BNXT_HWRM_LOCK(softc);
2467 	old_timeo = softc->hwrm_cmd_timeo;
2468 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2469 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2470 	softc->hwrm_cmd_timeo = old_timeo;
2471 	if (rc)
2472 		goto exit;
2473 	if (item_length)
2474 		*item_length = le32toh(resp->dir_item_length);
2475 	if (index)
2476 		*index = le16toh(resp->dir_idx);
2477 
2478 exit:
2479 	BNXT_HWRM_UNLOCK(softc);
2480 early_exit:
2481 	if (data_length)
2482 		iflib_dma_free(&dma_data);
2483 	return rc;
2484 }
2485 
2486 int
2487 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
2488 {
2489 	struct hwrm_nvm_erase_dir_entry_input req = {0};
2490 	uint32_t old_timeo;
2491 	int rc;
2492 
2493 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
2494 	req.dir_idx = htole16(index);
2495 	BNXT_HWRM_LOCK(softc);
2496 	old_timeo = softc->hwrm_cmd_timeo;
2497 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2498 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2499 	softc->hwrm_cmd_timeo = old_timeo;
2500 	BNXT_HWRM_UNLOCK(softc);
2501 	return rc;
2502 }
2503 
2504 int
2505 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
2506     uint32_t *entry_length)
2507 {
2508 	struct hwrm_nvm_get_dir_info_input req = {0};
2509 	struct hwrm_nvm_get_dir_info_output *resp =
2510 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2511 	int rc;
2512 	uint32_t old_timeo;
2513 
2514 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
2515 
2516 	BNXT_HWRM_LOCK(softc);
2517 	old_timeo = softc->hwrm_cmd_timeo;
2518 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2519 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2520 	softc->hwrm_cmd_timeo = old_timeo;
2521 	if (rc)
2522 		goto exit;
2523 
2524 	if (entries)
2525 		*entries = le32toh(resp->entries);
2526 	if (entry_length)
2527 		*entry_length = le32toh(resp->entry_length);
2528 
2529 exit:
2530 	BNXT_HWRM_UNLOCK(softc);
2531 	return rc;
2532 }
2533 
2534 int
2535 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
2536     uint32_t *entry_length, struct iflib_dma_info *dma_data)
2537 {
2538 	struct hwrm_nvm_get_dir_entries_input req = {0};
2539 	uint32_t ent;
2540 	uint32_t ent_len;
2541 	int rc;
2542 	uint32_t old_timeo;
2543 
2544 	if (!entries)
2545 		entries = &ent;
2546 	if (!entry_length)
2547 		entry_length = &ent_len;
2548 
2549 	rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
2550 	if (rc)
2551 		goto exit;
2552 	if (*entries * *entry_length > dma_data->idi_size) {
2553 		rc = EINVAL;
2554 		goto exit;
2555 	}
2556 
2557 	/*
2558 	 * TODO: There's a race condition here that could blow up DMA memory...
2559 	 *	 we need to allocate the max size, not the currently in use
2560 	 *	 size.  The command should totally have a max size here.
2561 	 */
2562 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
2563 	req.host_dest_addr = htole64(dma_data->idi_paddr);
2564 	BNXT_HWRM_LOCK(softc);
2565 	old_timeo = softc->hwrm_cmd_timeo;
2566 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2567 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2568 	softc->hwrm_cmd_timeo = old_timeo;
2569 	BNXT_HWRM_UNLOCK(softc);
2570 	if (rc)
2571 		goto exit;
2572 	bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
2573 	    BUS_DMASYNC_POSTWRITE);
2574 
2575 exit:
2576 	return rc;
2577 }
2578 
2579 int
2580 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
2581     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
2582     uint32_t *reserved_size, uint32_t *available_size)
2583 {
2584 	struct hwrm_nvm_get_dev_info_input req = {0};
2585 	struct hwrm_nvm_get_dev_info_output *resp =
2586 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2587 	int rc;
2588 	uint32_t old_timeo;
2589 
2590 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
2591 
2592 	BNXT_HWRM_LOCK(softc);
2593 	old_timeo = softc->hwrm_cmd_timeo;
2594 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2595 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2596 	softc->hwrm_cmd_timeo = old_timeo;
2597 	if (rc)
2598 		goto exit;
2599 
2600 	if (mfg_id)
2601 		*mfg_id = le16toh(resp->manufacturer_id);
2602 	if (device_id)
2603 		*device_id = le16toh(resp->device_id);
2604 	if (sector_size)
2605 		*sector_size = le32toh(resp->sector_size);
2606 	if (nvram_size)
2607 		*nvram_size = le32toh(resp->nvram_size);
2608 	if (reserved_size)
2609 		*reserved_size = le32toh(resp->reserved_size);
2610 	if (available_size)
2611 		*available_size = le32toh(resp->available_size);
2612 
2613 exit:
2614 	BNXT_HWRM_UNLOCK(softc);
2615 	return rc;
2616 }
2617 
2618 int
2619 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
2620     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
2621     uint8_t *problem_item, uint8_t *reset_required)
2622 {
2623 	struct hwrm_nvm_install_update_input req = {0};
2624 	struct hwrm_nvm_install_update_output *resp =
2625 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2626 	int rc;
2627 	uint32_t old_timeo;
2628 
2629 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
2630 	req.install_type = htole32(install_type);
2631 
2632 	BNXT_HWRM_LOCK(softc);
2633 	old_timeo = softc->hwrm_cmd_timeo;
2634 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2635 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2636 	softc->hwrm_cmd_timeo = old_timeo;
2637 	if (rc)
2638 		goto exit;
2639 
2640 	if (installed_items)
2641 		*installed_items = le32toh(resp->installed_items);
2642 	if (result)
2643 		*result = resp->result;
2644 	if (problem_item)
2645 		*problem_item = resp->problem_item;
2646 	if (reset_required)
2647 		*reset_required = resp->reset_required;
2648 
2649 exit:
2650 	BNXT_HWRM_UNLOCK(softc);
2651 	return rc;
2652 }
2653 
2654 int
2655 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
2656     uint16_t ordinal, uint16_t ext)
2657 {
2658 	struct hwrm_nvm_verify_update_input req = {0};
2659 	uint32_t old_timeo;
2660 	int rc;
2661 
2662 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
2663 
2664 	req.dir_type = htole16(type);
2665 	req.dir_ordinal = htole16(ordinal);
2666 	req.dir_ext = htole16(ext);
2667 
2668 	BNXT_HWRM_LOCK(softc);
2669 	old_timeo = softc->hwrm_cmd_timeo;
2670 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2671 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2672 	softc->hwrm_cmd_timeo = old_timeo;
2673 	BNXT_HWRM_UNLOCK(softc);
2674 	return rc;
2675 }
2676 
2677 int
2678 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
2679     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
2680     uint16_t *millisecond, uint16_t *zone)
2681 {
2682 	struct hwrm_fw_get_time_input req = {0};
2683 	struct hwrm_fw_get_time_output *resp =
2684 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2685 	int rc;
2686 
2687 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
2688 
2689 	BNXT_HWRM_LOCK(softc);
2690 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2691 	if (rc)
2692 		goto exit;
2693 
2694 	if (year)
2695 		*year = le16toh(resp->year);
2696 	if (month)
2697 		*month = resp->month;
2698 	if (day)
2699 		*day = resp->day;
2700 	if (hour)
2701 		*hour = resp->hour;
2702 	if (minute)
2703 		*minute = resp->minute;
2704 	if (second)
2705 		*second = resp->second;
2706 	if (millisecond)
2707 		*millisecond = le16toh(resp->millisecond);
2708 	if (zone)
2709 		*zone = le16toh(resp->zone);
2710 
2711 exit:
2712 	BNXT_HWRM_UNLOCK(softc);
2713 	return rc;
2714 }
2715 
2716 int
2717 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
2718     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
2719     uint16_t millisecond, uint16_t zone)
2720 {
2721 	struct hwrm_fw_set_time_input req = {0};
2722 
2723 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
2724 
2725 	req.year = htole16(year);
2726 	req.month = month;
2727 	req.day = day;
2728 	req.hour = hour;
2729 	req.minute = minute;
2730 	req.second = second;
2731 	req.millisecond = htole16(millisecond);
2732 	req.zone = htole16(zone);
2733 	return hwrm_send_message(softc, &req, sizeof(req));
2734 }
2735 
2736 int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *softc, uint16_t i2c_addr,
2737     uint16_t page_number, uint8_t bank,bool bank_sel_en, uint16_t start_addr,
2738     uint16_t data_length, uint8_t *buf)
2739 {
2740 	struct hwrm_port_phy_i2c_read_output *output =
2741 			(void *)softc->hwrm_cmd_resp.idi_vaddr;
2742 	struct hwrm_port_phy_i2c_read_input req = {0};
2743 	int rc = 0, byte_offset = 0;
2744 
2745 	BNXT_HWRM_LOCK(softc);
2746 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_I2C_READ);
2747 
2748 	req.i2c_slave_addr = i2c_addr;
2749 	req.page_number = htole16(page_number);
2750 	req.port_id = htole16(softc->pf.port_id);
2751 	do {
2752 		uint16_t xfer_size;
2753 
2754 		xfer_size = min_t(uint16_t, data_length, BNXT_MAX_PHY_I2C_RESP_SIZE);
2755 		data_length -= xfer_size;
2756 		req.page_offset = htole16(start_addr + byte_offset);
2757 		req.data_length = xfer_size;
2758 		req.bank_number = bank;
2759 		req.enables = htole32((start_addr + byte_offset ?
2760 				HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET : 0) |
2761 				(bank_sel_en ?
2762 				HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_BANK_NUMBER : 0));
2763 		rc = hwrm_send_message(softc, &req, sizeof(req));
2764 		if (!rc)
2765 			memcpy(buf + byte_offset, output->data, xfer_size);
2766 		byte_offset += xfer_size;
2767 	} while (!rc && data_length > 0);
2768 
2769 	BNXT_HWRM_UNLOCK(softc);
2770 
2771 	return rc;
2772 }
2773 
2774 int
2775 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
2776 {
2777 	struct bnxt_link_info *link_info = &softc->link_info;
2778 	struct hwrm_port_phy_qcfg_input req = {0};
2779 	struct hwrm_port_phy_qcfg_output *resp =
2780 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2781 	int rc = 0;
2782 
2783 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
2784 
2785 	BNXT_HWRM_LOCK(softc);
2786 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2787 	if (rc)
2788 		goto exit;
2789 
2790 	memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp));
2791 	link_info->phy_link_status = resp->link;
2792 	link_info->duplex =  resp->duplex_cfg;
2793 	link_info->auto_mode = resp->auto_mode;
2794 
2795         /*
2796          * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
2797          * the advertisement of pause is enabled.
2798          * 1. When the auto_mode is not set to none and this flag is set to 1,
2799          *    then the auto_pause bits on this port are being advertised and
2800          *    autoneg pause results are being interpreted.
2801          * 2. When the auto_mode is not set to none and this flag is set to 0,
2802          *    the pause is forced as indicated in force_pause, and also
2803 	 *    advertised as auto_pause bits, but the autoneg results are not
2804 	 *    interpreted since the pause configuration is being forced.
2805          * 3. When the auto_mode is set to none and this flag is set to 1,
2806          *    auto_pause bits should be ignored and should be set to 0.
2807          */
2808 
2809 	link_info->flow_ctrl.autoneg = false;
2810 	link_info->flow_ctrl.tx = false;
2811 	link_info->flow_ctrl.rx = false;
2812 
2813 	if ((resp->auto_mode) &&
2814             (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
2815 			link_info->flow_ctrl.autoneg = true;
2816 	}
2817 
2818 	if (link_info->flow_ctrl.autoneg) {
2819 		if (resp->auto_pause & BNXT_PAUSE_TX)
2820 			link_info->flow_ctrl.tx = true;
2821 		if (resp->auto_pause & BNXT_PAUSE_RX)
2822 			link_info->flow_ctrl.rx = true;
2823 	} else {
2824 		if (resp->force_pause & BNXT_PAUSE_TX)
2825 			link_info->flow_ctrl.tx = true;
2826 		if (resp->force_pause & BNXT_PAUSE_RX)
2827 			link_info->flow_ctrl.rx = true;
2828 	}
2829 
2830 	link_info->duplex_setting = resp->duplex_cfg;
2831 	if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
2832 		link_info->link_speed = le16toh(resp->link_speed);
2833 	else
2834 		link_info->link_speed = 0;
2835 	link_info->force_link_speed = le16toh(resp->force_link_speed);
2836 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed);
2837 	link_info->support_speeds = le16toh(resp->support_speeds);
2838 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
2839 	link_info->preemphasis = le32toh(resp->preemphasis);
2840 	link_info->phy_ver[0] = resp->phy_maj;
2841 	link_info->phy_ver[1] = resp->phy_min;
2842 	link_info->phy_ver[2] = resp->phy_bld;
2843 	snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
2844 	    "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
2845 	    link_info->phy_ver[2]);
2846 	strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
2847 	    BNXT_NAME_SIZE);
2848 	strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
2849 	    BNXT_NAME_SIZE);
2850 	link_info->media_type = resp->media_type;
2851 	link_info->phy_type = resp->phy_type;
2852 	link_info->transceiver = resp->xcvr_pkg_type;
2853 	link_info->phy_addr = resp->eee_config_phy_addr &
2854 	    HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
2855 	link_info->module_status = resp->module_status;
2856 	link_info->support_pam4_speeds = le16toh(resp->support_pam4_speeds);
2857 	link_info->auto_pam4_link_speeds = le16toh(resp->auto_pam4_link_speed_mask);
2858 	link_info->force_pam4_link_speed = le16toh(resp->force_pam4_link_speed);
2859 
2860 	if (softc->hwrm_spec_code >= 0x10504)
2861 		link_info->active_fec_sig_mode = resp->active_fec_signal_mode;
2862 
2863 exit:
2864 	BNXT_HWRM_UNLOCK(softc);
2865 	return rc;
2866 }
2867 
2868 static bool
2869 bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp)
2870 {
2871 	if (!resp->supported_speeds_auto_mode &&
2872 	    !resp->supported_speeds_force_mode &&
2873 	    !resp->supported_pam4_speeds_auto_mode &&
2874 	    !resp->supported_pam4_speeds_force_mode)
2875 		return true;
2876 
2877 	return false;
2878 }
2879 
2880 int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc)
2881 {
2882 	struct bnxt_link_info *link_info = &softc->link_info;
2883 	struct hwrm_port_phy_qcaps_output *resp =
2884 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2885 	struct hwrm_port_phy_qcaps_input req = {};
2886 	int rc;
2887 
2888 	if (softc->hwrm_spec_code < 0x10201)
2889 		return 0;
2890 
2891 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCAPS);
2892 
2893 	BNXT_HWRM_LOCK(softc);
2894 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2895 	if (rc)
2896 		goto exit;
2897 
2898 	softc->phy_flags = resp->flags | (resp->flags2 << 8);
2899 	if (resp->flags & HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS_EEE_SUPPORTED) {
2900 
2901 		softc->lpi_tmr_lo = le32toh(resp->tx_lpi_timer_low) &
2902 					    HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_MASK;
2903 		softc->lpi_tmr_hi = le32toh(resp->valid_tx_lpi_timer_high) &
2904 					    HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_MASK;
2905 	}
2906 
2907 	if (softc->hwrm_spec_code >= 0x10a01) {
2908 		if (bnxt_phy_qcaps_no_speed(resp)) {
2909 			link_info->phy_state = BNXT_PHY_STATE_DISABLED;
2910 			device_printf(softc->dev, "Ethernet link disabled\n");
2911 		} else if (link_info->phy_state == BNXT_PHY_STATE_DISABLED) {
2912 			link_info->phy_state = BNXT_PHY_STATE_ENABLED;
2913 			device_printf(softc->dev, "Ethernet link enabled\n");
2914 			/* Phy re-enabled, reprobe the speeds */
2915 			link_info->support_auto_speeds = 0;
2916 			link_info->support_pam4_auto_speeds = 0;
2917 		}
2918 	}
2919 	if (resp->supported_speeds_auto_mode)
2920 		link_info->support_auto_speeds =
2921 			le16toh(resp->supported_speeds_auto_mode);
2922 	if (resp->supported_speeds_force_mode)
2923 		link_info->support_force_speeds =
2924 			le16toh(resp->supported_speeds_force_mode);
2925 	if (resp->supported_pam4_speeds_auto_mode)
2926 		link_info->support_pam4_auto_speeds =
2927 			le16toh(resp->supported_pam4_speeds_auto_mode);
2928 	if (resp->supported_pam4_speeds_force_mode)
2929 		link_info->support_pam4_force_speeds =
2930 			le16toh(resp->supported_pam4_speeds_force_mode);
2931 
2932 exit:
2933 	BNXT_HWRM_UNLOCK(softc);
2934 	return rc;
2935 }
2936 
2937 uint16_t
2938 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
2939 {
2940 	struct hwrm_wol_filter_qcfg_input req = {0};
2941 	struct hwrm_wol_filter_qcfg_output *resp =
2942 			(void *)softc->hwrm_cmd_resp.idi_vaddr;
2943 	uint16_t next_handle = 0;
2944 	int rc;
2945 
2946 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
2947 	req.port_id = htole16(softc->pf.port_id);
2948 	req.handle = htole16(handle);
2949 	rc = hwrm_send_message(softc, &req, sizeof(req));
2950 	if (!rc) {
2951 		next_handle = le16toh(resp->next_handle);
2952 		if (next_handle != 0) {
2953 			if (resp->wol_type ==
2954 				HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
2955 				softc->wol = 1;
2956 				softc->wol_filter_id = resp->wol_filter_id;
2957 			}
2958 		}
2959 	}
2960 	return next_handle;
2961 }
2962 
2963 int
2964 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
2965 {
2966 	struct hwrm_wol_filter_alloc_input req = {0};
2967 	struct hwrm_wol_filter_alloc_output *resp =
2968 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
2969 	int rc;
2970 
2971 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
2972 	req.port_id = htole16(softc->pf.port_id);
2973 	req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
2974 	req.enables =
2975 		htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
2976 	memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
2977 	rc = hwrm_send_message(softc, &req, sizeof(req));
2978 	if (!rc)
2979 		softc->wol_filter_id = resp->wol_filter_id;
2980 
2981 	return rc;
2982 }
2983 
2984 int
2985 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
2986 {
2987 	struct hwrm_wol_filter_free_input req = {0};
2988 
2989 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
2990 	req.port_id = htole16(softc->pf.port_id);
2991 	req.enables =
2992 		htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
2993 	req.wol_filter_id = softc->wol_filter_id;
2994 	return hwrm_send_message(softc, &req, sizeof(req));
2995 }
2996 
2997 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
2998         uint32_t buf_tmrs, uint16_t flags,
2999         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
3000 {
3001         req->flags = htole16(flags);
3002         req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
3003         req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
3004         req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
3005         req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
3006         /* Minimum time between 2 interrupts set to buf_tmr x 2 */
3007         req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
3008         req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
3009         req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
3010 }
3011 
3012 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
3013 {
3014 	int i, rc = 0;
3015 	struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
3016 							   req_tx = {0}, *req;
3017 	uint16_t max_buf, max_buf_irq;
3018 	uint16_t buf_tmr, buf_tmr_irq;
3019 	uint32_t flags;
3020 
3021 	bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
3022 			       HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
3023 	bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
3024 			       HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
3025 
3026 	/* Each rx completion (2 records) should be DMAed immediately.
3027 	 * DMA 1/4 of the completion buffers at a time.
3028 	 */
3029 	max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
3030 	/* max_buf must not be zero */
3031 	max_buf = clamp_t(uint16_t, max_buf, 1, 63);
3032 	max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
3033 	buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
3034 	/* buf timer set to 1/4 of interrupt timer */
3035 	buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
3036 	buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
3037 	buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
3038 
3039 	flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
3040 
3041 	/* RING_IDLE generates more IRQs for lower latency.  Enable it only
3042 	 * if coal_usecs is less than 25 us.
3043 	 */
3044 	if (softc->rx_coal_usecs < 25)
3045 		flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
3046 
3047 	bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
3048 				  buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
3049 
3050 	/* max_buf must not be zero */
3051 	max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
3052 	max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
3053 	buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
3054 	/* buf timer set to 1/4 of interrupt timer */
3055 	buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
3056 	buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
3057 	buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
3058 	flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
3059 	bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
3060 				  buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
3061 
3062 	for (i = 0; i < softc->nrxqsets; i++) {
3063 
3064 		req = &req_rx;
3065 		req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
3066 
3067 		rc = hwrm_send_message(softc, req, sizeof(*req));
3068 		if (rc)
3069 			break;
3070 	}
3071 	return rc;
3072 }
3073 
3074 void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type,
3075 			     uint32_t ring_id, uint32_t *prod, uint32_t *cons)
3076 {
3077 	hwrm_dbg_ring_info_get_input_t req = {0};
3078 	hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
3079 	int rc = 0;
3080 
3081 	*prod = *cons = 0xffffffff;
3082 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET);
3083         req.ring_type = le32toh(ring_type);
3084         req.fw_ring_id = le32toh(ring_id);
3085 	rc = hwrm_send_message(softc, &req, sizeof(req));
3086 	if (!rc) {
3087 		*prod = resp->producer_index;
3088 		*cons = resp->consumer_index;
3089 	}
3090 
3091 	return;
3092 }
3093