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