xref: /freebsd-13.1/sys/dev/bnxt/bnxt_hwrm.c (revision 38fc6c14)
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 __FBSDID("$FreeBSD$");
31 
32 #include <sys/endian.h>
33 #include <sys/bitstring.h>
34 
35 #include "bnxt.h"
36 #include "bnxt_hwrm.h"
37 #include "hsi_struct_def.h"
38 
39 static int bnxt_hwrm_err_map(uint16_t err);
40 static inline int _is_valid_ether_addr(uint8_t *);
41 static inline void get_random_ether_addr(uint8_t *);
42 static void	bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
43 		    struct hwrm_port_phy_cfg_input *req);
44 static void	bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
45 		    struct hwrm_port_phy_cfg_input *req);
46 static void	bnxt_hwrm_set_eee(struct bnxt_softc *softc,
47 		    struct hwrm_port_phy_cfg_input *req);
48 static int	_hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
49 static int	hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
50 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
51 
52 /* NVRam stuff has a five minute timeout */
53 #define BNXT_NVM_TIMEO	(5 * 60 * 1000)
54 
55 static int
bnxt_hwrm_err_map(uint16_t err)56 bnxt_hwrm_err_map(uint16_t err)
57 {
58 	int rc;
59 
60 	switch (err) {
61 	case HWRM_ERR_CODE_SUCCESS:
62 		return 0;
63 	case HWRM_ERR_CODE_INVALID_PARAMS:
64 	case HWRM_ERR_CODE_INVALID_FLAGS:
65 	case HWRM_ERR_CODE_INVALID_ENABLES:
66 		return EINVAL;
67 	case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
68 		return EACCES;
69 	case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
70 		return ENOMEM;
71 	case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
72 		return ENOSYS;
73 	case HWRM_ERR_CODE_FAIL:
74 		return EIO;
75 	case HWRM_ERR_CODE_HWRM_ERROR:
76 	case HWRM_ERR_CODE_UNKNOWN_ERR:
77 	default:
78 		return EDOOFUS;
79 	}
80 
81 	return rc;
82 }
83 
84 int
bnxt_alloc_hwrm_dma_mem(struct bnxt_softc * softc)85 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
86 {
87 	int rc;
88 
89 	rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
90 	    BUS_DMA_NOWAIT);
91 	return rc;
92 }
93 
94 void
bnxt_free_hwrm_dma_mem(struct bnxt_softc * softc)95 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
96 {
97 	if (softc->hwrm_cmd_resp.idi_vaddr)
98 		iflib_dma_free(&softc->hwrm_cmd_resp);
99 	softc->hwrm_cmd_resp.idi_vaddr = NULL;
100 	return;
101 }
102 
103 static void
bnxt_hwrm_cmd_hdr_init(struct bnxt_softc * softc,void * request,uint16_t req_type)104 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
105     uint16_t req_type)
106 {
107 	struct input *req = request;
108 
109 	req->req_type = htole16(req_type);
110 	req->cmpl_ring = 0xffff;
111 	req->target_id = 0xffff;
112 	req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
113 }
114 
115 static int
_hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)116 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
117 {
118 	struct input *req = msg;
119 	struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
120 	uint32_t *data = msg;
121 	int i;
122 	uint16_t cp_ring_id;
123 	uint8_t *valid;
124 	uint16_t err;
125 	uint16_t max_req_len = HWRM_MAX_REQ_LEN;
126 	struct hwrm_short_input short_input = {0};
127 
128 	/* TODO: DMASYNC in here. */
129 	req->seq_id = htole16(softc->hwrm_cmd_seq++);
130 	memset(resp, 0, PAGE_SIZE);
131 	cp_ring_id = le16toh(req->cmpl_ring);
132 
133 	if (softc->flags & BNXT_FLAG_SHORT_CMD) {
134 		void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
135 
136 		memcpy(short_cmd_req, req, msg_len);
137 		memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len-
138 		    msg_len);
139 
140 		short_input.req_type = req->req_type;
141 		short_input.signature =
142 		    htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
143 		short_input.size = htole16(msg_len);
144 		short_input.req_addr =
145 		    htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
146 
147 		data = (uint32_t *)&short_input;
148 		msg_len = sizeof(short_input);
149 
150 		/* Sync memory write before updating doorbell */
151 		wmb();
152 
153 		max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
154 	}
155 
156 	/* Write request msg to hwrm channel */
157 	for (i = 0; i < msg_len; i += 4) {
158 		bus_space_write_4(softc->hwrm_bar.tag,
159 				  softc->hwrm_bar.handle,
160 				  i, *data);
161 		data++;
162 	}
163 
164 	/* Clear to the end of the request buffer */
165 	for (i = msg_len; i < max_req_len; i += 4)
166 		bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
167 		    i, 0);
168 
169 	/* Ring channel doorbell */
170 	bus_space_write_4(softc->hwrm_bar.tag,
171 			  softc->hwrm_bar.handle,
172 			  0x100, htole32(1));
173 
174 	/* Check if response len is updated */
175 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
176 		if (resp->resp_len && resp->resp_len <= 4096)
177 			break;
178 		DELAY(1000);
179 	}
180 	if (i >= softc->hwrm_cmd_timeo) {
181 		device_printf(softc->dev,
182 		    "Timeout sending %s: (timeout: %u) seq: %d\n",
183 		    GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
184 		    le16toh(req->seq_id));
185 		return ETIMEDOUT;
186 	}
187 	/* Last byte of resp contains the valid key */
188 	valid = (uint8_t *)resp + resp->resp_len - 1;
189 	for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
190 		if (*valid == HWRM_RESP_VALID_KEY)
191 			break;
192 		DELAY(1000);
193 	}
194 	if (i >= softc->hwrm_cmd_timeo) {
195 		device_printf(softc->dev, "Timeout sending %s: "
196 		    "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
197 		    GET_HWRM_REQ_TYPE(req->req_type),
198 		    softc->hwrm_cmd_timeo, le16toh(req->req_type),
199 		    le16toh(req->seq_id), msg_len,
200 		    *valid);
201 		return ETIMEDOUT;
202 	}
203 
204 	err = le16toh(resp->error_code);
205 	if (err) {
206 		/* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
207 		if (err != HWRM_ERR_CODE_FAIL) {
208 			device_printf(softc->dev,
209 			    "%s command returned %s error.\n",
210 			    GET_HWRM_REQ_TYPE(req->req_type),
211 			    GET_HWRM_ERROR_CODE(err));
212 		}
213 		return bnxt_hwrm_err_map(err);
214 	}
215 
216 	return 0;
217 }
218 
219 static int
hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)220 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
221 {
222 	int rc;
223 
224 	BNXT_HWRM_LOCK(softc);
225 	rc = _hwrm_send_message(softc, msg, msg_len);
226 	BNXT_HWRM_UNLOCK(softc);
227 	return rc;
228 }
229 
230 int
bnxt_hwrm_queue_qportcfg(struct bnxt_softc * softc)231 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
232 {
233 	struct hwrm_queue_qportcfg_input req = {0};
234 	struct hwrm_queue_qportcfg_output *resp =
235 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
236 
237 	int	rc = 0;
238 	uint8_t	*qptr;
239 
240 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
241 
242 	BNXT_HWRM_LOCK(softc);
243 	rc = _hwrm_send_message(softc, &req, sizeof(req));
244 	if (rc)
245 		goto qportcfg_exit;
246 
247 	if (!resp->max_configurable_queues) {
248 		rc = -EINVAL;
249 		goto qportcfg_exit;
250 	}
251 	softc->max_tc = resp->max_configurable_queues;
252 	if (softc->max_tc > BNXT_MAX_QUEUE)
253 		softc->max_tc = BNXT_MAX_QUEUE;
254 
255 	qptr = &resp->queue_id0;
256 	for (int i = 0; i < softc->max_tc; i++) {
257 		softc->q_info[i].id = *qptr++;
258 		softc->q_info[i].profile = *qptr++;
259 	}
260 
261 qportcfg_exit:
262 	BNXT_HWRM_UNLOCK(softc);
263 	return (rc);
264 }
265 
266 int
bnxt_hwrm_ver_get(struct bnxt_softc * softc)267 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
268 {
269 	struct hwrm_ver_get_input	req = {0};
270 	struct hwrm_ver_get_output	*resp =
271 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
272 	int				rc;
273 	const char nastr[] = "<not installed>";
274 	const char naver[] = "<N/A>";
275 	uint32_t dev_caps_cfg;
276 
277 	softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
278 	softc->hwrm_cmd_timeo = 1000;
279 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
280 
281 	req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
282 	req.hwrm_intf_min = HWRM_VERSION_MINOR;
283 	req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
284 
285 	BNXT_HWRM_LOCK(softc);
286 	rc = _hwrm_send_message(softc, &req, sizeof(req));
287 	if (rc)
288 		goto fail;
289 
290 	snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
291 	    resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
292 	softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
293 	softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
294 	softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
295 	snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
296 	    resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
297 	strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
298 	    BNXT_VERSTR_SIZE);
299 	strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
300 	    BNXT_NAME_SIZE);
301 
302 	if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
303 	    resp->mgmt_fw_bld == 0) {
304 		strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
305 		strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
306 	}
307 	else {
308 		snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
309 		    "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
310 		    resp->mgmt_fw_bld);
311 		strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
312 		    BNXT_NAME_SIZE);
313 	}
314 	if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
315 	    resp->netctrl_fw_bld == 0) {
316 		strlcpy(softc->ver_info->netctrl_fw_ver, naver,
317 		    BNXT_VERSTR_SIZE);
318 		strlcpy(softc->ver_info->netctrl_fw_name, nastr,
319 		    BNXT_NAME_SIZE);
320 	}
321 	else {
322 		snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
323 		    "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
324 		    resp->netctrl_fw_bld);
325 		strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
326 		    BNXT_NAME_SIZE);
327 	}
328 	if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
329 	    resp->roce_fw_bld == 0) {
330 		strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
331 		strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
332 	}
333 	else {
334 		snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
335 		    "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
336 		    resp->roce_fw_bld);
337 		strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
338 		    BNXT_NAME_SIZE);
339 	}
340 	softc->ver_info->chip_num = le16toh(resp->chip_num);
341 	softc->ver_info->chip_rev = resp->chip_rev;
342 	softc->ver_info->chip_metal = resp->chip_metal;
343 	softc->ver_info->chip_bond_id = resp->chip_bond_id;
344 	softc->ver_info->chip_type = resp->chip_platform_type;
345 
346 	if (resp->max_req_win_len)
347 		softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
348 	if (resp->def_req_timeout)
349 		softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
350 
351 	dev_caps_cfg = le32toh(resp->dev_caps_cfg);
352 	if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
353 	    (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
354 		softc->flags |= BNXT_FLAG_SHORT_CMD;
355 
356 fail:
357 	BNXT_HWRM_UNLOCK(softc);
358 	return rc;
359 }
360 
361 int
bnxt_hwrm_func_drv_rgtr(struct bnxt_softc * softc)362 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
363 {
364 	struct hwrm_func_drv_rgtr_input req = {0};
365 
366 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
367 
368 	req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
369 	    HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
370 	req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
371 
372 	req.ver_maj = __FreeBSD_version / 100000;
373 	req.ver_min = (__FreeBSD_version / 1000) % 100;
374 	req.ver_upd = (__FreeBSD_version / 100) % 10;
375 
376 	return hwrm_send_message(softc, &req, sizeof(req));
377 }
378 
379 int
bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc * softc,bool shutdown)380 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
381 {
382 	struct hwrm_func_drv_unrgtr_input req = {0};
383 
384 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
385 	if (shutdown == true)
386 		req.flags |=
387 		    HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
388 	return hwrm_send_message(softc, &req, sizeof(req));
389 }
390 
391 static inline int
_is_valid_ether_addr(uint8_t * addr)392 _is_valid_ether_addr(uint8_t *addr)
393 {
394 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
395 
396 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
397 		return (FALSE);
398 
399 	return (TRUE);
400 }
401 
402 static inline void
get_random_ether_addr(uint8_t * addr)403 get_random_ether_addr(uint8_t *addr)
404 {
405 	uint8_t temp[ETHER_ADDR_LEN];
406 
407 	arc4rand(&temp, sizeof(temp), 0);
408 	temp[0] &= 0xFE;
409 	temp[0] |= 0x02;
410 	bcopy(temp, addr, sizeof(temp));
411 }
412 
413 int
bnxt_hwrm_func_qcaps(struct bnxt_softc * softc)414 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
415 {
416 	int rc = 0;
417 	struct hwrm_func_qcaps_input req = {0};
418 	struct hwrm_func_qcaps_output *resp =
419 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
420 	struct bnxt_func_info *func = &softc->func;
421 
422 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
423 	req.fid = htole16(0xffff);
424 
425 	BNXT_HWRM_LOCK(softc);
426 	rc = _hwrm_send_message(softc, &req, sizeof(req));
427 	if (rc)
428 		goto fail;
429 
430 	if (resp->flags &
431 	    htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
432 		softc->flags |= BNXT_FLAG_WOL_CAP;
433 
434 	func->fw_fid = le16toh(resp->fid);
435 	memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
436 	func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
437 	func->max_cp_rings = le16toh(resp->max_cmpl_rings);
438 	func->max_tx_rings = le16toh(resp->max_tx_rings);
439 	func->max_rx_rings = le16toh(resp->max_rx_rings);
440 	func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
441 	if (!func->max_hw_ring_grps)
442 		func->max_hw_ring_grps = func->max_tx_rings;
443 	func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
444 	func->max_vnics = le16toh(resp->max_vnics);
445 	func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
446 	if (BNXT_PF(softc)) {
447 		struct bnxt_pf_info *pf = &softc->pf;
448 
449 		pf->port_id = le16toh(resp->port_id);
450 		pf->first_vf_id = le16toh(resp->first_vf_id);
451 		pf->max_vfs = le16toh(resp->max_vfs);
452 		pf->max_encap_records = le32toh(resp->max_encap_records);
453 		pf->max_decap_records = le32toh(resp->max_decap_records);
454 		pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
455 		pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
456 		pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
457 		pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
458 	}
459 	if (!_is_valid_ether_addr(func->mac_addr)) {
460 		device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
461 		get_random_ether_addr(func->mac_addr);
462 	}
463 
464 fail:
465 	BNXT_HWRM_UNLOCK(softc);
466 	return rc;
467 }
468 
469 int
bnxt_hwrm_func_qcfg(struct bnxt_softc * softc)470 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
471 {
472         struct hwrm_func_qcfg_input req = {0};
473         struct hwrm_func_qcfg_output *resp =
474 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
475 	struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
476         int rc;
477 
478 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
479         req.fid = htole16(0xffff);
480 	BNXT_HWRM_LOCK(softc);
481 	rc = _hwrm_send_message(softc, &req, sizeof(req));
482         if (rc)
483 		goto fail;
484 
485 	fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
486 	fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
487 	fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
488 	fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
489 fail:
490 	BNXT_HWRM_UNLOCK(softc);
491         return rc;
492 }
493 
494 int
bnxt_hwrm_func_reset(struct bnxt_softc * softc)495 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
496 {
497 	struct hwrm_func_reset_input req = {0};
498 
499 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
500 	req.enables = 0;
501 
502 	return hwrm_send_message(softc, &req, sizeof(req));
503 }
504 
505 static void
bnxt_hwrm_set_link_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)506 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
507     struct hwrm_port_phy_cfg_input *req)
508 {
509 	uint8_t autoneg = softc->link_info.autoneg;
510 	uint16_t fw_link_speed = softc->link_info.req_link_speed;
511 
512 	if (autoneg & BNXT_AUTONEG_SPEED) {
513 		req->auto_mode |=
514 		    HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
515 
516 		req->enables |=
517 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
518 		req->flags |=
519 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
520 	} else {
521 		req->force_link_speed = htole16(fw_link_speed);
522 		req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
523 	}
524 
525 	/* tell chimp that the setting takes effect immediately */
526 	req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
527 }
528 
529 static void
bnxt_hwrm_set_pause_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)530 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
531     struct hwrm_port_phy_cfg_input *req)
532 {
533 	struct bnxt_link_info *link_info = &softc->link_info;
534 
535 	if (link_info->flow_ctrl.autoneg) {
536 		req->auto_pause =
537 		    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
538 		if (link_info->flow_ctrl.rx)
539 			req->auto_pause |=
540 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
541 		if (link_info->flow_ctrl.tx)
542 			req->auto_pause |=
543 			    HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
544 		req->enables |=
545 		    htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
546 	} else {
547 		if (link_info->flow_ctrl.rx)
548 			req->force_pause |=
549 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
550 		if (link_info->flow_ctrl.tx)
551 			req->force_pause |=
552 			    HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
553 		req->enables |=
554 			htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
555 	}
556 }
557 
558 /* JFV this needs interface connection */
559 static void
bnxt_hwrm_set_eee(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)560 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
561 {
562 	/* struct ethtool_eee *eee = &softc->eee; */
563 	bool	eee_enabled = false;
564 
565 	if (eee_enabled) {
566 #if 0
567 		uint16_t eee_speeds;
568 		uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
569 
570 		if (eee->tx_lpi_enabled)
571 			flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
572 
573 		req->flags |= htole32(flags);
574 		eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
575 		req->eee_link_speed_mask = htole16(eee_speeds);
576 		req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
577 #endif
578 	} else {
579 		req->flags |=
580 		    htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
581 	}
582 }
583 
584 int
bnxt_hwrm_set_link_setting(struct bnxt_softc * softc,bool set_pause,bool set_eee,bool set_link)585 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
586     bool set_eee, bool set_link)
587 {
588 	struct hwrm_port_phy_cfg_input req = {0};
589 	int rc;
590 
591 	if (softc->flags & BNXT_FLAG_NPAR)
592 		return ENOTSUP;
593 
594 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
595 
596 	if (set_pause) {
597 		bnxt_hwrm_set_pause_common(softc, &req);
598 
599 		if (softc->link_info.flow_ctrl.autoneg)
600 			set_link = true;
601 	}
602 
603 	if (set_link)
604 		bnxt_hwrm_set_link_common(softc, &req);
605 
606 	if (set_eee)
607 		bnxt_hwrm_set_eee(softc, &req);
608 
609 	BNXT_HWRM_LOCK(softc);
610 	rc = _hwrm_send_message(softc, &req, sizeof(req));
611 
612 	if (!rc) {
613 		if (set_pause) {
614 			/* since changing of 'force pause' setting doesn't
615 			 * trigger any link change event, the driver needs to
616 			 * update the current pause result upon successfully i
617 			 * return of the phy_cfg command */
618 			if (!softc->link_info.flow_ctrl.autoneg)
619 				bnxt_report_link(softc);
620 		}
621 	}
622 	BNXT_HWRM_UNLOCK(softc);
623 	return rc;
624 }
625 
626 int
bnxt_hwrm_vnic_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)627 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
628 {
629 	struct hwrm_vnic_cfg_input req = {0};
630 
631 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
632 
633 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
634 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
635 	if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
636 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
637 	if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
638 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
639 	req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
640 	    HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
641 	    HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
642 	req.vnic_id = htole16(vnic->id);
643 	req.dflt_ring_grp = htole16(vnic->def_ring_grp);
644 	req.rss_rule = htole16(vnic->rss_id);
645 	req.cos_rule = htole16(vnic->cos_rule);
646 	req.lb_rule = htole16(vnic->lb_rule);
647 	req.mru = htole16(vnic->mru);
648 
649 	return hwrm_send_message(softc, &req, sizeof(req));
650 }
651 
652 int
bnxt_hwrm_vnic_alloc(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)653 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
654 {
655 	struct hwrm_vnic_alloc_input req = {0};
656 	struct hwrm_vnic_alloc_output *resp =
657 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
658 	int rc;
659 
660 	if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
661 		device_printf(softc->dev,
662 		    "Attempt to re-allocate vnic %04x\n", vnic->id);
663 		return EDOOFUS;
664 	}
665 
666 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
667 
668 	if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
669 		req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
670 
671 	BNXT_HWRM_LOCK(softc);
672 	rc = _hwrm_send_message(softc, &req, sizeof(req));
673 	if (rc)
674 		goto fail;
675 
676 	vnic->id = le32toh(resp->vnic_id);
677 
678 fail:
679 	BNXT_HWRM_UNLOCK(softc);
680 	return (rc);
681 }
682 
683 int
bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc * softc,uint16_t * ctx_id)684 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
685 {
686 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
687 	struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
688 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
689 	int rc;
690 
691 	if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
692 		device_printf(softc->dev,
693 		    "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
694 		return EDOOFUS;
695 	}
696 
697 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
698 
699 	BNXT_HWRM_LOCK(softc);
700 	rc = _hwrm_send_message(softc, &req, sizeof(req));
701 	if (rc)
702 		goto fail;
703 
704 	*ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
705 
706 fail:
707 	BNXT_HWRM_UNLOCK(softc);
708 	return (rc);
709 }
710 
711 int
bnxt_hwrm_ring_grp_alloc(struct bnxt_softc * softc,struct bnxt_grp_info * grp)712 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
713 {
714 	struct hwrm_ring_grp_alloc_input req = {0};
715 	struct hwrm_ring_grp_alloc_output *resp;
716 	int rc = 0;
717 
718 	if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
719 		device_printf(softc->dev,
720 		    "Attempt to re-allocate ring group %04x\n", grp->grp_id);
721 		return EDOOFUS;
722 	}
723 
724 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
725 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
726 	req.cr = htole16(grp->cp_ring_id);
727 	req.rr = htole16(grp->rx_ring_id);
728 	req.ar = htole16(grp->ag_ring_id);
729 	req.sc = htole16(grp->stats_ctx);
730 
731 	BNXT_HWRM_LOCK(softc);
732 	rc = _hwrm_send_message(softc, &req, sizeof(req));
733 	if (rc)
734 		goto fail;
735 
736 	grp->grp_id = le32toh(resp->ring_group_id);
737 
738 fail:
739 	BNXT_HWRM_UNLOCK(softc);
740 	return rc;
741 }
742 
743 /*
744  * Ring allocation message to the firmware
745  */
746 int
bnxt_hwrm_ring_alloc(struct bnxt_softc * softc,uint8_t type,struct bnxt_ring * ring,uint16_t cmpl_ring_id,uint32_t stat_ctx_id,bool irq)747 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
748     struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
749     bool irq)
750 {
751 	struct hwrm_ring_alloc_input req = {0};
752 	struct hwrm_ring_alloc_output *resp;
753 	int rc;
754 
755 	if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
756 		device_printf(softc->dev,
757 		    "Attempt to re-allocate ring %04x\n", ring->phys_id);
758 		return EDOOFUS;
759 	}
760 
761 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
762 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
763 	req.enables = htole32(0);
764 	req.fbo = htole32(0);
765 
766 	if (stat_ctx_id != HWRM_NA_SIGNATURE) {
767 		req.enables |= htole32(
768 		    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
769 		req.stat_ctx_id = htole32(stat_ctx_id);
770 	}
771 	req.ring_type = type;
772 	req.page_tbl_addr = htole64(ring->paddr);
773 	req.length = htole32(ring->ring_size);
774 	req.logical_id = htole16(ring->id);
775 	req.cmpl_ring_id = htole16(cmpl_ring_id);
776 	req.queue_id = htole16(softc->q_info[0].id);
777 #if 0
778 	/* MODE_POLL appears to crash the firmware */
779 	if (irq)
780 		req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
781 	else
782 		req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
783 #else
784 	req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
785 #endif
786 	BNXT_HWRM_LOCK(softc);
787 	rc = _hwrm_send_message(softc, &req, sizeof(req));
788 	if (rc)
789 		goto fail;
790 
791 	ring->phys_id = le16toh(resp->ring_id);
792 
793 fail:
794 	BNXT_HWRM_UNLOCK(softc);
795 	return rc;
796 }
797 
798 int
bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc * softc,struct bnxt_cp_ring * cpr,uint64_t paddr)799 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
800     uint64_t paddr)
801 {
802 	struct hwrm_stat_ctx_alloc_input req = {0};
803 	struct hwrm_stat_ctx_alloc_output *resp;
804 	int rc = 0;
805 
806 	if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
807 		device_printf(softc->dev,
808 		    "Attempt to re-allocate stats ctx %08x\n",
809 		    cpr->stats_ctx_id);
810 		return EDOOFUS;
811 	}
812 
813 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
814 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
815 
816 	req.update_period_ms = htole32(1000);
817 	req.stats_dma_addr = htole64(paddr);
818 
819 	BNXT_HWRM_LOCK(softc);
820 	rc = _hwrm_send_message(softc, &req, sizeof(req));
821 	if (rc)
822 		goto fail;
823 
824 	cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
825 
826 fail:
827 	BNXT_HWRM_UNLOCK(softc);
828 
829 	return rc;
830 }
831 
832 int
bnxt_hwrm_port_qstats(struct bnxt_softc * softc)833 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
834 {
835 	struct hwrm_port_qstats_input req = {0};
836 	int rc = 0;
837 
838 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
839 
840 	req.port_id = htole16(softc->pf.port_id);
841 	req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
842 	req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
843 
844 	BNXT_HWRM_LOCK(softc);
845 	rc = _hwrm_send_message(softc, &req, sizeof(req));
846 	BNXT_HWRM_UNLOCK(softc);
847 
848 	return rc;
849 }
850 
851 int
bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)852 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
853     struct bnxt_vnic_info *vnic)
854 {
855 	struct hwrm_cfa_l2_set_rx_mask_input req = {0};
856 	struct bnxt_vlan_tag *tag;
857 	uint32_t *tags;
858 	uint32_t num_vlan_tags = 0;
859 	uint32_t i;
860 	uint32_t mask = vnic->rx_mask;
861 	int rc;
862 
863 	SLIST_FOREACH(tag, &vnic->vlan_tags, next)
864 		num_vlan_tags++;
865 
866 	if (num_vlan_tags) {
867 		if (!(mask &
868 		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
869 			if (!vnic->vlan_only)
870 				mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
871 			else
872 				mask |=
873 				    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
874 		}
875 		if (vnic->vlan_tag_list.idi_vaddr) {
876 			iflib_dma_free(&vnic->vlan_tag_list);
877 			vnic->vlan_tag_list.idi_vaddr = NULL;
878 		}
879 		rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
880 		    &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
881 		if (rc)
882 			return rc;
883 		tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
884 
885 		i = 0;
886 		SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
887 			tags[i] = htole32((tag->tpid << 16) | tag->tag);
888 			i++;
889 		}
890 	}
891 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
892 
893 	req.vnic_id = htole32(vnic->id);
894 	req.mask = htole32(mask);
895 	req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
896 	req.num_mc_entries = htole32(vnic->mc_list_count);
897 	req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
898 	req.num_vlan_tags = htole32(num_vlan_tags);
899 	return hwrm_send_message(softc, &req, sizeof(req));
900 }
901 
902 int
bnxt_hwrm_set_filter(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)903 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
904 {
905 	struct hwrm_cfa_l2_filter_alloc_input	req = {0};
906 	struct hwrm_cfa_l2_filter_alloc_output	*resp;
907 	uint32_t enables = 0;
908 	int rc = 0;
909 
910 	if (vnic->filter_id != -1) {
911 		device_printf(softc->dev,
912 		    "Attempt to re-allocate l2 ctx filter\n");
913 		return EDOOFUS;
914 	}
915 
916 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
917 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
918 
919 	req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
920 	enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
921 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
922 	    | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
923 	req.enables = htole32(enables);
924 	req.dst_id = htole16(vnic->id);
925 	memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
926 	    ETHER_ADDR_LEN);
927 	memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
928 
929 	BNXT_HWRM_LOCK(softc);
930 	rc = _hwrm_send_message(softc, &req, sizeof(req));
931 	if (rc)
932 		goto fail;
933 
934 	vnic->filter_id = le64toh(resp->l2_filter_id);
935 	vnic->flow_id = le64toh(resp->flow_id);
936 
937 fail:
938 	BNXT_HWRM_UNLOCK(softc);
939 	return (rc);
940 }
941 
942 int
bnxt_hwrm_rss_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic,uint32_t hash_type)943 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
944     uint32_t hash_type)
945 {
946 	struct hwrm_vnic_rss_cfg_input	req = {0};
947 
948 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
949 
950 	req.hash_type = htole32(hash_type);
951 	req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
952 	req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
953 	req.rss_ctx_idx = htole16(vnic->rss_id);
954 
955 	return hwrm_send_message(softc, &req, sizeof(req));
956 }
957 
958 int
bnxt_cfg_async_cr(struct bnxt_softc * softc)959 bnxt_cfg_async_cr(struct bnxt_softc *softc)
960 {
961 	int rc = 0;
962 
963 	if (BNXT_PF(softc)) {
964 		struct hwrm_func_cfg_input req = {0};
965 
966 		bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
967 
968 		req.fid = htole16(0xffff);
969 		req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
970 		req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
971 
972 		rc = hwrm_send_message(softc, &req, sizeof(req));
973 	}
974 	else {
975 		struct hwrm_func_vf_cfg_input req = {0};
976 
977 		bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
978 
979 		req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
980 		req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
981 
982 		rc = hwrm_send_message(softc, &req, sizeof(req));
983 	}
984 	return rc;
985 }
986 
987 void
bnxt_validate_hw_lro_settings(struct bnxt_softc * softc)988 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
989 {
990 	softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
991 
992         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
993 
994 	softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
995 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
996 
997 	softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
998 		HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
999 
1000 	softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
1001 }
1002 
1003 int
bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc * softc)1004 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
1005 {
1006 	struct hwrm_vnic_tpa_cfg_input req = {0};
1007 	uint32_t flags;
1008 
1009 	if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
1010 		return 0;
1011 	}
1012 
1013 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
1014 
1015 	if (softc->hw_lro.enable) {
1016 		flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
1017 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
1018 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
1019 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
1020 
1021         	if (softc->hw_lro.is_mode_gro)
1022 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
1023 		else
1024 			flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
1025 
1026 		req.flags = htole32(flags);
1027 
1028 		req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
1029 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
1030 				HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
1031 
1032 		req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
1033 		req.max_aggs = htole16(softc->hw_lro.max_aggs);
1034 		req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
1035 	}
1036 
1037 	req.vnic_id = htole16(softc->vnic_info.id);
1038 
1039 	return hwrm_send_message(softc, &req, sizeof(req));
1040 }
1041 
1042 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)1043 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
1044     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
1045     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
1046     uint32_t *fw_ver)
1047 {
1048 	struct hwrm_nvm_find_dir_entry_input req = {0};
1049 	struct hwrm_nvm_find_dir_entry_output *resp =
1050 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1051 	int	rc = 0;
1052 	uint32_t old_timeo;
1053 
1054 	MPASS(ordinal);
1055 
1056 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
1057 	if (use_index) {
1058 		req.enables = htole32(
1059 		    HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
1060 		req.dir_idx = htole16(*index);
1061 	}
1062 	req.dir_type = htole16(type);
1063 	req.dir_ordinal = htole16(*ordinal);
1064 	req.dir_ext = htole16(ext);
1065 	req.opt_ordinal = search_opt;
1066 
1067 	BNXT_HWRM_LOCK(softc);
1068 	old_timeo = softc->hwrm_cmd_timeo;
1069 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1070 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1071 	softc->hwrm_cmd_timeo = old_timeo;
1072 	if (rc)
1073 		goto exit;
1074 
1075 	if (item_length)
1076 		*item_length = le32toh(resp->dir_item_length);
1077 	if (data_length)
1078 		*data_length = le32toh(resp->dir_data_length);
1079 	if (fw_ver)
1080 		*fw_ver = le32toh(resp->fw_ver);
1081 	*ordinal = le16toh(resp->dir_ordinal);
1082 	if (index)
1083 		*index = le16toh(resp->dir_idx);
1084 
1085 exit:
1086 	BNXT_HWRM_UNLOCK(softc);
1087 	return (rc);
1088 }
1089 
1090 int
bnxt_hwrm_nvm_read(struct bnxt_softc * softc,uint16_t index,uint32_t offset,uint32_t length,struct iflib_dma_info * data)1091 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1092     uint32_t length, struct iflib_dma_info *data)
1093 {
1094 	struct hwrm_nvm_read_input req = {0};
1095 	int rc;
1096 	uint32_t old_timeo;
1097 
1098 	if (length > data->idi_size) {
1099 		rc = EINVAL;
1100 		goto exit;
1101 	}
1102 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1103 	req.host_dest_addr = htole64(data->idi_paddr);
1104 	req.dir_idx = htole16(index);
1105 	req.offset = htole32(offset);
1106 	req.len = htole32(length);
1107 	BNXT_HWRM_LOCK(softc);
1108 	old_timeo = softc->hwrm_cmd_timeo;
1109 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1110 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1111 	softc->hwrm_cmd_timeo = old_timeo;
1112 	BNXT_HWRM_UNLOCK(softc);
1113 	if (rc)
1114 		goto exit;
1115 	bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1116 
1117 	goto exit;
1118 
1119 exit:
1120 	return rc;
1121 }
1122 
1123 int
bnxt_hwrm_nvm_modify(struct bnxt_softc * softc,uint16_t index,uint32_t offset,void * data,bool cpyin,uint32_t length)1124 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1125     void *data, bool cpyin, uint32_t length)
1126 {
1127 	struct hwrm_nvm_modify_input req = {0};
1128 	struct iflib_dma_info dma_data;
1129 	int rc;
1130 	uint32_t old_timeo;
1131 
1132 	if (length == 0 || !data)
1133 		return EINVAL;
1134 	rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1135 	    BUS_DMA_NOWAIT);
1136 	if (rc)
1137 		return ENOMEM;
1138 	if (cpyin) {
1139 		rc = copyin(data, dma_data.idi_vaddr, length);
1140 		if (rc)
1141 			goto exit;
1142 	}
1143 	else
1144 		memcpy(dma_data.idi_vaddr, data, length);
1145 	bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1146 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1147 
1148 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1149 	req.host_src_addr = htole64(dma_data.idi_paddr);
1150 	req.dir_idx = htole16(index);
1151 	req.offset = htole32(offset);
1152 	req.len = htole32(length);
1153 	BNXT_HWRM_LOCK(softc);
1154 	old_timeo = softc->hwrm_cmd_timeo;
1155 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1156 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1157 	softc->hwrm_cmd_timeo = old_timeo;
1158 	BNXT_HWRM_UNLOCK(softc);
1159 
1160 exit:
1161 	iflib_dma_free(&dma_data);
1162 	return rc;
1163 }
1164 
1165 int
bnxt_hwrm_fw_reset(struct bnxt_softc * softc,uint8_t processor,uint8_t * selfreset)1166 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1167     uint8_t *selfreset)
1168 {
1169 	struct hwrm_fw_reset_input req = {0};
1170 	struct hwrm_fw_reset_output *resp =
1171 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1172 	int rc;
1173 
1174 	MPASS(selfreset);
1175 
1176 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1177 	req.embedded_proc_type = processor;
1178 	req.selfrst_status = *selfreset;
1179 
1180 	BNXT_HWRM_LOCK(softc);
1181 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1182 	if (rc)
1183 		goto exit;
1184 	*selfreset = resp->selfrst_status;
1185 
1186 exit:
1187 	BNXT_HWRM_UNLOCK(softc);
1188 	return rc;
1189 }
1190 
1191 int
bnxt_hwrm_fw_qstatus(struct bnxt_softc * softc,uint8_t type,uint8_t * selfreset)1192 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1193 {
1194 	struct hwrm_fw_qstatus_input req = {0};
1195 	struct hwrm_fw_qstatus_output *resp =
1196 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1197 	int rc;
1198 
1199 	MPASS(selfreset);
1200 
1201 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1202 	req.embedded_proc_type = type;
1203 
1204 	BNXT_HWRM_LOCK(softc);
1205 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1206 	if (rc)
1207 		goto exit;
1208 	*selfreset = resp->selfrst_status;
1209 
1210 exit:
1211 	BNXT_HWRM_UNLOCK(softc);
1212 	return rc;
1213 }
1214 
1215 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)1216 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1217     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1218     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1219     uint16_t *index)
1220 {
1221 	struct hwrm_nvm_write_input req = {0};
1222 	struct hwrm_nvm_write_output *resp =
1223 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1224 	struct iflib_dma_info dma_data;
1225 	int rc;
1226 	uint32_t old_timeo;
1227 
1228 	if (data_length) {
1229 		rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1230 		    BUS_DMA_NOWAIT);
1231 		if (rc)
1232 			return ENOMEM;
1233 		if (cpyin) {
1234 			rc = copyin(data, dma_data.idi_vaddr, data_length);
1235 			if (rc)
1236 				goto early_exit;
1237 		}
1238 		else
1239 			memcpy(dma_data.idi_vaddr, data, data_length);
1240 		bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1241 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1242 	}
1243 	else
1244 		dma_data.idi_paddr = 0;
1245 
1246 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1247 
1248 	req.host_src_addr = htole64(dma_data.idi_paddr);
1249 	req.dir_type = htole16(type);
1250 	req.dir_ordinal = htole16(ordinal);
1251 	req.dir_ext = htole16(ext);
1252 	req.dir_attr = htole16(attr);
1253 	req.dir_data_length = htole32(data_length);
1254 	req.option = htole16(option);
1255 	if (keep) {
1256 		req.flags =
1257 		    htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1258 	}
1259 	if (item_length)
1260 		req.dir_item_length = htole32(*item_length);
1261 
1262 	BNXT_HWRM_LOCK(softc);
1263 	old_timeo = softc->hwrm_cmd_timeo;
1264 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1265 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1266 	softc->hwrm_cmd_timeo = old_timeo;
1267 	if (rc)
1268 		goto exit;
1269 	if (item_length)
1270 		*item_length = le32toh(resp->dir_item_length);
1271 	if (index)
1272 		*index = le16toh(resp->dir_idx);
1273 
1274 exit:
1275 	BNXT_HWRM_UNLOCK(softc);
1276 early_exit:
1277 	if (data_length)
1278 		iflib_dma_free(&dma_data);
1279 	return rc;
1280 }
1281 
1282 int
bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc * softc,uint16_t index)1283 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1284 {
1285 	struct hwrm_nvm_erase_dir_entry_input req = {0};
1286 	uint32_t old_timeo;
1287 	int rc;
1288 
1289 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1290 	req.dir_idx = htole16(index);
1291 	BNXT_HWRM_LOCK(softc);
1292 	old_timeo = softc->hwrm_cmd_timeo;
1293 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1294 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1295 	softc->hwrm_cmd_timeo = old_timeo;
1296 	BNXT_HWRM_UNLOCK(softc);
1297 	return rc;
1298 }
1299 
1300 int
bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length)1301 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1302     uint32_t *entry_length)
1303 {
1304 	struct hwrm_nvm_get_dir_info_input req = {0};
1305 	struct hwrm_nvm_get_dir_info_output *resp =
1306 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1307 	int rc;
1308 	uint32_t old_timeo;
1309 
1310 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1311 
1312 	BNXT_HWRM_LOCK(softc);
1313 	old_timeo = softc->hwrm_cmd_timeo;
1314 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1315 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1316 	softc->hwrm_cmd_timeo = old_timeo;
1317 	if (rc)
1318 		goto exit;
1319 
1320 	if (entries)
1321 		*entries = le32toh(resp->entries);
1322 	if (entry_length)
1323 		*entry_length = le32toh(resp->entry_length);
1324 
1325 exit:
1326 	BNXT_HWRM_UNLOCK(softc);
1327 	return rc;
1328 }
1329 
1330 int
bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length,struct iflib_dma_info * dma_data)1331 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1332     uint32_t *entry_length, struct iflib_dma_info *dma_data)
1333 {
1334 	struct hwrm_nvm_get_dir_entries_input req = {0};
1335 	uint32_t ent;
1336 	uint32_t ent_len;
1337 	int rc;
1338 	uint32_t old_timeo;
1339 
1340 	if (!entries)
1341 		entries = &ent;
1342 	if (!entry_length)
1343 		entry_length = &ent_len;
1344 
1345 	rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1346 	if (rc)
1347 		goto exit;
1348 	if (*entries * *entry_length > dma_data->idi_size) {
1349 		rc = EINVAL;
1350 		goto exit;
1351 	}
1352 
1353 	/*
1354 	 * TODO: There's a race condition here that could blow up DMA memory...
1355 	 *	 we need to allocate the max size, not the currently in use
1356 	 *	 size.  The command should totally have a max size here.
1357 	 */
1358 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1359 	req.host_dest_addr = htole64(dma_data->idi_paddr);
1360 	BNXT_HWRM_LOCK(softc);
1361 	old_timeo = softc->hwrm_cmd_timeo;
1362 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1363 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1364 	softc->hwrm_cmd_timeo = old_timeo;
1365 	BNXT_HWRM_UNLOCK(softc);
1366 	if (rc)
1367 		goto exit;
1368 	bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
1369 	    BUS_DMASYNC_POSTWRITE);
1370 
1371 exit:
1372 	return rc;
1373 }
1374 
1375 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)1376 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
1377     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
1378     uint32_t *reserved_size, uint32_t *available_size)
1379 {
1380 	struct hwrm_nvm_get_dev_info_input req = {0};
1381 	struct hwrm_nvm_get_dev_info_output *resp =
1382 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1383 	int rc;
1384 	uint32_t old_timeo;
1385 
1386 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
1387 
1388 	BNXT_HWRM_LOCK(softc);
1389 	old_timeo = softc->hwrm_cmd_timeo;
1390 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1391 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1392 	softc->hwrm_cmd_timeo = old_timeo;
1393 	if (rc)
1394 		goto exit;
1395 
1396 	if (mfg_id)
1397 		*mfg_id = le16toh(resp->manufacturer_id);
1398 	if (device_id)
1399 		*device_id = le16toh(resp->device_id);
1400 	if (sector_size)
1401 		*sector_size = le32toh(resp->sector_size);
1402 	if (nvram_size)
1403 		*nvram_size = le32toh(resp->nvram_size);
1404 	if (reserved_size)
1405 		*reserved_size = le32toh(resp->reserved_size);
1406 	if (available_size)
1407 		*available_size = le32toh(resp->available_size);
1408 
1409 exit:
1410 	BNXT_HWRM_UNLOCK(softc);
1411 	return rc;
1412 }
1413 
1414 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)1415 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
1416     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
1417     uint8_t *problem_item, uint8_t *reset_required)
1418 {
1419 	struct hwrm_nvm_install_update_input req = {0};
1420 	struct hwrm_nvm_install_update_output *resp =
1421 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1422 	int rc;
1423 	uint32_t old_timeo;
1424 
1425 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
1426 	req.install_type = htole32(install_type);
1427 
1428 	BNXT_HWRM_LOCK(softc);
1429 	old_timeo = softc->hwrm_cmd_timeo;
1430 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1431 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1432 	softc->hwrm_cmd_timeo = old_timeo;
1433 	if (rc)
1434 		goto exit;
1435 
1436 	if (installed_items)
1437 		*installed_items = le32toh(resp->installed_items);
1438 	if (result)
1439 		*result = resp->result;
1440 	if (problem_item)
1441 		*problem_item = resp->problem_item;
1442 	if (reset_required)
1443 		*reset_required = resp->reset_required;
1444 
1445 exit:
1446 	BNXT_HWRM_UNLOCK(softc);
1447 	return rc;
1448 }
1449 
1450 int
bnxt_hwrm_nvm_verify_update(struct bnxt_softc * softc,uint16_t type,uint16_t ordinal,uint16_t ext)1451 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
1452     uint16_t ordinal, uint16_t ext)
1453 {
1454 	struct hwrm_nvm_verify_update_input req = {0};
1455 	uint32_t old_timeo;
1456 	int rc;
1457 
1458 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
1459 
1460 	req.dir_type = htole16(type);
1461 	req.dir_ordinal = htole16(ordinal);
1462 	req.dir_ext = htole16(ext);
1463 
1464 	BNXT_HWRM_LOCK(softc);
1465 	old_timeo = softc->hwrm_cmd_timeo;
1466 	softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1467 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1468 	softc->hwrm_cmd_timeo = old_timeo;
1469 	BNXT_HWRM_UNLOCK(softc);
1470 	return rc;
1471 }
1472 
1473 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)1474 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
1475     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
1476     uint16_t *millisecond, uint16_t *zone)
1477 {
1478 	struct hwrm_fw_get_time_input req = {0};
1479 	struct hwrm_fw_get_time_output *resp =
1480 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1481 	int rc;
1482 
1483 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
1484 
1485 	BNXT_HWRM_LOCK(softc);
1486 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1487 	if (rc)
1488 		goto exit;
1489 
1490 	if (year)
1491 		*year = le16toh(resp->year);
1492 	if (month)
1493 		*month = resp->month;
1494 	if (day)
1495 		*day = resp->day;
1496 	if (hour)
1497 		*hour = resp->hour;
1498 	if (minute)
1499 		*minute = resp->minute;
1500 	if (second)
1501 		*second = resp->second;
1502 	if (millisecond)
1503 		*millisecond = le16toh(resp->millisecond);
1504 	if (zone)
1505 		*zone = le16toh(resp->zone);
1506 
1507 exit:
1508 	BNXT_HWRM_UNLOCK(softc);
1509 	return rc;
1510 }
1511 
1512 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)1513 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
1514     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
1515     uint16_t millisecond, uint16_t zone)
1516 {
1517 	struct hwrm_fw_set_time_input req = {0};
1518 
1519 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
1520 
1521 	req.year = htole16(year);
1522 	req.month = month;
1523 	req.day = day;
1524 	req.hour = hour;
1525 	req.minute = minute;
1526 	req.second = second;
1527 	req.millisecond = htole16(millisecond);
1528 	req.zone = htole16(zone);
1529 	return hwrm_send_message(softc, &req, sizeof(req));
1530 }
1531 
1532 int
bnxt_hwrm_port_phy_qcfg(struct bnxt_softc * softc)1533 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
1534 {
1535 	struct bnxt_link_info *link_info = &softc->link_info;
1536 	struct hwrm_port_phy_qcfg_input req = {0};
1537 	struct hwrm_port_phy_qcfg_output *resp =
1538 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
1539 	int rc = 0;
1540 
1541 	BNXT_HWRM_LOCK(softc);
1542 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
1543 
1544 	rc = _hwrm_send_message(softc, &req, sizeof(req));
1545 	if (rc)
1546 		goto exit;
1547 
1548 	link_info->phy_link_status = resp->link;
1549 	link_info->duplex =  resp->duplex_cfg;
1550 	link_info->auto_mode = resp->auto_mode;
1551 
1552         /*
1553          * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
1554          * the advertisement of pause is enabled.
1555          * 1. When the auto_mode is not set to none and this flag is set to 1,
1556          *    then the auto_pause bits on this port are being advertised and
1557          *    autoneg pause results are being interpreted.
1558          * 2. When the auto_mode is not set to none and this flag is set to 0,
1559          *    the pause is forced as indicated in force_pause, and also
1560 	 *    advertised as auto_pause bits, but the autoneg results are not
1561 	 *    interpreted since the pause configuration is being forced.
1562          * 3. When the auto_mode is set to none and this flag is set to 1,
1563          *    auto_pause bits should be ignored and should be set to 0.
1564          */
1565 
1566 	link_info->flow_ctrl.autoneg = false;
1567 	link_info->flow_ctrl.tx = false;
1568 	link_info->flow_ctrl.rx = false;
1569 
1570 	if ((resp->auto_mode) &&
1571             (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
1572 			link_info->flow_ctrl.autoneg = true;
1573 	}
1574 
1575 	if (link_info->flow_ctrl.autoneg) {
1576 		if (resp->auto_pause & BNXT_PAUSE_TX)
1577 			link_info->flow_ctrl.tx = true;
1578 		if (resp->auto_pause & BNXT_PAUSE_RX)
1579 			link_info->flow_ctrl.rx = true;
1580 	} else {
1581 		if (resp->force_pause & BNXT_PAUSE_TX)
1582 			link_info->flow_ctrl.tx = true;
1583 		if (resp->force_pause & BNXT_PAUSE_RX)
1584 			link_info->flow_ctrl.rx = true;
1585 	}
1586 
1587 	link_info->duplex_setting = resp->duplex_cfg;
1588 	if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
1589 		link_info->link_speed = le16toh(resp->link_speed);
1590 	else
1591 		link_info->link_speed = 0;
1592 	link_info->force_link_speed = le16toh(resp->force_link_speed);
1593 	link_info->auto_link_speed = le16toh(resp->auto_link_speed);
1594 	link_info->support_speeds = le16toh(resp->support_speeds);
1595 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
1596 	link_info->preemphasis = le32toh(resp->preemphasis);
1597 	link_info->phy_ver[0] = resp->phy_maj;
1598 	link_info->phy_ver[1] = resp->phy_min;
1599 	link_info->phy_ver[2] = resp->phy_bld;
1600 	snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
1601 	    "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
1602 	    link_info->phy_ver[2]);
1603 	strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
1604 	    BNXT_NAME_SIZE);
1605 	strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
1606 	    BNXT_NAME_SIZE);
1607 	link_info->media_type = resp->media_type;
1608 	link_info->phy_type = resp->phy_type;
1609 	link_info->transceiver = resp->xcvr_pkg_type;
1610 	link_info->phy_addr = resp->eee_config_phy_addr &
1611 	    HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
1612 
1613 exit:
1614 	BNXT_HWRM_UNLOCK(softc);
1615 	return rc;
1616 }
1617 
1618 uint16_t
bnxt_hwrm_get_wol_fltrs(struct bnxt_softc * softc,uint16_t handle)1619 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
1620 {
1621 	struct hwrm_wol_filter_qcfg_input req = {0};
1622 	struct hwrm_wol_filter_qcfg_output *resp =
1623 			(void *)softc->hwrm_cmd_resp.idi_vaddr;
1624 	uint16_t next_handle = 0;
1625 	int rc;
1626 
1627 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
1628 	req.port_id = htole16(softc->pf.port_id);
1629 	req.handle = htole16(handle);
1630 	rc = hwrm_send_message(softc, &req, sizeof(req));
1631 	if (!rc) {
1632 		next_handle = le16toh(resp->next_handle);
1633 		if (next_handle != 0) {
1634 			if (resp->wol_type ==
1635 				HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
1636 				softc->wol = 1;
1637 				softc->wol_filter_id = resp->wol_filter_id;
1638 			}
1639 		}
1640 	}
1641 	return next_handle;
1642 }
1643 
1644 int
bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc * softc)1645 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
1646 {
1647 	struct hwrm_wol_filter_alloc_input req = {0};
1648 	struct hwrm_wol_filter_alloc_output *resp =
1649 		(void *)softc->hwrm_cmd_resp.idi_vaddr;
1650 	int rc;
1651 
1652 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
1653 	req.port_id = htole16(softc->pf.port_id);
1654 	req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
1655 	req.enables =
1656 		htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
1657 	memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
1658 	rc = hwrm_send_message(softc, &req, sizeof(req));
1659 	if (!rc)
1660 		softc->wol_filter_id = resp->wol_filter_id;
1661 
1662 	return rc;
1663 }
1664 
1665 int
bnxt_hwrm_free_wol_fltr(struct bnxt_softc * softc)1666 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
1667 {
1668 	struct hwrm_wol_filter_free_input req = {0};
1669 
1670 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
1671 	req.port_id = htole16(softc->pf.port_id);
1672 	req.enables =
1673 		htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
1674 	req.wol_filter_id = softc->wol_filter_id;
1675 	return hwrm_send_message(softc, &req, sizeof(req));
1676 }
1677 
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)1678 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
1679         uint32_t buf_tmrs, uint16_t flags,
1680         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
1681 {
1682         req->flags = htole16(flags);
1683         req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
1684         req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
1685         req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
1686         req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
1687         /* Minimum time between 2 interrupts set to buf_tmr x 2 */
1688         req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
1689         req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
1690         req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
1691 }
1692 
bnxt_hwrm_set_coal(struct bnxt_softc * softc)1693 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
1694 {
1695         int i, rc = 0;
1696         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
1697                                                            req_tx = {0}, *req;
1698         uint16_t max_buf, max_buf_irq;
1699         uint16_t buf_tmr, buf_tmr_irq;
1700         uint32_t flags;
1701 
1702         bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
1703                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1704         bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
1705                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
1706 
1707         /* Each rx completion (2 records) should be DMAed immediately.
1708          * DMA 1/4 of the completion buffers at a time.
1709          */
1710         max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
1711         /* max_buf must not be zero */
1712         max_buf = clamp_t(uint16_t, max_buf, 1, 63);
1713         max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
1714         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
1715         /* buf timer set to 1/4 of interrupt timer */
1716         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1717         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
1718         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1719 
1720         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1721 
1722         /* RING_IDLE generates more IRQs for lower latency.  Enable it only
1723          * if coal_usecs is less than 25 us.
1724          */
1725         if (softc->rx_coal_usecs < 25)
1726                 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
1727 
1728         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1729                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
1730 
1731         /* max_buf must not be zero */
1732         max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
1733         max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
1734         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
1735         /* buf timer set to 1/4 of interrupt timer */
1736         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
1737         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
1738         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
1739         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1740         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
1741                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
1742 
1743         for (i = 0; i < softc->nrxqsets; i++) {
1744 
1745 		req = &req_rx;
1746                 /*
1747                  * TBD:
1748 		 *      Check if Tx also needs to be done
1749                  *      So far, Tx processing has been done in softirq contest
1750                  *
1751 		 * req = &req_tx;
1752 		 */
1753 		req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
1754 
1755                 rc = hwrm_send_message(softc, req, sizeof(*req));
1756                 if (rc)
1757                         break;
1758         }
1759         return rc;
1760 }
1761 
bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc * softc,unsigned long * bmap,int bmap_size)1762 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
1763                                      int bmap_size)
1764 {
1765 	struct hwrm_func_drv_rgtr_input req = {0};
1766 	bitstr_t *async_events_bmap;
1767 	uint32_t *events;
1768 	int i;
1769 
1770 #define AE_BMAP_SZ_BITS	256
1771 	async_events_bmap = bit_alloc(AE_BMAP_SZ_BITS, M_DEVBUF, M_WAITOK);
1772 
1773 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
1774 
1775 	req.enables =
1776 		htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
1777 
1778 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
1779 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
1780 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
1781 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
1782 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
1783 
1784 	if (bmap && bmap_size) {
1785 		for (i = 0; i < bmap_size; i++) {
1786 			if (bit_test(bmap, i))
1787 				bit_set(async_events_bmap, i);
1788 		}
1789 	}
1790 
1791 #define AE_BMAP_SZ_WORDS	(AE_BMAP_SZ_BITS / 8 / sizeof(uint32_t))
1792 	events = (uint32_t *)async_events_bmap;
1793 	for (i = 0; i < AE_BMAP_SZ_WORDS; i++)
1794 		req.async_event_fwd[i] |= htole32(events[i]);
1795 #undef AE_BMAP_SZ_WORDS
1796 #undef AE_BMAP_SZ_BITS
1797 
1798 	free(async_events_bmap, M_DEVBUF);
1799 
1800 	return hwrm_send_message(softc, &req, sizeof(req));
1801 }
1802