net/ice/base: add helper function to redirect flags
[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 void
8 cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set)
9 {
10         if (set)
11                 dev->flags |= CNXK_LINK_CFG_IN_PROGRESS_F;
12         else
13                 dev->flags &= ~CNXK_LINK_CFG_IN_PROGRESS_F;
14
15         rte_wmb();
16 }
17
18 static inline int
19 nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
20 {
21         uint16_t wait = 1000;
22
23         do {
24                 rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
25                 if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
26                         break;
27                 wait--;
28                 rte_delay_ms(1);
29         } while (wait);
30
31         return wait ? 0 : -1;
32 }
33
34 static void
35 nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
36 {
37         if (link && link->link_status)
38                 plt_info("Port %d: Link Up - speed %u Mbps - %s",
39                          (int)(eth_dev->data->port_id),
40                          (uint32_t)link->link_speed,
41                          link->link_duplex == ETH_LINK_FULL_DUPLEX
42                                  ? "full-duplex"
43                                  : "half-duplex");
44         else
45                 plt_info("Port %d: Link Down", (int)(eth_dev->data->port_id));
46 }
47
48 void
49 cnxk_eth_dev_link_status_get_cb(struct roc_nix *nix,
50                                 struct roc_nix_link_info *link)
51 {
52         struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
53         struct rte_eth_link eth_link;
54         struct rte_eth_dev *eth_dev;
55
56         if (!link || !nix)
57                 return;
58
59         eth_dev = dev->eth_dev;
60         if (!eth_dev)
61                 return;
62
63         rte_eth_linkstatus_get(eth_dev, &eth_link);
64
65         link->status = eth_link.link_status;
66         link->speed = eth_link.link_speed;
67         link->autoneg = eth_link.link_autoneg;
68         link->full_duplex = eth_link.link_duplex;
69 }
70
71 void
72 cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
73 {
74         struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
75         struct rte_eth_link eth_link;
76         struct rte_eth_dev *eth_dev;
77
78         if (!link || !nix)
79                 return;
80
81         eth_dev = dev->eth_dev;
82         if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
83                 return;
84
85         if (nix_wait_for_link_cfg(dev)) {
86                 plt_err("Timeout waiting for link_cfg to complete");
87                 return;
88         }
89
90         eth_link.link_status = link->status;
91         eth_link.link_speed = link->speed;
92         eth_link.link_autoneg = ETH_LINK_AUTONEG;
93         eth_link.link_duplex = link->full_duplex;
94
95         /* Print link info */
96         nix_link_status_print(eth_dev, &eth_link);
97
98         /* Update link info */
99         rte_eth_linkstatus_set(eth_dev, &eth_link);
100
101         /* Set the flag and execute application callbacks */
102         rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
103 }
104
105 int
106 cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
107 {
108         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
109         struct roc_nix_link_info info;
110         struct rte_eth_link link;
111         int rc;
112
113         RTE_SET_USED(wait_to_complete);
114         memset(&link, 0, sizeof(struct rte_eth_link));
115
116         if (!eth_dev->data->dev_started || roc_nix_is_sdp(&dev->nix))
117                 return 0;
118
119         if (roc_nix_is_lbk(&dev->nix)) {
120                 link.link_status = ETH_LINK_UP;
121                 link.link_speed = ETH_SPEED_NUM_100G;
122                 link.link_autoneg = ETH_LINK_FIXED;
123                 link.link_duplex = ETH_LINK_FULL_DUPLEX;
124         } else {
125                 rc = roc_nix_mac_link_info_get(&dev->nix, &info);
126                 if (rc)
127                         return rc;
128                 link.link_status = info.status;
129                 link.link_speed = info.speed;
130                 link.link_autoneg = ETH_LINK_AUTONEG;
131                 if (info.full_duplex)
132                         link.link_duplex = info.full_duplex;
133         }
134
135         return rte_eth_linkstatus_set(eth_dev, &link);
136 }