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