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