Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright(c) 2019-2021 Xilinx, Inc.
4 : : * Copyright(c) 2016-2019 Solarflare Communications Inc.
5 : : *
6 : : * This software was jointly developed between OKTET Labs (under contract
7 : : * for Solarflare) and Solarflare Communications, Inc.
8 : : */
9 : :
10 : : #include <rte_bitmap.h>
11 : : #include <rte_ether.h>
12 : :
13 : : #include "efx.h"
14 : :
15 : : #include "sfc.h"
16 : : #include "sfc_debug.h"
17 : : #include "sfc_log.h"
18 : : #include "sfc_kvargs.h"
19 : :
20 : : /** Default MAC statistics update period is 1 second */
21 : : #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF MS_PER_S
22 : :
23 : : /** The number of microseconds to sleep on attempt to get statistics update */
24 : : #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US 10
25 : :
26 : : /** The number of attempts to await arrival of freshly generated statistics */
27 : : #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS 50
28 : :
29 : : /**
30 : : * Update MAC statistics in the buffer.
31 : : *
32 : : * @param sa Adapter
33 : : * @param force_upload Flag to upload MAC stats in any case
34 : : *
35 : : * @return Status code
36 : : * @retval 0 Success
37 : : * @retval EAGAIN Try again
38 : : * @retval ENOMEM Memory allocation failure
39 : : */
40 : : int
41 : 0 : sfc_port_update_mac_stats(struct sfc_adapter *sa, boolean_t force_upload)
42 : : {
43 : : struct sfc_port *port = &sa->port;
44 : 0 : efsys_mem_t *esmp = &port->mac_stats_dma_mem;
45 : : uint32_t *genp = NULL;
46 : : uint32_t gen_old;
47 : : unsigned int nb_attempts = 0;
48 : : int rc;
49 : :
50 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
51 : :
52 [ # # ]: 0 : if (sa->state != SFC_ETHDEV_STARTED)
53 : : return 0;
54 : :
55 : : /*
56 : : * If periodic statistics DMA'ing is off or if not supported,
57 : : * make a manual request and keep an eye on timer if need be
58 : : */
59 [ # # ]: 0 : if (!port->mac_stats_periodic_dma_supported ||
60 [ # # # # ]: 0 : (port->mac_stats_update_period_ms == 0) || force_upload) {
61 [ # # ]: 0 : if (port->mac_stats_update_period_ms != 0) {
62 : : uint64_t timestamp = sfc_get_system_msecs();
63 : :
64 : 0 : if ((timestamp -
65 : 0 : port->mac_stats_last_request_timestamp) <
66 [ # # ]: 0 : port->mac_stats_update_period_ms)
67 : : return 0;
68 : :
69 : 0 : port->mac_stats_last_request_timestamp = timestamp;
70 : : }
71 : :
72 : 0 : rc = efx_mac_stats_upload(sa->nic, esmp);
73 [ # # ]: 0 : if (rc != 0)
74 : : return rc;
75 : :
76 : 0 : genp = &port->mac_stats_update_generation;
77 : 0 : gen_old = *genp;
78 : : }
79 : :
80 : : do {
81 [ # # ]: 0 : if (nb_attempts > 0)
82 : 0 : rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US);
83 : :
84 : 0 : rc = efx_mac_stats_update(sa->nic, esmp,
85 : 0 : port->mac_stats_buf, genp);
86 [ # # ]: 0 : if (rc != 0)
87 : 0 : return rc;
88 : :
89 [ # # # # : 0 : } while ((genp != NULL) && (*genp == gen_old) &&
# # ]
90 : : (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS));
91 : :
92 : : return 0;
93 : : }
94 : :
95 : : static void
96 : : sfc_port_reset_sw_stats(struct sfc_adapter *sa)
97 : : {
98 : : struct sfc_port *port = &sa->port;
99 : :
100 : : /*
101 : : * Reset diff stats explicitly since check which does not allow
102 : : * the statistics to grow backward could deny it.
103 : : */
104 : 0 : port->ipackets = 0;
105 : 0 : }
106 : :
107 : : int
108 : 0 : sfc_port_reset_mac_stats(struct sfc_adapter *sa)
109 : : {
110 : : int rc;
111 : :
112 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
113 : :
114 : 0 : rc = efx_mac_stats_clear(sa->nic);
115 [ # # ]: 0 : if (rc == 0)
116 : : sfc_port_reset_sw_stats(sa);
117 : :
118 : 0 : return rc;
119 : : }
120 : :
121 : : static int
122 : 0 : sfc_port_init_dev_link(struct sfc_adapter *sa)
123 : : {
124 : 0 : struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
125 : : int rc;
126 : : efx_link_mode_t link_mode;
127 : : struct rte_eth_link current_link;
128 : :
129 : 0 : rc = efx_port_poll(sa->nic, &link_mode);
130 [ # # ]: 0 : if (rc != 0)
131 : : return rc;
132 : :
133 : 0 : sfc_port_link_mode_to_info(link_mode, ¤t_link);
134 : :
135 : : EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
136 : 0 : rte_atomic64_set((rte_atomic64_t *)dev_link,
137 : 0 : *(uint64_t *)¤t_link);
138 : :
139 : 0 : return 0;
140 : : }
141 : :
142 : : #if EFSYS_OPT_LOOPBACK
143 : :
144 : : static efx_link_mode_t
145 : 0 : sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps)
146 : : {
147 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_200000FDX))
148 : : return EFX_LINK_200000FDX;
149 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_100000FDX))
150 : : return EFX_LINK_100000FDX;
151 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_50000FDX))
152 : : return EFX_LINK_50000FDX;
153 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_40000FDX))
154 : : return EFX_LINK_40000FDX;
155 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_25000FDX))
156 : : return EFX_LINK_25000FDX;
157 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_10000FDX))
158 : : return EFX_LINK_10000FDX;
159 [ # # ]: 0 : if (phy_caps & (1u << EFX_PHY_CAP_1000FDX))
160 : 0 : return EFX_LINK_1000FDX;
161 : : return EFX_LINK_UNKNOWN;
162 : : }
163 : :
164 : : #endif
165 : :
166 : : static void
167 : 0 : sfc_port_fill_mac_stats_info(struct sfc_adapter *sa)
168 : : {
169 : : unsigned int mac_stats_nb_supported = 0;
170 : : struct sfc_port *port = &sa->port;
171 : : unsigned int stat_idx;
172 : :
173 : 0 : efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask,
174 : : sizeof(port->mac_stats_mask));
175 : :
176 [ # # ]: 0 : for (stat_idx = 0; stat_idx < EFX_MAC_NSTATS; ++stat_idx) {
177 [ # # ]: 0 : if (!EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, stat_idx))
178 : 0 : continue;
179 : :
180 : 0 : port->mac_stats_by_id[mac_stats_nb_supported] = stat_idx;
181 : 0 : mac_stats_nb_supported++;
182 : : }
183 : :
184 : 0 : port->mac_stats_nb_supported = mac_stats_nb_supported;
185 : 0 : }
186 : :
187 : : int
188 : 0 : sfc_port_start(struct sfc_adapter *sa)
189 : : {
190 : 0 : efx_phy_link_state_t link_state = {0};
191 : : struct sfc_port *port = &sa->port;
192 : : int rc;
193 : : uint32_t phy_adv_cap;
194 : : const uint32_t phy_pause_caps =
195 : : ((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM));
196 : :
197 : 0 : sfc_log_init(sa, "entry");
198 : :
199 : 0 : sfc_log_init(sa, "init filters");
200 : 0 : rc = efx_filter_init(sa->nic);
201 [ # # ]: 0 : if (rc != 0)
202 : 0 : goto fail_filter_init;
203 : :
204 : 0 : sfc_log_init(sa, "init port");
205 : 0 : rc = efx_port_init(sa->nic);
206 [ # # ]: 0 : if (rc != 0)
207 : 0 : goto fail_port_init;
208 : :
209 : : #if EFSYS_OPT_LOOPBACK
210 [ # # ]: 0 : if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) {
211 : : efx_link_mode_t link_mode;
212 : :
213 : : link_mode =
214 : 0 : sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap);
215 : 0 : sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode,
216 : : sa->eth_dev->data->dev_conf.lpbk_mode);
217 : 0 : rc = efx_port_loopback_set(sa->nic, link_mode,
218 : 0 : sa->eth_dev->data->dev_conf.lpbk_mode);
219 [ # # ]: 0 : if (rc != 0)
220 : 0 : goto fail_loopback_set;
221 : : }
222 : : #endif
223 : :
224 : 0 : sfc_log_init(sa, "set flow control to %#x autoneg=%u",
225 : : port->flow_ctrl, port->flow_ctrl_autoneg);
226 : 0 : rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl,
227 : 0 : port->flow_ctrl_autoneg);
228 [ # # ]: 0 : if (rc != 0)
229 : 0 : goto fail_mac_fcntl_set;
230 : :
231 : 0 : sfc_log_init(sa, "set vlan strip to %u", port->vlan_strip);
232 : 0 : rc = efx_port_vlan_strip_set(sa->nic, port->vlan_strip);
233 [ # # ]: 0 : if (rc != 0)
234 : 0 : goto fail_mac_vlan_strip_set;
235 : :
236 : : /* Preserve pause capabilities set by above efx_mac_fcntl_set() */
237 : 0 : efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap);
238 : : SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0);
239 : 0 : phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps) |
240 : 0 : port->fec_cfg;
241 : :
242 : 0 : sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap);
243 : 0 : rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap);
244 [ # # ]: 0 : if (rc != 0)
245 : 0 : goto fail_phy_adv_cap_set;
246 : :
247 [ # # ]: 0 : sfc_log_init(sa, "set phy lane count -- %s",
248 : : (port->phy_lane_count_req == EFX_PHY_LANE_COUNT_DEFAULT) ?
249 : : "let EFX pick default value" : "use custom value");
250 : 0 : rc = efx_phy_lane_count_set(sa->nic, port->phy_lane_count_req);
251 [ # # ]: 0 : if (rc != 0)
252 : 0 : goto fail_phy_lane_count_set;
253 : :
254 : 0 : sfc_log_init(sa, "get phy lane count");
255 : 0 : rc = efx_phy_link_state_get(sa->nic, &link_state);
256 [ # # ]: 0 : if (rc != 0)
257 : 0 : goto fail_phy_lane_count_get;
258 : :
259 : 0 : port->phy_lane_count_active = link_state.epls_lane_count;
260 : :
261 : 0 : sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
262 : 0 : rc = efx_mac_pdu_set(sa->nic, port->pdu);
263 [ # # ]: 0 : if (rc != 0)
264 : 0 : goto fail_mac_pdu_set;
265 : :
266 : 0 : sfc_log_init(sa, "set include FCS=%u", port->include_fcs);
267 : 0 : rc = efx_mac_include_fcs_set(sa->nic, port->include_fcs);
268 [ # # ]: 0 : if (rc != 0)
269 : 0 : goto fail_include_fcs_set;
270 : :
271 [ # # ]: 0 : if (!sfc_sa2shared(sa)->isolated) {
272 : : struct rte_ether_addr *addr = &port->default_mac_addr;
273 : :
274 : 0 : sfc_log_init(sa, "set MAC address");
275 : 0 : rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
276 [ # # ]: 0 : if (rc != 0)
277 : 0 : goto fail_mac_addr_set;
278 : :
279 : 0 : sfc_log_init(sa, "set MAC filters");
280 : 0 : port->promisc = (sa->eth_dev->data->promiscuous != 0) ?
281 : 0 : B_TRUE : B_FALSE;
282 : 0 : port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
283 : 0 : B_TRUE : B_FALSE;
284 : 0 : rc = sfc_set_rx_mode_unchecked(sa);
285 [ # # ]: 0 : if (rc != 0)
286 : 0 : goto fail_mac_filter_set;
287 : :
288 : 0 : sfc_log_init(sa, "set multicast address list");
289 : 0 : rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
290 : 0 : port->nb_mcast_addrs);
291 [ # # ]: 0 : if (rc != 0)
292 : 0 : goto fail_mcast_address_list_set;
293 : : }
294 : :
295 [ # # ]: 0 : if (port->mac_stats_reset_pending) {
296 : 0 : rc = sfc_port_reset_mac_stats(sa);
297 [ # # ]: 0 : if (rc != 0)
298 : 0 : sfc_err(sa, "statistics reset failed (requested "
299 : : "before the port was started)");
300 : :
301 : 0 : port->mac_stats_reset_pending = B_FALSE;
302 : : }
303 : :
304 : 0 : sfc_port_fill_mac_stats_info(sa);
305 : :
306 : 0 : port->mac_stats_update_generation = 0;
307 : :
308 [ # # ]: 0 : if (port->mac_stats_update_period_ms != 0) {
309 : : /*
310 : : * Update MAC stats using periodic DMA;
311 : : * any positive update interval different from
312 : : * 1000 ms can be set only on SFN8xxx provided
313 : : * that FW version is 6.2.1.1033 or higher
314 : : */
315 : 0 : sfc_log_init(sa, "request MAC stats DMA'ing");
316 : 0 : rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
317 : 0 : port->mac_stats_update_period_ms,
318 : : B_FALSE);
319 [ # # ]: 0 : if (rc == 0) {
320 : 0 : port->mac_stats_periodic_dma_supported = B_TRUE;
321 [ # # ]: 0 : } else if (rc == EOPNOTSUPP) {
322 : 0 : port->mac_stats_periodic_dma_supported = B_FALSE;
323 : 0 : port->mac_stats_last_request_timestamp = 0;
324 : : } else {
325 : 0 : goto fail_mac_stats_periodic;
326 : : }
327 : : }
328 : :
329 [ # # ]: 0 : if ((port->mac_stats_update_period_ms != 0) &&
330 [ # # ]: 0 : port->mac_stats_periodic_dma_supported) {
331 : : /*
332 : : * Request an explicit MAC stats upload immediately to
333 : : * preclude bogus figures readback if the user decides
334 : : * to read stats before periodic DMA is really started
335 : : */
336 : 0 : rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem);
337 [ # # ]: 0 : if (rc != 0)
338 : 0 : goto fail_mac_stats_upload;
339 : : }
340 : :
341 : 0 : sfc_log_init(sa, "disable MAC drain");
342 : 0 : rc = efx_mac_drain(sa->nic, B_FALSE);
343 [ # # ]: 0 : if (rc != 0)
344 : 0 : goto fail_mac_drain;
345 : :
346 : : /* Synchronize link status knowledge */
347 : 0 : rc = sfc_port_init_dev_link(sa);
348 [ # # ]: 0 : if (rc != 0)
349 : 0 : goto fail_port_init_dev_link;
350 : :
351 : 0 : sfc_log_init(sa, "done");
352 : 0 : return 0;
353 : :
354 : : fail_port_init_dev_link:
355 : 0 : (void)efx_mac_drain(sa->nic, B_TRUE);
356 : :
357 : 0 : fail_mac_drain:
358 : 0 : fail_include_fcs_set:
359 : 0 : fail_mac_stats_upload:
360 : 0 : (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
361 : : 0, B_FALSE);
362 : :
363 : 0 : fail_mac_stats_periodic:
364 : 0 : fail_mcast_address_list_set:
365 : 0 : fail_mac_filter_set:
366 : 0 : fail_mac_addr_set:
367 : 0 : fail_mac_pdu_set:
368 : 0 : fail_phy_lane_count_get:
369 : 0 : fail_phy_lane_count_set:
370 : 0 : fail_phy_adv_cap_set:
371 : 0 : fail_mac_fcntl_set:
372 : 0 : fail_mac_vlan_strip_set:
373 : : #if EFSYS_OPT_LOOPBACK
374 : 0 : fail_loopback_set:
375 : : #endif
376 : 0 : efx_port_fini(sa->nic);
377 : :
378 : 0 : fail_port_init:
379 : 0 : efx_filter_fini(sa->nic);
380 : :
381 : 0 : fail_filter_init:
382 : 0 : sfc_log_init(sa, "failed %d", rc);
383 : 0 : return rc;
384 : : }
385 : :
386 : : void
387 : 0 : sfc_port_stop(struct sfc_adapter *sa)
388 : : {
389 : 0 : sfc_log_init(sa, "entry");
390 : :
391 : 0 : efx_mac_drain(sa->nic, B_TRUE);
392 : :
393 : 0 : (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem,
394 : : 0, B_FALSE);
395 : :
396 : 0 : sfc_port_update_mac_stats(sa, B_TRUE);
397 : :
398 : 0 : efx_port_fini(sa->nic);
399 : 0 : efx_filter_fini(sa->nic);
400 : :
401 : 0 : sfc_log_init(sa, "done");
402 : 0 : }
403 : :
404 : : int
405 : 0 : sfc_port_configure(struct sfc_adapter *sa)
406 : : {
407 : 0 : const struct rte_eth_dev_data *dev_data = sa->eth_dev->data;
408 : : struct sfc_port *port = &sa->port;
409 : : const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode;
410 : :
411 : 0 : sfc_log_init(sa, "entry");
412 : :
413 : 0 : port->pdu = efx_mac_pdu_from_sdu(sa->nic, dev_data->mtu);
414 : :
415 [ # # ]: 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
416 : 0 : port->include_fcs = true;
417 : : else
418 : 0 : port->include_fcs = false;
419 : :
420 [ # # ]: 0 : if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
421 : 0 : port->vlan_strip = true;
422 : : else
423 : 0 : port->vlan_strip = false;
424 : :
425 : 0 : return 0;
426 : : }
427 : :
428 : : void
429 : 0 : sfc_port_close(struct sfc_adapter *sa)
430 : : {
431 : 0 : sfc_log_init(sa, "entry");
432 : 0 : }
433 : :
434 : : int
435 : 0 : sfc_port_attach(struct sfc_adapter *sa)
436 : : {
437 : : struct sfc_port *port = &sa->port;
438 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
439 : : const struct rte_ether_addr *from;
440 : : uint32_t mac_nstats;
441 : : size_t mac_stats_size;
442 : : long kvarg_stats_update_period_ms;
443 : : int rc;
444 : :
445 : 0 : sfc_log_init(sa, "entry");
446 : :
447 : 0 : port->phy_lane_count_req = EFX_PHY_LANE_COUNT_DEFAULT;
448 : :
449 : 0 : efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask);
450 : :
451 : : /* Enable flow control by default */
452 : 0 : port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
453 : 0 : port->flow_ctrl_autoneg = B_TRUE;
454 : :
455 : : RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from));
456 : : from = (const struct rte_ether_addr *)(encp->enc_mac_addr);
457 : : rte_ether_addr_copy(from, &port->default_mac_addr);
458 : :
459 : 0 : port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
460 : 0 : port->nb_mcast_addrs = 0;
461 : 0 : port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
462 : : port->max_mcast_addrs,
463 : : EFX_MAC_ADDR_LEN, 0,
464 : : sa->socket_id);
465 [ # # ]: 0 : if (port->mcast_addrs == NULL) {
466 : : rc = ENOMEM;
467 : 0 : goto fail_mcast_addr_list_buf_alloc;
468 : : }
469 : :
470 : : rc = ENOMEM;
471 : 0 : port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS,
472 : : sizeof(uint64_t), 0,
473 : : sa->socket_id);
474 [ # # ]: 0 : if (port->mac_stats_buf == NULL)
475 : 0 : goto fail_mac_stats_buf_alloc;
476 : :
477 : 0 : mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats;
478 : 0 : mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE);
479 : 0 : rc = sfc_dma_alloc(sa, "mac_stats", 0, EFX_NIC_DMA_ADDR_MAC_STATS_BUF,
480 : : mac_stats_size,
481 : : sa->socket_id, &port->mac_stats_dma_mem);
482 [ # # ]: 0 : if (rc != 0)
483 : 0 : goto fail_mac_stats_dma_alloc;
484 : :
485 : 0 : port->mac_stats_reset_pending = B_FALSE;
486 : :
487 : 0 : kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF;
488 : :
489 : 0 : rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS,
490 : : sfc_kvarg_long_handler,
491 : : &kvarg_stats_update_period_ms);
492 [ # # ]: 0 : if ((rc == 0) &&
493 [ # # ]: 0 : ((kvarg_stats_update_period_ms < 0) ||
494 : : (kvarg_stats_update_period_ms > UINT16_MAX))) {
495 : 0 : sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' "
496 : : "was set (%ld);", kvarg_stats_update_period_ms);
497 : 0 : sfc_err(sa, "it must not be less than 0 "
498 : : "or greater than %" PRIu16, UINT16_MAX);
499 : : rc = EINVAL;
500 : 0 : goto fail_kvarg_stats_update_period_ms;
501 [ # # ]: 0 : } else if (rc != 0) {
502 : 0 : goto fail_kvarg_stats_update_period_ms;
503 : : }
504 : :
505 : 0 : port->mac_stats_update_period_ms = kvarg_stats_update_period_ms;
506 : :
507 : : /*
508 : : * Set default FEC mode.
509 : : * I.e. advertise everything supported (*_FEC=1), but do not request
510 : : * anything explicitly (*_FEC_REQUESTED=0).
511 : : */
512 : 0 : port->fec_cfg = port->phy_adv_cap_mask &
513 : : (EFX_PHY_CAP_FEC_BIT(BASER_FEC) |
514 : : EFX_PHY_CAP_FEC_BIT(RS_FEC) |
515 : : EFX_PHY_CAP_FEC_BIT(25G_BASER_FEC));
516 : 0 : port->fec_auto = true;
517 : :
518 : 0 : sfc_log_init(sa, "done");
519 : 0 : return 0;
520 : :
521 : 0 : fail_kvarg_stats_update_period_ms:
522 : 0 : sfc_dma_free(sa, &port->mac_stats_dma_mem);
523 : :
524 : 0 : fail_mac_stats_dma_alloc:
525 : 0 : rte_free(port->mac_stats_buf);
526 : :
527 : 0 : fail_mac_stats_buf_alloc:
528 : 0 : rte_free(port->mcast_addrs);
529 : :
530 : 0 : fail_mcast_addr_list_buf_alloc:
531 : 0 : sfc_log_init(sa, "failed %d", rc);
532 : 0 : return rc;
533 : : }
534 : :
535 : : void
536 : 0 : sfc_port_detach(struct sfc_adapter *sa)
537 : : {
538 : : struct sfc_port *port = &sa->port;
539 : :
540 : 0 : sfc_log_init(sa, "entry");
541 : :
542 : 0 : sfc_dma_free(sa, &port->mac_stats_dma_mem);
543 : 0 : rte_free(port->mac_stats_buf);
544 : :
545 : 0 : rte_free(port->mcast_addrs);
546 : :
547 : 0 : sfc_log_init(sa, "done");
548 : 0 : }
549 : :
550 : : static boolean_t
551 : : sfc_get_requested_all_ucast(struct sfc_port *port)
552 : : {
553 : 0 : return port->promisc;
554 : : }
555 : :
556 : : static boolean_t
557 : : sfc_get_requested_all_mcast(struct sfc_port *port)
558 : : {
559 : 0 : return port->promisc || port->allmulti;
560 : : }
561 : :
562 : : int
563 : 0 : sfc_set_rx_mode_unchecked(struct sfc_adapter *sa)
564 : : {
565 : : struct sfc_port *port = &sa->port;
566 : : boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
567 : : boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
568 : : int rc;
569 : :
570 : 0 : rc = efx_mac_filter_set(sa->nic, requested_all_ucast, B_TRUE,
571 : : requested_all_mcast, B_TRUE);
572 [ # # ]: 0 : if (rc != 0)
573 : 0 : return rc;
574 : :
575 : : return 0;
576 : : }
577 : :
578 : : int
579 : 0 : sfc_set_rx_mode(struct sfc_adapter *sa)
580 : : {
581 : : struct sfc_port *port = &sa->port;
582 : : boolean_t old_all_ucast;
583 : : boolean_t old_all_mcast;
584 : : boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
585 : : boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
586 : : boolean_t actual_all_ucast;
587 : : boolean_t actual_all_mcast;
588 : : int rc;
589 : :
590 : 0 : efx_mac_filter_get_all_ucast_mcast(sa->nic, &old_all_ucast,
591 : : &old_all_mcast);
592 : :
593 : 0 : rc = sfc_set_rx_mode_unchecked(sa);
594 [ # # ]: 0 : if (rc != 0)
595 : : return rc;
596 : :
597 : 0 : efx_mac_filter_get_all_ucast_mcast(sa->nic, &actual_all_ucast,
598 : : &actual_all_mcast);
599 : :
600 [ # # ]: 0 : if (actual_all_ucast != requested_all_ucast ||
601 [ # # ]: 0 : actual_all_mcast != requested_all_mcast) {
602 : : /*
603 : : * MAC filter set succeeded but not all requested modes
604 : : * were applied. The rollback is necessary to bring back the
605 : : * consistent old state.
606 : : */
607 : 0 : (void)efx_mac_filter_set(sa->nic, old_all_ucast, B_TRUE,
608 : : old_all_mcast, B_TRUE);
609 : :
610 : 0 : return EPERM;
611 : : }
612 : :
613 : : return 0;
614 : : }
615 : :
616 : : void
617 [ # # ]: 0 : sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
618 : : struct rte_eth_link *link_info)
619 : : {
620 : : SFC_ASSERT(link_mode < EFX_LINK_NMODES);
621 : :
622 : : memset(link_info, 0, sizeof(*link_info));
623 [ # # ]: 0 : if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN))
624 : : link_info->link_status = RTE_ETH_LINK_DOWN;
625 : : else
626 : 0 : link_info->link_status = RTE_ETH_LINK_UP;
627 : :
628 [ # # # # : 0 : switch (link_mode) {
# # # # #
# # # # ]
629 : 0 : case EFX_LINK_10HDX:
630 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_10M;
631 : : link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
632 : 0 : break;
633 : 0 : case EFX_LINK_10FDX:
634 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_10M;
635 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
636 : 0 : break;
637 : 0 : case EFX_LINK_100HDX:
638 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_100M;
639 : : link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
640 : 0 : break;
641 : 0 : case EFX_LINK_100FDX:
642 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_100M;
643 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
644 : 0 : break;
645 : 0 : case EFX_LINK_1000HDX:
646 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_1G;
647 : : link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
648 : 0 : break;
649 : 0 : case EFX_LINK_1000FDX:
650 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_1G;
651 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
652 : 0 : break;
653 : 0 : case EFX_LINK_10000FDX:
654 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_10G;
655 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
656 : 0 : break;
657 : 0 : case EFX_LINK_25000FDX:
658 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_25G;
659 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
660 : 0 : break;
661 : 0 : case EFX_LINK_40000FDX:
662 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_40G;
663 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
664 : 0 : break;
665 : 0 : case EFX_LINK_50000FDX:
666 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_50G;
667 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
668 : 0 : break;
669 : 0 : case EFX_LINK_100000FDX:
670 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_100G;
671 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
672 : 0 : break;
673 : 0 : case EFX_LINK_200000FDX:
674 : 0 : link_info->link_speed = RTE_ETH_SPEED_NUM_200G;
675 : 0 : link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
676 : 0 : break;
677 : : default:
678 : : SFC_ASSERT(B_FALSE);
679 : : /* FALLTHROUGH */
680 : : case EFX_LINK_UNKNOWN:
681 : : case EFX_LINK_DOWN:
682 : : link_info->link_speed = RTE_ETH_SPEED_NUM_NONE;
683 : : link_info->link_duplex = 0;
684 : : break;
685 : : }
686 : :
687 : 0 : link_info->link_autoneg = RTE_ETH_LINK_AUTONEG;
688 : 0 : }
689 : :
690 : : int
691 : 0 : sfc_port_get_mac_stats(struct sfc_adapter *sa, struct rte_eth_xstat *xstats,
692 : : unsigned int xstats_count, unsigned int *nb_written)
693 : : {
694 : : struct sfc_port *port = &sa->port;
695 : : uint64_t *mac_stats;
696 : : unsigned int i;
697 : : int nstats = 0;
698 : : int ret;
699 : :
700 : 0 : sfc_adapter_lock(sa);
701 : :
702 : 0 : ret = sfc_port_update_mac_stats(sa, B_FALSE);
703 [ # # ]: 0 : if (ret != 0) {
704 : : SFC_ASSERT(ret > 0);
705 : 0 : ret = -ret;
706 : 0 : goto unlock;
707 : : }
708 : :
709 : 0 : mac_stats = port->mac_stats_buf;
710 : :
711 [ # # ]: 0 : for (i = 0; i < EFX_MAC_NSTATS; ++i) {
712 [ # # ]: 0 : if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) {
713 [ # # ]: 0 : if (nstats < (int)xstats_count) {
714 : 0 : xstats[nstats].id = nstats;
715 : 0 : xstats[nstats].value = mac_stats[i];
716 : 0 : (*nb_written)++;
717 : : }
718 : 0 : nstats++;
719 : : }
720 : : }
721 : : ret = nstats;
722 : :
723 : 0 : unlock:
724 : : sfc_adapter_unlock(sa);
725 : :
726 : 0 : return ret;
727 : : }
728 : :
729 : : int
730 : 0 : sfc_port_get_mac_stats_by_id(struct sfc_adapter *sa, const uint64_t *ids,
731 : : uint64_t *values, unsigned int n)
732 : : {
733 : : struct sfc_port *port = &sa->port;
734 : : uint64_t *mac_stats;
735 : : unsigned int i;
736 : : int ret;
737 : : int rc;
738 : :
739 : 0 : sfc_adapter_lock(sa);
740 : :
741 : 0 : rc = sfc_port_update_mac_stats(sa, B_FALSE);
742 [ # # ]: 0 : if (rc != 0) {
743 : : SFC_ASSERT(rc > 0);
744 : 0 : ret = -rc;
745 : 0 : goto unlock;
746 : : }
747 : :
748 : 0 : mac_stats = port->mac_stats_buf;
749 : :
750 : : SFC_ASSERT(port->mac_stats_nb_supported <=
751 : : RTE_DIM(port->mac_stats_by_id));
752 : :
753 [ # # ]: 0 : for (i = 0; i < n; i++) {
754 [ # # ]: 0 : if (ids[i] < port->mac_stats_nb_supported)
755 : 0 : values[i] = mac_stats[port->mac_stats_by_id[ids[i]]];
756 : : }
757 : :
758 : : ret = 0;
759 : :
760 : 0 : unlock:
761 : : sfc_adapter_unlock(sa);
762 : :
763 : 0 : return ret;
764 : : }
|