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