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