]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bnxt/bnxt_hwrm.c
Update DTS files from Linux 4.12
[FreeBSD/FreeBSD.git] / sys / dev / bnxt / bnxt_hwrm.c
1 /*-
2  * Broadcom NetXtreme-C/E network driver.
3  *
4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/endian.h>
33
34 #include "bnxt.h"
35 #include "bnxt_hwrm.h"
36 #include "hsi_struct_def.h"
37
38 static int bnxt_hwrm_err_map(uint16_t err);
39 static inline int _is_valid_ether_addr(uint8_t *);
40 static inline void get_random_ether_addr(uint8_t *);
41 static void     bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
42                     struct hwrm_port_phy_cfg_input *req);
43 static void     bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
44                     struct hwrm_port_phy_cfg_input *req);
45 static void     bnxt_hwrm_set_eee(struct bnxt_softc *softc,
46                     struct hwrm_port_phy_cfg_input *req);
47 static int      _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
48 static int      hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
49 static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
50
51 /* NVRam stuff has a five minute timeout */
52 #define BNXT_NVM_TIMEO  (5 * 60 * 1000)
53
54 static int
55 bnxt_hwrm_err_map(uint16_t err)
56 {
57         int rc;
58
59         switch (err) {
60         case HWRM_ERR_CODE_SUCCESS:
61                 return 0;
62         case HWRM_ERR_CODE_INVALID_PARAMS:
63         case HWRM_ERR_CODE_INVALID_FLAGS:
64         case HWRM_ERR_CODE_INVALID_ENABLES:
65                 return EINVAL;
66         case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
67                 return EACCES;
68         case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
69                 return ENOMEM;
70         case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
71                 return ENOSYS;
72         case HWRM_ERR_CODE_FAIL:
73                 return EIO;
74         case HWRM_ERR_CODE_HWRM_ERROR:
75         case HWRM_ERR_CODE_UNKNOWN_ERR:
76         default:
77                 return EDOOFUS;
78         }
79
80         return rc;
81 }
82
83 int
84 bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc)
85 {
86         int rc;
87
88         rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp,
89             BUS_DMA_NOWAIT);
90         return rc;
91 }
92
93 void
94 bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc)
95 {
96         if (softc->hwrm_cmd_resp.idi_vaddr)
97                 iflib_dma_free(&softc->hwrm_cmd_resp);
98         softc->hwrm_cmd_resp.idi_vaddr = NULL;
99         return;
100 }
101
102 static void
103 bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
104     uint16_t req_type)
105 {
106         struct input *req = request;
107
108         req->req_type = htole16(req_type);
109         req->cmpl_ring = 0xffff;
110         req->target_id = 0xffff;
111         req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr);
112 }
113
114 static int
115 _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
116 {
117         struct input *req = msg;
118         struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
119         uint32_t *data = msg;
120         int i;
121         uint16_t cp_ring_id;
122         uint8_t *valid;
123         uint16_t err;
124
125         /* TODO: DMASYNC in here. */
126         req->seq_id = htole16(softc->hwrm_cmd_seq++);
127         memset(resp, 0, PAGE_SIZE);
128         cp_ring_id = le16toh(req->cmpl_ring);
129
130         /* Write request msg to hwrm channel */
131         for (i = 0; i < msg_len; i += 4) {
132                 bus_space_write_4(softc->hwrm_bar.tag,
133                                   softc->hwrm_bar.handle,
134                                   i, *data);
135                 data++;
136         }
137
138         /* Clear to the end of the request buffer */
139         for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4)
140                 bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle,
141                     i, 0);
142
143         /* Ring channel doorbell */
144         bus_space_write_4(softc->hwrm_bar.tag,
145                           softc->hwrm_bar.handle,
146                           0x100, htole32(1));
147
148         /* Check if response len is updated */
149         for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
150                 if (resp->resp_len && resp->resp_len <= 4096)
151                         break;
152                 DELAY(1000);
153         }
154         if (i >= softc->hwrm_cmd_timeo) {
155                 device_printf(softc->dev,
156                     "Timeout sending %s: (timeout: %u) seq: %d\n",
157                     GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo,
158                     le16toh(req->seq_id));
159                 return ETIMEDOUT;
160         }
161         /* Last byte of resp contains the valid key */
162         valid = (uint8_t *)resp + resp->resp_len - 1;
163         for (i = 0; i < softc->hwrm_cmd_timeo; i++) {
164                 if (*valid == HWRM_RESP_VALID_KEY)
165                         break;
166                 DELAY(1000);
167         }
168         if (i >= softc->hwrm_cmd_timeo) {
169                 device_printf(softc->dev, "Timeout sending %s: "
170                     "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
171                     GET_HWRM_REQ_TYPE(req->req_type),
172                     softc->hwrm_cmd_timeo, le16toh(req->req_type),
173                     le16toh(req->seq_id), msg_len,
174                     *valid);
175                 return ETIMEDOUT;
176         }
177
178         err = le16toh(resp->error_code);
179         if (err) {
180                 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
181                 if (err != HWRM_ERR_CODE_FAIL) {
182                         device_printf(softc->dev,
183                             "%s command returned %s error.\n",
184                             GET_HWRM_REQ_TYPE(req->req_type),
185                             GET_HWRM_ERROR_CODE(err));
186                 }
187                 return bnxt_hwrm_err_map(err);
188         }
189
190         return 0;
191 }
192
193 static int
194 hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
195 {
196         int rc;
197
198         BNXT_HWRM_LOCK(softc);
199         rc = _hwrm_send_message(softc, msg, msg_len);
200         BNXT_HWRM_UNLOCK(softc);
201         return rc;
202 }
203
204 int
205 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
206 {
207         struct hwrm_queue_qportcfg_input req = {0};
208         struct hwrm_queue_qportcfg_output *resp =
209             (void *)softc->hwrm_cmd_resp.idi_vaddr;
210
211         int     rc = 0;
212         uint8_t *qptr;
213
214         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
215
216         BNXT_HWRM_LOCK(softc);
217         rc = _hwrm_send_message(softc, &req, sizeof(req));
218         if (rc)
219                 goto qportcfg_exit;
220
221         if (!resp->max_configurable_queues) {
222                 rc = -EINVAL;
223                 goto qportcfg_exit;
224         }
225         softc->max_tc = resp->max_configurable_queues;
226         if (softc->max_tc > BNXT_MAX_QUEUE)
227                 softc->max_tc = BNXT_MAX_QUEUE;
228
229         qptr = &resp->queue_id0;
230         for (int i = 0; i < softc->max_tc; i++) {
231                 softc->q_info[i].id = *qptr++;
232                 softc->q_info[i].profile = *qptr++;
233         }
234
235 qportcfg_exit:
236         BNXT_HWRM_UNLOCK(softc);
237         return (rc);
238 }
239
240
241 int
242 bnxt_hwrm_ver_get(struct bnxt_softc *softc)
243 {
244         struct hwrm_ver_get_input       req = {0};
245         struct hwrm_ver_get_output      *resp =
246             (void *)softc->hwrm_cmd_resp.idi_vaddr;
247         int                             rc;
248         const char nastr[] = "<not installed>";
249         const char naver[] = "<N/A>";
250
251         softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN;
252         softc->hwrm_cmd_timeo = 1000;
253         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
254
255         req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
256         req.hwrm_intf_min = HWRM_VERSION_MINOR;
257         req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
258
259         BNXT_HWRM_LOCK(softc);
260         rc = _hwrm_send_message(softc, &req, sizeof(req));
261         if (rc)
262                 goto fail;
263
264         snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
265             resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
266         softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
267         softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
268         softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
269         snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
270             resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
271         strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
272             BNXT_VERSTR_SIZE);
273         strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
274             BNXT_NAME_SIZE);
275
276         if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
277             resp->mgmt_fw_bld == 0) {
278                 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
279                 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
280         }
281         else {
282                 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
283                     "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
284                     resp->mgmt_fw_bld);
285                 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
286                     BNXT_NAME_SIZE);
287         }
288         if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
289             resp->netctrl_fw_bld == 0) {
290                 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
291                     BNXT_VERSTR_SIZE);
292                 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
293                     BNXT_NAME_SIZE);
294         }
295         else {
296                 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
297                     "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
298                     resp->netctrl_fw_bld);
299                 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
300                     BNXT_NAME_SIZE);
301         }
302         if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
303             resp->roce_fw_bld == 0) {
304                 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
305                 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
306         }
307         else {
308                 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
309                     "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
310                     resp->roce_fw_bld);
311                 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
312                     BNXT_NAME_SIZE);
313         }
314         softc->ver_info->chip_num = le16toh(resp->chip_num);
315         softc->ver_info->chip_rev = resp->chip_rev;
316         softc->ver_info->chip_metal = resp->chip_metal;
317         softc->ver_info->chip_bond_id = resp->chip_bond_id;
318         softc->ver_info->chip_type = resp->chip_platform_type;
319
320         if (resp->max_req_win_len)
321                 softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
322         if (resp->def_req_timeout)
323                 softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
324
325 fail:
326         BNXT_HWRM_UNLOCK(softc);
327         return rc;
328 }
329
330 int
331 bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
332 {
333         struct hwrm_func_drv_rgtr_input req = {0};
334
335         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
336
337         req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
338             HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
339         req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
340
341         req.ver_maj = __FreeBSD_version / 100000;
342         req.ver_min = (__FreeBSD_version / 1000) % 100;
343         req.ver_upd = (__FreeBSD_version / 100) % 10;
344
345         return hwrm_send_message(softc, &req, sizeof(req));
346 }
347
348
349 int
350 bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
351 {
352         struct hwrm_func_drv_unrgtr_input req = {0};
353
354         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
355         if (shutdown == true)
356                 req.flags |=
357                     HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
358         return hwrm_send_message(softc, &req, sizeof(req));
359 }
360
361
362 static inline int
363 _is_valid_ether_addr(uint8_t *addr)
364 {
365         char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
366
367         if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
368                 return (FALSE);
369
370         return (TRUE);
371 }
372
373 static inline void
374 get_random_ether_addr(uint8_t *addr)
375 {
376         uint8_t temp[ETHER_ADDR_LEN];
377
378         arc4rand(&temp, sizeof(temp), 0);
379         temp[0] &= 0xFE;
380         temp[0] |= 0x02;
381         bcopy(temp, addr, sizeof(temp));
382 }
383
384 int
385 bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
386 {
387         int rc = 0;
388         struct hwrm_func_qcaps_input req = {0};
389         struct hwrm_func_qcaps_output *resp =
390             (void *)softc->hwrm_cmd_resp.idi_vaddr;
391         struct bnxt_func_info *func = &softc->func;
392
393         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
394         req.fid = htole16(0xffff);
395
396         BNXT_HWRM_LOCK(softc);
397         rc = _hwrm_send_message(softc, &req, sizeof(req));
398         if (rc)
399                 goto fail;
400
401         if (resp->flags &
402             htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
403                 softc->flags |= BNXT_FLAG_WOL_CAP;
404
405         func->fw_fid = le16toh(resp->fid);
406         memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
407         func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
408         func->max_cp_rings = le16toh(resp->max_cmpl_rings);
409         func->max_tx_rings = le16toh(resp->max_tx_rings);
410         func->max_rx_rings = le16toh(resp->max_rx_rings);
411         func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
412         if (!func->max_hw_ring_grps)
413                 func->max_hw_ring_grps = func->max_tx_rings;
414         func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
415         func->max_vnics = le16toh(resp->max_vnics);
416         func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
417         if (BNXT_PF(softc)) {
418                 struct bnxt_pf_info *pf = &softc->pf;
419
420                 pf->port_id = le16toh(resp->port_id);
421                 pf->first_vf_id = le16toh(resp->first_vf_id);
422                 pf->max_vfs = le16toh(resp->max_vfs);
423                 pf->max_encap_records = le32toh(resp->max_encap_records);
424                 pf->max_decap_records = le32toh(resp->max_decap_records);
425                 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
426                 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
427                 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
428                 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
429         }
430         if (!_is_valid_ether_addr(func->mac_addr)) {
431                 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
432                 get_random_ether_addr(func->mac_addr);
433         }
434
435 fail:
436         BNXT_HWRM_UNLOCK(softc);
437         return rc;
438 }
439
440 int
441 bnxt_hwrm_func_reset(struct bnxt_softc *softc)
442 {
443         struct hwrm_func_reset_input req = {0};
444
445         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
446         req.enables = 0;
447
448         return hwrm_send_message(softc, &req, sizeof(req));
449 }
450
451 static void
452 bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
453     struct hwrm_port_phy_cfg_input *req)
454 {
455         uint8_t autoneg = softc->link_info.autoneg;
456         uint16_t fw_link_speed = softc->link_info.req_link_speed;
457
458         if (autoneg & BNXT_AUTONEG_SPEED) {
459                 req->auto_mode |=
460                     HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
461
462                 req->enables |=
463                     htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
464                 req->flags |=
465                     htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
466         } else {
467                 req->force_link_speed = htole16(fw_link_speed);
468                 req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
469         }
470
471         /* tell chimp that the setting takes effect immediately */
472         req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
473 }
474
475
476 static void
477 bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
478     struct hwrm_port_phy_cfg_input *req)
479 {
480         if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) {
481                 req->auto_pause =
482                     HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
483                 if (softc->link_info.req_flow_ctrl &
484                     HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
485                         req->auto_pause |=
486                             HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
487                 if (softc->link_info.req_flow_ctrl &
488                     HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
489                         req->auto_pause |=
490                             HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
491                 req->enables |=
492                     htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
493         } else {
494                 if (softc->link_info.req_flow_ctrl &
495                     HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
496                         req->force_pause |=
497                             HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
498                 if (softc->link_info.req_flow_ctrl &
499                     HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
500                         req->force_pause |=
501                             HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
502                 req->enables |=
503                         htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
504                 req->auto_pause = req->force_pause;
505                 req->enables |= htole32(
506                     HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
507         }
508 }
509
510
511 /* JFV this needs interface connection */
512 static void
513 bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req)
514 {
515         /* struct ethtool_eee *eee = &softc->eee; */
516         bool    eee_enabled = false;
517
518         if (eee_enabled) {
519 #if 0
520                 uint16_t eee_speeds;
521                 uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
522
523                 if (eee->tx_lpi_enabled)
524                         flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
525
526                 req->flags |= htole32(flags);
527                 eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
528                 req->eee_link_speed_mask = htole16(eee_speeds);
529                 req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
530 #endif
531         } else {
532                 req->flags |=
533                     htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
534         }
535 }
536
537
538 int
539 bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
540     bool set_eee)
541 {
542         struct hwrm_port_phy_cfg_input req = {0};
543
544         if (softc->flags & BNXT_FLAG_NPAR)
545                 return ENOTSUP;
546
547         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
548         if (set_pause)
549                 bnxt_hwrm_set_pause_common(softc, &req);
550
551         bnxt_hwrm_set_link_common(softc, &req);
552         if (set_eee)
553                 bnxt_hwrm_set_eee(softc, &req);
554         return hwrm_send_message(softc, &req, sizeof(req));
555 }
556
557
558 int
559 bnxt_hwrm_set_pause(struct bnxt_softc *softc)
560 {
561         struct hwrm_port_phy_cfg_input req = {0};
562         int rc;
563
564         if (softc->flags & BNXT_FLAG_NPAR)
565                 return ENOTSUP;
566
567         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
568         bnxt_hwrm_set_pause_common(softc, &req);
569
570         if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)
571                 bnxt_hwrm_set_link_common(softc, &req);
572
573         BNXT_HWRM_LOCK(softc);
574         rc = _hwrm_send_message(softc, &req, sizeof(req));
575         if (!rc && !(softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
576                 /* since changing of pause setting doesn't trigger any link
577                  * change event, the driver needs to update the current pause
578                  * result upon successfully return of the phy_cfg command */
579                 softc->link_info.pause =
580                 softc->link_info.force_pause = softc->link_info.req_flow_ctrl;
581                 softc->link_info.auto_pause = 0;
582                 bnxt_report_link(softc);
583         }
584         BNXT_HWRM_UNLOCK(softc);
585         return rc;
586 }
587
588 int
589 bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
590 {
591         struct hwrm_vnic_cfg_input req = {0};
592         struct hwrm_vnic_cfg_output *resp;
593
594         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
595         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
596
597         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
598                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
599         if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
600                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
601         if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
602                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
603         req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
604             HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
605             HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
606         req.vnic_id = htole16(vnic->id);
607         req.dflt_ring_grp = htole16(vnic->def_ring_grp);
608         req.rss_rule = htole16(vnic->rss_id);
609         req.cos_rule = htole16(vnic->cos_rule);
610         req.lb_rule = htole16(vnic->lb_rule);
611         req.mru = htole16(vnic->mru);
612
613         return hwrm_send_message(softc, &req, sizeof(req));
614 }
615
616 int
617 bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
618 {
619         struct hwrm_vnic_alloc_input req = {0};
620         struct hwrm_vnic_alloc_output *resp =
621             (void *)softc->hwrm_cmd_resp.idi_vaddr;
622         int rc;
623
624         if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
625                 device_printf(softc->dev,
626                     "Attempt to re-allocate vnic %04x\n", vnic->id);
627                 return EDOOFUS;
628         }
629
630         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
631
632         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
633                 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
634
635         BNXT_HWRM_LOCK(softc);
636         rc = _hwrm_send_message(softc, &req, sizeof(req));
637         if (rc)
638                 goto fail;
639
640         vnic->id = le32toh(resp->vnic_id);
641
642 fail:
643         BNXT_HWRM_UNLOCK(softc);
644         return (rc);
645 }
646
647 int
648 bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
649 {
650         struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
651         struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
652             (void *)softc->hwrm_cmd_resp.idi_vaddr;
653         int rc;
654
655         if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
656                 device_printf(softc->dev,
657                     "Attempt to re-allocate vnic ctx %04x\n", *ctx_id);
658                 return EDOOFUS;
659         }
660
661         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
662
663         BNXT_HWRM_LOCK(softc);
664         rc = _hwrm_send_message(softc, &req, sizeof(req));
665         if (rc)
666                 goto fail;
667
668         *ctx_id = le32toh(resp->rss_cos_lb_ctx_id);
669
670 fail:
671         BNXT_HWRM_UNLOCK(softc);
672         return (rc);
673 }
674
675 int
676 bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
677 {
678         struct hwrm_ring_grp_alloc_input req = {0};
679         struct hwrm_ring_grp_alloc_output *resp;
680         int rc = 0;
681
682         if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) {
683                 device_printf(softc->dev,
684                     "Attempt to re-allocate ring group %04x\n", grp->grp_id);
685                 return EDOOFUS;
686         }
687
688         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
689         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
690         req.cr = htole16(grp->cp_ring_id);
691         req.rr = htole16(grp->rx_ring_id);
692         req.ar = htole16(grp->ag_ring_id);
693         req.sc = htole16(grp->stats_ctx);
694
695         BNXT_HWRM_LOCK(softc);
696         rc = _hwrm_send_message(softc, &req, sizeof(req));
697         if (rc)
698                 goto fail;
699
700         grp->grp_id = le32toh(resp->ring_group_id);
701
702 fail:
703         BNXT_HWRM_UNLOCK(softc);
704         return rc;
705 }
706
707 /*
708  * Ring allocation message to the firmware
709  */
710 int
711 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
712     struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
713     bool irq)
714 {
715         struct hwrm_ring_alloc_input req = {0};
716         struct hwrm_ring_alloc_output *resp;
717         int rc;
718
719         if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
720                 device_printf(softc->dev,
721                     "Attempt to re-allocate ring %04x\n", ring->phys_id);
722                 return EDOOFUS;
723         }
724
725         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
726         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
727         req.enables = htole32(0);
728         req.fbo = htole32(0);
729
730         if (stat_ctx_id != HWRM_NA_SIGNATURE) {
731                 req.enables |= htole32(
732                     HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
733                 req.stat_ctx_id = htole32(stat_ctx_id);
734         }
735         req.ring_type = type;
736         req.page_tbl_addr = htole64(ring->paddr);
737         req.length = htole32(ring->ring_size);
738         req.logical_id = htole16(ring->id);
739         req.cmpl_ring_id = htole16(cmpl_ring_id);
740         req.queue_id = htole16(softc->q_info[0].id);
741 #if 0
742         /* MODE_POLL appears to crash the firmware */
743         if (irq)
744                 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
745         else
746                 req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
747 #else
748         req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
749 #endif
750         BNXT_HWRM_LOCK(softc);
751         rc = _hwrm_send_message(softc, &req, sizeof(req));
752         if (rc)
753                 goto fail;
754
755         ring->phys_id = le16toh(resp->ring_id);
756
757 fail:
758         BNXT_HWRM_UNLOCK(softc);
759         return rc;
760 }
761
762 int
763 bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
764     uint64_t paddr)
765 {
766         struct hwrm_stat_ctx_alloc_input req = {0};
767         struct hwrm_stat_ctx_alloc_output *resp;
768         int rc = 0;
769
770         if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
771                 device_printf(softc->dev,
772                     "Attempt to re-allocate stats ctx %08x\n",
773                     cpr->stats_ctx_id);
774                 return EDOOFUS;
775         }
776
777         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
778         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
779
780         req.update_period_ms = htole32(1000);
781         req.stats_dma_addr = htole64(paddr);
782
783         BNXT_HWRM_LOCK(softc);
784         rc = _hwrm_send_message(softc, &req, sizeof(req));
785         if (rc)
786                 goto fail;
787
788         cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
789
790 fail:
791         BNXT_HWRM_UNLOCK(softc);
792
793         return rc;
794 }
795
796 int
797 bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
798     struct bnxt_vnic_info *vnic)
799 {
800         struct hwrm_cfa_l2_set_rx_mask_input req = {0};
801         struct bnxt_vlan_tag *tag;
802         uint32_t *tags;
803         uint32_t num_vlan_tags = 0;;
804         uint32_t i;
805         uint32_t mask = vnic->rx_mask;
806         int rc;
807
808         SLIST_FOREACH(tag, &vnic->vlan_tags, next)
809                 num_vlan_tags++;
810
811         if (num_vlan_tags) {
812                 if (!(mask &
813                     HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
814                         if (!vnic->vlan_only)
815                                 mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
816                         else
817                                 mask |=
818                                     HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
819                 }
820                 if (vnic->vlan_tag_list.idi_vaddr) {
821                         iflib_dma_free(&vnic->vlan_tag_list);
822                         vnic->vlan_tag_list.idi_vaddr = NULL;
823                 }
824                 rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
825                     &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
826                 if (rc)
827                         return rc;
828                 tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
829
830                 i = 0;
831                 SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
832                         tags[i] = htole32((tag->tpid << 16) | tag->tag);
833                         i++;
834                 }
835         }
836         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
837
838         req.vnic_id = htole32(vnic->id);
839         req.mask = htole32(mask);
840         req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
841         req.num_mc_entries = htole32(vnic->mc_list_count);
842         req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
843         req.num_vlan_tags = htole32(num_vlan_tags);
844         return hwrm_send_message(softc, &req, sizeof(req));
845 }
846
847
848 int
849 bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
850 {
851         struct hwrm_cfa_l2_filter_alloc_input   req = {0};
852         struct hwrm_cfa_l2_filter_alloc_output  *resp;
853         uint32_t enables = 0;
854         int rc = 0;
855
856         if (vnic->filter_id != -1) {
857                 device_printf(softc->dev,
858                     "Attempt to re-allocate l2 ctx filter\n");
859                 return EDOOFUS;
860         }
861
862         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
863         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
864
865         req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
866         enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
867             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
868             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
869         req.enables = htole32(enables);
870         req.dst_id = htole16(vnic->id);
871         memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)),
872             ETHER_ADDR_LEN);
873         memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
874
875         BNXT_HWRM_LOCK(softc);
876         rc = _hwrm_send_message(softc, &req, sizeof(req));
877         if (rc)
878                 goto fail;
879
880         vnic->filter_id = le64toh(resp->l2_filter_id);
881         vnic->flow_id = le64toh(resp->flow_id);
882
883 fail:
884         BNXT_HWRM_UNLOCK(softc);
885         return (rc);
886 }
887
888 int
889 bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
890     uint32_t hash_type)
891 {
892         struct hwrm_vnic_rss_cfg_input  req = {0};
893         struct hwrm_vnic_rss_cfg_output *resp;
894
895         resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
896         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
897
898         req.hash_type = htole32(hash_type);
899         req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
900         req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
901         req.rss_ctx_idx = htole16(vnic->rss_id);
902
903         return hwrm_send_message(softc, &req, sizeof(req));
904 }
905
906 int
907 bnxt_hwrm_func_cfg(struct bnxt_softc *softc)
908 {
909         struct hwrm_func_cfg_input req = {0};
910
911         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
912
913         req.fid = 0xffff;
914         req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
915
916         req.async_event_cr = softc->def_cp_ring.ring.phys_id;
917
918         return hwrm_send_message(softc, &req, sizeof(req));
919 }
920
921 int
922 bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
923     uint32_t flags)
924 {
925         struct hwrm_vnic_tpa_cfg_input req = {0};
926
927         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
928
929         req.flags = htole32(flags);
930         req.vnic_id = htole16(vnic->id);
931         req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
932             HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
933             /* HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER | */
934             HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
935         /* TODO: Calculate this based on ring size? */
936         req.max_agg_segs = htole16(3);
937         /* Base this in the allocated TPA start size... */
938         req.max_aggs = htole16(7);
939         /*
940          * TODO: max_agg_timer?
941          * req.mag_agg_timer = htole32(XXX);
942          */
943         req.min_agg_len = htole32(0);
944
945         return hwrm_send_message(softc, &req, sizeof(req));
946 }
947
948 int
949 bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
950     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
951     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
952     uint32_t *fw_ver)
953 {
954         struct hwrm_nvm_find_dir_entry_input req = {0};
955         struct hwrm_nvm_find_dir_entry_output *resp =
956             (void *)softc->hwrm_cmd_resp.idi_vaddr;
957         int     rc = 0;
958         uint32_t old_timeo;
959
960         MPASS(ordinal);
961
962         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
963         if (use_index) {
964                 req.enables = htole32(
965                     HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
966                 req.dir_idx = htole16(*index);
967         }
968         req.dir_type = htole16(type);
969         req.dir_ordinal = htole16(*ordinal);
970         req.dir_ext = htole16(ext);
971         req.opt_ordinal = search_opt;
972
973         BNXT_HWRM_LOCK(softc);
974         old_timeo = softc->hwrm_cmd_timeo;
975         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
976         rc = _hwrm_send_message(softc, &req, sizeof(req));
977         softc->hwrm_cmd_timeo = old_timeo;
978         if (rc)
979                 goto exit;
980
981         if (item_length)
982                 *item_length = le32toh(resp->dir_item_length);
983         if (data_length)
984                 *data_length = le32toh(resp->dir_data_length);
985         if (fw_ver)
986                 *fw_ver = le32toh(resp->fw_ver);
987         *ordinal = le16toh(resp->dir_ordinal);
988         if (index)
989                 *index = le16toh(resp->dir_idx);
990
991 exit:
992         BNXT_HWRM_UNLOCK(softc);
993         return (rc);
994 }
995
996 int
997 bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
998     uint32_t length, struct iflib_dma_info *data)
999 {
1000         struct hwrm_nvm_read_input req = {0};
1001         int rc;
1002         uint32_t old_timeo;
1003
1004         if (length > data->idi_size) {
1005                 rc = EINVAL;
1006                 goto exit;
1007         }
1008         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
1009         req.host_dest_addr = htole64(data->idi_paddr);
1010         req.dir_idx = htole16(index);
1011         req.offset = htole32(offset);
1012         req.len = htole32(length);
1013         BNXT_HWRM_LOCK(softc);
1014         old_timeo = softc->hwrm_cmd_timeo;
1015         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1016         rc = _hwrm_send_message(softc, &req, sizeof(req));
1017         softc->hwrm_cmd_timeo = old_timeo;
1018         BNXT_HWRM_UNLOCK(softc);
1019         if (rc)
1020                 goto exit;
1021         bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
1022
1023         goto exit;
1024
1025 exit:
1026         return rc;
1027 }
1028
1029 int
1030 bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
1031     void *data, bool cpyin, uint32_t length)
1032 {
1033         struct hwrm_nvm_modify_input req = {0};
1034         struct iflib_dma_info dma_data;
1035         int rc;
1036         uint32_t old_timeo;
1037
1038         if (length == 0 || !data)
1039                 return EINVAL;
1040         rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
1041             BUS_DMA_NOWAIT);
1042         if (rc)
1043                 return ENOMEM;
1044         if (cpyin) {
1045                 rc = copyin(data, dma_data.idi_vaddr, length);
1046                 if (rc)
1047                         goto exit;
1048         }
1049         else
1050                 memcpy(dma_data.idi_vaddr, data, length);
1051         bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1052             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1053
1054         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
1055         req.host_src_addr = htole64(dma_data.idi_paddr);
1056         req.dir_idx = htole16(index);
1057         req.offset = htole32(offset);
1058         req.len = htole32(length);
1059         BNXT_HWRM_LOCK(softc);
1060         old_timeo = softc->hwrm_cmd_timeo;
1061         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1062         rc = _hwrm_send_message(softc, &req, sizeof(req));
1063         softc->hwrm_cmd_timeo = old_timeo;
1064         BNXT_HWRM_UNLOCK(softc);
1065
1066 exit:
1067         iflib_dma_free(&dma_data);
1068         return rc;
1069 }
1070
1071 int
1072 bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
1073     uint8_t *selfreset)
1074 {
1075         struct hwrm_fw_reset_input req = {0};
1076         struct hwrm_fw_reset_output *resp =
1077             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1078         int rc;
1079
1080         MPASS(selfreset);
1081
1082         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
1083         req.embedded_proc_type = processor;
1084         req.selfrst_status = *selfreset;
1085
1086         BNXT_HWRM_LOCK(softc);
1087         rc = _hwrm_send_message(softc, &req, sizeof(req));
1088         if (rc)
1089                 goto exit;
1090         *selfreset = resp->selfrst_status;
1091
1092 exit:
1093         BNXT_HWRM_UNLOCK(softc);
1094         return rc;
1095 }
1096
1097 int
1098 bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
1099 {
1100         struct hwrm_fw_qstatus_input req = {0};
1101         struct hwrm_fw_qstatus_output *resp =
1102             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1103         int rc;
1104
1105         MPASS(selfreset);
1106
1107         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
1108         req.embedded_proc_type = type;
1109
1110         BNXT_HWRM_LOCK(softc);
1111         rc = _hwrm_send_message(softc, &req, sizeof(req));
1112         if (rc)
1113                 goto exit;
1114         *selfreset = resp->selfrst_status;
1115
1116 exit:
1117         BNXT_HWRM_UNLOCK(softc);
1118         return rc;
1119 }
1120
1121 int
1122 bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
1123     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
1124     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
1125     uint16_t *index)
1126 {
1127         struct hwrm_nvm_write_input req = {0};
1128         struct hwrm_nvm_write_output *resp =
1129             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1130         struct iflib_dma_info dma_data;
1131         int rc;
1132         uint32_t old_timeo;
1133
1134         if (data_length) {
1135                 rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
1136                     BUS_DMA_NOWAIT);
1137                 if (rc)
1138                         return ENOMEM;
1139                 if (cpyin) {
1140                         rc = copyin(data, dma_data.idi_vaddr, data_length);
1141                         if (rc)
1142                                 goto early_exit;
1143                 }
1144                 else
1145                         memcpy(dma_data.idi_vaddr, data, data_length);
1146                 bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
1147                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1148         }
1149         else
1150                 dma_data.idi_paddr = 0;
1151
1152         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
1153
1154         req.host_src_addr = htole64(dma_data.idi_paddr);
1155         req.dir_type = htole16(type);
1156         req.dir_ordinal = htole16(ordinal);
1157         req.dir_ext = htole16(ext);
1158         req.dir_attr = htole16(attr);
1159         req.dir_data_length = htole32(data_length);
1160         req.option = htole16(option);
1161         if (keep) {
1162                 req.flags =
1163                     htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
1164         }
1165         if (item_length)
1166                 req.dir_item_length = htole32(*item_length);
1167
1168         BNXT_HWRM_LOCK(softc);
1169         old_timeo = softc->hwrm_cmd_timeo;
1170         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1171         rc = _hwrm_send_message(softc, &req, sizeof(req));
1172         softc->hwrm_cmd_timeo = old_timeo;
1173         if (rc)
1174                 goto exit;
1175         if (item_length)
1176                 *item_length = le32toh(resp->dir_item_length);
1177         if (index)
1178                 *index = le16toh(resp->dir_idx);
1179
1180 exit:
1181         BNXT_HWRM_UNLOCK(softc);
1182 early_exit:
1183         if (data_length)
1184                 iflib_dma_free(&dma_data);
1185         return rc;
1186 }
1187
1188 int
1189 bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
1190 {
1191         struct hwrm_nvm_erase_dir_entry_input req = {0};
1192         uint32_t old_timeo;
1193         int rc;
1194
1195         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
1196         req.dir_idx = htole16(index);
1197         BNXT_HWRM_LOCK(softc);
1198         old_timeo = softc->hwrm_cmd_timeo;
1199         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1200         rc = _hwrm_send_message(softc, &req, sizeof(req));
1201         softc->hwrm_cmd_timeo = old_timeo;
1202         BNXT_HWRM_UNLOCK(softc);
1203         return rc;
1204 }
1205
1206 int
1207 bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
1208     uint32_t *entry_length)
1209 {
1210         struct hwrm_nvm_get_dir_info_input req = {0};
1211         struct hwrm_nvm_get_dir_info_output *resp =
1212             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1213         int rc;
1214         uint32_t old_timeo;
1215
1216         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
1217
1218         BNXT_HWRM_LOCK(softc);
1219         old_timeo = softc->hwrm_cmd_timeo;
1220         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1221         rc = _hwrm_send_message(softc, &req, sizeof(req));
1222         softc->hwrm_cmd_timeo = old_timeo;
1223         if (rc)
1224                 goto exit;
1225
1226         if (entries)
1227                 *entries = le32toh(resp->entries);
1228         if (entry_length)
1229                 *entry_length = le32toh(resp->entry_length);
1230
1231 exit:
1232         BNXT_HWRM_UNLOCK(softc);
1233         return rc;
1234 }
1235
1236 int
1237 bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
1238     uint32_t *entry_length, struct iflib_dma_info *dma_data)
1239 {
1240         struct hwrm_nvm_get_dir_entries_input req = {0};
1241         uint32_t ent;
1242         uint32_t ent_len;
1243         int rc;
1244         uint32_t old_timeo;
1245
1246         if (!entries)
1247                 entries = &ent;
1248         if (!entry_length)
1249                 entry_length = &ent_len;
1250
1251         rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
1252         if (rc)
1253                 goto exit;
1254         if (*entries * *entry_length > dma_data->idi_size) {
1255                 rc = EINVAL;
1256                 goto exit;
1257         }
1258
1259         /*
1260          * TODO: There's a race condition here that could blow up DMA memory...
1261          *       we need to allocate the max size, not the currently in use
1262          *       size.  The command should totally have a max size here.
1263          */
1264         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
1265         req.host_dest_addr = htole64(dma_data->idi_paddr);
1266         BNXT_HWRM_LOCK(softc);
1267         old_timeo = softc->hwrm_cmd_timeo;
1268         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1269         rc = _hwrm_send_message(softc, &req, sizeof(req));
1270         softc->hwrm_cmd_timeo = old_timeo;
1271         BNXT_HWRM_UNLOCK(softc);
1272         if (rc)
1273                 goto exit;
1274         bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
1275             BUS_DMASYNC_POSTWRITE);
1276
1277 exit:
1278         return rc;
1279 }
1280
1281 int
1282 bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
1283     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
1284     uint32_t *reserved_size, uint32_t *available_size)
1285 {
1286         struct hwrm_nvm_get_dev_info_input req = {0};
1287         struct hwrm_nvm_get_dev_info_output *resp =
1288             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1289         int rc;
1290         uint32_t old_timeo;
1291
1292         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
1293
1294         BNXT_HWRM_LOCK(softc);
1295         old_timeo = softc->hwrm_cmd_timeo;
1296         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1297         rc = _hwrm_send_message(softc, &req, sizeof(req));
1298         softc->hwrm_cmd_timeo = old_timeo;
1299         if (rc)
1300                 goto exit;
1301
1302         if (mfg_id)
1303                 *mfg_id = le16toh(resp->manufacturer_id);
1304         if (device_id)
1305                 *device_id = le16toh(resp->device_id);
1306         if (sector_size)
1307                 *sector_size = le32toh(resp->sector_size);
1308         if (nvram_size)
1309                 *nvram_size = le32toh(resp->nvram_size);
1310         if (reserved_size)
1311                 *reserved_size = le32toh(resp->reserved_size);
1312         if (available_size)
1313                 *available_size = le32toh(resp->available_size);
1314
1315 exit:
1316         BNXT_HWRM_UNLOCK(softc);
1317         return rc;
1318 }
1319
1320 int
1321 bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
1322     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
1323     uint8_t *problem_item, uint8_t *reset_required)
1324 {
1325         struct hwrm_nvm_install_update_input req = {0};
1326         struct hwrm_nvm_install_update_output *resp =
1327             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1328         int rc;
1329         uint32_t old_timeo;
1330
1331         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
1332         req.install_type = htole32(install_type);
1333
1334         BNXT_HWRM_LOCK(softc);
1335         old_timeo = softc->hwrm_cmd_timeo;
1336         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1337         rc = _hwrm_send_message(softc, &req, sizeof(req));
1338         softc->hwrm_cmd_timeo = old_timeo;
1339         if (rc)
1340                 goto exit;
1341
1342         if (installed_items)
1343                 *installed_items = le32toh(resp->installed_items);
1344         if (result)
1345                 *result = resp->result;
1346         if (problem_item)
1347                 *problem_item = resp->problem_item;
1348         if (reset_required)
1349                 *reset_required = resp->reset_required;
1350
1351 exit:
1352         BNXT_HWRM_UNLOCK(softc);
1353         return rc;
1354 }
1355
1356 int
1357 bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
1358     uint16_t ordinal, uint16_t ext)
1359 {
1360         struct hwrm_nvm_verify_update_input req = {0};
1361         uint32_t old_timeo;
1362         int rc;
1363
1364         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
1365
1366         req.dir_type = htole16(type);
1367         req.dir_ordinal = htole16(ordinal);
1368         req.dir_ext = htole16(ext);
1369
1370         BNXT_HWRM_LOCK(softc);
1371         old_timeo = softc->hwrm_cmd_timeo;
1372         softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
1373         rc = _hwrm_send_message(softc, &req, sizeof(req));
1374         softc->hwrm_cmd_timeo = old_timeo;
1375         BNXT_HWRM_UNLOCK(softc);
1376         return rc;
1377 }
1378
1379 int
1380 bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
1381     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
1382     uint16_t *millisecond, uint16_t *zone)
1383 {
1384         struct hwrm_fw_get_time_input req = {0};
1385         struct hwrm_fw_get_time_output *resp =
1386             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1387         int rc;
1388
1389         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
1390
1391         BNXT_HWRM_LOCK(softc);
1392         rc = _hwrm_send_message(softc, &req, sizeof(req));
1393         if (rc)
1394                 goto exit;
1395
1396         if (year)
1397                 *year = le16toh(resp->year);
1398         if (month)
1399                 *month = resp->month;
1400         if (day)
1401                 *day = resp->day;
1402         if (hour)
1403                 *hour = resp->hour;
1404         if (minute)
1405                 *minute = resp->minute;
1406         if (second)
1407                 *second = resp->second;
1408         if (millisecond)
1409                 *millisecond = le16toh(resp->millisecond);
1410         if (zone)
1411                 *zone = le16toh(resp->zone);
1412
1413 exit:
1414         BNXT_HWRM_UNLOCK(softc);
1415         return rc;
1416 }
1417
1418 int
1419 bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
1420     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
1421     uint16_t millisecond, uint16_t zone)
1422 {
1423         struct hwrm_fw_set_time_input req = {0};
1424
1425         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
1426
1427         req.year = htole16(year);
1428         req.month = month;
1429         req.day = day;
1430         req.hour = hour;
1431         req.minute = minute;
1432         req.second = second;
1433         req.millisecond = htole16(millisecond);
1434         req.zone = htole16(zone);
1435         return hwrm_send_message(softc, &req, sizeof(req));
1436 }
1437
1438 int
1439 bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
1440 {
1441         struct bnxt_link_info *link_info = &softc->link_info;
1442         struct hwrm_port_phy_qcfg_input req = {0};
1443         struct hwrm_port_phy_qcfg_output *resp =
1444             (void *)softc->hwrm_cmd_resp.idi_vaddr;
1445         int rc = 0;
1446
1447         BNXT_HWRM_LOCK(softc);
1448         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
1449
1450         rc = _hwrm_send_message(softc, &req, sizeof(req));
1451         if (rc)
1452                 goto exit;
1453
1454         link_info->phy_link_status = resp->link;
1455         link_info->duplex =  resp->duplex;
1456         link_info->pause = resp->pause;
1457         link_info->auto_mode = resp->auto_mode;
1458         link_info->auto_pause = resp->auto_pause;
1459         link_info->force_pause = resp->force_pause;
1460         link_info->duplex_setting = resp->duplex;
1461         if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
1462                 link_info->link_speed = le16toh(resp->link_speed);
1463         else
1464                 link_info->link_speed = 0;
1465         link_info->force_link_speed = le16toh(resp->force_link_speed);
1466         link_info->auto_link_speed = le16toh(resp->auto_link_speed);
1467         link_info->support_speeds = le16toh(resp->support_speeds);
1468         link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask);
1469         link_info->preemphasis = le32toh(resp->preemphasis);
1470         link_info->phy_ver[0] = resp->phy_maj;
1471         link_info->phy_ver[1] = resp->phy_min;
1472         link_info->phy_ver[2] = resp->phy_bld;
1473         snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver),
1474             "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1],
1475             link_info->phy_ver[2]);
1476         strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name,
1477             BNXT_NAME_SIZE);
1478         strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber,
1479             BNXT_NAME_SIZE);
1480         link_info->media_type = resp->media_type;
1481         link_info->phy_type = resp->phy_type;
1482         link_info->transceiver = resp->xcvr_pkg_type;
1483         link_info->phy_addr = resp->eee_config_phy_addr &
1484             HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK;
1485
1486 exit:
1487         BNXT_HWRM_UNLOCK(softc);
1488         return rc;
1489 }
1490
1491 uint16_t
1492 bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
1493 {
1494         struct hwrm_wol_filter_qcfg_input req = {0};
1495         struct hwrm_wol_filter_qcfg_output *resp =
1496                         (void *)softc->hwrm_cmd_resp.idi_vaddr;
1497         uint16_t next_handle = 0;
1498         int rc;
1499
1500         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
1501         req.port_id = htole16(softc->pf.port_id);
1502         req.handle = htole16(handle);
1503         rc = hwrm_send_message(softc, &req, sizeof(req));
1504         if (!rc) {
1505                 next_handle = le16toh(resp->next_handle);
1506                 if (next_handle != 0) {
1507                         if (resp->wol_type ==
1508                                 HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
1509                                 softc->wol = 1;
1510                                 softc->wol_filter_id = resp->wol_filter_id;
1511                         }
1512                 }
1513         }
1514         return next_handle;
1515 }
1516
1517 int
1518 bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
1519 {
1520         struct hwrm_wol_filter_alloc_input req = {0};
1521         struct hwrm_wol_filter_alloc_output *resp =
1522                 (void *)softc->hwrm_cmd_resp.idi_vaddr;
1523         int rc;
1524
1525         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
1526         req.port_id = htole16(softc->pf.port_id);
1527         req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
1528         req.enables =
1529                 htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
1530         memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
1531         rc = hwrm_send_message(softc, &req, sizeof(req));
1532         if (!rc)
1533                 softc->wol_filter_id = resp->wol_filter_id;
1534
1535         return rc;
1536 }
1537
1538 int
1539 bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
1540 {
1541         struct hwrm_wol_filter_free_input req = {0};
1542
1543         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
1544         req.port_id = htole16(softc->pf.port_id);
1545         req.enables =
1546                 htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
1547         req.wol_filter_id = softc->wol_filter_id;
1548         return hwrm_send_message(softc, &req, sizeof(req));
1549 }