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