Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include "cnxk_ethdev.h"
6 : :
7 : : const enum roc_nix_link_mode mac_to_ethtool_mode[CGX_LMAC_TYPE_MAX][2] = {
8 : : [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD,
9 : : [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_1000BASET_FD,
10 : : [CGX_LMAC_TYPE_10G_R][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASESR_FD,
11 : : [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD,
12 : : [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASET_FD,
13 : : };
14 : :
15 : : const enum roc_nix_link_mode rte_to_ethtool_mode[ROC_NIX_LINK_SPEED_MAX] = {
16 : : 0,
17 : : ROC_NIX_LINK_MODE_10BASET_HD,
18 : : ROC_NIX_LINK_MODE_10BASET_FD,
19 : : ROC_NIX_LINK_MODE_100BASET_HD,
20 : : ROC_NIX_LINK_MODE_100BASET_FD,
21 : : ROC_NIX_LINK_MODE_1000BASET_FD,
22 : : ROC_NIX_LINK_MODE_2500BASEX_FD,
23 : : 0,
24 : : ROC_NIX_LINK_MODE_10000BASESR_FD,
25 : : 0,
26 : : ROC_NIX_LINK_MODE_25000BASESR_FD,
27 : : ROC_NIX_LINK_MODE_40000BASELR4_FD,
28 : : ROC_NIX_LINK_MODE_50000BASELR_ER_FR_FD,
29 : : 0,
30 : : ROC_NIX_LINK_MODE_100000BASELR4_ER4_FD,
31 : : 0,
32 : : 0,
33 : : };
34 : :
35 : : static uint64_t
36 : 0 : nix_link_advertising_get(struct cnxk_eth_dev *dev, struct roc_nix_link_info *link_info)
37 : : {
38 : : struct roc_nix_mac_fwdata fwdata;
39 : : struct roc_nix_link_info linfo;
40 : : uint64_t advertise = 0;
41 : : int bit, rc;
42 : :
43 : : memset(&fwdata, 0, sizeof(fwdata));
44 : 0 : rc = roc_nix_mac_fwdata_get(&dev->nix, &fwdata);
45 [ # # ]: 0 : if (rc) {
46 : 0 : plt_err("Failed to get MAC firmware data");
47 : 0 : goto exit;
48 : : }
49 : :
50 : : memset(&linfo, 0, sizeof(linfo));
51 : 0 : rc = roc_nix_mac_link_info_get(&dev->nix, &linfo);
52 [ # # ]: 0 : if (rc) {
53 : 0 : plt_err("Failed to get MAC link info");
54 : 0 : goto exit;
55 : : }
56 : :
57 [ # # ]: 0 : if (link_info->autoneg) {
58 [ # # ]: 0 : if (!fwdata.supported_an) {
59 : 0 : plt_err("Autoneg is not supported");
60 : 0 : goto exit;
61 : : } else {
62 [ # # ]: 0 : for (bit = 0; bit < ROC_NIX_LINK_SPEED_MAX; bit++) {
63 [ # # ]: 0 : if (link_info->speed_bitmask & BIT_ULL(bit))
64 : 0 : advertise |= rte_to_ethtool_mode[bit];
65 : : }
66 : 0 : goto exit;
67 : : }
68 : : }
69 : :
70 : 0 : advertise |= mac_to_ethtool_mode[linfo.lmac_type_id][link_info->full_duplex];
71 : 0 : exit:
72 : 0 : return advertise;
73 : : }
74 : :
75 : : void
76 : 0 : cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set)
77 : : {
78 [ # # ]: 0 : if (set)
79 : 0 : dev->flags |= CNXK_LINK_CFG_IN_PROGRESS_F;
80 : : else
81 : 0 : dev->flags &= ~CNXK_LINK_CFG_IN_PROGRESS_F;
82 : :
83 : : /* Update link info for LBK */
84 [ # # # # ]: 0 : if (!set &&
85 [ # # # # ]: 0 : (roc_nix_is_lbk(&dev->nix) || roc_nix_is_sdp(&dev->nix) || roc_nix_is_esw(&dev->nix))) {
86 : : struct rte_eth_link link;
87 : :
88 : 0 : link.link_status = RTE_ETH_LINK_UP;
89 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_100G;
90 : 0 : link.link_autoneg = RTE_ETH_LINK_FIXED;
91 : 0 : link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
92 : 0 : rte_eth_linkstatus_set(dev->eth_dev, &link);
93 : : }
94 : :
95 : : rte_wmb();
96 : 0 : }
97 : :
98 : : static inline int
99 : 0 : nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
100 : : {
101 : : uint16_t wait = 1000;
102 : :
103 : : do {
104 : : rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
105 [ # # ]: 0 : if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
106 : : break;
107 : 0 : wait--;
108 : : rte_delay_ms(1);
109 [ # # ]: 0 : } while (wait);
110 : :
111 [ # # ]: 0 : return wait ? 0 : -1;
112 : : }
113 : :
114 : : static void
115 : 0 : nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
116 : : {
117 [ # # # # ]: 0 : if (link && link->link_status)
118 [ # # ]: 0 : plt_info("Port %d: Link Up - speed %u Mbps - %s - %s",
119 : : (int)(eth_dev->data->port_id),
120 : : (uint32_t)link->link_speed,
121 : : link->link_duplex == RTE_ETH_LINK_FULL_DUPLEX
122 : : ? "full-duplex"
123 : : : "half-duplex",
124 : : rte_eth_link_connector_to_str(link->link_connector));
125 : : else
126 : 0 : plt_info("Port %d: Link Down - %s", (int)(eth_dev->data->port_id),
127 : : rte_eth_link_connector_to_str(link->link_connector));
128 : 0 : }
129 : :
130 : : void
131 : 0 : cnxk_eth_dev_link_status_get_cb(struct roc_nix *nix,
132 : : struct roc_nix_link_info *link)
133 : : {
134 : : struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
135 : : struct rte_eth_link eth_link;
136 : : struct rte_eth_dev *eth_dev;
137 : :
138 [ # # ]: 0 : if (!link || !nix)
139 : 0 : return;
140 : :
141 : 0 : eth_dev = dev->eth_dev;
142 [ # # ]: 0 : if (!eth_dev)
143 : : return;
144 : :
145 : 0 : rte_eth_linkstatus_get(eth_dev, ð_link);
146 : :
147 : 0 : link->status = eth_link.link_status;
148 : 0 : link->speed = eth_link.link_speed;
149 : 0 : link->autoneg = eth_link.link_autoneg;
150 : 0 : link->full_duplex = eth_link.link_duplex;
151 : : }
152 : :
153 : : void
154 : 0 : cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
155 : : {
156 : : struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
157 : : struct rte_eth_link eth_link;
158 : : struct rte_eth_dev *eth_dev;
159 : :
160 [ # # ]: 0 : if (!link || !nix)
161 : 0 : return;
162 : :
163 : 0 : eth_dev = dev->eth_dev;
164 [ # # # # ]: 0 : if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
165 : : return;
166 : :
167 [ # # ]: 0 : if (nix_wait_for_link_cfg(dev)) {
168 : 0 : plt_err("Timeout waiting for link_cfg to complete");
169 : 0 : return;
170 : : }
171 : :
172 : 0 : eth_link.link_status = link->status;
173 : 0 : eth_link.link_speed = link->speed;
174 : 0 : eth_link.link_autoneg = link->autoneg ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
175 : 0 : eth_link.link_duplex = link->full_duplex;
176 : 0 : eth_link.link_connector = dev->link_type;
177 : :
178 : : /* Print link info */
179 : 0 : nix_link_status_print(eth_dev, ð_link);
180 : :
181 : : /* Update link info */
182 : 0 : rte_eth_linkstatus_set(eth_dev, ð_link);
183 : :
184 : : /* Set the flag and execute application callbacks */
185 : 0 : rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
186 : : }
187 : :
188 : : int
189 [ # # ]: 0 : cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
190 : : {
191 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
192 : : struct roc_nix_link_info info;
193 : : struct rte_eth_link link;
194 : : int rc;
195 : :
196 : : RTE_SET_USED(wait_to_complete);
197 : : memset(&link, 0, sizeof(struct rte_eth_link));
198 : :
199 [ # # ]: 0 : if (!eth_dev->data->dev_started)
200 : : return 0;
201 : :
202 [ # # # # ]: 0 : if (roc_nix_is_lbk(&dev->nix) || roc_nix_is_sdp(&dev->nix)) {
203 : 0 : link.link_status = RTE_ETH_LINK_UP;
204 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_100G;
205 : : link.link_autoneg = RTE_ETH_LINK_FIXED;
206 : 0 : link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
207 : : } else {
208 : 0 : rc = roc_nix_mac_link_info_get(&dev->nix, &info);
209 [ # # ]: 0 : if (rc)
210 : : return rc;
211 : 0 : link.link_status = info.status;
212 : 0 : link.link_speed = info.speed;
213 : 0 : link.link_autoneg = info.autoneg ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
214 [ # # ]: 0 : if (info.full_duplex)
215 : 0 : link.link_duplex = info.full_duplex;
216 : 0 : link.link_connector = dev->link_type;
217 : : }
218 : :
219 : : return rte_eth_linkstatus_set(eth_dev, &link);
220 : : }
221 : :
222 : : int
223 : 0 : cnxk_nix_link_info_configure(struct rte_eth_dev *eth_dev)
224 : : {
225 : 0 : uint32_t speed_map[] = {
226 : : RTE_ETH_SPEED_NUM_NONE, RTE_ETH_SPEED_NUM_10M, RTE_ETH_SPEED_NUM_10M,
227 : : RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G,
228 : : RTE_ETH_SPEED_NUM_2_5G, RTE_ETH_SPEED_NUM_5G, RTE_ETH_SPEED_NUM_10G,
229 : : RTE_ETH_SPEED_NUM_20G, RTE_ETH_SPEED_NUM_25G, RTE_ETH_SPEED_NUM_40G,
230 : : RTE_ETH_SPEED_NUM_50G, RTE_ETH_SPEED_NUM_56G, RTE_ETH_SPEED_NUM_100G,
231 : : RTE_ETH_SPEED_NUM_200G, RTE_ETH_SPEED_NUM_400G
232 : : };
233 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
234 : : struct rte_eth_dev_data *data = eth_dev->data;
235 : : struct rte_eth_conf *conf = &data->dev_conf;
236 : 0 : uint32_t link_speeds = conf->link_speeds;
237 : 0 : struct roc_nix_link_info link_info = {0};
238 : 0 : struct roc_nix *nix = &dev->nix;
239 : : uint32_t speed = link_speeds;
240 : : bool fixed;
241 : :
242 : 0 : plt_info("User passed link configuration: %x", link_speeds);
243 : :
244 [ # # # # ]: 0 : if (!roc_nix_is_pf(nix) || link_speeds == RTE_ETH_LINK_SPEED_AUTONEG)
245 : : return 0;
246 : :
247 : 0 : fixed = link_speeds & RTE_ETH_LINK_SPEED_FIXED ? true : false;
248 [ # # ]: 0 : if (fixed) {
249 [ # # ]: 0 : if (rte_popcount32(link_speeds) == 1) {
250 : 0 : plt_err("Desired speed is not specified in FIXED mode");
251 : 0 : return -EINVAL;
252 : : }
253 : :
254 [ # # ]: 0 : if (rte_popcount32(link_speeds) > 2) {
255 : 0 : plt_err("Multiple speeds can't be configured in FIXED mode");
256 : 0 : return -EINVAL;
257 : : }
258 : :
259 : 0 : link_info.autoneg = 0;
260 : : } else {
261 : 0 : link_info.autoneg = 1;
262 : : }
263 : :
264 : 0 : speed >>= 1;
265 : 0 : link_info.speed = speed_map[rte_bsf32(speed) + 1];
266 : 0 : link_info.speed_bitmask = link_speeds & ~RTE_ETH_LINK_SPEED_FIXED;
267 : 0 : link_info.full_duplex = ((link_speeds & RTE_ETH_LINK_SPEED_10M_HD) ||
268 : : (link_speeds & RTE_ETH_LINK_SPEED_100M_HD)) ?
269 : 0 : ROC_NIX_LINK_DUPLEX_HALF :
270 : : ROC_NIX_LINK_DUPLEX_FULL;
271 : 0 : link_info.advertising = nix_link_advertising_get(dev, &link_info);
272 [ # # ]: 0 : if (link_info.advertising == 0) {
273 : 0 : plt_err("advertising bitmap is not set");
274 : 0 : return -EINVAL;
275 : : }
276 : :
277 : 0 : plt_info("Following link settings are sent to firmware:");
278 : 0 : plt_info("Advertised modes: %" PRIX64, link_info.advertising);
279 : 0 : plt_info("speed: %u", link_info.speed);
280 [ # # ]: 0 : plt_info("duplex: %s", link_info.full_duplex == ROC_NIX_LINK_DUPLEX_HALF ?
281 : : "half-duplex" : "full-duplex");
282 [ # # ]: 0 : plt_info("autoneg: %s", link_info.autoneg ? "enabled" : "disabled");
283 : 0 : return roc_nix_mac_link_info_set(nix, &link_info);
284 : : }
|