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