net/cnxk: support link status update
[dpdk.git] / drivers / net / cnxk / cnxk_link.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "cnxk_ethdev.h"
6
7 static inline int
8 nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
9 {
10         uint16_t wait = 1000;
11
12         do {
13                 rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
14                 if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
15                         break;
16                 wait--;
17                 rte_delay_ms(1);
18         } while (wait);
19
20         return wait ? 0 : -1;
21 }
22
23 static void
24 nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
25 {
26         if (link && link->link_status)
27                 plt_info("Port %d: Link Up - speed %u Mbps - %s",
28                          (int)(eth_dev->data->port_id),
29                          (uint32_t)link->link_speed,
30                          link->link_duplex == ETH_LINK_FULL_DUPLEX
31                                  ? "full-duplex"
32                                  : "half-duplex");
33         else
34                 plt_info("Port %d: Link Down", (int)(eth_dev->data->port_id));
35 }
36
37 void
38 cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
39 {
40         struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
41         struct rte_eth_link eth_link;
42         struct rte_eth_dev *eth_dev;
43
44         if (!link || !nix)
45                 return;
46
47         eth_dev = dev->eth_dev;
48         if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
49                 return;
50
51         if (nix_wait_for_link_cfg(dev)) {
52                 plt_err("Timeout waiting for link_cfg to complete");
53                 return;
54         }
55
56         eth_link.link_status = link->status;
57         eth_link.link_speed = link->speed;
58         eth_link.link_autoneg = ETH_LINK_AUTONEG;
59         eth_link.link_duplex = link->full_duplex;
60
61         /* Print link info */
62         nix_link_status_print(eth_dev, &eth_link);
63
64         /* Update link info */
65         rte_eth_linkstatus_set(eth_dev, &eth_link);
66
67         /* Set the flag and execute application callbacks */
68         rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
69 }
70
71 int
72 cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
73 {
74         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
75         struct roc_nix_link_info info;
76         struct rte_eth_link link;
77         int rc;
78
79         RTE_SET_USED(wait_to_complete);
80         memset(&link, 0, sizeof(struct rte_eth_link));
81
82         if (roc_nix_is_sdp(&dev->nix))
83                 return 0;
84
85         if (roc_nix_is_lbk(&dev->nix)) {
86                 link.link_status = ETH_LINK_UP;
87                 link.link_speed = ETH_SPEED_NUM_100G;
88                 link.link_autoneg = ETH_LINK_FIXED;
89                 link.link_duplex = ETH_LINK_FULL_DUPLEX;
90         } else {
91                 rc = roc_nix_mac_link_info_get(&dev->nix, &info);
92                 if (rc)
93                         return rc;
94                 link.link_status = info.status;
95                 link.link_speed = info.speed;
96                 link.link_autoneg = ETH_LINK_AUTONEG;
97                 if (info.full_duplex)
98                         link.link_duplex = info.full_duplex;
99         }
100
101         return rte_eth_linkstatus_set(eth_dev, &link);
102 }