net/bnxt: add statistics
[dpdk.git] / drivers / net / bnxt / bnxt_hwrm.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) Broadcom Limited.
5  *   All rights reserved.
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  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Broadcom Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_byteorder.h>
35 #include <rte_common.h>
36 #include <rte_cycles.h>
37 #include <rte_malloc.h>
38 #include <rte_memzone.h>
39 #include <rte_version.h>
40
41 #include "bnxt.h"
42 #include "bnxt_cpr.h"
43 #include "bnxt_filter.h"
44 #include "bnxt_hwrm.h"
45 #include "bnxt_rxq.h"
46 #include "bnxt_txq.h"
47 #include "bnxt_vnic.h"
48 #include "hsi_struct_def_dpdk.h"
49
50 #define HWRM_CMD_TIMEOUT                2000
51
52 /*
53  * HWRM Functions (sent to HWRM)
54  * These are named bnxt_hwrm_*() and return -1 if bnxt_hwrm_send_message()
55  * fails (ie: a timeout), and a positive non-zero HWRM error code if the HWRM
56  * command was failed by the ChiMP.
57  */
58
59 static int bnxt_hwrm_send_message_locked(struct bnxt *bp, void *msg,
60                                         uint32_t msg_len)
61 {
62         unsigned int i;
63         struct input *req = msg;
64         struct output *resp = bp->hwrm_cmd_resp_addr;
65         uint32_t *data = msg;
66         uint8_t *bar;
67         uint8_t *valid;
68
69         /* Write request msg to hwrm channel */
70         for (i = 0; i < msg_len; i += 4) {
71                 bar = (uint8_t *)bp->bar0 + i;
72                 *(volatile uint32_t *)bar = *data;
73                 data++;
74         }
75
76         /* Zero the rest of the request space */
77         for (; i < bp->max_req_len; i += 4) {
78                 bar = (uint8_t *)bp->bar0 + i;
79                 *(volatile uint32_t *)bar = 0;
80         }
81
82         /* Ring channel doorbell */
83         bar = (uint8_t *)bp->bar0 + 0x100;
84         *(volatile uint32_t *)bar = 1;
85
86         /* Poll for the valid bit */
87         for (i = 0; i < HWRM_CMD_TIMEOUT; i++) {
88                 /* Sanity check on the resp->resp_len */
89                 rte_rmb();
90                 if (resp->resp_len && resp->resp_len <=
91                                 bp->max_resp_len) {
92                         /* Last byte of resp contains the valid key */
93                         valid = (uint8_t *)resp + resp->resp_len - 1;
94                         if (*valid == HWRM_RESP_VALID_KEY)
95                                 break;
96                 }
97                 rte_delay_us(600);
98         }
99
100         if (i >= HWRM_CMD_TIMEOUT) {
101                 RTE_LOG(ERR, PMD, "Error sending msg %x\n",
102                         req->req_type);
103                 goto err_ret;
104         }
105         return 0;
106
107 err_ret:
108         return -1;
109 }
110
111 static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg, uint32_t msg_len)
112 {
113         int rc;
114
115         rte_spinlock_lock(&bp->hwrm_lock);
116         rc = bnxt_hwrm_send_message_locked(bp, msg, msg_len);
117         rte_spinlock_unlock(&bp->hwrm_lock);
118         return rc;
119 }
120
121 #define HWRM_PREP(req, type, cr, resp) \
122         memset(bp->hwrm_cmd_resp_addr, 0, bp->max_resp_len); \
123         req.req_type = rte_cpu_to_le_16(HWRM_##type); \
124         req.cmpl_ring = rte_cpu_to_le_16(cr); \
125         req.seq_id = rte_cpu_to_le_16(bp->hwrm_cmd_seq++); \
126         req.target_id = rte_cpu_to_le_16(0xffff); \
127         req.resp_addr = rte_cpu_to_le_64(bp->hwrm_cmd_resp_dma_addr)
128
129 #define HWRM_CHECK_RESULT \
130         { \
131                 if (rc) { \
132                         RTE_LOG(ERR, PMD, "%s failed rc:%d\n", \
133                                 __func__, rc); \
134                         return rc; \
135                 } \
136                 if (resp->error_code) { \
137                         rc = rte_le_to_cpu_16(resp->error_code); \
138                         RTE_LOG(ERR, PMD, "%s error %d\n", __func__, rc); \
139                         return rc; \
140                 } \
141         }
142
143 int bnxt_hwrm_clear_filter(struct bnxt *bp,
144                            struct bnxt_filter_info *filter)
145 {
146         int rc = 0;
147         struct hwrm_cfa_l2_filter_free_input req = {.req_type = 0 };
148         struct hwrm_cfa_l2_filter_free_output *resp = bp->hwrm_cmd_resp_addr;
149
150         HWRM_PREP(req, CFA_L2_FILTER_FREE, -1, resp);
151
152         req.l2_filter_id = rte_cpu_to_le_64(filter->fw_l2_filter_id);
153
154         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
155
156         HWRM_CHECK_RESULT;
157
158         filter->fw_l2_filter_id = -1;
159
160         return 0;
161 }
162
163 int bnxt_hwrm_set_filter(struct bnxt *bp,
164                          struct bnxt_vnic_info *vnic,
165                          struct bnxt_filter_info *filter)
166 {
167         int rc = 0;
168         struct hwrm_cfa_l2_filter_alloc_input req = {.req_type = 0 };
169         struct hwrm_cfa_l2_filter_alloc_output *resp = bp->hwrm_cmd_resp_addr;
170         uint32_t enables = 0;
171
172         HWRM_PREP(req, CFA_L2_FILTER_ALLOC, -1, resp);
173
174         req.flags = rte_cpu_to_le_32(filter->flags);
175
176         enables = filter->enables |
177               HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
178         req.dst_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
179
180         if (enables &
181             HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR)
182                 memcpy(req.l2_addr, filter->l2_addr,
183                        ETHER_ADDR_LEN);
184         if (enables &
185             HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK)
186                 memcpy(req.l2_addr_mask, filter->l2_addr_mask,
187                        ETHER_ADDR_LEN);
188         if (enables &
189             HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN)
190                 req.l2_ovlan = filter->l2_ovlan;
191         if (enables &
192             HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN_MASK)
193                 req.l2_ovlan_mask = filter->l2_ovlan_mask;
194
195         req.enables = rte_cpu_to_le_32(enables);
196
197         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
198
199         HWRM_CHECK_RESULT;
200
201         filter->fw_l2_filter_id = rte_le_to_cpu_64(resp->l2_filter_id);
202
203         return rc;
204 }
205
206 int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, void *fwd_cmd)
207 {
208         int rc;
209         struct hwrm_exec_fwd_resp_input req = {.req_type = 0 };
210         struct hwrm_exec_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr;
211
212         HWRM_PREP(req, EXEC_FWD_RESP, -1, resp);
213
214         memcpy(req.encap_request, fwd_cmd,
215                sizeof(req.encap_request));
216
217         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
218
219         HWRM_CHECK_RESULT;
220
221         return rc;
222 }
223
224 int bnxt_hwrm_func_qcaps(struct bnxt *bp)
225 {
226         int rc = 0;
227         struct hwrm_func_qcaps_input req = {.req_type = 0 };
228         struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
229
230         HWRM_PREP(req, FUNC_QCAPS, -1, resp);
231
232         req.fid = rte_cpu_to_le_16(0xffff);
233
234         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
235
236         HWRM_CHECK_RESULT;
237
238         if (BNXT_PF(bp)) {
239                 struct bnxt_pf_info *pf = &bp->pf;
240
241                 pf->fw_fid = rte_le_to_cpu_32(resp->fid);
242                 pf->port_id = resp->port_id;
243                 memcpy(pf->mac_addr, resp->perm_mac_address, ETHER_ADDR_LEN);
244                 pf->max_rsscos_ctx = rte_le_to_cpu_16(resp->max_rsscos_ctx);
245                 pf->max_cp_rings = rte_le_to_cpu_16(resp->max_cmpl_rings);
246                 pf->max_tx_rings = rte_le_to_cpu_16(resp->max_tx_rings);
247                 pf->max_rx_rings = rte_le_to_cpu_16(resp->max_rx_rings);
248                 pf->max_l2_ctx = rte_le_to_cpu_16(resp->max_l2_ctxs);
249                 pf->max_vnics = rte_le_to_cpu_16(resp->max_vnics);
250                 pf->first_vf_id = rte_le_to_cpu_16(resp->first_vf_id);
251                 pf->max_vfs = rte_le_to_cpu_16(resp->max_vfs);
252         } else {
253                 struct bnxt_vf_info *vf = &bp->vf;
254
255                 vf->fw_fid = rte_le_to_cpu_32(resp->fid);
256                 memcpy(vf->mac_addr, &resp->perm_mac_address, ETHER_ADDR_LEN);
257                 vf->max_rsscos_ctx = rte_le_to_cpu_16(resp->max_rsscos_ctx);
258                 vf->max_cp_rings = rte_le_to_cpu_16(resp->max_cmpl_rings);
259                 vf->max_tx_rings = rte_le_to_cpu_16(resp->max_tx_rings);
260                 vf->max_rx_rings = rte_le_to_cpu_16(resp->max_rx_rings);
261                 vf->max_l2_ctx = rte_le_to_cpu_16(resp->max_l2_ctxs);
262                 vf->max_vnics = rte_le_to_cpu_16(resp->max_vnics);
263         }
264
265         return rc;
266 }
267
268 int bnxt_hwrm_func_driver_register(struct bnxt *bp, uint32_t flags,
269                                    uint32_t *vf_req_fwd)
270 {
271         int rc;
272         struct hwrm_func_drv_rgtr_input req = {.req_type = 0 };
273         struct hwrm_func_drv_rgtr_output *resp = bp->hwrm_cmd_resp_addr;
274
275         if (bp->flags & BNXT_FLAG_REGISTERED)
276                 return 0;
277
278         HWRM_PREP(req, FUNC_DRV_RGTR, -1, resp);
279         req.flags = flags;
280         req.enables = HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER;
281         req.ver_maj = RTE_VER_YEAR;
282         req.ver_min = RTE_VER_MONTH;
283         req.ver_upd = RTE_VER_MINOR;
284
285         memcpy(req.vf_req_fwd, vf_req_fwd, sizeof(req.vf_req_fwd));
286
287         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
288
289         HWRM_CHECK_RESULT;
290
291         bp->flags |= BNXT_FLAG_REGISTERED;
292
293         return rc;
294 }
295
296 int bnxt_hwrm_ver_get(struct bnxt *bp)
297 {
298         int rc = 0;
299         struct hwrm_ver_get_input req = {.req_type = 0 };
300         struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr;
301         uint32_t my_version;
302         uint32_t fw_version;
303         uint16_t max_resp_len;
304         char type[RTE_MEMZONE_NAMESIZE];
305
306         HWRM_PREP(req, VER_GET, -1, resp);
307
308         req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
309         req.hwrm_intf_min = HWRM_VERSION_MINOR;
310         req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
311
312         /*
313          * Hold the lock since we may be adjusting the response pointers.
314          */
315         rte_spinlock_lock(&bp->hwrm_lock);
316         rc = bnxt_hwrm_send_message_locked(bp, &req, sizeof(req));
317
318         HWRM_CHECK_RESULT;
319
320         RTE_LOG(INFO, PMD, "%d.%d.%d:%d.%d.%d\n",
321                 resp->hwrm_intf_maj, resp->hwrm_intf_min,
322                 resp->hwrm_intf_upd,
323                 resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
324
325         my_version = HWRM_VERSION_MAJOR << 16;
326         my_version |= HWRM_VERSION_MINOR << 8;
327         my_version |= HWRM_VERSION_UPDATE;
328
329         fw_version = resp->hwrm_intf_maj << 16;
330         fw_version |= resp->hwrm_intf_min << 8;
331         fw_version |= resp->hwrm_intf_upd;
332
333         if (resp->hwrm_intf_maj != HWRM_VERSION_MAJOR) {
334                 RTE_LOG(ERR, PMD, "Unsupported firmware API version\n");
335                 rc = -EINVAL;
336                 goto error;
337         }
338
339         if (my_version != fw_version) {
340                 RTE_LOG(INFO, PMD, "BNXT Driver/HWRM API mismatch.\n");
341                 if (my_version < fw_version) {
342                         RTE_LOG(INFO, PMD,
343                                 "Firmware API version is newer than driver.\n");
344                         RTE_LOG(INFO, PMD,
345                                 "The driver may be missing features.\n");
346                 } else {
347                         RTE_LOG(INFO, PMD,
348                                 "Firmware API version is older than driver.\n");
349                         RTE_LOG(INFO, PMD,
350                                 "Not all driver features may be functional.\n");
351                 }
352         }
353
354         if (bp->max_req_len > resp->max_req_win_len) {
355                 RTE_LOG(ERR, PMD, "Unsupported request length\n");
356                 rc = -EINVAL;
357         }
358         bp->max_req_len = resp->max_req_win_len;
359         max_resp_len = resp->max_resp_len;
360         if (bp->max_resp_len != max_resp_len) {
361                 sprintf(type, "bnxt_hwrm_%04x:%02x:%02x:%02x",
362                         bp->pdev->addr.domain, bp->pdev->addr.bus,
363                         bp->pdev->addr.devid, bp->pdev->addr.function);
364
365                 rte_free(bp->hwrm_cmd_resp_addr);
366
367                 bp->hwrm_cmd_resp_addr = rte_malloc(type, max_resp_len, 0);
368                 if (bp->hwrm_cmd_resp_addr == NULL) {
369                         rc = -ENOMEM;
370                         goto error;
371                 }
372                 bp->hwrm_cmd_resp_dma_addr =
373                         rte_malloc_virt2phy(bp->hwrm_cmd_resp_addr);
374                 bp->max_resp_len = max_resp_len;
375         }
376
377 error:
378         rte_spinlock_unlock(&bp->hwrm_lock);
379         return rc;
380 }
381
382 int bnxt_hwrm_func_driver_unregister(struct bnxt *bp, uint32_t flags)
383 {
384         int rc;
385         struct hwrm_func_drv_unrgtr_input req = {.req_type = 0 };
386         struct hwrm_func_drv_unrgtr_output *resp = bp->hwrm_cmd_resp_addr;
387
388         if (!(bp->flags & BNXT_FLAG_REGISTERED))
389                 return 0;
390
391         HWRM_PREP(req, FUNC_DRV_UNRGTR, -1, resp);
392         req.flags = flags;
393
394         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
395
396         HWRM_CHECK_RESULT;
397
398         bp->flags &= ~BNXT_FLAG_REGISTERED;
399
400         return rc;
401 }
402
403 static int bnxt_hwrm_port_phy_cfg(struct bnxt *bp, struct bnxt_link_info *conf)
404 {
405         int rc = 0;
406         struct hwrm_port_phy_cfg_input req = {.req_type = 0};
407         struct hwrm_port_phy_cfg_output *resp = bp->hwrm_cmd_resp_addr;
408
409         HWRM_PREP(req, PORT_PHY_CFG, -1, resp);
410
411         req.flags = conf->phy_flags;
412         if (conf->link_up) {
413                 req.force_link_speed = conf->link_speed;
414                 /*
415                  * Note, ChiMP FW 20.2.1 and 20.2.2 return an error when we set
416                  * any auto mode, even "none".
417                  */
418                 if (req.auto_mode == HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE) {
419                         req.flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE;
420                 } else {
421                         req.auto_mode = conf->auto_mode;
422                         req.enables |=
423                                 HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
424                         req.auto_link_speed_mask = conf->auto_link_speed_mask;
425                         req.enables |=
426                            HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK;
427                         req.auto_link_speed = conf->auto_link_speed;
428                         req.enables |=
429                                 HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED;
430                 }
431                 req.auto_duplex = conf->duplex;
432                 req.enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX;
433                 req.auto_pause = conf->auto_pause;
434                 /* Set force_pause if there is no auto or if there is a force */
435                 if (req.auto_pause)
436                         req.enables |=
437                                 HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE;
438                 else
439                         req.enables |=
440                                 HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE;
441                 req.force_pause = conf->force_pause;
442                 if (req.force_pause)
443                         req.enables |=
444                                 HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE;
445         } else {
446                 req.flags &= ~HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG;
447                 req.flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE_LINK_DOWN;
448                 req.force_link_speed = 0;
449         }
450
451         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
452
453         HWRM_CHECK_RESULT;
454
455         return rc;
456 }
457
458 int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
459 {
460         int rc = 0;
461         struct hwrm_queue_qportcfg_input req = {.req_type = 0 };
462         struct hwrm_queue_qportcfg_output *resp = bp->hwrm_cmd_resp_addr;
463
464         HWRM_PREP(req, QUEUE_QPORTCFG, -1, resp);
465
466         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
467
468         HWRM_CHECK_RESULT;
469
470 #define GET_QUEUE_INFO(x) \
471         bp->cos_queue[x].id = resp->queue_id##x; \
472         bp->cos_queue[x].profile = resp->queue_id##x##_service_profile
473
474         GET_QUEUE_INFO(0);
475         GET_QUEUE_INFO(1);
476         GET_QUEUE_INFO(2);
477         GET_QUEUE_INFO(3);
478         GET_QUEUE_INFO(4);
479         GET_QUEUE_INFO(5);
480         GET_QUEUE_INFO(6);
481         GET_QUEUE_INFO(7);
482
483         return rc;
484 }
485
486 int bnxt_hwrm_stat_clear(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
487 {
488         int rc = 0;
489         struct hwrm_stat_ctx_clr_stats_input req = {.req_type = 0 };
490         struct hwrm_stat_ctx_clr_stats_output *resp = bp->hwrm_cmd_resp_addr;
491
492         HWRM_PREP(req, STAT_CTX_CLR_STATS, -1, resp);
493
494         if (cpr->hw_stats_ctx_id == (uint32_t)HWRM_NA_SIGNATURE)
495                 return rc;
496
497         req.stat_ctx_id = rte_cpu_to_le_16(cpr->hw_stats_ctx_id);
498         req.seq_id = rte_cpu_to_le_16(bp->hwrm_cmd_seq++);
499
500         rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
501
502         HWRM_CHECK_RESULT;
503
504         return rc;
505 }
506
507 /*
508  * HWRM utility functions
509  */
510
511 int bnxt_clear_all_hwrm_stat_ctxs(struct bnxt *bp)
512 {
513         unsigned int i;
514         int rc = 0;
515
516         for (i = 0; i < bp->rx_cp_nr_rings + bp->tx_cp_nr_rings; i++) {
517                 struct bnxt_tx_queue *txq;
518                 struct bnxt_rx_queue *rxq;
519                 struct bnxt_cp_ring_info *cpr;
520
521                 if (i >= bp->rx_cp_nr_rings) {
522                         txq = bp->tx_queues[i - bp->rx_cp_nr_rings];
523                         cpr = txq->cp_ring;
524                 } else {
525                         rxq = bp->rx_queues[i];
526                         cpr = rxq->cp_ring;
527                 }
528
529                 rc = bnxt_hwrm_stat_clear(bp, cpr);
530                 if (rc)
531                         return rc;
532         }
533         return 0;
534 }
535
536 void bnxt_free_hwrm_resources(struct bnxt *bp)
537 {
538         /* Release memzone */
539         rte_free(bp->hwrm_cmd_resp_addr);
540         bp->hwrm_cmd_resp_addr = NULL;
541         bp->hwrm_cmd_resp_dma_addr = 0;
542 }
543
544 int bnxt_alloc_hwrm_resources(struct bnxt *bp)
545 {
546         struct rte_pci_device *pdev = bp->pdev;
547         char type[RTE_MEMZONE_NAMESIZE];
548
549         sprintf(type, "bnxt_hwrm_%04x:%02x:%02x:%02x", pdev->addr.domain,
550                 pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
551         bp->max_req_len = HWRM_MAX_REQ_LEN;
552         bp->max_resp_len = HWRM_MAX_RESP_LEN;
553         bp->hwrm_cmd_resp_addr = rte_malloc(type, bp->max_resp_len, 0);
554         if (bp->hwrm_cmd_resp_addr == NULL)
555                 return -ENOMEM;
556         bp->hwrm_cmd_resp_dma_addr =
557                 rte_malloc_virt2phy(bp->hwrm_cmd_resp_addr);
558         rte_spinlock_init(&bp->hwrm_lock);
559
560         return 0;
561 }
562
563 static uint16_t bnxt_parse_eth_link_duplex(uint32_t conf_link_speed)
564 {
565         uint8_t hw_link_duplex = HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH;
566
567         if ((conf_link_speed & ETH_LINK_SPEED_FIXED) == ETH_LINK_SPEED_AUTONEG)
568                 return HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH;
569
570         switch (conf_link_speed) {
571         case ETH_LINK_SPEED_10M_HD:
572         case ETH_LINK_SPEED_100M_HD:
573                 return HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_HALF;
574         }
575         return hw_link_duplex;
576 }
577
578 static uint16_t bnxt_parse_eth_link_speed(uint32_t conf_link_speed)
579 {
580         uint16_t eth_link_speed = 0;
581
582         if ((conf_link_speed & ETH_LINK_SPEED_FIXED) == ETH_LINK_SPEED_AUTONEG)
583                 return ETH_LINK_SPEED_AUTONEG;
584
585         switch (conf_link_speed & ~ETH_LINK_SPEED_FIXED) {
586         case ETH_LINK_SPEED_100M:
587         case ETH_LINK_SPEED_100M_HD:
588                 eth_link_speed =
589                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10MB;
590                 break;
591         case ETH_LINK_SPEED_1G:
592                 eth_link_speed =
593                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB;
594                 break;
595         case ETH_LINK_SPEED_2_5G:
596                 eth_link_speed =
597                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2_5GB;
598                 break;
599         case ETH_LINK_SPEED_10G:
600                 eth_link_speed =
601                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB;
602                 break;
603         case ETH_LINK_SPEED_20G:
604                 eth_link_speed =
605                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_20GB;
606                 break;
607         case ETH_LINK_SPEED_25G:
608                 eth_link_speed =
609                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_25GB;
610                 break;
611         case ETH_LINK_SPEED_40G:
612                 eth_link_speed =
613                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_40GB;
614                 break;
615         case ETH_LINK_SPEED_50G:
616                 eth_link_speed =
617                         HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_50GB;
618                 break;
619         default:
620                 RTE_LOG(ERR, PMD,
621                         "Unsupported link speed %d; default to AUTO\n",
622                         conf_link_speed);
623                 break;
624         }
625         return eth_link_speed;
626 }
627
628 #define BNXT_SUPPORTED_SPEEDS (ETH_LINK_SPEED_100M | ETH_LINK_SPEED_100M_HD | \
629                 ETH_LINK_SPEED_1G | ETH_LINK_SPEED_2_5G | \
630                 ETH_LINK_SPEED_10G | ETH_LINK_SPEED_20G | ETH_LINK_SPEED_25G | \
631                 ETH_LINK_SPEED_40G | ETH_LINK_SPEED_50G)
632
633 static int bnxt_valid_link_speed(uint32_t link_speed, uint8_t port_id)
634 {
635         uint32_t one_speed;
636
637         if (link_speed == ETH_LINK_SPEED_AUTONEG)
638                 return 0;
639
640         if (link_speed & ETH_LINK_SPEED_FIXED) {
641                 one_speed = link_speed & ~ETH_LINK_SPEED_FIXED;
642
643                 if (one_speed & (one_speed - 1)) {
644                         RTE_LOG(ERR, PMD,
645                                 "Invalid advertised speeds (%u) for port %u\n",
646                                 link_speed, port_id);
647                         return -EINVAL;
648                 }
649                 if ((one_speed & BNXT_SUPPORTED_SPEEDS) != one_speed) {
650                         RTE_LOG(ERR, PMD,
651                                 "Unsupported advertised speed (%u) for port %u\n",
652                                 link_speed, port_id);
653                         return -EINVAL;
654                 }
655         } else {
656                 if (!(link_speed & BNXT_SUPPORTED_SPEEDS)) {
657                         RTE_LOG(ERR, PMD,
658                                 "Unsupported advertised speeds (%u) for port %u\n",
659                                 link_speed, port_id);
660                         return -EINVAL;
661                 }
662         }
663         return 0;
664 }
665
666 static uint16_t bnxt_parse_eth_link_speed_mask(uint32_t link_speed)
667 {
668         uint16_t ret = 0;
669
670         if (link_speed == ETH_LINK_SPEED_AUTONEG)
671                 link_speed = BNXT_SUPPORTED_SPEEDS;
672
673         if (link_speed & ETH_LINK_SPEED_100M)
674                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MB;
675         if (link_speed & ETH_LINK_SPEED_100M_HD)
676                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MB;
677         if (link_speed & ETH_LINK_SPEED_1G)
678                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB;
679         if (link_speed & ETH_LINK_SPEED_2_5G)
680                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2_5GB;
681         if (link_speed & ETH_LINK_SPEED_10G)
682                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB;
683         if (link_speed & ETH_LINK_SPEED_20G)
684                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_20GB;
685         if (link_speed & ETH_LINK_SPEED_25G)
686                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_25GB;
687         if (link_speed & ETH_LINK_SPEED_40G)
688                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_40GB;
689         if (link_speed & ETH_LINK_SPEED_50G)
690                 ret |= HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_50GB;
691         return ret;
692 }
693
694 int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
695 {
696         int rc = 0;
697         struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
698         struct bnxt_link_info link_req;
699         uint16_t speed;
700
701         rc = bnxt_valid_link_speed(dev_conf->link_speeds,
702                         bp->eth_dev->data->port_id);
703         if (rc)
704                 goto error;
705
706         memset(&link_req, 0, sizeof(link_req));
707         speed = bnxt_parse_eth_link_speed(dev_conf->link_speeds);
708         link_req.link_up = link_up;
709         if (speed == 0) {
710                 link_req.phy_flags =
711                                 HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG;
712                 link_req.auto_mode =
713                                 HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_OR_BELOW;
714                 link_req.auto_link_speed_mask =
715                         bnxt_parse_eth_link_speed_mask(dev_conf->link_speeds);
716                 link_req.auto_link_speed =
717                                 HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_50GB;
718         } else {
719                 link_req.auto_mode = HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE;
720                 link_req.phy_flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE |
721                         HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY;
722                 link_req.link_speed = speed;
723         }
724         link_req.duplex = bnxt_parse_eth_link_duplex(dev_conf->link_speeds);
725         link_req.auto_pause = bp->link_info.auto_pause;
726         link_req.force_pause = bp->link_info.force_pause;
727
728         rc = bnxt_hwrm_port_phy_cfg(bp, &link_req);
729         if (rc) {
730                 RTE_LOG(ERR, PMD,
731                         "Set link config failed with rc %d\n", rc);
732         }
733
734 error:
735         return rc;
736 }