xref: /freebsd/sys/dev/bnxt/bnxt_hwrm.c (revision 770e7ba3)
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 
32 #include "bnxt.h"
33 #include "bnxt_hwrm.h"
34 #include "hsi_struct_def.h"
35 
36 static int bnxt_hwrm_err_map(uint16_t err);
37 static inline int _is_valid_ether_addr(uint8_t *);
38 static inline void get_random_ether_addr(uint8_t *);
39 static void	bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
40 		    struct hwrm_port_phy_cfg_input *req);
41 static void	bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
42 		    struct hwrm_port_phy_cfg_input *req);
43 static void	bnxt_hwrm_set_eee(struct bnxt_softc *softc,
44 		    struct hwrm_port_phy_cfg_input *req);
45 static int	_hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
46 static int	hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
47 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
48 
49 /* NVRam stuff has a five minute timeout */
50 #define BNXT_NVM_TIMEO	(5 * 60 * 1000)
51 
52 static int
bnxt_hwrm_err_map(uint16_t err)53 bnxt_hwrm_err_map(uint16_t err)
54 {
55 	int rc;
56 
57 	switch (err) {
58 	case HWRM_ERR_CODE_SUCCESS:
59 		return 0;
60 	case HWRM_ERR_CODE_INVALID_PARAMS:
61 	case HWRM_ERR_CODE_INVALID_FLAGS:
62 	case HWRM_ERR_CODE_INVALID_ENABLES:
63 		return EINVAL;
64 	case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
65 		return EACCES;
66 	case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
67 		return ENOMEM;
68 	case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
69 		return ENOSYS;
70 	case HWRM_ERR_CODE_FAIL:
71 		return EIO;
72 	case HWRM_ERR_CODE_HWRM_ERROR:
73 	case HWRM_ERR_CODE_UNKNOWN_ERR:
74 	default:
75 		return EDOOFUS;
76 	}
77 
78 	return rc;
79 }
80 
81 int
bnxt_alloc_hwrm_dma_mem(struct bnxt_softc * softc)82 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
83 {
84 	int rc;
85 
86 	rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
87 	    BUS_DMA_NOWAIT);
88 	return rc;
89 }
90 
91 void
bnxt_free_hwrm_dma_mem(struct bnxt_softc * softc)92 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
93 {
94 	if (softc->hwrm_cmd_resp.idi_vaddr)
95 		iflib_dma_free(&softc->hwrm_cmd_resp);
96 	softc->hwrm_cmd_resp.idi_vaddr = NULL;
97 	return;
98 }
99 
100 static void
bnxt_hwrm_cmd_hdr_init(struct bnxt_softc * softc,void * request,uint16_t req_type)101 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
102     uint16_t req_type)
103 {
104 	struct input *req = request;
105 
106 	req->req_type = htole16(req_type);
107 	req->cmpl_ring = 0xffff;
108 	req->target_id = 0xffff;
109 	req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
110 }
111 
112 static int
_hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)113 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
114 {
115 	struct input *req = msg;
116 	struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
117 	uint32_t *data = msg;
118 	int i;
119 	uint8_t *valid;
120 	uint16_t err;
121 	uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
122 	struct hwrm_short_input short_input = {0};
123 
124 	/* TODO: DMASYNC in here. */
125 	req->seq_id = htole16(softc->hwrm_cmd_seq++);
126 	memset(resp, 0, PAGE_SIZE);
127 
128 	if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
129 	    msg_len > BNXT_HWRM_MAX_REQ_LEN) {
130 		void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
131                 uint16_t max_msg_len;
132 
133                 /* Set boundary for maximum extended request length for short
134                  * cmd format. If passed up from device use the max supported
135                  * internal req length.
136 		 */
137 
138 		max_msg_len = softc->hwrm_max_ext_req_len;
139 
140 
141 		memcpy(short_cmd_req, req, msg_len);
142                 if (msg_len < max_msg_len)
143 			memset((uint8_t *) short_cmd_req + msg_len, 0,
144 				max_msg_len - msg_len);
145 
146 		short_input.req_type = req->req_type;
147 		short_input.signature =
148 		    htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
149 		short_input.size = htole16(msg_len);
150 		short_input.req_addr =
151 		    htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
152 
153 		data = (uint32_t *)&short_input;
154 		msg_len = sizeof(short_input);
155 
156 		/* Sync memory write before updating doorbell */
157 		wmb();
158 
159 		max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
160 	}
161 
162 	/* Write request msg to hwrm channel */
163 	for (i = 0; i < msg_len; i += 4) {
164 		bus_space_write_4(softc->hwrm_bar.tag,
165 				  softc->hwrm_bar.handle,
166 				  i, *data);
167 		data++;
168 	}
169 
170 	/* Clear to the end of the request buffer */
171 	for (i = msg_len; i < max_req_len; i += 4)
172 		bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
173 		    i, 0);
174 
175 	/* Ring channel doorbell */
176 	bus_space_write_4(softc->hwrm_bar.tag,
177 			  softc->hwrm_bar.handle,
178 			  0x100, htole32(1));
179 
180 	/* Check if response len is updated */
181 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
182 		if (resp->resp_len && resp->resp_len <= 4096)
183 			break;
184 		DELAY(1000);
185 	}
186 	if (i >= softc->hwrm_cmd_timeo) {
187 		device_printf(softc->dev,
188 		    "Timeout sending %s: (timeout: %u) seq: %d\n",
189 		    GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
190 		    le16toh(req->seq_id));
191 		return ETIMEDOUT;
192 	}
193 	/* Last byte of resp contains the valid key */
194 	valid = (uint8_t *)resp + resp->resp_len - 1;
195 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
196 		if (*valid == HWRM_RESP_VALID_KEY)
197 			break;
198 		DELAY(1000);
199 	}
200 	if (i >= softc->hwrm_cmd_timeo) {
201 		device_printf(softc->dev, "Timeout sending %s: "
202 		    "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
203 		    GET_HWRM_REQ_TYPE(req->req_type),
204 		    softc->hwrm_cmd_timeo, le16toh(req->req_type),
205 		    le16toh(req->seq_id), msg_len,
206 		    *valid);
207 		return ETIMEDOUT;
208 	}
209 
210 	err = le16toh(resp->error_code);
211 	if (err) {
212 		/* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
213 		if (err != HWRM_ERR_CODE_FAIL) {
214 			device_printf(softc->dev,
215 			    "%s command returned %s error.\n",
216 			    GET_HWRM_REQ_TYPE(req->req_type),
217 			    GET_HWRM_ERROR_CODE(err));
218 		}
219 		return bnxt_hwrm_err_map(err);
220 	}
221 
222 	return 0;
223 }
224 
225 static int
hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)226 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
227 {
228 	int rc;
229 
230 	BNXT_HWRM_LOCK(softc);
231 	rc = _hwrm_send_message(softc, msg, msg_len);
232 	BNXT_HWRM_UNLOCK(softc);
233 	return rc;
234 }
235 
236 int
bnxt_hwrm_queue_qportcfg(struct bnxt_softc * softc)237 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
238 {
239 	int rc = 0;
240 	struct hwrm_queue_qportcfg_input req = {0};
241 	struct hwrm_queue_qportcfg_output *resp =
242 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
243 	uint8_t i, j, *qptr;
244 	bool no_rdma;
245 
246 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
247 
248 	BNXT_HWRM_LOCK(softc);
249 	rc = _hwrm_send_message(softc, &req, sizeof(req));
250 	if (rc)
251 		goto qportcfg_exit;
252 
253 	if (!resp->max_configurable_queues) {
254 		rc = -EINVAL;
255 		goto qportcfg_exit;
256 	}
257 	softc->max_tc = resp->max_configurable_queues;
258 	softc->max_lltc = resp->max_configurable_lossless_queues;
259 	if (softc->max_tc > BNXT_MAX_COS_QUEUE)
260 		softc->max_tc = BNXT_MAX_COS_QUEUE;
261 
262 	/* Currently no RDMA support */
263 	no_rdma = true;
264 
265 	qptr = &resp->queue_id0;
266 	for (i = 0, j = 0; i < softc->max_tc; i++) {
267 		softc->q_info[j].id = *qptr;
268 		softc->q_ids[i] = *qptr++;
269 		softc->q_info[j].profile = *qptr++;
270 		softc->tc_to_qidx[j] = j;
271 		if (!BNXT_CNPQ(softc->q_info[j].profile) ||
272 				(no_rdma && BNXT_PF(softc)))
273 			j++;
274 	}
275 	softc->max_q = softc->max_tc;
276 	softc->max_tc = max_t(uint32_t, j, 1);
277 
278 	if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG)
279 		softc->max_tc = 1;
280 
281 	if (softc->max_lltc > softc->max_tc)
282 		softc->max_lltc = softc->max_tc;
283 
284 qportcfg_exit:
285 	BNXT_HWRM_UNLOCK(softc);
286 	return rc;
287 }
288 
bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc * softc)289 int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
290 {
291 	struct hwrm_func_backing_store_qcaps_input req = {0};
292 	struct hwrm_func_backing_store_qcaps_output *resp =
293 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
294 	int rc;
295 
296 	if (softc->hwrm_spec_code < 0x10902 || BNXT_VF(softc) || softc->ctx_mem)
297 		return 0;
298 
299 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
300 	BNXT_HWRM_LOCK(softc);
301 	rc = _hwrm_send_message(softc, &req, sizeof(req));
302 	if (!rc) {
303 		struct bnxt_ctx_pg_info *ctx_pg;
304 		struct bnxt_ctx_mem_info *ctx;
305 		int i;
306 
307 		ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
308 		if (!ctx) {
309 			rc = -ENOMEM;
310 			goto ctx_err;
311 		}
312 		ctx_pg = malloc(sizeof(*ctx_pg) * (softc->max_q + 1),
313 				M_DEVBUF, M_NOWAIT | M_ZERO);
314 		if (!ctx_pg) {
315 			free(ctx, M_DEVBUF);
316 			rc = -ENOMEM;
317 			goto ctx_err;
318 		}
319 		for (i = 0; i < softc->max_q + 1; i++, ctx_pg++)
320 			ctx->tqm_mem[i] = ctx_pg;
321 
322 		softc->ctx_mem = ctx;
323 		ctx->qp_max_entries = le32toh(resp->qp_max_entries);
324 		ctx->qp_min_qp1_entries = le16toh(resp->qp_min_qp1_entries);
325 		ctx->qp_max_l2_entries = le16toh(resp->qp_max_l2_entries);
326 		ctx->qp_entry_size = le16toh(resp->qp_entry_size);
327 		ctx->srq_max_l2_entries = le16toh(resp->srq_max_l2_entries);
328 		ctx->srq_max_entries = le32toh(resp->srq_max_entries);
329 		ctx->srq_entry_size = le16toh(resp->srq_entry_size);
330 		ctx->cq_max_l2_entries = le16toh(resp->cq_max_l2_entries);
331 		ctx->cq_max_entries = le32toh(resp->cq_max_entries);
332 		ctx->cq_entry_size = le16toh(resp->cq_entry_size);
333 		ctx->vnic_max_vnic_entries =
334 			le16toh(resp->vnic_max_vnic_entries);
335 		ctx->vnic_max_ring_table_entries =
336 			le16toh(resp->vnic_max_ring_table_entries);
337 		ctx->vnic_entry_size = le16toh(resp->vnic_entry_size);
338 		ctx->stat_max_entries = le32toh(resp->stat_max_entries);
339 		ctx->stat_entry_size = le16toh(resp->stat_entry_size);
340 		ctx->tqm_entry_size = le16toh(resp->tqm_entry_size);
341 		ctx->tqm_min_entries_per_ring =
342 			le32toh(resp->tqm_min_entries_per_ring);
343 		ctx->tqm_max_entries_per_ring =
344 			le32toh(resp->tqm_max_entries_per_ring);
345 		ctx->tqm_entries_multiple = resp->tqm_entries_multiple;
346 		if (!ctx->tqm_entries_multiple)
347 			ctx->tqm_entries_multiple = 1;
348 		ctx->mrav_max_entries = le32toh(resp->mrav_max_entries);
349 		ctx->mrav_entry_size = le16toh(resp->mrav_entry_size);
350 		ctx->tim_entry_size = le16toh(resp->tim_entry_size);
351 		ctx->tim_max_entries = le32toh(resp->tim_max_entries);
352 		ctx->ctx_kind_initializer = resp->ctx_kind_initializer;
353 	} else {
354 		rc = 0;
355 	}
356 ctx_err:
357 	BNXT_HWRM_UNLOCK(softc);
358 	return rc;
359 }
360 
361 #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES                 \
362         (HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP |                \
363          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ |               \
364          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ |                \
365          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC |              \
366          HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
367 
bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info * rmem,uint8_t * pg_attr,uint64_t * pg_dir)368 static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
369 				  uint64_t *pg_dir)
370 {
371 	uint8_t pg_size = 0;
372 
373 	if (BNXT_PAGE_SHIFT == 13)
374 		pg_size = 1 << 4;
375 	else if (BNXT_PAGE_SIZE == 16)
376 		pg_size = 2 << 4;
377 
378 	*pg_attr = pg_size;
379 	if (rmem->depth >= 1) {
380 		if (rmem->depth == 2)
381 			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
382 		else
383 			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
384 		*pg_dir = htole64(rmem->pg_tbl.idi_paddr);
385 	} else {
386 		*pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
387 	}
388 }
389 
bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc * softc,uint32_t enables)390 int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
391 {
392 	struct hwrm_func_backing_store_cfg_input req = {0};
393 	struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
394 	struct bnxt_ctx_pg_info *ctx_pg;
395 	uint32_t *num_entries, req_len = sizeof(req);
396 	uint64_t *pg_dir;
397 	uint8_t *pg_attr;
398 	int i, rc;
399 	uint32_t ena;
400 
401 	if (!ctx)
402 		return 0;
403 
404 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
405 	req.enables = htole32(enables);
406 
407 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
408 		ctx_pg = &ctx->qp_mem;
409 		req.qp_num_entries = htole32(ctx_pg->entries);
410 		req.qp_num_qp1_entries = htole16(ctx->qp_min_qp1_entries);
411 		req.qp_num_l2_entries = htole16(ctx->qp_max_l2_entries);
412 		req.qp_entry_size = htole16(ctx->qp_entry_size);
413 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
414 				&req.qpc_pg_size_qpc_lvl,
415 				&req.qpc_page_dir);
416 	}
417 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
418 		ctx_pg = &ctx->srq_mem;
419 		req.srq_num_entries = htole32(ctx_pg->entries);
420 		req.srq_num_l2_entries = htole16(ctx->srq_max_l2_entries);
421 		req.srq_entry_size = htole16(ctx->srq_entry_size);
422 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
423 				&req.srq_pg_size_srq_lvl,
424 				&req.srq_page_dir);
425 	}
426 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
427 		ctx_pg = &ctx->cq_mem;
428 		req.cq_num_entries = htole32(ctx_pg->entries);
429 		req.cq_num_l2_entries = htole16(ctx->cq_max_l2_entries);
430 		req.cq_entry_size = htole16(ctx->cq_entry_size);
431 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, &req.cq_pg_size_cq_lvl,
432 				&req.cq_page_dir);
433 	}
434 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
435 		ctx_pg = &ctx->mrav_mem;
436 		req.mrav_num_entries = htole32(ctx_pg->entries);
437 		req.mrav_entry_size = htole16(ctx->mrav_entry_size);
438 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
439 				&req.mrav_pg_size_mrav_lvl,
440 				&req.mrav_page_dir);
441 	}
442 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
443 		ctx_pg = &ctx->tim_mem;
444 		req.tim_num_entries = htole32(ctx_pg->entries);
445 		req.tim_entry_size = htole16(ctx->tim_entry_size);
446 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
447 				&req.tim_pg_size_tim_lvl,
448 				&req.tim_page_dir);
449 	}
450 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
451 		ctx_pg = &ctx->vnic_mem;
452 		req.vnic_num_vnic_entries =
453 			htole16(ctx->vnic_max_vnic_entries);
454 		req.vnic_num_ring_table_entries =
455 			htole16(ctx->vnic_max_ring_table_entries);
456 		req.vnic_entry_size = htole16(ctx->vnic_entry_size);
457 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
458 				&req.vnic_pg_size_vnic_lvl,
459 				&req.vnic_page_dir);
460 	}
461 	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
462 		ctx_pg = &ctx->stat_mem;
463 		req.stat_num_entries = htole32(ctx->stat_max_entries);
464 		req.stat_entry_size = htole16(ctx->stat_entry_size);
465 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
466 				&req.stat_pg_size_stat_lvl,
467 				&req.stat_page_dir);
468 	}
469 	for (i = 0, num_entries = &req.tqm_sp_num_entries,
470 			pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
471 			pg_dir = &req.tqm_sp_page_dir,
472 			ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP;
473 			i < 9; i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
474 		if (!(enables & ena))
475 			continue;
476 
477 		req.tqm_entry_size = htole16(ctx->tqm_entry_size);
478 		ctx_pg = ctx->tqm_mem[i];
479 		*num_entries = htole32(ctx_pg->entries);
480 		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
481 	}
482 
483 	if (req_len > softc->hwrm_max_ext_req_len)
484 		req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN;
485 
486 	rc = hwrm_send_message(softc, &req, req_len);
487 	if (rc)
488 		rc = -EIO;
489 	return rc;
490 }
491 
bnxt_hwrm_func_resc_qcaps(struct bnxt_softc * softc,bool all)492 int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
493 {
494         struct hwrm_func_resource_qcaps_output *resp =
495 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
496         struct hwrm_func_resource_qcaps_input req = {0};
497         struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
498         int rc;
499 
500         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
501         req.fid = htole16(0xffff);
502 
503 	BNXT_HWRM_LOCK(softc);
504         rc = _hwrm_send_message(softc, &req, sizeof(req));
505         if (rc) {
506                 rc = -EIO;
507                 goto hwrm_func_resc_qcaps_exit;
508         }
509 
510         hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
511         if (!all)
512                 goto hwrm_func_resc_qcaps_exit;
513 
514         hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
515         hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
516         hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
517         hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
518         hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
519         hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
520         hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
521         hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
522         hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
523         hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
524         hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
525         hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
526         hw_resc->min_vnics = le16toh(resp->min_vnics);
527         hw_resc->max_vnics = le16toh(resp->max_vnics);
528         hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
529         hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
530 
531 	if (BNXT_CHIP_P5(softc)) {
532                 hw_resc->max_nqs = le16toh(resp->max_msix);
533                 hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
534         }
535 
536 hwrm_func_resc_qcaps_exit:
537 	BNXT_HWRM_UNLOCK(softc);
538         return rc;
539 }
540 
541 int
bnxt_hwrm_passthrough(struct bnxt_softc * softc,void * req,uint32_t req_len,void * resp,uint32_t resp_len,uint32_t app_timeout)542 bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len,
543 		void *resp, uint32_t resp_len, uint32_t app_timeout)
544 {
545 	int rc = 0;
546 	void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr;
547 	struct input *input = req;
548 	uint32_t old_timeo;
549 
550 	input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
551 	BNXT_HWRM_LOCK(softc);
552 	old_timeo = softc->hwrm_cmd_timeo;
553 	if (input->req_type == HWRM_NVM_INSTALL_UPDATE)
554 		softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
555 	else
556 		softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo);
557 	rc = _hwrm_send_message(softc, req, req_len);
558 	softc->hwrm_cmd_timeo = old_timeo;
559 	if (rc) {
560 		device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n",
561 			      __FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc);
562 		goto fail;
563 	}
564 
565 	memcpy(resp, output, resp_len);
566 fail:
567 	BNXT_HWRM_UNLOCK(softc);
568 	return rc;
569 }
570 
571 
572 int
bnxt_hwrm_ver_get(struct bnxt_softc * softc)573 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
574 {
575 	struct hwrm_ver_get_input	req = {0};
576 	struct hwrm_ver_get_output	*resp =
577 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
578 	int				rc;
579 	const char nastr[] = "<not installed>";
580 	const char naver[] = "<N/A>";
581 	uint32_t dev_caps_cfg;
582 	uint16_t fw_maj, fw_min, fw_bld, fw_rsv, len;
583 
584 	softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
585 	softc->hwrm_cmd_timeo = 1000;
586 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
587 
588 	req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
589 	req.hwrm_intf_min = HWRM_VERSION_MINOR;
590 	req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
591 
592 	BNXT_HWRM_LOCK(softc);
593 	rc = _hwrm_send_message(softc, &req, sizeof(req));
594 	if (rc)
595 		goto fail;
596 
597 	snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
598 	    resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
599 	softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b;
600 	softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b;
601 	softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b;
602 	snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
603 	    resp->hwrm_fw_major, resp->hwrm_fw_minor, resp->hwrm_fw_build);
604 	strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
605 	    BNXT_VERSTR_SIZE);
606 	strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
607 	    BNXT_NAME_SIZE);
608 
609 	 softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
610                              resp->hwrm_intf_min_8b << 8 |
611                              resp->hwrm_intf_upd_8b;
612 	if (resp->hwrm_intf_maj_8b < 1) {
613 		 device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
614 			       "than 1.0.0.\n", resp->hwrm_intf_maj_8b,
615 			       resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
616 		 device_printf(softc->dev, "Please update firmware with HWRM "
617 				"interface 1.0.0 or newer.\n");
618 	 }
619 	if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
620 	    resp->mgmt_fw_build == 0) {
621 		strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
622 		strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
623 	}
624 	else {
625 		snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
626 		    "%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor,
627 		    resp->mgmt_fw_build);
628 		strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
629 		    BNXT_NAME_SIZE);
630 	}
631 	if (resp->netctrl_fw_major == 0 && resp->netctrl_fw_minor == 0 &&
632 	    resp->netctrl_fw_build == 0) {
633 		strlcpy(softc->ver_info->netctrl_fw_ver, naver,
634 		    BNXT_VERSTR_SIZE);
635 		strlcpy(softc->ver_info->netctrl_fw_name, nastr,
636 		    BNXT_NAME_SIZE);
637 	}
638 	else {
639 		snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
640 		    "%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor,
641 		    resp->netctrl_fw_build);
642 		strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
643 		    BNXT_NAME_SIZE);
644 	}
645 	if (resp->roce_fw_major == 0 && resp->roce_fw_minor == 0 &&
646 	    resp->roce_fw_build == 0) {
647 		strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
648 		strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
649 	}
650 	else {
651 		snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
652 		    "%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor,
653 		    resp->roce_fw_build);
654 		strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
655 		    BNXT_NAME_SIZE);
656 	}
657 
658 	fw_maj = le32toh(resp->hwrm_fw_major);
659 	if (softc->hwrm_spec_code > 0x10803 && fw_maj) {
660 		fw_min = le16toh(resp->hwrm_fw_minor);
661 		fw_bld = le16toh(resp->hwrm_fw_build);
662 		fw_rsv = le16toh(resp->hwrm_fw_patch);
663 		len = FW_VER_STR_LEN;
664 	} else {
665 		fw_maj = resp->hwrm_fw_maj_8b;
666 		fw_min = resp->hwrm_fw_min_8b;
667 		fw_bld = resp->hwrm_fw_bld_8b;
668 		fw_rsv = resp->hwrm_fw_rsvd_8b;
669 		len = BC_HWRM_STR_LEN;
670 	}
671 
672 	snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d",
673 			fw_maj, fw_min, fw_bld, fw_rsv);
674 
675 	if (strlen(resp->active_pkg_name)) {
676 		int fw_ver_len = strlen (softc->ver_info->fw_ver_str);
677 
678 		snprintf(softc->ver_info->fw_ver_str + fw_ver_len,
679 				FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
680 				resp->active_pkg_name);
681 	}
682 
683 	softc->ver_info->chip_num = le16toh(resp->chip_num);
684 	softc->ver_info->chip_rev = resp->chip_rev;
685 	softc->ver_info->chip_metal = resp->chip_metal;
686 	softc->ver_info->chip_bond_id = resp->chip_bond_id;
687 	softc->ver_info->chip_type = resp->chip_platform_type;
688 
689 	if (resp->hwrm_intf_maj_8b >= 1) {
690 		softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
691 		softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
692 	}
693 #define DFLT_HWRM_CMD_TIMEOUT		500
694 	softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
695 	if (!softc->hwrm_cmd_timeo)
696 		softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
697 
698 
699 	dev_caps_cfg = le32toh(resp->dev_caps_cfg);
700 	if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
701 	    (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
702 		softc->flags |= BNXT_FLAG_SHORT_CMD;
703 
704 fail:
705 	BNXT_HWRM_UNLOCK(softc);
706 	return rc;
707 }
708 
709 int
bnxt_hwrm_func_drv_rgtr(struct bnxt_softc * softc)710 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
711 {
712 	struct hwrm_func_drv_rgtr_input req = {0};
713 
714 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
715 
716 	req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
717 	    HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
718 	req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
719 
720 	req.ver_maj = __FreeBSD_version / 100000;
721 	req.ver_min = (__FreeBSD_version / 1000) % 100;
722 	req.ver_upd = (__FreeBSD_version / 100) % 10;
723 
724 	return hwrm_send_message(softc, &req, sizeof(req));
725 }
726 
727 int
bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc * softc,bool shutdown)728 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
729 {
730 	struct hwrm_func_drv_unrgtr_input req = {0};
731 
732 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
733 	if (shutdown == true)
734 		req.flags |=
735 		    HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
736 	return hwrm_send_message(softc, &req, sizeof(req));
737 }
738 
739 static inline int
_is_valid_ether_addr(uint8_t * addr)740 _is_valid_ether_addr(uint8_t *addr)
741 {
742 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
743 
744 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
745 		return (FALSE);
746 
747 	return (TRUE);
748 }
749 
750 static inline void
get_random_ether_addr(uint8_t * addr)751 get_random_ether_addr(uint8_t *addr)
752 {
753 	uint8_t temp[ETHER_ADDR_LEN];
754 
755 	arc4rand(&temp, sizeof(temp), 0);
756 	temp[0] &= 0xFE;
757 	temp[0] |= 0x02;
758 	bcopy(temp, addr, sizeof(temp));
759 }
760 
761 int
bnxt_hwrm_func_qcaps(struct bnxt_softc * softc)762 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
763 {
764 	int rc = 0;
765 	struct hwrm_func_qcaps_input req = {0};
766 	struct hwrm_func_qcaps_output *resp =
767 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
768 	struct bnxt_func_info *func = &softc->func;
769 
770 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
771 	req.fid = htole16(0xffff);
772 
773 	BNXT_HWRM_LOCK(softc);
774 	rc = _hwrm_send_message(softc, &req, sizeof(req));
775 	if (rc)
776 		goto fail;
777 
778 	if (resp->flags &
779 	    htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
780 		softc->flags |= BNXT_FLAG_WOL_CAP;
781 	if (resp->flags &
782 	    htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED))
783 		softc->flags |= BNXT_FLAG_FW_CAP_EXT_STATS;
784 
785 	func->fw_fid = le16toh(resp->fid);
786 	memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
787 	func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
788 	func->max_cp_rings = le16toh(resp->max_cmpl_rings);
789 	func->max_tx_rings = le16toh(resp->max_tx_rings);
790 	func->max_rx_rings = le16toh(resp->max_rx_rings);
791 	func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
792 	if (!func->max_hw_ring_grps)
793 		func->max_hw_ring_grps = func->max_tx_rings;
794 	func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
795 	func->max_vnics = le16toh(resp->max_vnics);
796 	func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
797 	if (BNXT_PF(softc)) {
798 		struct bnxt_pf_info *pf = &softc->pf;
799 
800 		pf->port_id = le16toh(resp->port_id);
801 		pf->first_vf_id = le16toh(resp->first_vf_id);
802 		pf->max_vfs = le16toh(resp->max_vfs);
803 		pf->max_encap_records = le32toh(resp->max_encap_records);
804 		pf->max_decap_records = le32toh(resp->max_decap_records);
805 		pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
806 		pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
807 		pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
808 		pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
809 	}
810 	if (!_is_valid_ether_addr(func->mac_addr)) {
811 		device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
812 		get_random_ether_addr(func->mac_addr);
813 	}
814 
815 fail:
816 	BNXT_HWRM_UNLOCK(softc);
817 	return rc;
818 }
819 
820 int
bnxt_hwrm_func_qcfg(struct bnxt_softc * softc)821 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
822 {
823         struct hwrm_func_qcfg_input req = {0};
824         struct hwrm_func_qcfg_output *resp =
825 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
826 	struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
827         int rc;
828 
829 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
830         req.fid = htole16(0xffff);
831 	BNXT_HWRM_LOCK(softc);
832 	rc = _hwrm_send_message(softc, &req, sizeof(req));
833         if (rc)
834 		goto fail;
835 
836 	fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
837 	fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
838 	fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
839 	fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
840 fail:
841 	BNXT_HWRM_UNLOCK(softc);
842         return rc;
843 }
844 
845 int
bnxt_hwrm_func_reset(struct bnxt_softc * softc)846 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
847 {
848 	struct hwrm_func_reset_input req = {0};
849 
850 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
851 	req.enables = 0;
852 
853 	return hwrm_send_message(softc, &req, sizeof(req));
854 }
855 
856 static void
bnxt_hwrm_set_link_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)857 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
858     struct hwrm_port_phy_cfg_input *req)
859 {
860 	struct bnxt_link_info *link_info = &softc->link_info;
861 	uint8_t autoneg = softc->link_info.autoneg;
862 	uint16_t fw_link_speed = softc->link_info.req_link_speed;
863 
864 	if (autoneg & BNXT_AUTONEG_SPEED) {
865 		uint8_t phy_type = get_phy_type(softc);
866 
867 		if (phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET ||
868 		    phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
869 		    phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE) {
870 
871 			req->auto_mode |= htole32(HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK);
872 			if (link_info->advertising) {
873 				req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK);
874 				req->auto_link_speed_mask = htole16(link_info->advertising);
875 			}
876 		} else {
877 			req->auto_mode |= HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
878 		}
879 
880 		req->enables |=
881 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
882 		req->flags |=
883 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
884 	} else {
885 		req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
886 
887 		if (link_info->force_pam4_speed_set_by_user) {
888 			req->force_pam4_link_speed = htole16(fw_link_speed);
889 			req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED);
890 			link_info->force_pam4_speed_set_by_user = false;
891 		} else {
892 			req->force_link_speed = htole16(fw_link_speed);
893 		}
894 	}
895 
896 	/* tell chimp that the setting takes effect immediately */
897 	req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
898 }
899 
900 static void
bnxt_hwrm_set_pause_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)901 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
902     struct hwrm_port_phy_cfg_input *req)
903 {
904 	struct bnxt_link_info *link_info = &softc->link_info;
905 
906 	if (link_info->flow_ctrl.autoneg) {
907 		req->auto_pause =
908 		    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
909 		if (link_info->flow_ctrl.rx)
910 			req->auto_pause |=
911 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
912 		if (link_info->flow_ctrl.tx)
913 			req->auto_pause |=
914 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
915 		req->enables |=
916 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
917 	} else {
918 		if (link_info->flow_ctrl.rx)
919 			req->force_pause |=
920 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
921 		if (link_info->flow_ctrl.tx)
922 			req->force_pause |=
923 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
924 		req->enables |=
925 			htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
926 		req->auto_pause = req->force_pause;
927 		req->enables |=
928 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
929 	}
930 }
931 
932 /* JFV this needs interface connection */
933 static void
bnxt_hwrm_set_eee(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)934 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
935 {
936 	/* struct ethtool_eee *eee = &softc->eee; */
937 	bool	eee_enabled = false;
938 
939 	if (eee_enabled) {
940 #if 0
941 		uint16_t eee_speeds;
942 		uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
943 
944 		if (eee->tx_lpi_enabled)
945 			flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
946 
947 		req->flags |= htole32(flags);
948 		eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
949 		req->eee_link_speed_mask = htole16(eee_speeds);
950 		req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
951 #endif
952 	} else {
953 		req->flags |=
954 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
955 	}
956 }
957 
958 int
bnxt_hwrm_set_link_setting(struct bnxt_softc * softc,bool set_pause,bool set_eee,bool set_link)959 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
960     bool set_eee, bool set_link)
961 {
962 	struct hwrm_port_phy_cfg_input req = {0};
963 	int rc;
964 
965 	if (softc->flags & BNXT_FLAG_NPAR)
966 		return ENOTSUP;
967 
968 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
969 
970 	if (set_pause) {
971 		bnxt_hwrm_set_pause_common(softc, &req);
972 
973 		if (softc->link_info.flow_ctrl.autoneg)
974 			set_link = true;
975 	}
976 
977 	if (set_link)
978 		bnxt_hwrm_set_link_common(softc, &req);
979 
980 	if (set_eee)
981 		bnxt_hwrm_set_eee(softc, &req);
982 
983 	BNXT_HWRM_LOCK(softc);
984 	rc = _hwrm_send_message(softc, &req, sizeof(req));
985 
986 	if (!rc) {
987 		if (set_pause) {
988 			/* since changing of 'force pause' setting doesn't
989 			 * trigger any link change event, the driver needs to
990 			 * update the current pause result upon successfully i
991 			 * return of the phy_cfg command */
992 			if (!softc->link_info.flow_ctrl.autoneg)
993 				bnxt_report_link(softc);
994 		}
995 	}
996 	BNXT_HWRM_UNLOCK(softc);
997 	return rc;
998 }
999 
1000 int
bnxt_hwrm_vnic_set_hds(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1001 bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1002 {
1003         struct hwrm_vnic_plcmodes_cfg_input req = {0};
1004 
1005 	if (!BNXT_CHIP_P5(softc))
1006 		return 0;
1007 
1008 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
1009 
1010 	/*
1011 	 * TBD -- Explore these flags
1012 	 * 	1. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4
1013 	 * 	2. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6
1014 	 * 	3. req.jumbo_thresh
1015 	 * 	4. req.hds_threshold
1016 	 */
1017         req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
1018 	req.vnic_id = htole16(vnic->id);
1019 
1020 	return hwrm_send_message(softc, &req, sizeof(req));
1021 }
1022 
1023 int
bnxt_hwrm_vnic_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1024 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1025 {
1026 	struct hwrm_vnic_cfg_input req = {0};
1027 
1028 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
1029 
1030 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1031 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
1032 	if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
1033 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
1034 	if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
1035 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
1036 	if (BNXT_CHIP_P5 (softc)) {
1037 		req.default_rx_ring_id =
1038 			htole16(softc->rx_rings[0].phys_id);
1039 		req.default_cmpl_ring_id =
1040 			htole16(softc->rx_cp_rings[0].ring.phys_id);
1041 		req.enables |=
1042 			htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
1043 			    HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
1044 		req.vnic_id = htole16(vnic->id);
1045 	} else {
1046 		req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
1047 				HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
1048 		req.vnic_id = htole16(vnic->id);
1049 		req.dflt_ring_grp = htole16(vnic->def_ring_grp);
1050 	}
1051 	req.rss_rule = htole16(vnic->rss_id);
1052 	req.cos_rule = htole16(vnic->cos_rule);
1053 	req.lb_rule = htole16(vnic->lb_rule);
1054 	req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
1055 	req.mru = htole16(vnic->mru);
1056 
1057 	return hwrm_send_message(softc, &req, sizeof(req));
1058 }
1059 
1060 int
bnxt_hwrm_vnic_free(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1061 bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1062 {
1063 	struct hwrm_vnic_free_input req = {0};
1064 	int rc = 0;
1065 
1066 	if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE)
1067 		return rc;
1068 
1069 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
1070 
1071 	req.vnic_id = htole32(vnic->id);
1072 
1073 	BNXT_HWRM_LOCK(softc);
1074 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1075 	if (rc)
1076 		goto fail;
1077 
1078 fail:
1079 	BNXT_HWRM_UNLOCK(softc);
1080 	return (rc);
1081 }
1082 
1083 int
bnxt_hwrm_vnic_alloc(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1084 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1085 {
1086 	struct hwrm_vnic_alloc_input req = {0};
1087 	struct hwrm_vnic_alloc_output *resp =
1088 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1089 	int rc;
1090 
1091 	if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
1092 		device_printf(softc->dev,
1093 		    "Attempt to re-allocate vnic %04x\n", vnic->id);
1094 		return EDOOFUS;
1095 	}
1096 
1097 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
1098 
1099 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1100 		req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
1101 
1102 	BNXT_HWRM_LOCK(softc);
1103 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1104 	if (rc)
1105 		goto fail;
1106 
1107 	vnic->id = le32toh(resp->vnic_id);
1108 
1109 fail:
1110 	BNXT_HWRM_UNLOCK(softc);
1111 	return (rc);
1112 }
1113 
1114 int
bnxt_hwrm_vnic_ctx_free(struct bnxt_softc * softc,uint16_t ctx_id)1115 bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t ctx_id)
1116 {
1117 	struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
1118 	int rc = 0;
1119 
1120 	if (ctx_id == (uint16_t)HWRM_NA_SIGNATURE)
1121 		return rc;
1122 
1123 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
1124 	req.rss_cos_lb_ctx_id = htole16(ctx_id);
1125 	BNXT_HWRM_LOCK(softc);
1126 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1127 	if (rc)
1128 		goto fail;
1129 
1130 fail:
1131 	BNXT_HWRM_UNLOCK(softc);
1132 	return rc;
1133 }
1134 
1135 int
bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc * softc,uint16_t * ctx_id)1136 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
1137 {
1138 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
1139 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
1140 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1141 	int rc;
1142 
1143 	if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
1144 		device_printf(softc->dev,
1145 		    "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
1146 		return EDOOFUS;
1147 	}
1148 
1149 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
1150 
1151 	BNXT_HWRM_LOCK(softc);
1152 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1153 	if (rc)
1154 		goto fail;
1155 
1156 	*ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
1157 
1158 fail:
1159 	BNXT_HWRM_UNLOCK(softc);
1160 	return (rc);
1161 }
1162 
1163 int
bnxt_hwrm_ring_grp_alloc(struct bnxt_softc * softc,struct bnxt_grp_info * grp)1164 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1165 {
1166 	struct hwrm_ring_grp_alloc_input req = {0};
1167 	struct hwrm_ring_grp_alloc_output *resp;
1168 	int rc = 0;
1169 
1170 	if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
1171 		device_printf(softc->dev,
1172 		    "Attempt to re-allocate ring group %04x\n", grp->grp_id);
1173 		return EDOOFUS;
1174 	}
1175 
1176 	if (BNXT_CHIP_P5 (softc))
1177 		return 0;
1178 
1179 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1180 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
1181 	req.cr = htole16(grp->cp_ring_id);
1182 	req.rr = htole16(grp->rx_ring_id);
1183 	req.ar = htole16(grp->ag_ring_id);
1184 	req.sc = htole16(grp->stats_ctx);
1185 
1186 	BNXT_HWRM_LOCK(softc);
1187 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1188 	if (rc)
1189 		goto fail;
1190 
1191 	grp->grp_id = le32toh(resp->ring_group_id);
1192 
1193 fail:
1194 	BNXT_HWRM_UNLOCK(softc);
1195 	return rc;
1196 }
1197 
1198 int
bnxt_hwrm_ring_grp_free(struct bnxt_softc * softc,struct bnxt_grp_info * grp)1199 bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1200 {
1201 	struct hwrm_ring_grp_free_input req = {0};
1202 	int rc = 0;
1203 
1204 	if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE)
1205 		return 0;
1206 
1207 	if (BNXT_CHIP_P5 (softc))
1208 		return 0;
1209 
1210 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
1211 
1212 	req.ring_group_id = htole32(grp->grp_id);
1213 
1214 	BNXT_HWRM_LOCK(softc);
1215 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1216 	if (rc)
1217 		goto fail;
1218 
1219 fail:
1220 	BNXT_HWRM_UNLOCK(softc);
1221 	return rc;
1222 }
1223 
bnxt_hwrm_ring_free(struct bnxt_softc * softc,uint32_t ring_type,struct bnxt_ring * ring,int cmpl_ring_id)1224 int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t ring_type,
1225 		struct bnxt_ring *ring, int cmpl_ring_id)
1226 {
1227         struct hwrm_ring_free_input req = {0};
1228 	struct hwrm_ring_free_output *resp;
1229 	int rc = 0;
1230         uint16_t error_code;
1231 
1232 	if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE)
1233 		return 0;
1234 
1235 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1236 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
1237 	req.cmpl_ring = htole16(cmpl_ring_id);
1238         req.ring_type = ring_type;
1239         req.ring_id = htole16(ring->phys_id);
1240 
1241 	BNXT_HWRM_LOCK(softc);
1242 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1243         error_code = le16toh(resp->error_code);
1244 
1245 	if (rc || error_code) {
1246 		device_printf(softc->dev, "hwrm_ring_free type %d failed. "
1247 				"rc:%x err:%x\n", ring_type, rc, error_code);
1248 		if (!rc)
1249 			rc = -EIO;
1250 	}
1251 
1252 	BNXT_HWRM_UNLOCK(softc);
1253 	return rc;
1254 }
1255 
1256 /*
1257  * Ring allocation message to the firmware
1258  */
1259 int
bnxt_hwrm_ring_alloc(struct bnxt_softc * softc,uint8_t type,struct bnxt_ring * ring)1260 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
1261                      struct bnxt_ring *ring)
1262 {
1263 	struct hwrm_ring_alloc_input req = {0};
1264 	struct hwrm_ring_alloc_output *resp;
1265 	uint16_t idx = ring->idx;
1266 	struct bnxt_cp_ring *cp_ring;
1267 	int rc;
1268 
1269 	if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1270 		device_printf(softc->dev,
1271 		    "Attempt to re-allocate ring %04x\n", ring->phys_id);
1272 		return EDOOFUS;
1273 	}
1274 
1275 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1276 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
1277 	req.enables = htole32(0);
1278 	req.fbo = htole32(0);
1279 	req.ring_type = type;
1280 	req.page_tbl_addr = htole64(ring->paddr);
1281 	req.logical_id = htole16(ring->id);
1282 	req.length = htole32(ring->ring_size);
1283 
1284 	switch (type) {
1285         case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
1286 		cp_ring = &softc->tx_cp_rings[idx];
1287 
1288                 req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
1289 		/* queue_id - what CoS queue the TX ring is associated with */
1290                 req.queue_id = htole16(softc->q_info[0].id);
1291 
1292                 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1293 		req.enables |= htole32(
1294 		    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1295                 break;
1296         case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
1297 		if (!BNXT_CHIP_P5(softc))
1298 			break;
1299 
1300 		cp_ring = &softc->rx_cp_rings[idx];
1301 
1302                 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1303 		req.rx_buf_size = htole16(softc->rx_buf_size);
1304                 req.enables |= htole32(
1305 			HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1306 			HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1307                 break;
1308         case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
1309 		if (!BNXT_CHIP_P5(softc)) {
1310                         req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
1311 			break;
1312                 }
1313 
1314 		cp_ring = &softc->rx_cp_rings[idx];
1315 
1316                 req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
1317 		req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1318 		req.rx_buf_size = htole16(softc->rx_buf_size);
1319                 req.enables |= htole32(
1320                             HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
1321                             HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1322 			    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1323                 break;
1324        case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
1325 		if (!BNXT_CHIP_P5(softc)) {
1326                         req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1327 			break;
1328 		}
1329 
1330                 req.cq_handle = htole64(ring->id);
1331 		req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
1332 		req.enables |= htole32(
1333 			HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
1334                 break;
1335         case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
1336                 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1337                 break;
1338         default:
1339                 printf("hwrm alloc invalid ring type %d\n", type);
1340                 return -1;
1341         }
1342 
1343 	BNXT_HWRM_LOCK(softc);
1344 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1345 	if (rc)
1346 		goto fail;
1347 
1348 	ring->phys_id = le16toh(resp->ring_id);
1349 
1350 fail:
1351 	BNXT_HWRM_UNLOCK(softc);
1352 	return rc;
1353 }
1354 
1355 int
bnxt_hwrm_stat_ctx_free(struct bnxt_softc * softc,struct bnxt_cp_ring * cpr)1356 bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
1357 {
1358 	struct hwrm_stat_ctx_free_input req = {0};
1359 	int rc = 0;
1360 
1361 	if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE)
1362 		return rc;
1363 
1364 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
1365 
1366 	req.stat_ctx_id = htole16(cpr->stats_ctx_id);
1367 	BNXT_HWRM_LOCK(softc);
1368 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1369 	if (rc)
1370 		goto fail;
1371 
1372 fail:
1373 	BNXT_HWRM_UNLOCK(softc);
1374 
1375 	return rc;
1376 }
1377 
1378 int
bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc * softc,struct bnxt_cp_ring * cpr,uint64_t paddr)1379 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
1380     uint64_t paddr)
1381 {
1382 	struct hwrm_stat_ctx_alloc_input req = {0};
1383 	struct hwrm_stat_ctx_alloc_output *resp;
1384 	int rc = 0;
1385 
1386 	if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
1387 		device_printf(softc->dev,
1388 		    "Attempt to re-allocate stats ctx %08x\n",
1389 		    cpr->stats_ctx_id);
1390 		return EDOOFUS;
1391 	}
1392 
1393 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1394 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
1395 
1396 	req.update_period_ms = htole32(1000);
1397 	req.stats_dma_addr = htole64(paddr);
1398 	if (BNXT_CHIP_P5(softc))
1399 		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
1400 	else
1401 		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
1402 
1403 	BNXT_HWRM_LOCK(softc);
1404 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1405 	if (rc)
1406 		goto fail;
1407 
1408 	cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
1409 
1410 fail:
1411 	BNXT_HWRM_UNLOCK(softc);
1412 
1413 	return rc;
1414 }
1415 
1416 int
bnxt_hwrm_port_qstats(struct bnxt_softc * softc)1417 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
1418 {
1419 	struct hwrm_port_qstats_input req = {0};
1420 	int rc = 0;
1421 
1422 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
1423 
1424 	req.port_id = htole16(softc->pf.port_id);
1425 	req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
1426 	req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
1427 
1428 	BNXT_HWRM_LOCK(softc);
1429 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1430 	BNXT_HWRM_UNLOCK(softc);
1431 
1432 	return rc;
1433 }
1434 
1435 void
bnxt_hwrm_port_qstats_ext(struct bnxt_softc * softc)1436 bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc)
1437 {
1438 	struct hwrm_port_qstats_ext_input req = {0};
1439 
1440 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS_EXT);
1441 
1442 	req.port_id = htole16(softc->pf.port_id);
1443 	req.tx_stat_size = htole16(sizeof(struct tx_port_stats_ext));
1444 	req.rx_stat_size = htole16(sizeof(struct rx_port_stats_ext));
1445 	req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats_ext.idi_paddr);
1446 	req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats_ext.idi_paddr);
1447 
1448 	BNXT_HWRM_LOCK(softc);
1449 	_hwrm_send_message(softc, &req, sizeof(req));
1450 	BNXT_HWRM_UNLOCK(softc);
1451 
1452 	return;
1453 }
1454 
1455 int
bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1456 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
1457     struct bnxt_vnic_info *vnic)
1458 {
1459 	struct hwrm_cfa_l2_set_rx_mask_input req = {0};
1460 	uint32_t mask = vnic->rx_mask;
1461 
1462 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
1463 
1464 	req.vnic_id = htole32(vnic->id);
1465 	req.mask = htole32(mask);
1466 	req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
1467 	req.num_mc_entries = htole32(vnic->mc_list_count);
1468 	return hwrm_send_message(softc, &req, sizeof(req));
1469 }
1470 
1471 int
bnxt_hwrm_l2_filter_free(struct bnxt_softc * softc,uint64_t filter_id)1472 bnxt_hwrm_l2_filter_free(struct bnxt_softc *softc, uint64_t filter_id)
1473 {
1474 	struct hwrm_cfa_l2_filter_free_input	req = {0};
1475 	int rc = 0;
1476 
1477 	if (filter_id == -1)
1478 		return rc;
1479 
1480 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
1481 
1482 	req.l2_filter_id = htole64(filter_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
bnxt_hwrm_free_filter(struct bnxt_softc * softc)1495 bnxt_hwrm_free_filter(struct bnxt_softc *softc)
1496 {
1497 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
1498 	struct bnxt_vlan_tag *tag;
1499 	int rc = 0;
1500 
1501 	rc = bnxt_hwrm_l2_filter_free(softc, softc->vnic_info.filter_id);
1502 	if (rc)
1503 		goto end;
1504 
1505 	SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1506 		rc = bnxt_hwrm_l2_filter_free(softc, tag->filter_id);
1507 		if (rc)
1508 			goto end;
1509 		tag->filter_id = -1;
1510 	}
1511 
1512 end:
1513 	return rc;
1514 }
1515 
1516 int
bnxt_hwrm_l2_filter_alloc(struct bnxt_softc * softc,uint16_t vlan_tag,uint64_t * filter_id)1517 bnxt_hwrm_l2_filter_alloc(struct bnxt_softc *softc, uint16_t vlan_tag,
1518 		uint64_t *filter_id)
1519 {
1520 	struct hwrm_cfa_l2_filter_alloc_input	req = {0};
1521 	struct hwrm_cfa_l2_filter_alloc_output	*resp;
1522 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
1523 	uint32_t enables = 0;
1524 	int rc = 0;
1525 
1526 	if (*filter_id != -1) {
1527 		device_printf(softc->dev, "Attempt to re-allocate l2 ctx "
1528 		    "filter (fid: 0x%jx)\n", (uintmax_t)*filter_id);
1529 		return EDOOFUS;
1530 	}
1531 
1532 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1533 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
1534 
1535 	req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
1536 	enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
1537 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
1538 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
1539 
1540 	if (vlan_tag != 0xffff) {
1541 		enables |=
1542 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN |
1543 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK |
1544 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_NUM_VLANS;
1545 		req.l2_ivlan_mask = 0xffff;
1546 		req.l2_ivlan = vlan_tag;
1547 		req.num_vlans = 1;
1548 	}
1549 
1550 	req.enables = htole32(enables);
1551 	req.dst_id = htole16(vnic->id);
1552 	memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
1553 	    ETHER_ADDR_LEN);
1554 	memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
1555 
1556 	BNXT_HWRM_LOCK(softc);
1557 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1558 	if (rc)
1559 		goto fail;
1560 
1561 	*filter_id = le64toh(resp->l2_filter_id);
1562 fail:
1563 	BNXT_HWRM_UNLOCK(softc);
1564 	return (rc);
1565 }
1566 
1567 int
bnxt_hwrm_set_filter(struct bnxt_softc * softc)1568 bnxt_hwrm_set_filter(struct bnxt_softc *softc)
1569 {
1570 	struct bnxt_vnic_info *vnic = &softc->vnic_info;
1571 	struct bnxt_vlan_tag *tag;
1572 	int rc = 0;
1573 
1574 	rc = bnxt_hwrm_l2_filter_alloc(softc, 0xffff, &vnic->filter_id);
1575 	if (rc)
1576 		goto end;
1577 
1578 	SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1579 		rc = bnxt_hwrm_l2_filter_alloc(softc, tag->tag,
1580 				&tag->filter_id);
1581 		if (rc)
1582 			goto end;
1583 	}
1584 
1585 end:
1586 	return rc;
1587 }
1588 
1589 int
bnxt_hwrm_rss_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic,uint32_t hash_type)1590 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
1591     uint32_t hash_type)
1592 {
1593 	struct hwrm_vnic_rss_cfg_input	req = {0};
1594 
1595 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
1596 
1597 	req.hash_type = htole32(hash_type);
1598 	req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
1599 	req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
1600 	req.rss_ctx_idx = htole16(vnic->rss_id);
1601 	req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
1602 	if (BNXT_CHIP_P5(softc)) {
1603 		req.vnic_id = htole16(vnic->id);
1604 		req.ring_table_pair_index = 0x0;
1605 	}
1606 
1607 	return hwrm_send_message(softc, &req, sizeof(req));
1608 }
1609 
1610 int
bnxt_hwrm_reserve_pf_rings(struct bnxt_softc * softc)1611 bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
1612 {
1613 	struct hwrm_func_cfg_input req = {0};
1614 
1615 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1616 
1617 	req.fid = htole16(0xffff);
1618 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
1619 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
1620 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
1621 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
1622 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
1623 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
1624 	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
1625 	req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
1626 	req.num_rsscos_ctxs = htole16(0x8);
1627 	req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
1628 	req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1629 	req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1630 	req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
1631 	req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
1632 
1633 	return hwrm_send_message(softc, &req, sizeof(req));
1634 }
1635 
1636 int
bnxt_cfg_async_cr(struct bnxt_softc * softc)1637 bnxt_cfg_async_cr(struct bnxt_softc *softc)
1638 {
1639 	int rc = 0;
1640 	struct hwrm_func_cfg_input req = {0};
1641 
1642 	if (!BNXT_PF(softc))
1643 		return 0;
1644 
1645 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1646 
1647 	req.fid = htole16(0xffff);
1648 	req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
1649 	if (BNXT_CHIP_P5(softc))
1650 		req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id);
1651 	else
1652 		req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
1653 
1654 	rc = hwrm_send_message(softc, &req, sizeof(req));
1655 
1656 	return rc;
1657 }
1658 
1659 void
bnxt_validate_hw_lro_settings(struct bnxt_softc * softc)1660 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
1661 {
1662 	softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
1663 
1664         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
1665 
1666 	softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
1667 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
1668 
1669 	softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
1670 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
1671 
1672 	softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
1673 }
1674 
1675 int
bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc * softc)1676 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
1677 {
1678 	struct hwrm_vnic_tpa_cfg_input req = {0};
1679 	uint32_t flags;
1680 
1681 	if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
1682 		return 0;
1683 	}
1684 
1685 	if (!(softc->flags & BNXT_FLAG_TPA))
1686 		return 0;
1687 
1688 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
1689 
1690 	if (softc->hw_lro.enable) {
1691 		flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
1692 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
1693 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
1694 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
1695 
1696         	if (softc->hw_lro.is_mode_gro)
1697 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
1698 		else
1699 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
1700 
1701 		req.flags = htole32(flags);
1702 
1703 		req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
1704 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
1705 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
1706 
1707 		req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
1708 		req.max_aggs = htole16(softc->hw_lro.max_aggs);
1709 		req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
1710 	}
1711 
1712 	req.vnic_id = htole16(softc->vnic_info.id);
1713 
1714 	return hwrm_send_message(softc, &req, sizeof(req));
1715 }
1716 
1717 int
bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc * softc,uint16_t type,uint16_t * ordinal,uint16_t ext,uint16_t * index,bool use_index,uint8_t search_opt,uint32_t * data_length,uint32_t * item_length,uint32_t * fw_ver)1718 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
1719     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
1720     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
1721     uint32_t *fw_ver)
1722 {
1723 	struct hwrm_nvm_find_dir_entry_input req = {0};
1724 	struct hwrm_nvm_find_dir_entry_output *resp =
1725 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1726 	int	rc = 0;
1727 	uint32_t old_timeo;
1728 
1729 	MPASS(ordinal);
1730 
1731 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
1732 	if (use_index) {
1733 		req.enables = htole32(
1734 		    HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
1735 		req.dir_idx = htole16(*index);
1736 	}
1737 	req.dir_type = htole16(type);
1738 	req.dir_ordinal = htole16(*ordinal);
1739 	req.dir_ext = htole16(ext);
1740 	req.opt_ordinal = search_opt;
1741 
1742 	BNXT_HWRM_LOCK(softc);
1743 	old_timeo = softc->hwrm_cmd_timeo;
1744 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1745 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1746 	softc->hwrm_cmd_timeo = old_timeo;
1747 	if (rc)
1748 		goto exit;
1749 
1750 	if (item_length)
1751 		*item_length = le32toh(resp->dir_item_length);
1752 	if (data_length)
1753 		*data_length = le32toh(resp->dir_data_length);
1754 	if (fw_ver)
1755 		*fw_ver = le32toh(resp->fw_ver);
1756 	*ordinal = le16toh(resp->dir_ordinal);
1757 	if (index)
1758 		*index = le16toh(resp->dir_idx);
1759 
1760 exit:
1761 	BNXT_HWRM_UNLOCK(softc);
1762 	return (rc);
1763 }
1764 
1765 int
bnxt_hwrm_nvm_read(struct bnxt_softc * softc,uint16_t index,uint32_t offset,uint32_t length,struct iflib_dma_info * data)1766 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1767     uint32_t length, struct iflib_dma_info *data)
1768 {
1769 	struct hwrm_nvm_read_input req = {0};
1770 	int rc;
1771 	uint32_t old_timeo;
1772 
1773 	if (length > data->idi_size) {
1774 		rc = EINVAL;
1775 		goto exit;
1776 	}
1777 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1778 	req.host_dest_addr = htole64(data->idi_paddr);
1779 	req.dir_idx = htole16(index);
1780 	req.offset = htole32(offset);
1781 	req.len = htole32(length);
1782 	BNXT_HWRM_LOCK(softc);
1783 	old_timeo = softc->hwrm_cmd_timeo;
1784 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1785 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1786 	softc->hwrm_cmd_timeo = old_timeo;
1787 	BNXT_HWRM_UNLOCK(softc);
1788 	if (rc)
1789 		goto exit;
1790 	bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1791 
1792 	goto exit;
1793 
1794 exit:
1795 	return rc;
1796 }
1797 
1798 int
bnxt_hwrm_nvm_modify(struct bnxt_softc * softc,uint16_t index,uint32_t offset,void * data,bool cpyin,uint32_t length)1799 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1800     void *data, bool cpyin, uint32_t length)
1801 {
1802 	struct hwrm_nvm_modify_input req = {0};
1803 	struct iflib_dma_info dma_data;
1804 	int rc;
1805 	uint32_t old_timeo;
1806 
1807 	if (length == 0 || !data)
1808 		return EINVAL;
1809 	rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1810 	    BUS_DMA_NOWAIT);
1811 	if (rc)
1812 		return ENOMEM;
1813 	if (cpyin) {
1814 		rc = copyin(data, dma_data.idi_vaddr, length);
1815 		if (rc)
1816 			goto exit;
1817 	}
1818 	else
1819 		memcpy(dma_data.idi_vaddr, data, length);
1820 	bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1821 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1822 
1823 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1824 	req.host_src_addr = htole64(dma_data.idi_paddr);
1825 	req.dir_idx = htole16(index);
1826 	req.offset = htole32(offset);
1827 	req.len = htole32(length);
1828 	BNXT_HWRM_LOCK(softc);
1829 	old_timeo = softc->hwrm_cmd_timeo;
1830 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1831 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1832 	softc->hwrm_cmd_timeo = old_timeo;
1833 	BNXT_HWRM_UNLOCK(softc);
1834 
1835 exit:
1836 	iflib_dma_free(&dma_data);
1837 	return rc;
1838 }
1839 
1840 int
bnxt_hwrm_fw_reset(struct bnxt_softc * softc,uint8_t processor,uint8_t * selfreset)1841 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1842     uint8_t *selfreset)
1843 {
1844 	struct hwrm_fw_reset_input req = {0};
1845 	struct hwrm_fw_reset_output *resp =
1846 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1847 	int rc;
1848 
1849 	MPASS(selfreset);
1850 
1851 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1852 	req.embedded_proc_type = processor;
1853 	req.selfrst_status = *selfreset;
1854 
1855 	BNXT_HWRM_LOCK(softc);
1856 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1857 	if (rc)
1858 		goto exit;
1859 	*selfreset = resp->selfrst_status;
1860 
1861 exit:
1862 	BNXT_HWRM_UNLOCK(softc);
1863 	return rc;
1864 }
1865 
1866 int
bnxt_hwrm_fw_qstatus(struct bnxt_softc * softc,uint8_t type,uint8_t * selfreset)1867 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1868 {
1869 	struct hwrm_fw_qstatus_input req = {0};
1870 	struct hwrm_fw_qstatus_output *resp =
1871 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1872 	int rc;
1873 
1874 	MPASS(selfreset);
1875 
1876 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1877 	req.embedded_proc_type = type;
1878 
1879 	BNXT_HWRM_LOCK(softc);
1880 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1881 	if (rc)
1882 		goto exit;
1883 	*selfreset = resp->selfrst_status;
1884 
1885 exit:
1886 	BNXT_HWRM_UNLOCK(softc);
1887 	return rc;
1888 }
1889 
1890 int
bnxt_hwrm_nvm_write(struct bnxt_softc * softc,void * data,bool cpyin,uint16_t type,uint16_t ordinal,uint16_t ext,uint16_t attr,uint16_t option,uint32_t data_length,bool keep,uint32_t * item_length,uint16_t * index)1891 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1892     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1893     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1894     uint16_t *index)
1895 {
1896 	struct hwrm_nvm_write_input req = {0};
1897 	struct hwrm_nvm_write_output *resp =
1898 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1899 	struct iflib_dma_info dma_data;
1900 	int rc;
1901 	uint32_t old_timeo;
1902 
1903 	if (data_length) {
1904 		rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1905 		    BUS_DMA_NOWAIT);
1906 		if (rc)
1907 			return ENOMEM;
1908 		if (cpyin) {
1909 			rc = copyin(data, dma_data.idi_vaddr, data_length);
1910 			if (rc)
1911 				goto early_exit;
1912 		}
1913 		else
1914 			memcpy(dma_data.idi_vaddr, data, data_length);
1915 		bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1916 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1917 	}
1918 	else
1919 		dma_data.idi_paddr = 0;
1920 
1921 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1922 
1923 	req.host_src_addr = htole64(dma_data.idi_paddr);
1924 	req.dir_type = htole16(type);
1925 	req.dir_ordinal = htole16(ordinal);
1926 	req.dir_ext = htole16(ext);
1927 	req.dir_attr = htole16(attr);
1928 	req.dir_data_length = htole32(data_length);
1929 	req.option = htole16(option);
1930 	if (keep) {
1931 		req.flags =
1932 		    htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1933 	}
1934 	if (item_length)
1935 		req.dir_item_length = htole32(*item_length);
1936 
1937 	BNXT_HWRM_LOCK(softc);
1938 	old_timeo = softc->hwrm_cmd_timeo;
1939 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1940 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1941 	softc->hwrm_cmd_timeo = old_timeo;
1942 	if (rc)
1943 		goto exit;
1944 	if (item_length)
1945 		*item_length = le32toh(resp->dir_item_length);
1946 	if (index)
1947 		*index = le16toh(resp->dir_idx);
1948 
1949 exit:
1950 	BNXT_HWRM_UNLOCK(softc);
1951 early_exit:
1952 	if (data_length)
1953 		iflib_dma_free(&dma_data);
1954 	return rc;
1955 }
1956 
1957 int
bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc * softc,uint16_t index)1958 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1959 {
1960 	struct hwrm_nvm_erase_dir_entry_input req = {0};
1961 	uint32_t old_timeo;
1962 	int rc;
1963 
1964 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1965 	req.dir_idx = htole16(index);
1966 	BNXT_HWRM_LOCK(softc);
1967 	old_timeo = softc->hwrm_cmd_timeo;
1968 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1969 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1970 	softc->hwrm_cmd_timeo = old_timeo;
1971 	BNXT_HWRM_UNLOCK(softc);
1972 	return rc;
1973 }
1974 
1975 int
bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length)1976 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1977     uint32_t *entry_length)
1978 {
1979 	struct hwrm_nvm_get_dir_info_input req = {0};
1980 	struct hwrm_nvm_get_dir_info_output *resp =
1981 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1982 	int rc;
1983 	uint32_t old_timeo;
1984 
1985 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1986 
1987 	BNXT_HWRM_LOCK(softc);
1988 	old_timeo = softc->hwrm_cmd_timeo;
1989 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1990 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1991 	softc->hwrm_cmd_timeo = old_timeo;
1992 	if (rc)
1993 		goto exit;
1994 
1995 	if (entries)
1996 		*entries = le32toh(resp->entries);
1997 	if (entry_length)
1998 		*entry_length = le32toh(resp->entry_length);
1999 
2000 exit:
2001 	BNXT_HWRM_UNLOCK(softc);
2002 	return rc;
2003 }
2004 
2005 int
bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length,struct iflib_dma_info * dma_data)2006 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
2007     uint32_t *entry_length, struct iflib_dma_info *dma_data)
2008 {
2009 	struct hwrm_nvm_get_dir_entries_input req = {0};
2010 	uint32_t ent;
2011 	uint32_t ent_len;
2012 	int rc;
2013 	uint32_t old_timeo;
2014 
2015 	if (!entries)
2016 		entries = &ent;
2017 	if (!entry_length)
2018 		entry_length = &ent_len;
2019 
2020 	rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
2021 	if (rc)
2022 		goto exit;
2023 	if (*entries * *entry_length > dma_data->idi_size) {
2024 		rc = EINVAL;
2025 		goto exit;
2026 	}
2027 
2028 	/*
2029 	 * TODO: There's a race condition here that could blow up DMA memory...
2030 	 *	 we need to allocate the max size, not the currently in use
2031 	 *	 size.  The command should totally have a max size here.
2032 	 */
2033 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
2034 	req.host_dest_addr = htole64(dma_data->idi_paddr);
2035 	BNXT_HWRM_LOCK(softc);
2036 	old_timeo = softc->hwrm_cmd_timeo;
2037 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2038 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2039 	softc->hwrm_cmd_timeo = old_timeo;
2040 	BNXT_HWRM_UNLOCK(softc);
2041 	if (rc)
2042 		goto exit;
2043 	bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
2044 	    BUS_DMASYNC_POSTWRITE);
2045 
2046 exit:
2047 	return rc;
2048 }
2049 
2050 int
bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc * softc,uint16_t * mfg_id,uint16_t * device_id,uint32_t * sector_size,uint32_t * nvram_size,uint32_t * reserved_size,uint32_t * available_size)2051 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
2052     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
2053     uint32_t *reserved_size, uint32_t *available_size)
2054 {
2055 	struct hwrm_nvm_get_dev_info_input req = {0};
2056 	struct hwrm_nvm_get_dev_info_output *resp =
2057 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2058 	int rc;
2059 	uint32_t old_timeo;
2060 
2061 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
2062 
2063 	BNXT_HWRM_LOCK(softc);
2064 	old_timeo = softc->hwrm_cmd_timeo;
2065 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2066 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2067 	softc->hwrm_cmd_timeo = old_timeo;
2068 	if (rc)
2069 		goto exit;
2070 
2071 	if (mfg_id)
2072 		*mfg_id = le16toh(resp->manufacturer_id);
2073 	if (device_id)
2074 		*device_id = le16toh(resp->device_id);
2075 	if (sector_size)
2076 		*sector_size = le32toh(resp->sector_size);
2077 	if (nvram_size)
2078 		*nvram_size = le32toh(resp->nvram_size);
2079 	if (reserved_size)
2080 		*reserved_size = le32toh(resp->reserved_size);
2081 	if (available_size)
2082 		*available_size = le32toh(resp->available_size);
2083 
2084 exit:
2085 	BNXT_HWRM_UNLOCK(softc);
2086 	return rc;
2087 }
2088 
2089 int
bnxt_hwrm_nvm_install_update(struct bnxt_softc * softc,uint32_t install_type,uint64_t * installed_items,uint8_t * result,uint8_t * problem_item,uint8_t * reset_required)2090 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
2091     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
2092     uint8_t *problem_item, uint8_t *reset_required)
2093 {
2094 	struct hwrm_nvm_install_update_input req = {0};
2095 	struct hwrm_nvm_install_update_output *resp =
2096 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2097 	int rc;
2098 	uint32_t old_timeo;
2099 
2100 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
2101 	req.install_type = htole32(install_type);
2102 
2103 	BNXT_HWRM_LOCK(softc);
2104 	old_timeo = softc->hwrm_cmd_timeo;
2105 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2106 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2107 	softc->hwrm_cmd_timeo = old_timeo;
2108 	if (rc)
2109 		goto exit;
2110 
2111 	if (installed_items)
2112 		*installed_items = le32toh(resp->installed_items);
2113 	if (result)
2114 		*result = resp->result;
2115 	if (problem_item)
2116 		*problem_item = resp->problem_item;
2117 	if (reset_required)
2118 		*reset_required = resp->reset_required;
2119 
2120 exit:
2121 	BNXT_HWRM_UNLOCK(softc);
2122 	return rc;
2123 }
2124 
2125 int
bnxt_hwrm_nvm_verify_update(struct bnxt_softc * softc,uint16_t type,uint16_t ordinal,uint16_t ext)2126 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
2127     uint16_t ordinal, uint16_t ext)
2128 {
2129 	struct hwrm_nvm_verify_update_input req = {0};
2130 	uint32_t old_timeo;
2131 	int rc;
2132 
2133 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
2134 
2135 	req.dir_type = htole16(type);
2136 	req.dir_ordinal = htole16(ordinal);
2137 	req.dir_ext = htole16(ext);
2138 
2139 	BNXT_HWRM_LOCK(softc);
2140 	old_timeo = softc->hwrm_cmd_timeo;
2141 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2142 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2143 	softc->hwrm_cmd_timeo = old_timeo;
2144 	BNXT_HWRM_UNLOCK(softc);
2145 	return rc;
2146 }
2147 
2148 int
bnxt_hwrm_fw_get_time(struct bnxt_softc * softc,uint16_t * year,uint8_t * month,uint8_t * day,uint8_t * hour,uint8_t * minute,uint8_t * second,uint16_t * millisecond,uint16_t * zone)2149 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
2150     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
2151     uint16_t *millisecond, uint16_t *zone)
2152 {
2153 	struct hwrm_fw_get_time_input req = {0};
2154 	struct hwrm_fw_get_time_output *resp =
2155 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2156 	int rc;
2157 
2158 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
2159 
2160 	BNXT_HWRM_LOCK(softc);
2161 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2162 	if (rc)
2163 		goto exit;
2164 
2165 	if (year)
2166 		*year = le16toh(resp->year);
2167 	if (month)
2168 		*month = resp->month;
2169 	if (day)
2170 		*day = resp->day;
2171 	if (hour)
2172 		*hour = resp->hour;
2173 	if (minute)
2174 		*minute = resp->minute;
2175 	if (second)
2176 		*second = resp->second;
2177 	if (millisecond)
2178 		*millisecond = le16toh(resp->millisecond);
2179 	if (zone)
2180 		*zone = le16toh(resp->zone);
2181 
2182 exit:
2183 	BNXT_HWRM_UNLOCK(softc);
2184 	return rc;
2185 }
2186 
2187 int
bnxt_hwrm_fw_set_time(struct bnxt_softc * softc,uint16_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second,uint16_t millisecond,uint16_t zone)2188 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
2189     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
2190     uint16_t millisecond, uint16_t zone)
2191 {
2192 	struct hwrm_fw_set_time_input req = {0};
2193 
2194 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
2195 
2196 	req.year = htole16(year);
2197 	req.month = month;
2198 	req.day = day;
2199 	req.hour = hour;
2200 	req.minute = minute;
2201 	req.second = second;
2202 	req.millisecond = htole16(millisecond);
2203 	req.zone = htole16(zone);
2204 	return hwrm_send_message(softc, &req, sizeof(req));
2205 }
2206 
bnxt_read_sfp_module_eeprom_info(struct bnxt_softc * softc,uint16_t i2c_addr,uint16_t page_number,uint8_t bank,bool bank_sel_en,uint16_t start_addr,uint16_t data_length,uint8_t * buf)2207 int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *softc, uint16_t i2c_addr,
2208     uint16_t page_number, uint8_t bank,bool bank_sel_en, uint16_t start_addr,
2209     uint16_t data_length, uint8_t *buf)
2210 {
2211 	struct hwrm_port_phy_i2c_read_output *output =
2212 			(void *)softc->hwrm_cmd_resp.idi_vaddr;
2213 	struct hwrm_port_phy_i2c_read_input req = {0};
2214 	int rc = 0, byte_offset = 0;
2215 
2216 	BNXT_HWRM_LOCK(softc);
2217 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_I2C_READ);
2218 
2219 	req.i2c_slave_addr = i2c_addr;
2220 	req.page_number = htole16(page_number);
2221 	req.port_id = htole16(softc->pf.port_id);
2222 	do {
2223 		uint16_t xfer_size;
2224 
2225 		xfer_size = min_t(uint16_t, data_length, BNXT_MAX_PHY_I2C_RESP_SIZE);
2226 		data_length -= xfer_size;
2227 		req.page_offset = htole16(start_addr + byte_offset);
2228 		req.data_length = xfer_size;
2229 		req.bank_number = bank;
2230 		req.enables = htole32((start_addr + byte_offset ?
2231 				HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET : 0) |
2232 				(bank_sel_en ?
2233 				HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_BANK_NUMBER : 0));
2234 		rc = hwrm_send_message(softc, &req, sizeof(req));
2235 		if (!rc)
2236 			memcpy(buf + byte_offset, output->data, xfer_size);
2237 		byte_offset += xfer_size;
2238 	} while (!rc && data_length > 0);
2239 
2240 	BNXT_HWRM_UNLOCK(softc);
2241 
2242 	return rc;
2243 }
2244 
2245 int
bnxt_hwrm_port_phy_qcfg(struct bnxt_softc * softc)2246 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
2247 {
2248 	struct bnxt_link_info *link_info = &softc->link_info;
2249 	struct hwrm_port_phy_qcfg_input req = {0};
2250 	struct hwrm_port_phy_qcfg_output *resp =
2251 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2252 	int rc = 0;
2253 
2254 	BNXT_HWRM_LOCK(softc);
2255 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
2256 
2257 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2258 	if (rc)
2259 		goto exit;
2260 
2261 	memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp));
2262 	link_info->phy_link_status = resp->link;
2263 	link_info->duplex =  resp->duplex_cfg;
2264 	link_info->auto_mode = resp->auto_mode;
2265 
2266         /*
2267          * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
2268          * the advertisement of pause is enabled.
2269          * 1. When the auto_mode is not set to none and this flag is set to 1,
2270          *    then the auto_pause bits on this port are being advertised and
2271          *    autoneg pause results are being interpreted.
2272          * 2. When the auto_mode is not set to none and this flag is set to 0,
2273          *    the pause is forced as indicated in force_pause, and also
2274 	 *    advertised as auto_pause bits, but the autoneg results are not
2275 	 *    interpreted since the pause configuration is being forced.
2276          * 3. When the auto_mode is set to none and this flag is set to 1,
2277          *    auto_pause bits should be ignored and should be set to 0.
2278          */
2279 
2280 	link_info->flow_ctrl.autoneg = false;
2281 	link_info->flow_ctrl.tx = false;
2282 	link_info->flow_ctrl.rx = false;
2283 
2284 	if ((resp->auto_mode) &&
2285             (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
2286 			link_info->flow_ctrl.autoneg = true;
2287 	}
2288 
2289 	if (link_info->flow_ctrl.autoneg) {
2290 		if (resp->auto_pause & BNXT_PAUSE_TX)
2291 			link_info->flow_ctrl.tx = true;
2292 		if (resp->auto_pause & BNXT_PAUSE_RX)
2293 			link_info->flow_ctrl.rx = true;
2294 	} else {
2295 		if (resp->force_pause & BNXT_PAUSE_TX)
2296 			link_info->flow_ctrl.tx = true;
2297 		if (resp->force_pause & BNXT_PAUSE_RX)
2298 			link_info->flow_ctrl.rx = true;
2299 	}
2300 
2301 	link_info->duplex_setting = resp->duplex_cfg;
2302 	if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
2303 		link_info->link_speed = le16toh(resp->link_speed);
2304 	else
2305 		link_info->link_speed = 0;
2306 	link_info->force_link_speed = le16toh(resp->force_link_speed);
2307 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed);
2308 	link_info->support_speeds = le16toh(resp->support_speeds);
2309 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
2310 	link_info->preemphasis = le32toh(resp->preemphasis);
2311 	link_info->phy_ver[0] = resp->phy_maj;
2312 	link_info->phy_ver[1] = resp->phy_min;
2313 	link_info->phy_ver[2] = resp->phy_bld;
2314 	snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
2315 	    "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
2316 	    link_info->phy_ver[2]);
2317 	strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
2318 	    BNXT_NAME_SIZE);
2319 	strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
2320 	    BNXT_NAME_SIZE);
2321 	link_info->media_type = resp->media_type;
2322 	link_info->phy_type = resp->phy_type;
2323 	link_info->transceiver = resp->xcvr_pkg_type;
2324 	link_info->phy_addr = resp->eee_config_phy_addr &
2325 	    HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
2326 	link_info->module_status = resp->module_status;
2327 	link_info->support_pam4_speeds = le16toh(resp->support_pam4_speeds);
2328 	link_info->auto_pam4_link_speeds = le16toh(resp->auto_pam4_link_speed_mask);
2329 	link_info->force_pam4_link_speed = le16toh(resp->force_pam4_link_speed);
2330 
2331 	if (softc->hwrm_spec_code >= 0x10504)
2332 		link_info->active_fec_sig_mode = resp->active_fec_signal_mode;
2333 
2334 exit:
2335 	BNXT_HWRM_UNLOCK(softc);
2336 	return rc;
2337 }
2338 
2339 static bool
bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output * resp)2340 bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp)
2341 {
2342 	if (!resp->supported_speeds_auto_mode &&
2343 	    !resp->supported_speeds_force_mode &&
2344 	    !resp->supported_pam4_speeds_auto_mode &&
2345 	    !resp->supported_pam4_speeds_force_mode)
2346 		return true;
2347 
2348 	return false;
2349 }
2350 
bnxt_hwrm_phy_qcaps(struct bnxt_softc * softc)2351 int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc)
2352 {
2353 	struct bnxt_link_info *link_info = &softc->link_info;
2354 	struct hwrm_port_phy_qcaps_output *resp =
2355 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
2356 	struct hwrm_port_phy_qcaps_input req = {};
2357 	int rc;
2358 
2359 	if (softc->hwrm_spec_code < 0x10201)
2360 		return 0;
2361 
2362 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCAPS);
2363 
2364 	BNXT_HWRM_LOCK(softc);
2365 	rc = _hwrm_send_message(softc, &req, sizeof(req));
2366 	if (rc)
2367 		goto exit;
2368 
2369 	if (softc->hwrm_spec_code >= 0x10a01) {
2370 		if (bnxt_phy_qcaps_no_speed(resp)) {
2371 			link_info->phy_state = BNXT_PHY_STATE_DISABLED;
2372 			device_printf(softc->dev, "Ethernet link disabled\n");
2373 		} else if (link_info->phy_state == BNXT_PHY_STATE_DISABLED) {
2374 			link_info->phy_state = BNXT_PHY_STATE_ENABLED;
2375 			device_printf(softc->dev, "Ethernet link enabled\n");
2376 			/* Phy re-enabled, reprobe the speeds */
2377 			link_info->support_auto_speeds = 0;
2378 			link_info->support_pam4_auto_speeds = 0;
2379 		}
2380 	}
2381 	if (resp->supported_speeds_auto_mode)
2382 		link_info->support_auto_speeds =
2383 			le16toh(resp->supported_speeds_auto_mode);
2384 	if (resp->supported_speeds_force_mode)
2385 		link_info->support_force_speeds =
2386 			le16toh(resp->supported_speeds_force_mode);
2387 	if (resp->supported_pam4_speeds_auto_mode)
2388 		link_info->support_pam4_auto_speeds =
2389 			le16toh(resp->supported_pam4_speeds_auto_mode);
2390 	if (resp->supported_pam4_speeds_force_mode)
2391 		link_info->support_pam4_force_speeds =
2392 			le16toh(resp->supported_pam4_speeds_force_mode);
2393 
2394 exit:
2395 	BNXT_HWRM_UNLOCK(softc);
2396 	return rc;
2397 }
2398 
2399 uint16_t
bnxt_hwrm_get_wol_fltrs(struct bnxt_softc * softc,uint16_t handle)2400 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
2401 {
2402 	struct hwrm_wol_filter_qcfg_input req = {0};
2403 	struct hwrm_wol_filter_qcfg_output *resp =
2404 			(void *)softc->hwrm_cmd_resp.idi_vaddr;
2405 	uint16_t next_handle = 0;
2406 	int rc;
2407 
2408 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
2409 	req.port_id = htole16(softc->pf.port_id);
2410 	req.handle = htole16(handle);
2411 	rc = hwrm_send_message(softc, &req, sizeof(req));
2412 	if (!rc) {
2413 		next_handle = le16toh(resp->next_handle);
2414 		if (next_handle != 0) {
2415 			if (resp->wol_type ==
2416 				HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
2417 				softc->wol = 1;
2418 				softc->wol_filter_id = resp->wol_filter_id;
2419 			}
2420 		}
2421 	}
2422 	return next_handle;
2423 }
2424 
2425 int
bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc * softc)2426 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
2427 {
2428 	struct hwrm_wol_filter_alloc_input req = {0};
2429 	struct hwrm_wol_filter_alloc_output *resp =
2430 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
2431 	int rc;
2432 
2433 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
2434 	req.port_id = htole16(softc->pf.port_id);
2435 	req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
2436 	req.enables =
2437 		htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
2438 	memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
2439 	rc = hwrm_send_message(softc, &req, sizeof(req));
2440 	if (!rc)
2441 		softc->wol_filter_id = resp->wol_filter_id;
2442 
2443 	return rc;
2444 }
2445 
2446 int
bnxt_hwrm_free_wol_fltr(struct bnxt_softc * softc)2447 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
2448 {
2449 	struct hwrm_wol_filter_free_input req = {0};
2450 
2451 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
2452 	req.port_id = htole16(softc->pf.port_id);
2453 	req.enables =
2454 		htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
2455 	req.wol_filter_id = softc->wol_filter_id;
2456 	return hwrm_send_message(softc, &req, sizeof(req));
2457 }
2458 
bnxt_hwrm_set_coal_params(struct bnxt_softc * softc,uint32_t max_frames,uint32_t buf_tmrs,uint16_t flags,struct hwrm_ring_cmpl_ring_cfg_aggint_params_input * req)2459 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
2460         uint32_t buf_tmrs, uint16_t flags,
2461         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
2462 {
2463         req->flags = htole16(flags);
2464         req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
2465         req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
2466         req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
2467         req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
2468         /* Minimum time between 2 interrupts set to buf_tmr x 2 */
2469         req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
2470         req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
2471         req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
2472 }
2473 
bnxt_hwrm_set_coal(struct bnxt_softc * softc)2474 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
2475 {
2476         int i, rc = 0;
2477         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
2478                                                            req_tx = {0}, *req;
2479         uint16_t max_buf, max_buf_irq;
2480         uint16_t buf_tmr, buf_tmr_irq;
2481         uint32_t flags;
2482 
2483         bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
2484                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2485         bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
2486                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2487 
2488         /* Each rx completion (2 records) should be DMAed immediately.
2489          * DMA 1/4 of the completion buffers at a time.
2490          */
2491         max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
2492         /* max_buf must not be zero */
2493         max_buf = clamp_t(uint16_t, max_buf, 1, 63);
2494         max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
2495         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
2496         /* buf timer set to 1/4 of interrupt timer */
2497         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2498         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
2499         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2500 
2501         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2502 
2503         /* RING_IDLE generates more IRQs for lower latency.  Enable it only
2504          * if coal_usecs is less than 25 us.
2505          */
2506         if (softc->rx_coal_usecs < 25)
2507                 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
2508 
2509         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2510                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
2511 
2512         /* max_buf must not be zero */
2513         max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
2514         max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
2515         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
2516         /* buf timer set to 1/4 of interrupt timer */
2517         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2518         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
2519         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2520         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2521         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2522                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
2523 
2524         for (i = 0; i < softc->nrxqsets; i++) {
2525 
2526 		req = &req_rx;
2527                 /*
2528                  * TBD:
2529 		 *      Check if Tx also needs to be done
2530                  *      So far, Tx processing has been done in softirq contest
2531                  *
2532 		 * req = &req_tx;
2533 		 */
2534 		req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
2535 
2536                 rc = hwrm_send_message(softc, req, sizeof(*req));
2537                 if (rc)
2538                         break;
2539         }
2540         return rc;
2541 }
2542 
bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc * softc,unsigned long * bmap,int bmap_size)2543 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
2544                                      int bmap_size)
2545 {
2546 	struct hwrm_func_drv_rgtr_input req = {0};
2547 	bitstr_t *async_events_bmap;
2548 	uint32_t *events;
2549 	int i;
2550 
2551 #define BNXT_MAX_NUM_ASYNC_EVENTS 256
2552 	async_events_bmap = bit_alloc(BNXT_MAX_NUM_ASYNC_EVENTS, M_DEVBUF,
2553 			M_WAITOK|M_ZERO);
2554 	events = (uint32_t *)async_events_bmap;
2555 
2556 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
2557 
2558 	req.enables =
2559 		htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
2560 
2561 	memset(async_events_bmap, 0, sizeof(BNXT_MAX_NUM_ASYNC_EVENTS / 8));
2562 
2563 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
2564 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
2565 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
2566 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
2567 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
2568 
2569 	if (bmap && bmap_size) {
2570 		for (i = 0; i < bmap_size; i++) {
2571 			if (bit_test(bmap, i))
2572 				bit_set(async_events_bmap, i);
2573 		}
2574 	}
2575 
2576 	for (i = 0; i < 8; i++)
2577 		req.async_event_fwd[i] |= htole32(events[i]);
2578 
2579 	free(async_events_bmap, M_DEVBUF);
2580 
2581 	return hwrm_send_message(softc, &req, sizeof(req));
2582 }
2583 
bnxt_hwrm_ring_info_get(struct bnxt_softc * softc,uint8_t ring_type,uint32_t ring_id,uint32_t * prod,uint32_t * cons)2584 void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type,
2585                                        uint32_t ring_id,  uint32_t *prod, uint32_t *cons)
2586 {
2587         hwrm_dbg_ring_info_get_input_t req = {0};
2588         hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
2589         int rc = 0;
2590 
2591 	*prod = *cons = 0xffffffff;
2592 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET);
2593         req.ring_type = le32toh(ring_type);
2594         req.fw_ring_id = le32toh(ring_id);
2595 	rc = hwrm_send_message(softc, &req, sizeof(req));
2596 	if (!rc) {
2597 		*prod = resp->producer_index;
2598 		*cons = resp->consumer_index;
2599 	}
2600 
2601 	return;
2602 }
2603