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
32 #include "bnxt.h"
33 #include "bnxt_hwrm.h"
34 #include "hsi_struct_def.h"
35
36 static int bnxt_hwrm_err_map(uint16_t err);
37 static inline int _is_valid_ether_addr(uint8_t *);
38 static inline void get_random_ether_addr(uint8_t *);
39 static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
40 struct hwrm_port_phy_cfg_input *req);
41 static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
42 struct hwrm_port_phy_cfg_input *req);
43 static void bnxt_hwrm_set_eee(struct bnxt_softc *softc,
44 struct hwrm_port_phy_cfg_input *req);
45 static int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
46 static int hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
47 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
48
49 /* NVRam stuff has a five minute timeout */
50 #define BNXT_NVM_TIMEO (5 * 60 * 1000)
51
52 static int
bnxt_hwrm_err_map(uint16_t err)53 bnxt_hwrm_err_map(uint16_t err)
54 {
55 int rc;
56
57 switch (err) {
58 case HWRM_ERR_CODE_SUCCESS:
59 return 0;
60 case HWRM_ERR_CODE_INVALID_PARAMS:
61 case HWRM_ERR_CODE_INVALID_FLAGS:
62 case HWRM_ERR_CODE_INVALID_ENABLES:
63 return EINVAL;
64 case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
65 return EACCES;
66 case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
67 return ENOMEM;
68 case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
69 return ENOSYS;
70 case HWRM_ERR_CODE_FAIL:
71 return EIO;
72 case HWRM_ERR_CODE_HWRM_ERROR:
73 case HWRM_ERR_CODE_UNKNOWN_ERR:
74 default:
75 return EDOOFUS;
76 }
77
78 return rc;
79 }
80
81 int
bnxt_alloc_hwrm_dma_mem(struct bnxt_softc * softc)82 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
83 {
84 int rc;
85
86 rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
87 BUS_DMA_NOWAIT);
88 return rc;
89 }
90
91 void
bnxt_free_hwrm_dma_mem(struct bnxt_softc * softc)92 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
93 {
94 if (softc->hwrm_cmd_resp.idi_vaddr)
95 iflib_dma_free(&softc->hwrm_cmd_resp);
96 softc->hwrm_cmd_resp.idi_vaddr = NULL;
97 return;
98 }
99
100 static void
bnxt_hwrm_cmd_hdr_init(struct bnxt_softc * softc,void * request,uint16_t req_type)101 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
102 uint16_t req_type)
103 {
104 struct input *req = request;
105
106 req->req_type = htole16(req_type);
107 req->cmpl_ring = 0xffff;
108 req->target_id = 0xffff;
109 req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
110 }
111
112 static int
_hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)113 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
114 {
115 struct input *req = msg;
116 struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
117 uint32_t *data = msg;
118 int i;
119 uint8_t *valid;
120 uint16_t err;
121 uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
122 struct hwrm_short_input short_input = {0};
123
124 /* TODO: DMASYNC in here. */
125 req->seq_id = htole16(softc->hwrm_cmd_seq++);
126 memset(resp, 0, PAGE_SIZE);
127
128 if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
129 msg_len > BNXT_HWRM_MAX_REQ_LEN) {
130 void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
131 uint16_t max_msg_len;
132
133 /* Set boundary for maximum extended request length for short
134 * cmd format. If passed up from device use the max supported
135 * internal req length.
136 */
137
138 max_msg_len = softc->hwrm_max_ext_req_len;
139
140
141 memcpy(short_cmd_req, req, msg_len);
142 if (msg_len < max_msg_len)
143 memset((uint8_t *) short_cmd_req + msg_len, 0,
144 max_msg_len - msg_len);
145
146 short_input.req_type = req->req_type;
147 short_input.signature =
148 htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
149 short_input.size = htole16(msg_len);
150 short_input.req_addr =
151 htole64(softc->hwrm_short_cmd_req_addr.idi_paddr);
152
153 data = (uint32_t *)&short_input;
154 msg_len = sizeof(short_input);
155
156 /* Sync memory write before updating doorbell */
157 wmb();
158
159 max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
160 }
161
162 /* Write request msg to hwrm channel */
163 for (i = 0; i < msg_len; i += 4) {
164 bus_space_write_4(softc->hwrm_bar.tag,
165 softc->hwrm_bar.handle,
166 i, *data);
167 data++;
168 }
169
170 /* Clear to the end of the request buffer */
171 for (i = msg_len; i < max_req_len; i += 4)
172 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
173 i, 0);
174
175 /* Ring channel doorbell */
176 bus_space_write_4(softc->hwrm_bar.tag,
177 softc->hwrm_bar.handle,
178 0x100, htole32(1));
179
180 /* Check if response len is updated */
181 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
182 if (resp->resp_len && resp->resp_len <= 4096)
183 break;
184 DELAY(1000);
185 }
186 if (i >= softc->hwrm_cmd_timeo) {
187 device_printf(softc->dev,
188 "Timeout sending %s: (timeout: %u) seq: %d\n",
189 GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
190 le16toh(req->seq_id));
191 return ETIMEDOUT;
192 }
193 /* Last byte of resp contains the valid key */
194 valid = (uint8_t *)resp + resp->resp_len - 1;
195 for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
196 if (*valid == HWRM_RESP_VALID_KEY)
197 break;
198 DELAY(1000);
199 }
200 if (i >= softc->hwrm_cmd_timeo) {
201 device_printf(softc->dev, "Timeout sending %s: "
202 "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
203 GET_HWRM_REQ_TYPE(req->req_type),
204 softc->hwrm_cmd_timeo, le16toh(req->req_type),
205 le16toh(req->seq_id), msg_len,
206 *valid);
207 return ETIMEDOUT;
208 }
209
210 err = le16toh(resp->error_code);
211 if (err) {
212 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
213 if (err != HWRM_ERR_CODE_FAIL) {
214 device_printf(softc->dev,
215 "%s command returned %s error.\n",
216 GET_HWRM_REQ_TYPE(req->req_type),
217 GET_HWRM_ERROR_CODE(err));
218 }
219 return bnxt_hwrm_err_map(err);
220 }
221
222 return 0;
223 }
224
225 static int
hwrm_send_message(struct bnxt_softc * softc,void * msg,uint32_t msg_len)226 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
227 {
228 int rc;
229
230 BNXT_HWRM_LOCK(softc);
231 rc = _hwrm_send_message(softc, msg, msg_len);
232 BNXT_HWRM_UNLOCK(softc);
233 return rc;
234 }
235
236 int
bnxt_hwrm_queue_qportcfg(struct bnxt_softc * softc)237 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
238 {
239 int rc = 0;
240 struct hwrm_queue_qportcfg_input req = {0};
241 struct hwrm_queue_qportcfg_output *resp =
242 (void *)softc->hwrm_cmd_resp.idi_vaddr;
243 uint8_t i, j, *qptr;
244 bool no_rdma;
245
246 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
247
248 BNXT_HWRM_LOCK(softc);
249 rc = _hwrm_send_message(softc, &req, sizeof(req));
250 if (rc)
251 goto qportcfg_exit;
252
253 if (!resp->max_configurable_queues) {
254 rc = -EINVAL;
255 goto qportcfg_exit;
256 }
257 softc->max_tc = resp->max_configurable_queues;
258 softc->max_lltc = resp->max_configurable_lossless_queues;
259 if (softc->max_tc > BNXT_MAX_COS_QUEUE)
260 softc->max_tc = BNXT_MAX_COS_QUEUE;
261
262 /* Currently no RDMA support */
263 no_rdma = true;
264
265 qptr = &resp->queue_id0;
266 for (i = 0, j = 0; i < softc->max_tc; i++) {
267 softc->q_info[j].id = *qptr;
268 softc->q_ids[i] = *qptr++;
269 softc->q_info[j].profile = *qptr++;
270 softc->tc_to_qidx[j] = j;
271 if (!BNXT_CNPQ(softc->q_info[j].profile) ||
272 (no_rdma && BNXT_PF(softc)))
273 j++;
274 }
275 softc->max_q = softc->max_tc;
276 softc->max_tc = max_t(uint32_t, j, 1);
277
278 if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG)
279 softc->max_tc = 1;
280
281 if (softc->max_lltc > softc->max_tc)
282 softc->max_lltc = softc->max_tc;
283
284 qportcfg_exit:
285 BNXT_HWRM_UNLOCK(softc);
286 return rc;
287 }
288
bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc * softc)289 int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
290 {
291 struct hwrm_func_backing_store_qcaps_input req = {0};
292 struct hwrm_func_backing_store_qcaps_output *resp =
293 (void *)softc->hwrm_cmd_resp.idi_vaddr;
294 int rc;
295
296 if (softc->hwrm_spec_code < 0x10902 || BNXT_VF(softc) || softc->ctx_mem)
297 return 0;
298
299 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
300 BNXT_HWRM_LOCK(softc);
301 rc = _hwrm_send_message(softc, &req, sizeof(req));
302 if (!rc) {
303 struct bnxt_ctx_pg_info *ctx_pg;
304 struct bnxt_ctx_mem_info *ctx;
305 int i;
306
307 ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
308 if (!ctx) {
309 rc = -ENOMEM;
310 goto ctx_err;
311 }
312 ctx_pg = malloc(sizeof(*ctx_pg) * (softc->max_q + 1),
313 M_DEVBUF, M_NOWAIT | M_ZERO);
314 if (!ctx_pg) {
315 free(ctx, M_DEVBUF);
316 rc = -ENOMEM;
317 goto ctx_err;
318 }
319 for (i = 0; i < softc->max_q + 1; i++, ctx_pg++)
320 ctx->tqm_mem[i] = ctx_pg;
321
322 softc->ctx_mem = ctx;
323 ctx->qp_max_entries = le32toh(resp->qp_max_entries);
324 ctx->qp_min_qp1_entries = le16toh(resp->qp_min_qp1_entries);
325 ctx->qp_max_l2_entries = le16toh(resp->qp_max_l2_entries);
326 ctx->qp_entry_size = le16toh(resp->qp_entry_size);
327 ctx->srq_max_l2_entries = le16toh(resp->srq_max_l2_entries);
328 ctx->srq_max_entries = le32toh(resp->srq_max_entries);
329 ctx->srq_entry_size = le16toh(resp->srq_entry_size);
330 ctx->cq_max_l2_entries = le16toh(resp->cq_max_l2_entries);
331 ctx->cq_max_entries = le32toh(resp->cq_max_entries);
332 ctx->cq_entry_size = le16toh(resp->cq_entry_size);
333 ctx->vnic_max_vnic_entries =
334 le16toh(resp->vnic_max_vnic_entries);
335 ctx->vnic_max_ring_table_entries =
336 le16toh(resp->vnic_max_ring_table_entries);
337 ctx->vnic_entry_size = le16toh(resp->vnic_entry_size);
338 ctx->stat_max_entries = le32toh(resp->stat_max_entries);
339 ctx->stat_entry_size = le16toh(resp->stat_entry_size);
340 ctx->tqm_entry_size = le16toh(resp->tqm_entry_size);
341 ctx->tqm_min_entries_per_ring =
342 le32toh(resp->tqm_min_entries_per_ring);
343 ctx->tqm_max_entries_per_ring =
344 le32toh(resp->tqm_max_entries_per_ring);
345 ctx->tqm_entries_multiple = resp->tqm_entries_multiple;
346 if (!ctx->tqm_entries_multiple)
347 ctx->tqm_entries_multiple = 1;
348 ctx->mrav_max_entries = le32toh(resp->mrav_max_entries);
349 ctx->mrav_entry_size = le16toh(resp->mrav_entry_size);
350 ctx->tim_entry_size = le16toh(resp->tim_entry_size);
351 ctx->tim_max_entries = le32toh(resp->tim_max_entries);
352 ctx->ctx_kind_initializer = resp->ctx_kind_initializer;
353 } else {
354 rc = 0;
355 }
356 ctx_err:
357 BNXT_HWRM_UNLOCK(softc);
358 return rc;
359 }
360
361 #define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES \
362 (HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP | \
363 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ | \
364 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ | \
365 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC | \
366 HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
367
bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info * rmem,uint8_t * pg_attr,uint64_t * pg_dir)368 static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
369 uint64_t *pg_dir)
370 {
371 uint8_t pg_size = 0;
372
373 if (BNXT_PAGE_SHIFT == 13)
374 pg_size = 1 << 4;
375 else if (BNXT_PAGE_SIZE == 16)
376 pg_size = 2 << 4;
377
378 *pg_attr = pg_size;
379 if (rmem->depth >= 1) {
380 if (rmem->depth == 2)
381 *pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
382 else
383 *pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
384 *pg_dir = htole64(rmem->pg_tbl.idi_paddr);
385 } else {
386 *pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
387 }
388 }
389
bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc * softc,uint32_t enables)390 int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
391 {
392 struct hwrm_func_backing_store_cfg_input req = {0};
393 struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
394 struct bnxt_ctx_pg_info *ctx_pg;
395 uint32_t *num_entries, req_len = sizeof(req);
396 uint64_t *pg_dir;
397 uint8_t *pg_attr;
398 int i, rc;
399 uint32_t ena;
400
401 if (!ctx)
402 return 0;
403
404 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
405 req.enables = htole32(enables);
406
407 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
408 ctx_pg = &ctx->qp_mem;
409 req.qp_num_entries = htole32(ctx_pg->entries);
410 req.qp_num_qp1_entries = htole16(ctx->qp_min_qp1_entries);
411 req.qp_num_l2_entries = htole16(ctx->qp_max_l2_entries);
412 req.qp_entry_size = htole16(ctx->qp_entry_size);
413 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
414 &req.qpc_pg_size_qpc_lvl,
415 &req.qpc_page_dir);
416 }
417 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
418 ctx_pg = &ctx->srq_mem;
419 req.srq_num_entries = htole32(ctx_pg->entries);
420 req.srq_num_l2_entries = htole16(ctx->srq_max_l2_entries);
421 req.srq_entry_size = htole16(ctx->srq_entry_size);
422 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
423 &req.srq_pg_size_srq_lvl,
424 &req.srq_page_dir);
425 }
426 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
427 ctx_pg = &ctx->cq_mem;
428 req.cq_num_entries = htole32(ctx_pg->entries);
429 req.cq_num_l2_entries = htole16(ctx->cq_max_l2_entries);
430 req.cq_entry_size = htole16(ctx->cq_entry_size);
431 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, &req.cq_pg_size_cq_lvl,
432 &req.cq_page_dir);
433 }
434 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
435 ctx_pg = &ctx->mrav_mem;
436 req.mrav_num_entries = htole32(ctx_pg->entries);
437 req.mrav_entry_size = htole16(ctx->mrav_entry_size);
438 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
439 &req.mrav_pg_size_mrav_lvl,
440 &req.mrav_page_dir);
441 }
442 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
443 ctx_pg = &ctx->tim_mem;
444 req.tim_num_entries = htole32(ctx_pg->entries);
445 req.tim_entry_size = htole16(ctx->tim_entry_size);
446 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
447 &req.tim_pg_size_tim_lvl,
448 &req.tim_page_dir);
449 }
450 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
451 ctx_pg = &ctx->vnic_mem;
452 req.vnic_num_vnic_entries =
453 htole16(ctx->vnic_max_vnic_entries);
454 req.vnic_num_ring_table_entries =
455 htole16(ctx->vnic_max_ring_table_entries);
456 req.vnic_entry_size = htole16(ctx->vnic_entry_size);
457 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
458 &req.vnic_pg_size_vnic_lvl,
459 &req.vnic_page_dir);
460 }
461 if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
462 ctx_pg = &ctx->stat_mem;
463 req.stat_num_entries = htole32(ctx->stat_max_entries);
464 req.stat_entry_size = htole16(ctx->stat_entry_size);
465 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
466 &req.stat_pg_size_stat_lvl,
467 &req.stat_page_dir);
468 }
469 for (i = 0, num_entries = &req.tqm_sp_num_entries,
470 pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
471 pg_dir = &req.tqm_sp_page_dir,
472 ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP;
473 i < 9; i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
474 if (!(enables & ena))
475 continue;
476
477 req.tqm_entry_size = htole16(ctx->tqm_entry_size);
478 ctx_pg = ctx->tqm_mem[i];
479 *num_entries = htole32(ctx_pg->entries);
480 bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
481 }
482
483 if (req_len > softc->hwrm_max_ext_req_len)
484 req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN;
485
486 rc = hwrm_send_message(softc, &req, req_len);
487 if (rc)
488 rc = -EIO;
489 return rc;
490 }
491
bnxt_hwrm_func_resc_qcaps(struct bnxt_softc * softc,bool all)492 int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
493 {
494 struct hwrm_func_resource_qcaps_output *resp =
495 (void *)softc->hwrm_cmd_resp.idi_vaddr;
496 struct hwrm_func_resource_qcaps_input req = {0};
497 struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
498 int rc;
499
500 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
501 req.fid = htole16(0xffff);
502
503 BNXT_HWRM_LOCK(softc);
504 rc = _hwrm_send_message(softc, &req, sizeof(req));
505 if (rc) {
506 rc = -EIO;
507 goto hwrm_func_resc_qcaps_exit;
508 }
509
510 hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
511 if (!all)
512 goto hwrm_func_resc_qcaps_exit;
513
514 hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
515 hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
516 hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
517 hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
518 hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
519 hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
520 hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
521 hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
522 hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
523 hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
524 hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
525 hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
526 hw_resc->min_vnics = le16toh(resp->min_vnics);
527 hw_resc->max_vnics = le16toh(resp->max_vnics);
528 hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
529 hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
530
531 if (BNXT_CHIP_P5(softc)) {
532 hw_resc->max_nqs = le16toh(resp->max_msix);
533 hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
534 }
535
536 hwrm_func_resc_qcaps_exit:
537 BNXT_HWRM_UNLOCK(softc);
538 return rc;
539 }
540
541 int
bnxt_hwrm_passthrough(struct bnxt_softc * softc,void * req,uint32_t req_len,void * resp,uint32_t resp_len,uint32_t app_timeout)542 bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len,
543 void *resp, uint32_t resp_len, uint32_t app_timeout)
544 {
545 int rc = 0;
546 void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr;
547 struct input *input = req;
548 uint32_t old_timeo;
549
550 input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
551 BNXT_HWRM_LOCK(softc);
552 old_timeo = softc->hwrm_cmd_timeo;
553 if (input->req_type == HWRM_NVM_INSTALL_UPDATE)
554 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
555 else
556 softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo);
557 rc = _hwrm_send_message(softc, req, req_len);
558 softc->hwrm_cmd_timeo = old_timeo;
559 if (rc) {
560 device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n",
561 __FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc);
562 goto fail;
563 }
564
565 memcpy(resp, output, resp_len);
566 fail:
567 BNXT_HWRM_UNLOCK(softc);
568 return rc;
569 }
570
571
572 int
bnxt_hwrm_ver_get(struct bnxt_softc * softc)573 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
574 {
575 struct hwrm_ver_get_input req = {0};
576 struct hwrm_ver_get_output *resp =
577 (void *)softc->hwrm_cmd_resp.idi_vaddr;
578 int rc;
579 const char nastr[] = "<not installed>";
580 const char naver[] = "<N/A>";
581 uint32_t dev_caps_cfg;
582 uint16_t fw_maj, fw_min, fw_bld, fw_rsv, len;
583
584 softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
585 softc->hwrm_cmd_timeo = 1000;
586 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
587
588 req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
589 req.hwrm_intf_min = HWRM_VERSION_MINOR;
590 req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
591
592 BNXT_HWRM_LOCK(softc);
593 rc = _hwrm_send_message(softc, &req, sizeof(req));
594 if (rc)
595 goto fail;
596
597 snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
598 resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
599 softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj_8b;
600 softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min_8b;
601 softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd_8b;
602 snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
603 resp->hwrm_fw_major, resp->hwrm_fw_minor, resp->hwrm_fw_build);
604 strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
605 BNXT_VERSTR_SIZE);
606 strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
607 BNXT_NAME_SIZE);
608
609 softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
610 resp->hwrm_intf_min_8b << 8 |
611 resp->hwrm_intf_upd_8b;
612 if (resp->hwrm_intf_maj_8b < 1) {
613 device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
614 "than 1.0.0.\n", resp->hwrm_intf_maj_8b,
615 resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
616 device_printf(softc->dev, "Please update firmware with HWRM "
617 "interface 1.0.0 or newer.\n");
618 }
619 if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
620 resp->mgmt_fw_build == 0) {
621 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
622 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
623 }
624 else {
625 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
626 "%d.%d.%d", resp->mgmt_fw_major, resp->mgmt_fw_minor,
627 resp->mgmt_fw_build);
628 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
629 BNXT_NAME_SIZE);
630 }
631 if (resp->netctrl_fw_major == 0 && resp->netctrl_fw_minor == 0 &&
632 resp->netctrl_fw_build == 0) {
633 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
634 BNXT_VERSTR_SIZE);
635 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
636 BNXT_NAME_SIZE);
637 }
638 else {
639 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
640 "%d.%d.%d", resp->netctrl_fw_major, resp->netctrl_fw_minor,
641 resp->netctrl_fw_build);
642 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
643 BNXT_NAME_SIZE);
644 }
645 if (resp->roce_fw_major == 0 && resp->roce_fw_minor == 0 &&
646 resp->roce_fw_build == 0) {
647 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
648 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
649 }
650 else {
651 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
652 "%d.%d.%d", resp->roce_fw_major, resp->roce_fw_minor,
653 resp->roce_fw_build);
654 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
655 BNXT_NAME_SIZE);
656 }
657
658 fw_maj = le32toh(resp->hwrm_fw_major);
659 if (softc->hwrm_spec_code > 0x10803 && fw_maj) {
660 fw_min = le16toh(resp->hwrm_fw_minor);
661 fw_bld = le16toh(resp->hwrm_fw_build);
662 fw_rsv = le16toh(resp->hwrm_fw_patch);
663 len = FW_VER_STR_LEN;
664 } else {
665 fw_maj = resp->hwrm_fw_maj_8b;
666 fw_min = resp->hwrm_fw_min_8b;
667 fw_bld = resp->hwrm_fw_bld_8b;
668 fw_rsv = resp->hwrm_fw_rsvd_8b;
669 len = BC_HWRM_STR_LEN;
670 }
671
672 snprintf (softc->ver_info->fw_ver_str, len, "%d.%d.%d.%d",
673 fw_maj, fw_min, fw_bld, fw_rsv);
674
675 if (strlen(resp->active_pkg_name)) {
676 int fw_ver_len = strlen (softc->ver_info->fw_ver_str);
677
678 snprintf(softc->ver_info->fw_ver_str + fw_ver_len,
679 FW_VER_STR_LEN - fw_ver_len - 1, "/pkg %s",
680 resp->active_pkg_name);
681 }
682
683 softc->ver_info->chip_num = le16toh(resp->chip_num);
684 softc->ver_info->chip_rev = resp->chip_rev;
685 softc->ver_info->chip_metal = resp->chip_metal;
686 softc->ver_info->chip_bond_id = resp->chip_bond_id;
687 softc->ver_info->chip_type = resp->chip_platform_type;
688
689 if (resp->hwrm_intf_maj_8b >= 1) {
690 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
691 softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
692 }
693 #define DFLT_HWRM_CMD_TIMEOUT 500
694 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
695 if (!softc->hwrm_cmd_timeo)
696 softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
697
698
699 dev_caps_cfg = le32toh(resp->dev_caps_cfg);
700 if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
701 (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
702 softc->flags |= BNXT_FLAG_SHORT_CMD;
703
704 fail:
705 BNXT_HWRM_UNLOCK(softc);
706 return rc;
707 }
708
709 int
bnxt_hwrm_func_drv_rgtr(struct bnxt_softc * softc)710 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
711 {
712 struct hwrm_func_drv_rgtr_input req = {0};
713
714 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
715
716 req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
717 HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
718 req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
719
720 req.ver_maj = __FreeBSD_version / 100000;
721 req.ver_min = (__FreeBSD_version / 1000) % 100;
722 req.ver_upd = (__FreeBSD_version / 100) % 10;
723
724 return hwrm_send_message(softc, &req, sizeof(req));
725 }
726
727 int
bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc * softc,bool shutdown)728 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
729 {
730 struct hwrm_func_drv_unrgtr_input req = {0};
731
732 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
733 if (shutdown == true)
734 req.flags |=
735 HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
736 return hwrm_send_message(softc, &req, sizeof(req));
737 }
738
739 static inline int
_is_valid_ether_addr(uint8_t * addr)740 _is_valid_ether_addr(uint8_t *addr)
741 {
742 char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
743
744 if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
745 return (FALSE);
746
747 return (TRUE);
748 }
749
750 static inline void
get_random_ether_addr(uint8_t * addr)751 get_random_ether_addr(uint8_t *addr)
752 {
753 uint8_t temp[ETHER_ADDR_LEN];
754
755 arc4rand(&temp, sizeof(temp), 0);
756 temp[0] &= 0xFE;
757 temp[0] |= 0x02;
758 bcopy(temp, addr, sizeof(temp));
759 }
760
761 int
bnxt_hwrm_func_qcaps(struct bnxt_softc * softc)762 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
763 {
764 int rc = 0;
765 struct hwrm_func_qcaps_input req = {0};
766 struct hwrm_func_qcaps_output *resp =
767 (void *)softc->hwrm_cmd_resp.idi_vaddr;
768 struct bnxt_func_info *func = &softc->func;
769
770 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
771 req.fid = htole16(0xffff);
772
773 BNXT_HWRM_LOCK(softc);
774 rc = _hwrm_send_message(softc, &req, sizeof(req));
775 if (rc)
776 goto fail;
777
778 if (resp->flags &
779 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
780 softc->flags |= BNXT_FLAG_WOL_CAP;
781 if (resp->flags &
782 htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED))
783 softc->flags |= BNXT_FLAG_FW_CAP_EXT_STATS;
784
785 func->fw_fid = le16toh(resp->fid);
786 memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
787 func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
788 func->max_cp_rings = le16toh(resp->max_cmpl_rings);
789 func->max_tx_rings = le16toh(resp->max_tx_rings);
790 func->max_rx_rings = le16toh(resp->max_rx_rings);
791 func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
792 if (!func->max_hw_ring_grps)
793 func->max_hw_ring_grps = func->max_tx_rings;
794 func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
795 func->max_vnics = le16toh(resp->max_vnics);
796 func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
797 if (BNXT_PF(softc)) {
798 struct bnxt_pf_info *pf = &softc->pf;
799
800 pf->port_id = le16toh(resp->port_id);
801 pf->first_vf_id = le16toh(resp->first_vf_id);
802 pf->max_vfs = le16toh(resp->max_vfs);
803 pf->max_encap_records = le32toh(resp->max_encap_records);
804 pf->max_decap_records = le32toh(resp->max_decap_records);
805 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
806 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
807 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
808 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
809 }
810 if (!_is_valid_ether_addr(func->mac_addr)) {
811 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
812 get_random_ether_addr(func->mac_addr);
813 }
814
815 fail:
816 BNXT_HWRM_UNLOCK(softc);
817 return rc;
818 }
819
820 int
bnxt_hwrm_func_qcfg(struct bnxt_softc * softc)821 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
822 {
823 struct hwrm_func_qcfg_input req = {0};
824 struct hwrm_func_qcfg_output *resp =
825 (void *)softc->hwrm_cmd_resp.idi_vaddr;
826 struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg;
827 int rc;
828
829 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
830 req.fid = htole16(0xffff);
831 BNXT_HWRM_LOCK(softc);
832 rc = _hwrm_send_message(softc, &req, sizeof(req));
833 if (rc)
834 goto fail;
835
836 fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
837 fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
838 fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
839 fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
840 fail:
841 BNXT_HWRM_UNLOCK(softc);
842 return rc;
843 }
844
845 int
bnxt_hwrm_func_reset(struct bnxt_softc * softc)846 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
847 {
848 struct hwrm_func_reset_input req = {0};
849
850 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
851 req.enables = 0;
852
853 return hwrm_send_message(softc, &req, sizeof(req));
854 }
855
856 static void
bnxt_hwrm_set_link_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)857 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
858 struct hwrm_port_phy_cfg_input *req)
859 {
860 struct bnxt_link_info *link_info = &softc->link_info;
861 uint8_t autoneg = softc->link_info.autoneg;
862 uint16_t fw_link_speed = softc->link_info.req_link_speed;
863
864 if (autoneg & BNXT_AUTONEG_SPEED) {
865 uint8_t phy_type = get_phy_type(softc);
866
867 if (phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET ||
868 phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
869 phy_type == HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE) {
870
871 req->auto_mode |= htole32(HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK);
872 if (link_info->advertising) {
873 req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK);
874 req->auto_link_speed_mask = htole16(link_info->advertising);
875 }
876 } else {
877 req->auto_mode |= HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
878 }
879
880 req->enables |=
881 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
882 req->flags |=
883 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
884 } else {
885 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
886
887 if (link_info->force_pam4_speed_set_by_user) {
888 req->force_pam4_link_speed = htole16(fw_link_speed);
889 req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED);
890 link_info->force_pam4_speed_set_by_user = false;
891 } else {
892 req->force_link_speed = htole16(fw_link_speed);
893 }
894 }
895
896 /* tell chimp that the setting takes effect immediately */
897 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
898 }
899
900 static void
bnxt_hwrm_set_pause_common(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)901 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
902 struct hwrm_port_phy_cfg_input *req)
903 {
904 struct bnxt_link_info *link_info = &softc->link_info;
905
906 if (link_info->flow_ctrl.autoneg) {
907 req->auto_pause =
908 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
909 if (link_info->flow_ctrl.rx)
910 req->auto_pause |=
911 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
912 if (link_info->flow_ctrl.tx)
913 req->auto_pause |=
914 HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
915 req->enables |=
916 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
917 } else {
918 if (link_info->flow_ctrl.rx)
919 req->force_pause |=
920 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
921 if (link_info->flow_ctrl.tx)
922 req->force_pause |=
923 HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
924 req->enables |=
925 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
926 req->auto_pause = req->force_pause;
927 req->enables |=
928 htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
929 }
930 }
931
932 /* JFV this needs interface connection */
933 static void
bnxt_hwrm_set_eee(struct bnxt_softc * softc,struct hwrm_port_phy_cfg_input * req)934 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
935 {
936 /* struct ethtool_eee *eee = &softc->eee; */
937 bool eee_enabled = false;
938
939 if (eee_enabled) {
940 #if 0
941 uint16_t eee_speeds;
942 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
943
944 if (eee->tx_lpi_enabled)
945 flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
946
947 req->flags |= htole32(flags);
948 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
949 req->eee_link_speed_mask = htole16(eee_speeds);
950 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
951 #endif
952 } else {
953 req->flags |=
954 htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
955 }
956 }
957
958 int
bnxt_hwrm_set_link_setting(struct bnxt_softc * softc,bool set_pause,bool set_eee,bool set_link)959 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
960 bool set_eee, bool set_link)
961 {
962 struct hwrm_port_phy_cfg_input req = {0};
963 int rc;
964
965 if (softc->flags & BNXT_FLAG_NPAR)
966 return ENOTSUP;
967
968 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
969
970 if (set_pause) {
971 bnxt_hwrm_set_pause_common(softc, &req);
972
973 if (softc->link_info.flow_ctrl.autoneg)
974 set_link = true;
975 }
976
977 if (set_link)
978 bnxt_hwrm_set_link_common(softc, &req);
979
980 if (set_eee)
981 bnxt_hwrm_set_eee(softc, &req);
982
983 BNXT_HWRM_LOCK(softc);
984 rc = _hwrm_send_message(softc, &req, sizeof(req));
985
986 if (!rc) {
987 if (set_pause) {
988 /* since changing of 'force pause' setting doesn't
989 * trigger any link change event, the driver needs to
990 * update the current pause result upon successfully i
991 * return of the phy_cfg command */
992 if (!softc->link_info.flow_ctrl.autoneg)
993 bnxt_report_link(softc);
994 }
995 }
996 BNXT_HWRM_UNLOCK(softc);
997 return rc;
998 }
999
1000 int
bnxt_hwrm_vnic_set_hds(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1001 bnxt_hwrm_vnic_set_hds(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1002 {
1003 struct hwrm_vnic_plcmodes_cfg_input req = {0};
1004
1005 if (!BNXT_CHIP_P5(softc))
1006 return 0;
1007
1008 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
1009
1010 /*
1011 * TBD -- Explore these flags
1012 * 1. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4
1013 * 2. VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6
1014 * 3. req.jumbo_thresh
1015 * 4. req.hds_threshold
1016 */
1017 req.flags = htole32(HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
1018 req.vnic_id = htole16(vnic->id);
1019
1020 return hwrm_send_message(softc, &req, sizeof(req));
1021 }
1022
1023 int
bnxt_hwrm_vnic_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1024 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1025 {
1026 struct hwrm_vnic_cfg_input req = {0};
1027
1028 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
1029
1030 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1031 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
1032 if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
1033 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
1034 if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
1035 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
1036 if (BNXT_CHIP_P5 (softc)) {
1037 req.default_rx_ring_id =
1038 htole16(softc->rx_rings[0].phys_id);
1039 req.default_cmpl_ring_id =
1040 htole16(softc->rx_cp_rings[0].ring.phys_id);
1041 req.enables |=
1042 htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
1043 HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
1044 req.vnic_id = htole16(vnic->id);
1045 } else {
1046 req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
1047 HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
1048 req.vnic_id = htole16(vnic->id);
1049 req.dflt_ring_grp = htole16(vnic->def_ring_grp);
1050 }
1051 req.rss_rule = htole16(vnic->rss_id);
1052 req.cos_rule = htole16(vnic->cos_rule);
1053 req.lb_rule = htole16(vnic->lb_rule);
1054 req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
1055 req.mru = htole16(vnic->mru);
1056
1057 return hwrm_send_message(softc, &req, sizeof(req));
1058 }
1059
1060 int
bnxt_hwrm_vnic_free(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1061 bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1062 {
1063 struct hwrm_vnic_free_input req = {0};
1064 int rc = 0;
1065
1066 if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE)
1067 return rc;
1068
1069 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
1070
1071 req.vnic_id = htole32(vnic->id);
1072
1073 BNXT_HWRM_LOCK(softc);
1074 rc = _hwrm_send_message(softc, &req, sizeof(req));
1075 if (rc)
1076 goto fail;
1077
1078 fail:
1079 BNXT_HWRM_UNLOCK(softc);
1080 return (rc);
1081 }
1082
1083 int
bnxt_hwrm_vnic_alloc(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1084 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
1085 {
1086 struct hwrm_vnic_alloc_input req = {0};
1087 struct hwrm_vnic_alloc_output *resp =
1088 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1089 int rc;
1090
1091 if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
1092 device_printf(softc->dev,
1093 "Attempt to re-allocate vnic %04x\n", vnic->id);
1094 return EDOOFUS;
1095 }
1096
1097 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
1098
1099 if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
1100 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
1101
1102 BNXT_HWRM_LOCK(softc);
1103 rc = _hwrm_send_message(softc, &req, sizeof(req));
1104 if (rc)
1105 goto fail;
1106
1107 vnic->id = le32toh(resp->vnic_id);
1108
1109 fail:
1110 BNXT_HWRM_UNLOCK(softc);
1111 return (rc);
1112 }
1113
1114 int
bnxt_hwrm_vnic_ctx_free(struct bnxt_softc * softc,uint16_t ctx_id)1115 bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t ctx_id)
1116 {
1117 struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
1118 int rc = 0;
1119
1120 if (ctx_id == (uint16_t)HWRM_NA_SIGNATURE)
1121 return rc;
1122
1123 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
1124 req.rss_cos_lb_ctx_id = htole16(ctx_id);
1125 BNXT_HWRM_LOCK(softc);
1126 rc = _hwrm_send_message(softc, &req, sizeof(req));
1127 if (rc)
1128 goto fail;
1129
1130 fail:
1131 BNXT_HWRM_UNLOCK(softc);
1132 return rc;
1133 }
1134
1135 int
bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc * softc,uint16_t * ctx_id)1136 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
1137 {
1138 struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
1139 struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
1140 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1141 int rc;
1142
1143 if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
1144 device_printf(softc->dev,
1145 "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
1146 return EDOOFUS;
1147 }
1148
1149 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
1150
1151 BNXT_HWRM_LOCK(softc);
1152 rc = _hwrm_send_message(softc, &req, sizeof(req));
1153 if (rc)
1154 goto fail;
1155
1156 *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
1157
1158 fail:
1159 BNXT_HWRM_UNLOCK(softc);
1160 return (rc);
1161 }
1162
1163 int
bnxt_hwrm_ring_grp_alloc(struct bnxt_softc * softc,struct bnxt_grp_info * grp)1164 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1165 {
1166 struct hwrm_ring_grp_alloc_input req = {0};
1167 struct hwrm_ring_grp_alloc_output *resp;
1168 int rc = 0;
1169
1170 if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
1171 device_printf(softc->dev,
1172 "Attempt to re-allocate ring group %04x\n", grp->grp_id);
1173 return EDOOFUS;
1174 }
1175
1176 if (BNXT_CHIP_P5 (softc))
1177 return 0;
1178
1179 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1180 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
1181 req.cr = htole16(grp->cp_ring_id);
1182 req.rr = htole16(grp->rx_ring_id);
1183 req.ar = htole16(grp->ag_ring_id);
1184 req.sc = htole16(grp->stats_ctx);
1185
1186 BNXT_HWRM_LOCK(softc);
1187 rc = _hwrm_send_message(softc, &req, sizeof(req));
1188 if (rc)
1189 goto fail;
1190
1191 grp->grp_id = le32toh(resp->ring_group_id);
1192
1193 fail:
1194 BNXT_HWRM_UNLOCK(softc);
1195 return rc;
1196 }
1197
1198 int
bnxt_hwrm_ring_grp_free(struct bnxt_softc * softc,struct bnxt_grp_info * grp)1199 bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
1200 {
1201 struct hwrm_ring_grp_free_input req = {0};
1202 int rc = 0;
1203
1204 if (grp->grp_id == (uint16_t)HWRM_NA_SIGNATURE)
1205 return 0;
1206
1207 if (BNXT_CHIP_P5 (softc))
1208 return 0;
1209
1210 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
1211
1212 req.ring_group_id = htole32(grp->grp_id);
1213
1214 BNXT_HWRM_LOCK(softc);
1215 rc = _hwrm_send_message(softc, &req, sizeof(req));
1216 if (rc)
1217 goto fail;
1218
1219 fail:
1220 BNXT_HWRM_UNLOCK(softc);
1221 return rc;
1222 }
1223
bnxt_hwrm_ring_free(struct bnxt_softc * softc,uint32_t ring_type,struct bnxt_ring * ring,int cmpl_ring_id)1224 int bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint32_t ring_type,
1225 struct bnxt_ring *ring, int cmpl_ring_id)
1226 {
1227 struct hwrm_ring_free_input req = {0};
1228 struct hwrm_ring_free_output *resp;
1229 int rc = 0;
1230 uint16_t error_code;
1231
1232 if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE)
1233 return 0;
1234
1235 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1236 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
1237 req.cmpl_ring = htole16(cmpl_ring_id);
1238 req.ring_type = ring_type;
1239 req.ring_id = htole16(ring->phys_id);
1240
1241 BNXT_HWRM_LOCK(softc);
1242 rc = _hwrm_send_message(softc, &req, sizeof(req));
1243 error_code = le16toh(resp->error_code);
1244
1245 if (rc || error_code) {
1246 device_printf(softc->dev, "hwrm_ring_free type %d failed. "
1247 "rc:%x err:%x\n", ring_type, rc, error_code);
1248 if (!rc)
1249 rc = -EIO;
1250 }
1251
1252 BNXT_HWRM_UNLOCK(softc);
1253 return rc;
1254 }
1255
1256 /*
1257 * Ring allocation message to the firmware
1258 */
1259 int
bnxt_hwrm_ring_alloc(struct bnxt_softc * softc,uint8_t type,struct bnxt_ring * ring)1260 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
1261 struct bnxt_ring *ring)
1262 {
1263 struct hwrm_ring_alloc_input req = {0};
1264 struct hwrm_ring_alloc_output *resp;
1265 uint16_t idx = ring->idx;
1266 struct bnxt_cp_ring *cp_ring;
1267 int rc;
1268
1269 if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1270 device_printf(softc->dev,
1271 "Attempt to re-allocate ring %04x\n", ring->phys_id);
1272 return EDOOFUS;
1273 }
1274
1275 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1276 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
1277 req.enables = htole32(0);
1278 req.fbo = htole32(0);
1279 req.ring_type = type;
1280 req.page_tbl_addr = htole64(ring->paddr);
1281 req.logical_id = htole16(ring->id);
1282 req.length = htole32(ring->ring_size);
1283
1284 switch (type) {
1285 case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
1286 cp_ring = &softc->tx_cp_rings[idx];
1287
1288 req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
1289 /* queue_id - what CoS queue the TX ring is associated with */
1290 req.queue_id = htole16(softc->q_info[0].id);
1291
1292 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1293 req.enables |= htole32(
1294 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1295 break;
1296 case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
1297 if (!BNXT_CHIP_P5(softc))
1298 break;
1299
1300 cp_ring = &softc->rx_cp_rings[idx];
1301
1302 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1303 req.rx_buf_size = htole16(softc->rx_buf_size);
1304 req.enables |= htole32(
1305 HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1306 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1307 break;
1308 case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
1309 if (!BNXT_CHIP_P5(softc)) {
1310 req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
1311 break;
1312 }
1313
1314 cp_ring = &softc->rx_cp_rings[idx];
1315
1316 req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
1317 req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
1318 req.rx_buf_size = htole16(softc->rx_buf_size);
1319 req.enables |= htole32(
1320 HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
1321 HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
1322 HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
1323 break;
1324 case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
1325 if (!BNXT_CHIP_P5(softc)) {
1326 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1327 break;
1328 }
1329
1330 req.cq_handle = htole64(ring->id);
1331 req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
1332 req.enables |= htole32(
1333 HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
1334 break;
1335 case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
1336 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
1337 break;
1338 default:
1339 printf("hwrm alloc invalid ring type %d\n", type);
1340 return -1;
1341 }
1342
1343 BNXT_HWRM_LOCK(softc);
1344 rc = _hwrm_send_message(softc, &req, sizeof(req));
1345 if (rc)
1346 goto fail;
1347
1348 ring->phys_id = le16toh(resp->ring_id);
1349
1350 fail:
1351 BNXT_HWRM_UNLOCK(softc);
1352 return rc;
1353 }
1354
1355 int
bnxt_hwrm_stat_ctx_free(struct bnxt_softc * softc,struct bnxt_cp_ring * cpr)1356 bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
1357 {
1358 struct hwrm_stat_ctx_free_input req = {0};
1359 int rc = 0;
1360
1361 if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE)
1362 return rc;
1363
1364 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
1365
1366 req.stat_ctx_id = htole16(cpr->stats_ctx_id);
1367 BNXT_HWRM_LOCK(softc);
1368 rc = _hwrm_send_message(softc, &req, sizeof(req));
1369 if (rc)
1370 goto fail;
1371
1372 fail:
1373 BNXT_HWRM_UNLOCK(softc);
1374
1375 return rc;
1376 }
1377
1378 int
bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc * softc,struct bnxt_cp_ring * cpr,uint64_t paddr)1379 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
1380 uint64_t paddr)
1381 {
1382 struct hwrm_stat_ctx_alloc_input req = {0};
1383 struct hwrm_stat_ctx_alloc_output *resp;
1384 int rc = 0;
1385
1386 if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
1387 device_printf(softc->dev,
1388 "Attempt to re-allocate stats ctx %08x\n",
1389 cpr->stats_ctx_id);
1390 return EDOOFUS;
1391 }
1392
1393 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1394 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
1395
1396 req.update_period_ms = htole32(1000);
1397 req.stats_dma_addr = htole64(paddr);
1398 if (BNXT_CHIP_P5(softc))
1399 req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
1400 else
1401 req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
1402
1403 BNXT_HWRM_LOCK(softc);
1404 rc = _hwrm_send_message(softc, &req, sizeof(req));
1405 if (rc)
1406 goto fail;
1407
1408 cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
1409
1410 fail:
1411 BNXT_HWRM_UNLOCK(softc);
1412
1413 return rc;
1414 }
1415
1416 int
bnxt_hwrm_port_qstats(struct bnxt_softc * softc)1417 bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
1418 {
1419 struct hwrm_port_qstats_input req = {0};
1420 int rc = 0;
1421
1422 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
1423
1424 req.port_id = htole16(softc->pf.port_id);
1425 req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
1426 req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
1427
1428 BNXT_HWRM_LOCK(softc);
1429 rc = _hwrm_send_message(softc, &req, sizeof(req));
1430 BNXT_HWRM_UNLOCK(softc);
1431
1432 return rc;
1433 }
1434
1435 void
bnxt_hwrm_port_qstats_ext(struct bnxt_softc * softc)1436 bnxt_hwrm_port_qstats_ext(struct bnxt_softc *softc)
1437 {
1438 struct hwrm_port_qstats_ext_input req = {0};
1439
1440 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS_EXT);
1441
1442 req.port_id = htole16(softc->pf.port_id);
1443 req.tx_stat_size = htole16(sizeof(struct tx_port_stats_ext));
1444 req.rx_stat_size = htole16(sizeof(struct rx_port_stats_ext));
1445 req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats_ext.idi_paddr);
1446 req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats_ext.idi_paddr);
1447
1448 BNXT_HWRM_LOCK(softc);
1449 _hwrm_send_message(softc, &req, sizeof(req));
1450 BNXT_HWRM_UNLOCK(softc);
1451
1452 return;
1453 }
1454
1455 int
bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic)1456 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
1457 struct bnxt_vnic_info *vnic)
1458 {
1459 struct hwrm_cfa_l2_set_rx_mask_input req = {0};
1460 uint32_t mask = vnic->rx_mask;
1461
1462 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
1463
1464 req.vnic_id = htole32(vnic->id);
1465 req.mask = htole32(mask);
1466 req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
1467 req.num_mc_entries = htole32(vnic->mc_list_count);
1468 return hwrm_send_message(softc, &req, sizeof(req));
1469 }
1470
1471 int
bnxt_hwrm_l2_filter_free(struct bnxt_softc * softc,uint64_t filter_id)1472 bnxt_hwrm_l2_filter_free(struct bnxt_softc *softc, uint64_t filter_id)
1473 {
1474 struct hwrm_cfa_l2_filter_free_input req = {0};
1475 int rc = 0;
1476
1477 if (filter_id == -1)
1478 return rc;
1479
1480 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
1481
1482 req.l2_filter_id = htole64(filter_id);
1483
1484 BNXT_HWRM_LOCK(softc);
1485 rc = _hwrm_send_message(softc, &req, sizeof(req));
1486 if (rc)
1487 goto fail;
1488
1489 fail:
1490 BNXT_HWRM_UNLOCK(softc);
1491 return (rc);
1492 }
1493
1494 int
bnxt_hwrm_free_filter(struct bnxt_softc * softc)1495 bnxt_hwrm_free_filter(struct bnxt_softc *softc)
1496 {
1497 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1498 struct bnxt_vlan_tag *tag;
1499 int rc = 0;
1500
1501 rc = bnxt_hwrm_l2_filter_free(softc, softc->vnic_info.filter_id);
1502 if (rc)
1503 goto end;
1504
1505 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1506 rc = bnxt_hwrm_l2_filter_free(softc, tag->filter_id);
1507 if (rc)
1508 goto end;
1509 tag->filter_id = -1;
1510 }
1511
1512 end:
1513 return rc;
1514 }
1515
1516 int
bnxt_hwrm_l2_filter_alloc(struct bnxt_softc * softc,uint16_t vlan_tag,uint64_t * filter_id)1517 bnxt_hwrm_l2_filter_alloc(struct bnxt_softc *softc, uint16_t vlan_tag,
1518 uint64_t *filter_id)
1519 {
1520 struct hwrm_cfa_l2_filter_alloc_input req = {0};
1521 struct hwrm_cfa_l2_filter_alloc_output *resp;
1522 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1523 uint32_t enables = 0;
1524 int rc = 0;
1525
1526 if (*filter_id != -1) {
1527 device_printf(softc->dev, "Attempt to re-allocate l2 ctx "
1528 "filter (fid: 0x%jx)\n", (uintmax_t)*filter_id);
1529 return EDOOFUS;
1530 }
1531
1532 resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
1533 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
1534
1535 req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
1536 enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
1537 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
1538 | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
1539
1540 if (vlan_tag != 0xffff) {
1541 enables |=
1542 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN |
1543 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK |
1544 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_NUM_VLANS;
1545 req.l2_ivlan_mask = 0xffff;
1546 req.l2_ivlan = vlan_tag;
1547 req.num_vlans = 1;
1548 }
1549
1550 req.enables = htole32(enables);
1551 req.dst_id = htole16(vnic->id);
1552 memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
1553 ETHER_ADDR_LEN);
1554 memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
1555
1556 BNXT_HWRM_LOCK(softc);
1557 rc = _hwrm_send_message(softc, &req, sizeof(req));
1558 if (rc)
1559 goto fail;
1560
1561 *filter_id = le64toh(resp->l2_filter_id);
1562 fail:
1563 BNXT_HWRM_UNLOCK(softc);
1564 return (rc);
1565 }
1566
1567 int
bnxt_hwrm_set_filter(struct bnxt_softc * softc)1568 bnxt_hwrm_set_filter(struct bnxt_softc *softc)
1569 {
1570 struct bnxt_vnic_info *vnic = &softc->vnic_info;
1571 struct bnxt_vlan_tag *tag;
1572 int rc = 0;
1573
1574 rc = bnxt_hwrm_l2_filter_alloc(softc, 0xffff, &vnic->filter_id);
1575 if (rc)
1576 goto end;
1577
1578 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
1579 rc = bnxt_hwrm_l2_filter_alloc(softc, tag->tag,
1580 &tag->filter_id);
1581 if (rc)
1582 goto end;
1583 }
1584
1585 end:
1586 return rc;
1587 }
1588
1589 int
bnxt_hwrm_rss_cfg(struct bnxt_softc * softc,struct bnxt_vnic_info * vnic,uint32_t hash_type)1590 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
1591 uint32_t hash_type)
1592 {
1593 struct hwrm_vnic_rss_cfg_input req = {0};
1594
1595 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
1596
1597 req.hash_type = htole32(hash_type);
1598 req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
1599 req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
1600 req.rss_ctx_idx = htole16(vnic->rss_id);
1601 req.hash_mode_flags = HWRM_FUNC_SPD_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
1602 if (BNXT_CHIP_P5(softc)) {
1603 req.vnic_id = htole16(vnic->id);
1604 req.ring_table_pair_index = 0x0;
1605 }
1606
1607 return hwrm_send_message(softc, &req, sizeof(req));
1608 }
1609
1610 int
bnxt_hwrm_reserve_pf_rings(struct bnxt_softc * softc)1611 bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
1612 {
1613 struct hwrm_func_cfg_input req = {0};
1614
1615 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1616
1617 req.fid = htole16(0xffff);
1618 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
1619 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
1620 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
1621 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
1622 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
1623 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
1624 req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
1625 req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
1626 req.num_rsscos_ctxs = htole16(0x8);
1627 req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
1628 req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1629 req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
1630 req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
1631 req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
1632
1633 return hwrm_send_message(softc, &req, sizeof(req));
1634 }
1635
1636 int
bnxt_cfg_async_cr(struct bnxt_softc * softc)1637 bnxt_cfg_async_cr(struct bnxt_softc *softc)
1638 {
1639 int rc = 0;
1640 struct hwrm_func_cfg_input req = {0};
1641
1642 if (!BNXT_PF(softc))
1643 return 0;
1644
1645 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
1646
1647 req.fid = htole16(0xffff);
1648 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
1649 if (BNXT_CHIP_P5(softc))
1650 req.async_event_cr = htole16(softc->nq_rings[0].ring.phys_id);
1651 else
1652 req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id);
1653
1654 rc = hwrm_send_message(softc, &req, sizeof(req));
1655
1656 return rc;
1657 }
1658
1659 void
bnxt_validate_hw_lro_settings(struct bnxt_softc * softc)1660 bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
1661 {
1662 softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
1663
1664 softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
1665
1666 softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
1667 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
1668
1669 softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
1670 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
1671
1672 softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
1673 }
1674
1675 int
bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc * softc)1676 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
1677 {
1678 struct hwrm_vnic_tpa_cfg_input req = {0};
1679 uint32_t flags;
1680
1681 if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
1682 return 0;
1683 }
1684
1685 if (!(softc->flags & BNXT_FLAG_TPA))
1686 return 0;
1687
1688 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
1689
1690 if (softc->hw_lro.enable) {
1691 flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
1692 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
1693 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
1694 HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
1695
1696 if (softc->hw_lro.is_mode_gro)
1697 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
1698 else
1699 flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
1700
1701 req.flags = htole32(flags);
1702
1703 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
1704 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
1705 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
1706
1707 req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
1708 req.max_aggs = htole16(softc->hw_lro.max_aggs);
1709 req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
1710 }
1711
1712 req.vnic_id = htole16(softc->vnic_info.id);
1713
1714 return hwrm_send_message(softc, &req, sizeof(req));
1715 }
1716
1717 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)1718 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
1719 uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
1720 uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
1721 uint32_t *fw_ver)
1722 {
1723 struct hwrm_nvm_find_dir_entry_input req = {0};
1724 struct hwrm_nvm_find_dir_entry_output *resp =
1725 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1726 int rc = 0;
1727 uint32_t old_timeo;
1728
1729 MPASS(ordinal);
1730
1731 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
1732 if (use_index) {
1733 req.enables = htole32(
1734 HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
1735 req.dir_idx = htole16(*index);
1736 }
1737 req.dir_type = htole16(type);
1738 req.dir_ordinal = htole16(*ordinal);
1739 req.dir_ext = htole16(ext);
1740 req.opt_ordinal = search_opt;
1741
1742 BNXT_HWRM_LOCK(softc);
1743 old_timeo = softc->hwrm_cmd_timeo;
1744 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1745 rc = _hwrm_send_message(softc, &req, sizeof(req));
1746 softc->hwrm_cmd_timeo = old_timeo;
1747 if (rc)
1748 goto exit;
1749
1750 if (item_length)
1751 *item_length = le32toh(resp->dir_item_length);
1752 if (data_length)
1753 *data_length = le32toh(resp->dir_data_length);
1754 if (fw_ver)
1755 *fw_ver = le32toh(resp->fw_ver);
1756 *ordinal = le16toh(resp->dir_ordinal);
1757 if (index)
1758 *index = le16toh(resp->dir_idx);
1759
1760 exit:
1761 BNXT_HWRM_UNLOCK(softc);
1762 return (rc);
1763 }
1764
1765 int
bnxt_hwrm_nvm_read(struct bnxt_softc * softc,uint16_t index,uint32_t offset,uint32_t length,struct iflib_dma_info * data)1766 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1767 uint32_t length, struct iflib_dma_info *data)
1768 {
1769 struct hwrm_nvm_read_input req = {0};
1770 int rc;
1771 uint32_t old_timeo;
1772
1773 if (length > data->idi_size) {
1774 rc = EINVAL;
1775 goto exit;
1776 }
1777 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1778 req.host_dest_addr = htole64(data->idi_paddr);
1779 req.dir_idx = htole16(index);
1780 req.offset = htole32(offset);
1781 req.len = htole32(length);
1782 BNXT_HWRM_LOCK(softc);
1783 old_timeo = softc->hwrm_cmd_timeo;
1784 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1785 rc = _hwrm_send_message(softc, &req, sizeof(req));
1786 softc->hwrm_cmd_timeo = old_timeo;
1787 BNXT_HWRM_UNLOCK(softc);
1788 if (rc)
1789 goto exit;
1790 bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1791
1792 goto exit;
1793
1794 exit:
1795 return rc;
1796 }
1797
1798 int
bnxt_hwrm_nvm_modify(struct bnxt_softc * softc,uint16_t index,uint32_t offset,void * data,bool cpyin,uint32_t length)1799 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1800 void *data, bool cpyin, uint32_t length)
1801 {
1802 struct hwrm_nvm_modify_input req = {0};
1803 struct iflib_dma_info dma_data;
1804 int rc;
1805 uint32_t old_timeo;
1806
1807 if (length == 0 || !data)
1808 return EINVAL;
1809 rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1810 BUS_DMA_NOWAIT);
1811 if (rc)
1812 return ENOMEM;
1813 if (cpyin) {
1814 rc = copyin(data, dma_data.idi_vaddr, length);
1815 if (rc)
1816 goto exit;
1817 }
1818 else
1819 memcpy(dma_data.idi_vaddr, data, length);
1820 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1821 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1822
1823 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1824 req.host_src_addr = htole64(dma_data.idi_paddr);
1825 req.dir_idx = htole16(index);
1826 req.offset = htole32(offset);
1827 req.len = htole32(length);
1828 BNXT_HWRM_LOCK(softc);
1829 old_timeo = softc->hwrm_cmd_timeo;
1830 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1831 rc = _hwrm_send_message(softc, &req, sizeof(req));
1832 softc->hwrm_cmd_timeo = old_timeo;
1833 BNXT_HWRM_UNLOCK(softc);
1834
1835 exit:
1836 iflib_dma_free(&dma_data);
1837 return rc;
1838 }
1839
1840 int
bnxt_hwrm_fw_reset(struct bnxt_softc * softc,uint8_t processor,uint8_t * selfreset)1841 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1842 uint8_t *selfreset)
1843 {
1844 struct hwrm_fw_reset_input req = {0};
1845 struct hwrm_fw_reset_output *resp =
1846 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1847 int rc;
1848
1849 MPASS(selfreset);
1850
1851 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1852 req.embedded_proc_type = processor;
1853 req.selfrst_status = *selfreset;
1854
1855 BNXT_HWRM_LOCK(softc);
1856 rc = _hwrm_send_message(softc, &req, sizeof(req));
1857 if (rc)
1858 goto exit;
1859 *selfreset = resp->selfrst_status;
1860
1861 exit:
1862 BNXT_HWRM_UNLOCK(softc);
1863 return rc;
1864 }
1865
1866 int
bnxt_hwrm_fw_qstatus(struct bnxt_softc * softc,uint8_t type,uint8_t * selfreset)1867 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1868 {
1869 struct hwrm_fw_qstatus_input req = {0};
1870 struct hwrm_fw_qstatus_output *resp =
1871 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1872 int rc;
1873
1874 MPASS(selfreset);
1875
1876 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1877 req.embedded_proc_type = type;
1878
1879 BNXT_HWRM_LOCK(softc);
1880 rc = _hwrm_send_message(softc, &req, sizeof(req));
1881 if (rc)
1882 goto exit;
1883 *selfreset = resp->selfrst_status;
1884
1885 exit:
1886 BNXT_HWRM_UNLOCK(softc);
1887 return rc;
1888 }
1889
1890 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)1891 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1892 uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1893 uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1894 uint16_t *index)
1895 {
1896 struct hwrm_nvm_write_input req = {0};
1897 struct hwrm_nvm_write_output *resp =
1898 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1899 struct iflib_dma_info dma_data;
1900 int rc;
1901 uint32_t old_timeo;
1902
1903 if (data_length) {
1904 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1905 BUS_DMA_NOWAIT);
1906 if (rc)
1907 return ENOMEM;
1908 if (cpyin) {
1909 rc = copyin(data, dma_data.idi_vaddr, data_length);
1910 if (rc)
1911 goto early_exit;
1912 }
1913 else
1914 memcpy(dma_data.idi_vaddr, data, data_length);
1915 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1916 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1917 }
1918 else
1919 dma_data.idi_paddr = 0;
1920
1921 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1922
1923 req.host_src_addr = htole64(dma_data.idi_paddr);
1924 req.dir_type = htole16(type);
1925 req.dir_ordinal = htole16(ordinal);
1926 req.dir_ext = htole16(ext);
1927 req.dir_attr = htole16(attr);
1928 req.dir_data_length = htole32(data_length);
1929 req.option = htole16(option);
1930 if (keep) {
1931 req.flags =
1932 htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1933 }
1934 if (item_length)
1935 req.dir_item_length = htole32(*item_length);
1936
1937 BNXT_HWRM_LOCK(softc);
1938 old_timeo = softc->hwrm_cmd_timeo;
1939 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1940 rc = _hwrm_send_message(softc, &req, sizeof(req));
1941 softc->hwrm_cmd_timeo = old_timeo;
1942 if (rc)
1943 goto exit;
1944 if (item_length)
1945 *item_length = le32toh(resp->dir_item_length);
1946 if (index)
1947 *index = le16toh(resp->dir_idx);
1948
1949 exit:
1950 BNXT_HWRM_UNLOCK(softc);
1951 early_exit:
1952 if (data_length)
1953 iflib_dma_free(&dma_data);
1954 return rc;
1955 }
1956
1957 int
bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc * softc,uint16_t index)1958 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1959 {
1960 struct hwrm_nvm_erase_dir_entry_input req = {0};
1961 uint32_t old_timeo;
1962 int rc;
1963
1964 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1965 req.dir_idx = htole16(index);
1966 BNXT_HWRM_LOCK(softc);
1967 old_timeo = softc->hwrm_cmd_timeo;
1968 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1969 rc = _hwrm_send_message(softc, &req, sizeof(req));
1970 softc->hwrm_cmd_timeo = old_timeo;
1971 BNXT_HWRM_UNLOCK(softc);
1972 return rc;
1973 }
1974
1975 int
bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length)1976 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1977 uint32_t *entry_length)
1978 {
1979 struct hwrm_nvm_get_dir_info_input req = {0};
1980 struct hwrm_nvm_get_dir_info_output *resp =
1981 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1982 int rc;
1983 uint32_t old_timeo;
1984
1985 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1986
1987 BNXT_HWRM_LOCK(softc);
1988 old_timeo = softc->hwrm_cmd_timeo;
1989 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1990 rc = _hwrm_send_message(softc, &req, sizeof(req));
1991 softc->hwrm_cmd_timeo = old_timeo;
1992 if (rc)
1993 goto exit;
1994
1995 if (entries)
1996 *entries = le32toh(resp->entries);
1997 if (entry_length)
1998 *entry_length = le32toh(resp->entry_length);
1999
2000 exit:
2001 BNXT_HWRM_UNLOCK(softc);
2002 return rc;
2003 }
2004
2005 int
bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc * softc,uint32_t * entries,uint32_t * entry_length,struct iflib_dma_info * dma_data)2006 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
2007 uint32_t *entry_length, struct iflib_dma_info *dma_data)
2008 {
2009 struct hwrm_nvm_get_dir_entries_input req = {0};
2010 uint32_t ent;
2011 uint32_t ent_len;
2012 int rc;
2013 uint32_t old_timeo;
2014
2015 if (!entries)
2016 entries = &ent;
2017 if (!entry_length)
2018 entry_length = &ent_len;
2019
2020 rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
2021 if (rc)
2022 goto exit;
2023 if (*entries * *entry_length > dma_data->idi_size) {
2024 rc = EINVAL;
2025 goto exit;
2026 }
2027
2028 /*
2029 * TODO: There's a race condition here that could blow up DMA memory...
2030 * we need to allocate the max size, not the currently in use
2031 * size. The command should totally have a max size here.
2032 */
2033 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
2034 req.host_dest_addr = htole64(dma_data->idi_paddr);
2035 BNXT_HWRM_LOCK(softc);
2036 old_timeo = softc->hwrm_cmd_timeo;
2037 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2038 rc = _hwrm_send_message(softc, &req, sizeof(req));
2039 softc->hwrm_cmd_timeo = old_timeo;
2040 BNXT_HWRM_UNLOCK(softc);
2041 if (rc)
2042 goto exit;
2043 bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
2044 BUS_DMASYNC_POSTWRITE);
2045
2046 exit:
2047 return rc;
2048 }
2049
2050 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)2051 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
2052 uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
2053 uint32_t *reserved_size, uint32_t *available_size)
2054 {
2055 struct hwrm_nvm_get_dev_info_input req = {0};
2056 struct hwrm_nvm_get_dev_info_output *resp =
2057 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2058 int rc;
2059 uint32_t old_timeo;
2060
2061 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
2062
2063 BNXT_HWRM_LOCK(softc);
2064 old_timeo = softc->hwrm_cmd_timeo;
2065 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2066 rc = _hwrm_send_message(softc, &req, sizeof(req));
2067 softc->hwrm_cmd_timeo = old_timeo;
2068 if (rc)
2069 goto exit;
2070
2071 if (mfg_id)
2072 *mfg_id = le16toh(resp->manufacturer_id);
2073 if (device_id)
2074 *device_id = le16toh(resp->device_id);
2075 if (sector_size)
2076 *sector_size = le32toh(resp->sector_size);
2077 if (nvram_size)
2078 *nvram_size = le32toh(resp->nvram_size);
2079 if (reserved_size)
2080 *reserved_size = le32toh(resp->reserved_size);
2081 if (available_size)
2082 *available_size = le32toh(resp->available_size);
2083
2084 exit:
2085 BNXT_HWRM_UNLOCK(softc);
2086 return rc;
2087 }
2088
2089 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)2090 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
2091 uint32_t install_type, uint64_t *installed_items, uint8_t *result,
2092 uint8_t *problem_item, uint8_t *reset_required)
2093 {
2094 struct hwrm_nvm_install_update_input req = {0};
2095 struct hwrm_nvm_install_update_output *resp =
2096 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2097 int rc;
2098 uint32_t old_timeo;
2099
2100 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
2101 req.install_type = htole32(install_type);
2102
2103 BNXT_HWRM_LOCK(softc);
2104 old_timeo = softc->hwrm_cmd_timeo;
2105 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2106 rc = _hwrm_send_message(softc, &req, sizeof(req));
2107 softc->hwrm_cmd_timeo = old_timeo;
2108 if (rc)
2109 goto exit;
2110
2111 if (installed_items)
2112 *installed_items = le32toh(resp->installed_items);
2113 if (result)
2114 *result = resp->result;
2115 if (problem_item)
2116 *problem_item = resp->problem_item;
2117 if (reset_required)
2118 *reset_required = resp->reset_required;
2119
2120 exit:
2121 BNXT_HWRM_UNLOCK(softc);
2122 return rc;
2123 }
2124
2125 int
bnxt_hwrm_nvm_verify_update(struct bnxt_softc * softc,uint16_t type,uint16_t ordinal,uint16_t ext)2126 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
2127 uint16_t ordinal, uint16_t ext)
2128 {
2129 struct hwrm_nvm_verify_update_input req = {0};
2130 uint32_t old_timeo;
2131 int rc;
2132
2133 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
2134
2135 req.dir_type = htole16(type);
2136 req.dir_ordinal = htole16(ordinal);
2137 req.dir_ext = htole16(ext);
2138
2139 BNXT_HWRM_LOCK(softc);
2140 old_timeo = softc->hwrm_cmd_timeo;
2141 softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
2142 rc = _hwrm_send_message(softc, &req, sizeof(req));
2143 softc->hwrm_cmd_timeo = old_timeo;
2144 BNXT_HWRM_UNLOCK(softc);
2145 return rc;
2146 }
2147
2148 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)2149 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
2150 uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
2151 uint16_t *millisecond, uint16_t *zone)
2152 {
2153 struct hwrm_fw_get_time_input req = {0};
2154 struct hwrm_fw_get_time_output *resp =
2155 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2156 int rc;
2157
2158 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
2159
2160 BNXT_HWRM_LOCK(softc);
2161 rc = _hwrm_send_message(softc, &req, sizeof(req));
2162 if (rc)
2163 goto exit;
2164
2165 if (year)
2166 *year = le16toh(resp->year);
2167 if (month)
2168 *month = resp->month;
2169 if (day)
2170 *day = resp->day;
2171 if (hour)
2172 *hour = resp->hour;
2173 if (minute)
2174 *minute = resp->minute;
2175 if (second)
2176 *second = resp->second;
2177 if (millisecond)
2178 *millisecond = le16toh(resp->millisecond);
2179 if (zone)
2180 *zone = le16toh(resp->zone);
2181
2182 exit:
2183 BNXT_HWRM_UNLOCK(softc);
2184 return rc;
2185 }
2186
2187 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)2188 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
2189 uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
2190 uint16_t millisecond, uint16_t zone)
2191 {
2192 struct hwrm_fw_set_time_input req = {0};
2193
2194 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
2195
2196 req.year = htole16(year);
2197 req.month = month;
2198 req.day = day;
2199 req.hour = hour;
2200 req.minute = minute;
2201 req.second = second;
2202 req.millisecond = htole16(millisecond);
2203 req.zone = htole16(zone);
2204 return hwrm_send_message(softc, &req, sizeof(req));
2205 }
2206
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)2207 int bnxt_read_sfp_module_eeprom_info(struct bnxt_softc *softc, uint16_t i2c_addr,
2208 uint16_t page_number, uint8_t bank,bool bank_sel_en, uint16_t start_addr,
2209 uint16_t data_length, uint8_t *buf)
2210 {
2211 struct hwrm_port_phy_i2c_read_output *output =
2212 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2213 struct hwrm_port_phy_i2c_read_input req = {0};
2214 int rc = 0, byte_offset = 0;
2215
2216 BNXT_HWRM_LOCK(softc);
2217 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_I2C_READ);
2218
2219 req.i2c_slave_addr = i2c_addr;
2220 req.page_number = htole16(page_number);
2221 req.port_id = htole16(softc->pf.port_id);
2222 do {
2223 uint16_t xfer_size;
2224
2225 xfer_size = min_t(uint16_t, data_length, BNXT_MAX_PHY_I2C_RESP_SIZE);
2226 data_length -= xfer_size;
2227 req.page_offset = htole16(start_addr + byte_offset);
2228 req.data_length = xfer_size;
2229 req.bank_number = bank;
2230 req.enables = htole32((start_addr + byte_offset ?
2231 HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_PAGE_OFFSET : 0) |
2232 (bank_sel_en ?
2233 HWRM_PORT_PHY_I2C_READ_INPUT_ENABLES_BANK_NUMBER : 0));
2234 rc = hwrm_send_message(softc, &req, sizeof(req));
2235 if (!rc)
2236 memcpy(buf + byte_offset, output->data, xfer_size);
2237 byte_offset += xfer_size;
2238 } while (!rc && data_length > 0);
2239
2240 BNXT_HWRM_UNLOCK(softc);
2241
2242 return rc;
2243 }
2244
2245 int
bnxt_hwrm_port_phy_qcfg(struct bnxt_softc * softc)2246 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
2247 {
2248 struct bnxt_link_info *link_info = &softc->link_info;
2249 struct hwrm_port_phy_qcfg_input req = {0};
2250 struct hwrm_port_phy_qcfg_output *resp =
2251 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2252 int rc = 0;
2253
2254 BNXT_HWRM_LOCK(softc);
2255 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
2256
2257 rc = _hwrm_send_message(softc, &req, sizeof(req));
2258 if (rc)
2259 goto exit;
2260
2261 memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp));
2262 link_info->phy_link_status = resp->link;
2263 link_info->duplex = resp->duplex_cfg;
2264 link_info->auto_mode = resp->auto_mode;
2265
2266 /*
2267 * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
2268 * the advertisement of pause is enabled.
2269 * 1. When the auto_mode is not set to none and this flag is set to 1,
2270 * then the auto_pause bits on this port are being advertised and
2271 * autoneg pause results are being interpreted.
2272 * 2. When the auto_mode is not set to none and this flag is set to 0,
2273 * the pause is forced as indicated in force_pause, and also
2274 * advertised as auto_pause bits, but the autoneg results are not
2275 * interpreted since the pause configuration is being forced.
2276 * 3. When the auto_mode is set to none and this flag is set to 1,
2277 * auto_pause bits should be ignored and should be set to 0.
2278 */
2279
2280 link_info->flow_ctrl.autoneg = false;
2281 link_info->flow_ctrl.tx = false;
2282 link_info->flow_ctrl.rx = false;
2283
2284 if ((resp->auto_mode) &&
2285 (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
2286 link_info->flow_ctrl.autoneg = true;
2287 }
2288
2289 if (link_info->flow_ctrl.autoneg) {
2290 if (resp->auto_pause & BNXT_PAUSE_TX)
2291 link_info->flow_ctrl.tx = true;
2292 if (resp->auto_pause & BNXT_PAUSE_RX)
2293 link_info->flow_ctrl.rx = true;
2294 } else {
2295 if (resp->force_pause & BNXT_PAUSE_TX)
2296 link_info->flow_ctrl.tx = true;
2297 if (resp->force_pause & BNXT_PAUSE_RX)
2298 link_info->flow_ctrl.rx = true;
2299 }
2300
2301 link_info->duplex_setting = resp->duplex_cfg;
2302 if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
2303 link_info->link_speed = le16toh(resp->link_speed);
2304 else
2305 link_info->link_speed = 0;
2306 link_info->force_link_speed = le16toh(resp->force_link_speed);
2307 link_info->auto_link_speeds = le16toh(resp->auto_link_speed);
2308 link_info->support_speeds = le16toh(resp->support_speeds);
2309 link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
2310 link_info->preemphasis = le32toh(resp->preemphasis);
2311 link_info->phy_ver[0] = resp->phy_maj;
2312 link_info->phy_ver[1] = resp->phy_min;
2313 link_info->phy_ver[2] = resp->phy_bld;
2314 snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
2315 "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
2316 link_info->phy_ver[2]);
2317 strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
2318 BNXT_NAME_SIZE);
2319 strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
2320 BNXT_NAME_SIZE);
2321 link_info->media_type = resp->media_type;
2322 link_info->phy_type = resp->phy_type;
2323 link_info->transceiver = resp->xcvr_pkg_type;
2324 link_info->phy_addr = resp->eee_config_phy_addr &
2325 HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
2326 link_info->module_status = resp->module_status;
2327 link_info->support_pam4_speeds = le16toh(resp->support_pam4_speeds);
2328 link_info->auto_pam4_link_speeds = le16toh(resp->auto_pam4_link_speed_mask);
2329 link_info->force_pam4_link_speed = le16toh(resp->force_pam4_link_speed);
2330
2331 if (softc->hwrm_spec_code >= 0x10504)
2332 link_info->active_fec_sig_mode = resp->active_fec_signal_mode;
2333
2334 exit:
2335 BNXT_HWRM_UNLOCK(softc);
2336 return rc;
2337 }
2338
2339 static bool
bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output * resp)2340 bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp)
2341 {
2342 if (!resp->supported_speeds_auto_mode &&
2343 !resp->supported_speeds_force_mode &&
2344 !resp->supported_pam4_speeds_auto_mode &&
2345 !resp->supported_pam4_speeds_force_mode)
2346 return true;
2347
2348 return false;
2349 }
2350
bnxt_hwrm_phy_qcaps(struct bnxt_softc * softc)2351 int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc)
2352 {
2353 struct bnxt_link_info *link_info = &softc->link_info;
2354 struct hwrm_port_phy_qcaps_output *resp =
2355 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2356 struct hwrm_port_phy_qcaps_input req = {};
2357 int rc;
2358
2359 if (softc->hwrm_spec_code < 0x10201)
2360 return 0;
2361
2362 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCAPS);
2363
2364 BNXT_HWRM_LOCK(softc);
2365 rc = _hwrm_send_message(softc, &req, sizeof(req));
2366 if (rc)
2367 goto exit;
2368
2369 if (softc->hwrm_spec_code >= 0x10a01) {
2370 if (bnxt_phy_qcaps_no_speed(resp)) {
2371 link_info->phy_state = BNXT_PHY_STATE_DISABLED;
2372 device_printf(softc->dev, "Ethernet link disabled\n");
2373 } else if (link_info->phy_state == BNXT_PHY_STATE_DISABLED) {
2374 link_info->phy_state = BNXT_PHY_STATE_ENABLED;
2375 device_printf(softc->dev, "Ethernet link enabled\n");
2376 /* Phy re-enabled, reprobe the speeds */
2377 link_info->support_auto_speeds = 0;
2378 link_info->support_pam4_auto_speeds = 0;
2379 }
2380 }
2381 if (resp->supported_speeds_auto_mode)
2382 link_info->support_auto_speeds =
2383 le16toh(resp->supported_speeds_auto_mode);
2384 if (resp->supported_speeds_force_mode)
2385 link_info->support_force_speeds =
2386 le16toh(resp->supported_speeds_force_mode);
2387 if (resp->supported_pam4_speeds_auto_mode)
2388 link_info->support_pam4_auto_speeds =
2389 le16toh(resp->supported_pam4_speeds_auto_mode);
2390 if (resp->supported_pam4_speeds_force_mode)
2391 link_info->support_pam4_force_speeds =
2392 le16toh(resp->supported_pam4_speeds_force_mode);
2393
2394 exit:
2395 BNXT_HWRM_UNLOCK(softc);
2396 return rc;
2397 }
2398
2399 uint16_t
bnxt_hwrm_get_wol_fltrs(struct bnxt_softc * softc,uint16_t handle)2400 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
2401 {
2402 struct hwrm_wol_filter_qcfg_input req = {0};
2403 struct hwrm_wol_filter_qcfg_output *resp =
2404 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2405 uint16_t next_handle = 0;
2406 int rc;
2407
2408 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
2409 req.port_id = htole16(softc->pf.port_id);
2410 req.handle = htole16(handle);
2411 rc = hwrm_send_message(softc, &req, sizeof(req));
2412 if (!rc) {
2413 next_handle = le16toh(resp->next_handle);
2414 if (next_handle != 0) {
2415 if (resp->wol_type ==
2416 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
2417 softc->wol = 1;
2418 softc->wol_filter_id = resp->wol_filter_id;
2419 }
2420 }
2421 }
2422 return next_handle;
2423 }
2424
2425 int
bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc * softc)2426 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
2427 {
2428 struct hwrm_wol_filter_alloc_input req = {0};
2429 struct hwrm_wol_filter_alloc_output *resp =
2430 (void *)softc->hwrm_cmd_resp.idi_vaddr;
2431 int rc;
2432
2433 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
2434 req.port_id = htole16(softc->pf.port_id);
2435 req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
2436 req.enables =
2437 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
2438 memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
2439 rc = hwrm_send_message(softc, &req, sizeof(req));
2440 if (!rc)
2441 softc->wol_filter_id = resp->wol_filter_id;
2442
2443 return rc;
2444 }
2445
2446 int
bnxt_hwrm_free_wol_fltr(struct bnxt_softc * softc)2447 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
2448 {
2449 struct hwrm_wol_filter_free_input req = {0};
2450
2451 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
2452 req.port_id = htole16(softc->pf.port_id);
2453 req.enables =
2454 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
2455 req.wol_filter_id = softc->wol_filter_id;
2456 return hwrm_send_message(softc, &req, sizeof(req));
2457 }
2458
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)2459 static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
2460 uint32_t buf_tmrs, uint16_t flags,
2461 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
2462 {
2463 req->flags = htole16(flags);
2464 req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
2465 req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
2466 req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
2467 req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
2468 /* Minimum time between 2 interrupts set to buf_tmr x 2 */
2469 req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
2470 req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
2471 req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
2472 }
2473
bnxt_hwrm_set_coal(struct bnxt_softc * softc)2474 int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
2475 {
2476 int i, rc = 0;
2477 struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
2478 req_tx = {0}, *req;
2479 uint16_t max_buf, max_buf_irq;
2480 uint16_t buf_tmr, buf_tmr_irq;
2481 uint32_t flags;
2482
2483 bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
2484 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2485 bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
2486 HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
2487
2488 /* Each rx completion (2 records) should be DMAed immediately.
2489 * DMA 1/4 of the completion buffers at a time.
2490 */
2491 max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
2492 /* max_buf must not be zero */
2493 max_buf = clamp_t(uint16_t, max_buf, 1, 63);
2494 max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
2495 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
2496 /* buf timer set to 1/4 of interrupt timer */
2497 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2498 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
2499 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2500
2501 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2502
2503 /* RING_IDLE generates more IRQs for lower latency. Enable it only
2504 * if coal_usecs is less than 25 us.
2505 */
2506 if (softc->rx_coal_usecs < 25)
2507 flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
2508
2509 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2510 buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
2511
2512 /* max_buf must not be zero */
2513 max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
2514 max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
2515 buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
2516 /* buf timer set to 1/4 of interrupt timer */
2517 buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
2518 buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
2519 buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
2520 flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
2521 bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
2522 buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
2523
2524 for (i = 0; i < softc->nrxqsets; i++) {
2525
2526 req = &req_rx;
2527 /*
2528 * TBD:
2529 * Check if Tx also needs to be done
2530 * So far, Tx processing has been done in softirq contest
2531 *
2532 * req = &req_tx;
2533 */
2534 req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
2535
2536 rc = hwrm_send_message(softc, req, sizeof(*req));
2537 if (rc)
2538 break;
2539 }
2540 return rc;
2541 }
2542
bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc * softc,unsigned long * bmap,int bmap_size)2543 int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
2544 int bmap_size)
2545 {
2546 struct hwrm_func_drv_rgtr_input req = {0};
2547 bitstr_t *async_events_bmap;
2548 uint32_t *events;
2549 int i;
2550
2551 #define BNXT_MAX_NUM_ASYNC_EVENTS 256
2552 async_events_bmap = bit_alloc(BNXT_MAX_NUM_ASYNC_EVENTS, M_DEVBUF,
2553 M_WAITOK|M_ZERO);
2554 events = (uint32_t *)async_events_bmap;
2555
2556 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
2557
2558 req.enables =
2559 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
2560
2561 memset(async_events_bmap, 0, sizeof(BNXT_MAX_NUM_ASYNC_EVENTS / 8));
2562
2563 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
2564 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
2565 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
2566 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
2567 bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
2568
2569 if (bmap && bmap_size) {
2570 for (i = 0; i < bmap_size; i++) {
2571 if (bit_test(bmap, i))
2572 bit_set(async_events_bmap, i);
2573 }
2574 }
2575
2576 for (i = 0; i < 8; i++)
2577 req.async_event_fwd[i] |= htole32(events[i]);
2578
2579 free(async_events_bmap, M_DEVBUF);
2580
2581 return hwrm_send_message(softc, &req, sizeof(req));
2582 }
2583
bnxt_hwrm_ring_info_get(struct bnxt_softc * softc,uint8_t ring_type,uint32_t ring_id,uint32_t * prod,uint32_t * cons)2584 void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type,
2585 uint32_t ring_id, uint32_t *prod, uint32_t *cons)
2586 {
2587 hwrm_dbg_ring_info_get_input_t req = {0};
2588 hwrm_dbg_ring_info_get_output_t *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
2589 int rc = 0;
2590
2591 *prod = *cons = 0xffffffff;
2592 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_DBG_RING_INFO_GET);
2593 req.ring_type = le32toh(ring_type);
2594 req.fw_ring_id = le32toh(ring_id);
2595 rc = hwrm_send_message(softc, &req, sizeof(req));
2596 if (!rc) {
2597 *prod = resp->producer_index;
2598 *cons = resp->consumer_index;
2599 }
2600
2601 return;
2602 }
2603