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