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