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