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