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