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