144c0947bSAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
2244cfa79SAndrew Rybchenko *
398d26ef7SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
4a0147be5SAndrew Rybchenko * Copyright(c) 2016-2019 Solarflare Communications Inc.
503ed2119SAndrew Rybchenko *
603ed2119SAndrew Rybchenko * This software was jointly developed between OKTET Labs (under contract
703ed2119SAndrew Rybchenko * for Solarflare) and Solarflare Communications, Inc.
803ed2119SAndrew Rybchenko */
903ed2119SAndrew Rybchenko
10fdd7719eSIvan Ilchenko #include <rte_bitmap.h>
11ae9aafe4SIvan Malov #include <rte_ether.h>
12fdd7719eSIvan Ilchenko
1303ed2119SAndrew Rybchenko #include "efx.h"
1403ed2119SAndrew Rybchenko
1503ed2119SAndrew Rybchenko #include "sfc.h"
161b0236e2SAndrew Rybchenko #include "sfc_debug.h"
1703ed2119SAndrew Rybchenko #include "sfc_log.h"
18e56fa9c2SIvan Malov #include "sfc_kvargs.h"
19e56fa9c2SIvan Malov
20e56fa9c2SIvan Malov /** Default MAC statistics update period is 1 second */
21e56fa9c2SIvan Malov #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF MS_PER_S
22e56fa9c2SIvan Malov
23e56fa9c2SIvan Malov /** The number of microseconds to sleep on attempt to get statistics update */
24e56fa9c2SIvan Malov #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US 10
25e56fa9c2SIvan Malov
26e56fa9c2SIvan Malov /** The number of attempts to await arrival of freshly generated statistics */
27e56fa9c2SIvan Malov #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS 50
2803ed2119SAndrew Rybchenko
291caab2f1SAndrew Rybchenko /**
301caab2f1SAndrew Rybchenko * Update MAC statistics in the buffer.
311caab2f1SAndrew Rybchenko *
321caab2f1SAndrew Rybchenko * @param sa Adapter
331827b073SIvan Ilchenko * @param force_upload Flag to upload MAC stats in any case
341caab2f1SAndrew Rybchenko *
351caab2f1SAndrew Rybchenko * @return Status code
361caab2f1SAndrew Rybchenko * @retval 0 Success
371caab2f1SAndrew Rybchenko * @retval EAGAIN Try again
381caab2f1SAndrew Rybchenko * @retval ENOMEM Memory allocation failure
391caab2f1SAndrew Rybchenko */
401caab2f1SAndrew Rybchenko int
sfc_port_update_mac_stats(struct sfc_adapter * sa,boolean_t force_upload)411827b073SIvan Ilchenko sfc_port_update_mac_stats(struct sfc_adapter *sa, boolean_t force_upload)
421caab2f1SAndrew Rybchenko {
431caab2f1SAndrew Rybchenko struct sfc_port *port = &sa->port;
44e56fa9c2SIvan Malov efsys_mem_t *esmp = &port->mac_stats_dma_mem;
45e56fa9c2SIvan Malov uint32_t *genp = NULL;
46e56fa9c2SIvan Malov uint32_t gen_old;
47e56fa9c2SIvan Malov unsigned int nb_attempts = 0;
481caab2f1SAndrew Rybchenko int rc;
491caab2f1SAndrew Rybchenko
5017b0d7b3SIvan Ilchenko SFC_ASSERT(sfc_adapter_is_locked(sa));
511caab2f1SAndrew Rybchenko
52ac478689SIgor Romanov if (sa->state != SFC_ETHDEV_STARTED)
531827b073SIvan Ilchenko return 0;
541caab2f1SAndrew Rybchenko
55178fc0d3SIvan Malov /*
56178fc0d3SIvan Malov * If periodic statistics DMA'ing is off or if not supported,
57178fc0d3SIvan Malov * make a manual request and keep an eye on timer if need be
58178fc0d3SIvan Malov */
59178fc0d3SIvan Malov if (!port->mac_stats_periodic_dma_supported ||
601827b073SIvan Ilchenko (port->mac_stats_update_period_ms == 0) || force_upload) {
61178fc0d3SIvan Malov if (port->mac_stats_update_period_ms != 0) {
62178fc0d3SIvan Malov uint64_t timestamp = sfc_get_system_msecs();
63178fc0d3SIvan Malov
64178fc0d3SIvan Malov if ((timestamp -
65178fc0d3SIvan Malov port->mac_stats_last_request_timestamp) <
66178fc0d3SIvan Malov port->mac_stats_update_period_ms)
67178fc0d3SIvan Malov return 0;
68178fc0d3SIvan Malov
69178fc0d3SIvan Malov port->mac_stats_last_request_timestamp = timestamp;
70178fc0d3SIvan Malov }
71178fc0d3SIvan Malov
72e56fa9c2SIvan Malov rc = efx_mac_stats_upload(sa->nic, esmp);
731caab2f1SAndrew Rybchenko if (rc != 0)
741caab2f1SAndrew Rybchenko return rc;
751caab2f1SAndrew Rybchenko
76e56fa9c2SIvan Malov genp = &port->mac_stats_update_generation;
77e56fa9c2SIvan Malov gen_old = *genp;
78e56fa9c2SIvan Malov }
79e56fa9c2SIvan Malov
80e56fa9c2SIvan Malov do {
81e56fa9c2SIvan Malov if (nb_attempts > 0)
82e56fa9c2SIvan Malov rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US);
83e56fa9c2SIvan Malov
84e56fa9c2SIvan Malov rc = efx_mac_stats_update(sa->nic, esmp,
85e56fa9c2SIvan Malov port->mac_stats_buf, genp);
86e56fa9c2SIvan Malov if (rc != 0)
87e56fa9c2SIvan Malov return rc;
88e56fa9c2SIvan Malov
89e56fa9c2SIvan Malov } while ((genp != NULL) && (*genp == gen_old) &&
90e56fa9c2SIvan Malov (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS));
91e56fa9c2SIvan Malov
921caab2f1SAndrew Rybchenko return 0;
931caab2f1SAndrew Rybchenko }
9403ed2119SAndrew Rybchenko
95ab77a001SAndrew Rybchenko static void
sfc_port_reset_sw_stats(struct sfc_adapter * sa)96ab77a001SAndrew Rybchenko sfc_port_reset_sw_stats(struct sfc_adapter *sa)
97ab77a001SAndrew Rybchenko {
98ab77a001SAndrew Rybchenko struct sfc_port *port = &sa->port;
99ab77a001SAndrew Rybchenko
100ab77a001SAndrew Rybchenko /*
101ab77a001SAndrew Rybchenko * Reset diff stats explicitly since check which does not allow
102ab77a001SAndrew Rybchenko * the statistics to grow backward could deny it.
103ab77a001SAndrew Rybchenko */
104ab77a001SAndrew Rybchenko port->ipackets = 0;
105ab77a001SAndrew Rybchenko }
106ab77a001SAndrew Rybchenko
107e8acb329SIvan Malov int
sfc_port_reset_mac_stats(struct sfc_adapter * sa)108e8acb329SIvan Malov sfc_port_reset_mac_stats(struct sfc_adapter *sa)
109e8acb329SIvan Malov {
110e8acb329SIvan Malov int rc;
111e8acb329SIvan Malov
11217b0d7b3SIvan Ilchenko SFC_ASSERT(sfc_adapter_is_locked(sa));
11317b0d7b3SIvan Ilchenko
114e8acb329SIvan Malov rc = efx_mac_stats_clear(sa->nic);
115ab77a001SAndrew Rybchenko if (rc == 0)
116ab77a001SAndrew Rybchenko sfc_port_reset_sw_stats(sa);
117e8acb329SIvan Malov
118e8acb329SIvan Malov return rc;
119e8acb329SIvan Malov }
120e8acb329SIvan Malov
121f08a2377SAndrew Rybchenko static int
sfc_port_init_dev_link(struct sfc_adapter * sa)122f08a2377SAndrew Rybchenko sfc_port_init_dev_link(struct sfc_adapter *sa)
123f08a2377SAndrew Rybchenko {
124f08a2377SAndrew Rybchenko struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
125f08a2377SAndrew Rybchenko int rc;
126f08a2377SAndrew Rybchenko efx_link_mode_t link_mode;
127f08a2377SAndrew Rybchenko struct rte_eth_link current_link;
128f08a2377SAndrew Rybchenko
129f08a2377SAndrew Rybchenko rc = efx_port_poll(sa->nic, &link_mode);
130f08a2377SAndrew Rybchenko if (rc != 0)
131f08a2377SAndrew Rybchenko return rc;
132f08a2377SAndrew Rybchenko
133f08a2377SAndrew Rybchenko sfc_port_link_mode_to_info(link_mode, ¤t_link);
134f08a2377SAndrew Rybchenko
135f08a2377SAndrew Rybchenko EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
136f08a2377SAndrew Rybchenko rte_atomic64_set((rte_atomic64_t *)dev_link,
137f08a2377SAndrew Rybchenko *(uint64_t *)¤t_link);
138f08a2377SAndrew Rybchenko
139f08a2377SAndrew Rybchenko return 0;
140f08a2377SAndrew Rybchenko }
141f08a2377SAndrew Rybchenko
142b16cf4b2SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
143b16cf4b2SAndrew Rybchenko
144b16cf4b2SAndrew Rybchenko static efx_link_mode_t
sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps)145b16cf4b2SAndrew Rybchenko sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps)
146b16cf4b2SAndrew Rybchenko {
147b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_100000FDX))
148b16cf4b2SAndrew Rybchenko return EFX_LINK_100000FDX;
149b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_50000FDX))
150b16cf4b2SAndrew Rybchenko return EFX_LINK_50000FDX;
151b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_40000FDX))
152b16cf4b2SAndrew Rybchenko return EFX_LINK_40000FDX;
153b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_25000FDX))
154b16cf4b2SAndrew Rybchenko return EFX_LINK_25000FDX;
155b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_10000FDX))
156b16cf4b2SAndrew Rybchenko return EFX_LINK_10000FDX;
157b16cf4b2SAndrew Rybchenko if (phy_caps & (1u << EFX_PHY_CAP_1000FDX))
158b16cf4b2SAndrew Rybchenko return EFX_LINK_1000FDX;
159b16cf4b2SAndrew Rybchenko return EFX_LINK_UNKNOWN;
160b16cf4b2SAndrew Rybchenko }
161b16cf4b2SAndrew Rybchenko
162b16cf4b2SAndrew Rybchenko #endif
163b16cf4b2SAndrew Rybchenko
1647d466e5fSIvan Ilchenko static void
sfc_port_fill_mac_stats_info(struct sfc_adapter * sa)1657d466e5fSIvan Ilchenko sfc_port_fill_mac_stats_info(struct sfc_adapter *sa)
1667d466e5fSIvan Ilchenko {
1677d466e5fSIvan Ilchenko unsigned int mac_stats_nb_supported = 0;
1687d466e5fSIvan Ilchenko struct sfc_port *port = &sa->port;
1697d466e5fSIvan Ilchenko unsigned int stat_idx;
1707d466e5fSIvan Ilchenko
1717d466e5fSIvan Ilchenko efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask,
1727d466e5fSIvan Ilchenko sizeof(port->mac_stats_mask));
1737d466e5fSIvan Ilchenko
1747d466e5fSIvan Ilchenko for (stat_idx = 0; stat_idx < EFX_MAC_NSTATS; ++stat_idx) {
1757d466e5fSIvan Ilchenko if (!EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, stat_idx))
1767d466e5fSIvan Ilchenko continue;
1777d466e5fSIvan Ilchenko
1787d466e5fSIvan Ilchenko port->mac_stats_by_id[mac_stats_nb_supported] = stat_idx;
1797d466e5fSIvan Ilchenko mac_stats_nb_supported++;
1807d466e5fSIvan Ilchenko }
1817d466e5fSIvan Ilchenko
1827d466e5fSIvan Ilchenko port->mac_stats_nb_supported = mac_stats_nb_supported;
1837d466e5fSIvan Ilchenko }
1847d466e5fSIvan Ilchenko
18503ed2119SAndrew Rybchenko int
sfc_port_start(struct sfc_adapter * sa)18603ed2119SAndrew Rybchenko sfc_port_start(struct sfc_adapter *sa)
18703ed2119SAndrew Rybchenko {
18803ed2119SAndrew Rybchenko struct sfc_port *port = &sa->port;
18903ed2119SAndrew Rybchenko int rc;
1900e7449caSAndrew Rybchenko uint32_t phy_adv_cap;
1910e7449caSAndrew Rybchenko const uint32_t phy_pause_caps =
1920e7449caSAndrew Rybchenko ((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM));
19303ed2119SAndrew Rybchenko
19403ed2119SAndrew Rybchenko sfc_log_init(sa, "entry");
19503ed2119SAndrew Rybchenko
19603ed2119SAndrew Rybchenko sfc_log_init(sa, "init filters");
19703ed2119SAndrew Rybchenko rc = efx_filter_init(sa->nic);
19803ed2119SAndrew Rybchenko if (rc != 0)
19903ed2119SAndrew Rybchenko goto fail_filter_init;
20003ed2119SAndrew Rybchenko
20103ed2119SAndrew Rybchenko sfc_log_init(sa, "init port");
20203ed2119SAndrew Rybchenko rc = efx_port_init(sa->nic);
20303ed2119SAndrew Rybchenko if (rc != 0)
20403ed2119SAndrew Rybchenko goto fail_port_init;
20503ed2119SAndrew Rybchenko
206b16cf4b2SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
207b16cf4b2SAndrew Rybchenko if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) {
208b16cf4b2SAndrew Rybchenko efx_link_mode_t link_mode;
209b16cf4b2SAndrew Rybchenko
210b16cf4b2SAndrew Rybchenko link_mode =
211b16cf4b2SAndrew Rybchenko sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap);
212b16cf4b2SAndrew Rybchenko sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode,
213b16cf4b2SAndrew Rybchenko sa->eth_dev->data->dev_conf.lpbk_mode);
214b16cf4b2SAndrew Rybchenko rc = efx_port_loopback_set(sa->nic, link_mode,
215b16cf4b2SAndrew Rybchenko sa->eth_dev->data->dev_conf.lpbk_mode);
216b16cf4b2SAndrew Rybchenko if (rc != 0)
217b16cf4b2SAndrew Rybchenko goto fail_loopback_set;
218b16cf4b2SAndrew Rybchenko }
219b16cf4b2SAndrew Rybchenko #endif
220b16cf4b2SAndrew Rybchenko
221cdbb29cfSAndrew Rybchenko sfc_log_init(sa, "set flow control to %#x autoneg=%u",
222cdbb29cfSAndrew Rybchenko port->flow_ctrl, port->flow_ctrl_autoneg);
223cdbb29cfSAndrew Rybchenko rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl,
224cdbb29cfSAndrew Rybchenko port->flow_ctrl_autoneg);
225cdbb29cfSAndrew Rybchenko if (rc != 0)
226cdbb29cfSAndrew Rybchenko goto fail_mac_fcntl_set;
227cdbb29cfSAndrew Rybchenko
228*62082124SArtemii Morozov sfc_log_init(sa, "set vlan strip to %u", port->vlan_strip);
229*62082124SArtemii Morozov rc = efx_port_vlan_strip_set(sa->nic, port->vlan_strip);
230*62082124SArtemii Morozov if (rc != 0)
231*62082124SArtemii Morozov goto fail_mac_vlan_strip_set;
232*62082124SArtemii Morozov
2330e7449caSAndrew Rybchenko /* Preserve pause capabilities set by above efx_mac_fcntl_set() */
2340e7449caSAndrew Rybchenko efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap);
2350e7449caSAndrew Rybchenko SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0);
2365efa8fc1SDenis Pryazhennikov phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps) |
2375efa8fc1SDenis Pryazhennikov port->fec_cfg;
2380b19aec1SAndrew Rybchenko
2390e7449caSAndrew Rybchenko sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap);
2400e7449caSAndrew Rybchenko rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap);
241d23f3a89SAndrew Rybchenko if (rc != 0)
242d23f3a89SAndrew Rybchenko goto fail_phy_adv_cap_set;
243d23f3a89SAndrew Rybchenko
24403ed2119SAndrew Rybchenko sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu);
24503ed2119SAndrew Rybchenko rc = efx_mac_pdu_set(sa->nic, port->pdu);
24603ed2119SAndrew Rybchenko if (rc != 0)
24703ed2119SAndrew Rybchenko goto fail_mac_pdu_set;
24803ed2119SAndrew Rybchenko
24904a04943SDenis Pryazhennikov sfc_log_init(sa, "set include FCS=%u", port->include_fcs);
25004a04943SDenis Pryazhennikov rc = efx_mac_include_fcs_set(sa->nic, port->include_fcs);
25104a04943SDenis Pryazhennikov if (rc != 0)
25204a04943SDenis Pryazhennikov goto fail_include_fcs_set;
25304a04943SDenis Pryazhennikov
254e0d5ba7eSAndrew Rybchenko if (!sfc_sa2shared(sa)->isolated) {
2556d13ea8eSOlivier Matz struct rte_ether_addr *addr = &port->default_mac_addr;
25684a9b481SIvan Malov
25703ed2119SAndrew Rybchenko sfc_log_init(sa, "set MAC address");
258642088ddSIvan Malov rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
25903ed2119SAndrew Rybchenko if (rc != 0)
26003ed2119SAndrew Rybchenko goto fail_mac_addr_set;
26103ed2119SAndrew Rybchenko
26203ed2119SAndrew Rybchenko sfc_log_init(sa, "set MAC filters");
263f3de3840SIvan Malov port->promisc = (sa->eth_dev->data->promiscuous != 0) ?
264f3de3840SIvan Malov B_TRUE : B_FALSE;
265f3de3840SIvan Malov port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
266f3de3840SIvan Malov B_TRUE : B_FALSE;
26798608e18SIgor Romanov rc = sfc_set_rx_mode_unchecked(sa);
26803ed2119SAndrew Rybchenko if (rc != 0)
26903ed2119SAndrew Rybchenko goto fail_mac_filter_set;
27003ed2119SAndrew Rybchenko
271295f647aSIvan Malov sfc_log_init(sa, "set multicast address list");
272295f647aSIvan Malov rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
273295f647aSIvan Malov port->nb_mcast_addrs);
274295f647aSIvan Malov if (rc != 0)
275295f647aSIvan Malov goto fail_mcast_address_list_set;
27684a9b481SIvan Malov }
277295f647aSIvan Malov
278e8acb329SIvan Malov if (port->mac_stats_reset_pending) {
279e8acb329SIvan Malov rc = sfc_port_reset_mac_stats(sa);
280e8acb329SIvan Malov if (rc != 0)
281e8acb329SIvan Malov sfc_err(sa, "statistics reset failed (requested "
282e8acb329SIvan Malov "before the port was started)");
283e8acb329SIvan Malov
284e8acb329SIvan Malov port->mac_stats_reset_pending = B_FALSE;
285e8acb329SIvan Malov }
286e8acb329SIvan Malov
2877d466e5fSIvan Ilchenko sfc_port_fill_mac_stats_info(sa);
28873280c1eSIvan Malov
289e56fa9c2SIvan Malov port->mac_stats_update_generation = 0;
290e56fa9c2SIvan Malov
291e56fa9c2SIvan Malov if (port->mac_stats_update_period_ms != 0) {
292e56fa9c2SIvan Malov /*
293e56fa9c2SIvan Malov * Update MAC stats using periodic DMA;
294e56fa9c2SIvan Malov * any positive update interval different from
295e56fa9c2SIvan Malov * 1000 ms can be set only on SFN8xxx provided
296e56fa9c2SIvan Malov * that FW version is 6.2.1.1033 or higher
2971caab2f1SAndrew Rybchenko */
2981caab2f1SAndrew Rybchenko sfc_log_init(sa, "request MAC stats DMA'ing");
2991caab2f1SAndrew Rybchenko rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
300e56fa9c2SIvan Malov port->mac_stats_update_period_ms,
301e56fa9c2SIvan Malov B_FALSE);
302178fc0d3SIvan Malov if (rc == 0) {
303178fc0d3SIvan Malov port->mac_stats_periodic_dma_supported = B_TRUE;
304178fc0d3SIvan Malov } else if (rc == EOPNOTSUPP) {
305178fc0d3SIvan Malov port->mac_stats_periodic_dma_supported = B_FALSE;
306178fc0d3SIvan Malov port->mac_stats_last_request_timestamp = 0;
307178fc0d3SIvan Malov } else {
3081caab2f1SAndrew Rybchenko goto fail_mac_stats_periodic;
309e56fa9c2SIvan Malov }
310178fc0d3SIvan Malov }
3111caab2f1SAndrew Rybchenko
3123b257f7eSIvan Malov if ((port->mac_stats_update_period_ms != 0) &&
3133b257f7eSIvan Malov port->mac_stats_periodic_dma_supported) {
3143b257f7eSIvan Malov /*
3153b257f7eSIvan Malov * Request an explicit MAC stats upload immediately to
3163b257f7eSIvan Malov * preclude bogus figures readback if the user decides
3173b257f7eSIvan Malov * to read stats before periodic DMA is really started
3183b257f7eSIvan Malov */
3193b257f7eSIvan Malov rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem);
3203b257f7eSIvan Malov if (rc != 0)
3213b257f7eSIvan Malov goto fail_mac_stats_upload;
3223b257f7eSIvan Malov }
3233b257f7eSIvan Malov
32403ed2119SAndrew Rybchenko sfc_log_init(sa, "disable MAC drain");
32503ed2119SAndrew Rybchenko rc = efx_mac_drain(sa->nic, B_FALSE);
32603ed2119SAndrew Rybchenko if (rc != 0)
32703ed2119SAndrew Rybchenko goto fail_mac_drain;
32803ed2119SAndrew Rybchenko
329f08a2377SAndrew Rybchenko /* Synchronize link status knowledge */
330f08a2377SAndrew Rybchenko rc = sfc_port_init_dev_link(sa);
331f08a2377SAndrew Rybchenko if (rc != 0)
332f08a2377SAndrew Rybchenko goto fail_port_init_dev_link;
333f08a2377SAndrew Rybchenko
33403ed2119SAndrew Rybchenko sfc_log_init(sa, "done");
33503ed2119SAndrew Rybchenko return 0;
33603ed2119SAndrew Rybchenko
337f08a2377SAndrew Rybchenko fail_port_init_dev_link:
338f08a2377SAndrew Rybchenko (void)efx_mac_drain(sa->nic, B_TRUE);
339f08a2377SAndrew Rybchenko
34003ed2119SAndrew Rybchenko fail_mac_drain:
34104a04943SDenis Pryazhennikov fail_include_fcs_set:
3426636afdfSAndrew Rybchenko fail_mac_stats_upload:
3431caab2f1SAndrew Rybchenko (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
3441caab2f1SAndrew Rybchenko 0, B_FALSE);
3451caab2f1SAndrew Rybchenko
3461caab2f1SAndrew Rybchenko fail_mac_stats_periodic:
347295f647aSIvan Malov fail_mcast_address_list_set:
34803ed2119SAndrew Rybchenko fail_mac_filter_set:
34903ed2119SAndrew Rybchenko fail_mac_addr_set:
35003ed2119SAndrew Rybchenko fail_mac_pdu_set:
351d23f3a89SAndrew Rybchenko fail_phy_adv_cap_set:
352cdbb29cfSAndrew Rybchenko fail_mac_fcntl_set:
353*62082124SArtemii Morozov fail_mac_vlan_strip_set:
354b16cf4b2SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
355b16cf4b2SAndrew Rybchenko fail_loopback_set:
356b16cf4b2SAndrew Rybchenko #endif
35703ed2119SAndrew Rybchenko efx_port_fini(sa->nic);
35803ed2119SAndrew Rybchenko
35903ed2119SAndrew Rybchenko fail_port_init:
36003ed2119SAndrew Rybchenko efx_filter_fini(sa->nic);
36103ed2119SAndrew Rybchenko
36203ed2119SAndrew Rybchenko fail_filter_init:
36303ed2119SAndrew Rybchenko sfc_log_init(sa, "failed %d", rc);
36403ed2119SAndrew Rybchenko return rc;
36503ed2119SAndrew Rybchenko }
36603ed2119SAndrew Rybchenko
36703ed2119SAndrew Rybchenko void
sfc_port_stop(struct sfc_adapter * sa)36803ed2119SAndrew Rybchenko sfc_port_stop(struct sfc_adapter *sa)
36903ed2119SAndrew Rybchenko {
37003ed2119SAndrew Rybchenko sfc_log_init(sa, "entry");
37103ed2119SAndrew Rybchenko
37203ed2119SAndrew Rybchenko efx_mac_drain(sa->nic, B_TRUE);
3731caab2f1SAndrew Rybchenko
3741caab2f1SAndrew Rybchenko (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem,
3751caab2f1SAndrew Rybchenko 0, B_FALSE);
3761caab2f1SAndrew Rybchenko
3771827b073SIvan Ilchenko sfc_port_update_mac_stats(sa, B_TRUE);
3781827b073SIvan Ilchenko
37903ed2119SAndrew Rybchenko efx_port_fini(sa->nic);
38003ed2119SAndrew Rybchenko efx_filter_fini(sa->nic);
38103ed2119SAndrew Rybchenko
38203ed2119SAndrew Rybchenko sfc_log_init(sa, "done");
38303ed2119SAndrew Rybchenko }
38403ed2119SAndrew Rybchenko
38503ed2119SAndrew Rybchenko int
sfc_port_configure(struct sfc_adapter * sa)386c577a525SAndrew Rybchenko sfc_port_configure(struct sfc_adapter *sa)
38703ed2119SAndrew Rybchenko {
38803ed2119SAndrew Rybchenko const struct rte_eth_dev_data *dev_data = sa->eth_dev->data;
38903ed2119SAndrew Rybchenko struct sfc_port *port = &sa->port;
39004a04943SDenis Pryazhennikov const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode;
391c577a525SAndrew Rybchenko
392c577a525SAndrew Rybchenko sfc_log_init(sa, "entry");
393c577a525SAndrew Rybchenko
394c577a525SAndrew Rybchenko port->pdu = EFX_MAC_PDU(dev_data->mtu);
395c577a525SAndrew Rybchenko
39604a04943SDenis Pryazhennikov if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
39704a04943SDenis Pryazhennikov port->include_fcs = true;
39804a04943SDenis Pryazhennikov else
39904a04943SDenis Pryazhennikov port->include_fcs = false;
40004a04943SDenis Pryazhennikov
401*62082124SArtemii Morozov if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
402*62082124SArtemii Morozov port->vlan_strip = true;
403*62082124SArtemii Morozov else
404*62082124SArtemii Morozov port->vlan_strip = false;
405*62082124SArtemii Morozov
406c577a525SAndrew Rybchenko return 0;
407c577a525SAndrew Rybchenko }
408c577a525SAndrew Rybchenko
409c577a525SAndrew Rybchenko void
sfc_port_close(struct sfc_adapter * sa)410c577a525SAndrew Rybchenko sfc_port_close(struct sfc_adapter *sa)
411c577a525SAndrew Rybchenko {
412c577a525SAndrew Rybchenko sfc_log_init(sa, "entry");
413c577a525SAndrew Rybchenko }
414c577a525SAndrew Rybchenko
415c577a525SAndrew Rybchenko int
sfc_port_attach(struct sfc_adapter * sa)416c577a525SAndrew Rybchenko sfc_port_attach(struct sfc_adapter *sa)
417c577a525SAndrew Rybchenko {
418c577a525SAndrew Rybchenko struct sfc_port *port = &sa->port;
419642088ddSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
4206d13ea8eSOlivier Matz const struct rte_ether_addr *from;
421c953aea9SAndrew Rybchenko uint32_t mac_nstats;
422c953aea9SAndrew Rybchenko size_t mac_stats_size;
423e56fa9c2SIvan Malov long kvarg_stats_update_period_ms;
4241caab2f1SAndrew Rybchenko int rc;
42503ed2119SAndrew Rybchenko
42603ed2119SAndrew Rybchenko sfc_log_init(sa, "entry");
42703ed2119SAndrew Rybchenko
428c577a525SAndrew Rybchenko efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask);
429c577a525SAndrew Rybchenko
43003ed2119SAndrew Rybchenko /* Enable flow control by default */
43103ed2119SAndrew Rybchenko port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
43203ed2119SAndrew Rybchenko port->flow_ctrl_autoneg = B_TRUE;
43303ed2119SAndrew Rybchenko
434642088ddSIvan Malov RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from));
4356d13ea8eSOlivier Matz from = (const struct rte_ether_addr *)(encp->enc_mac_addr);
436538da7a1SOlivier Matz rte_ether_addr_copy(from, &port->default_mac_addr);
437642088ddSIvan Malov
438295f647aSIvan Malov port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
439295f647aSIvan Malov port->nb_mcast_addrs = 0;
440295f647aSIvan Malov port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
441295f647aSIvan Malov port->max_mcast_addrs,
442295f647aSIvan Malov EFX_MAC_ADDR_LEN, 0,
443295f647aSIvan Malov sa->socket_id);
444295f647aSIvan Malov if (port->mcast_addrs == NULL) {
445295f647aSIvan Malov rc = ENOMEM;
446295f647aSIvan Malov goto fail_mcast_addr_list_buf_alloc;
447295f647aSIvan Malov }
448295f647aSIvan Malov
4491caab2f1SAndrew Rybchenko rc = ENOMEM;
4501caab2f1SAndrew Rybchenko port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS,
4511caab2f1SAndrew Rybchenko sizeof(uint64_t), 0,
4521caab2f1SAndrew Rybchenko sa->socket_id);
4531caab2f1SAndrew Rybchenko if (port->mac_stats_buf == NULL)
4541caab2f1SAndrew Rybchenko goto fail_mac_stats_buf_alloc;
4551caab2f1SAndrew Rybchenko
456c953aea9SAndrew Rybchenko mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats;
457c953aea9SAndrew Rybchenko mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE);
4583037e6cfSViacheslav Galaktionov rc = sfc_dma_alloc(sa, "mac_stats", 0, EFX_NIC_DMA_ADDR_MAC_STATS_BUF,
4593037e6cfSViacheslav Galaktionov mac_stats_size,
4601caab2f1SAndrew Rybchenko sa->socket_id, &port->mac_stats_dma_mem);
4611caab2f1SAndrew Rybchenko if (rc != 0)
4621caab2f1SAndrew Rybchenko goto fail_mac_stats_dma_alloc;
4631caab2f1SAndrew Rybchenko
464e8acb329SIvan Malov port->mac_stats_reset_pending = B_FALSE;
465e8acb329SIvan Malov
466e56fa9c2SIvan Malov kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF;
467e56fa9c2SIvan Malov
468e56fa9c2SIvan Malov rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS,
469e56fa9c2SIvan Malov sfc_kvarg_long_handler,
470e56fa9c2SIvan Malov &kvarg_stats_update_period_ms);
471e56fa9c2SIvan Malov if ((rc == 0) &&
472e56fa9c2SIvan Malov ((kvarg_stats_update_period_ms < 0) ||
473e56fa9c2SIvan Malov (kvarg_stats_update_period_ms > UINT16_MAX))) {
474e56fa9c2SIvan Malov sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' "
475e56fa9c2SIvan Malov "was set (%ld);", kvarg_stats_update_period_ms);
476e56fa9c2SIvan Malov sfc_err(sa, "it must not be less than 0 "
477e56fa9c2SIvan Malov "or greater than %" PRIu16, UINT16_MAX);
478e56fa9c2SIvan Malov rc = EINVAL;
479e56fa9c2SIvan Malov goto fail_kvarg_stats_update_period_ms;
480e56fa9c2SIvan Malov } else if (rc != 0) {
481e56fa9c2SIvan Malov goto fail_kvarg_stats_update_period_ms;
482e56fa9c2SIvan Malov }
483e56fa9c2SIvan Malov
484e56fa9c2SIvan Malov port->mac_stats_update_period_ms = kvarg_stats_update_period_ms;
485e56fa9c2SIvan Malov
4865efa8fc1SDenis Pryazhennikov /*
4875efa8fc1SDenis Pryazhennikov * Set default FEC mode.
4885efa8fc1SDenis Pryazhennikov * I.e. advertise everything supported (*_FEC=1), but do not request
4895efa8fc1SDenis Pryazhennikov * anything explicitly (*_FEC_REQUESTED=0).
4905efa8fc1SDenis Pryazhennikov */
4915efa8fc1SDenis Pryazhennikov port->fec_cfg = port->phy_adv_cap_mask &
4925efa8fc1SDenis Pryazhennikov (EFX_PHY_CAP_FEC_BIT(BASER_FEC) |
4935efa8fc1SDenis Pryazhennikov EFX_PHY_CAP_FEC_BIT(RS_FEC) |
4945efa8fc1SDenis Pryazhennikov EFX_PHY_CAP_FEC_BIT(25G_BASER_FEC));
4955efa8fc1SDenis Pryazhennikov port->fec_auto = true;
4965efa8fc1SDenis Pryazhennikov
49703ed2119SAndrew Rybchenko sfc_log_init(sa, "done");
49803ed2119SAndrew Rybchenko return 0;
4991caab2f1SAndrew Rybchenko
500e56fa9c2SIvan Malov fail_kvarg_stats_update_period_ms:
5011883f4b8SAndrew Rybchenko sfc_dma_free(sa, &port->mac_stats_dma_mem);
5021883f4b8SAndrew Rybchenko
5031caab2f1SAndrew Rybchenko fail_mac_stats_dma_alloc:
5041caab2f1SAndrew Rybchenko rte_free(port->mac_stats_buf);
5058ae36890SAndrew Rybchenko
5061caab2f1SAndrew Rybchenko fail_mac_stats_buf_alloc:
5078ae36890SAndrew Rybchenko rte_free(port->mcast_addrs);
5088ae36890SAndrew Rybchenko
509295f647aSIvan Malov fail_mcast_addr_list_buf_alloc:
5101caab2f1SAndrew Rybchenko sfc_log_init(sa, "failed %d", rc);
5111caab2f1SAndrew Rybchenko return rc;
51203ed2119SAndrew Rybchenko }
51303ed2119SAndrew Rybchenko
51403ed2119SAndrew Rybchenko void
sfc_port_detach(struct sfc_adapter * sa)515c577a525SAndrew Rybchenko sfc_port_detach(struct sfc_adapter *sa)
51603ed2119SAndrew Rybchenko {
5171caab2f1SAndrew Rybchenko struct sfc_port *port = &sa->port;
5181caab2f1SAndrew Rybchenko
51903ed2119SAndrew Rybchenko sfc_log_init(sa, "entry");
52003ed2119SAndrew Rybchenko
5211caab2f1SAndrew Rybchenko sfc_dma_free(sa, &port->mac_stats_dma_mem);
5221caab2f1SAndrew Rybchenko rte_free(port->mac_stats_buf);
5231caab2f1SAndrew Rybchenko
5248ae36890SAndrew Rybchenko rte_free(port->mcast_addrs);
5258ae36890SAndrew Rybchenko
52603ed2119SAndrew Rybchenko sfc_log_init(sa, "done");
52703ed2119SAndrew Rybchenko }
528886f8d8aSArtem Andreev
52998608e18SIgor Romanov static boolean_t
sfc_get_requested_all_ucast(struct sfc_port * port)53098608e18SIgor Romanov sfc_get_requested_all_ucast(struct sfc_port *port)
53198608e18SIgor Romanov {
53298608e18SIgor Romanov return port->promisc;
53398608e18SIgor Romanov }
53498608e18SIgor Romanov
53598608e18SIgor Romanov static boolean_t
sfc_get_requested_all_mcast(struct sfc_port * port)53698608e18SIgor Romanov sfc_get_requested_all_mcast(struct sfc_port *port)
53798608e18SIgor Romanov {
53898608e18SIgor Romanov return port->promisc || port->allmulti;
53998608e18SIgor Romanov }
54098608e18SIgor Romanov
54198608e18SIgor Romanov int
sfc_set_rx_mode_unchecked(struct sfc_adapter * sa)54298608e18SIgor Romanov sfc_set_rx_mode_unchecked(struct sfc_adapter *sa)
54398608e18SIgor Romanov {
54498608e18SIgor Romanov struct sfc_port *port = &sa->port;
54598608e18SIgor Romanov boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
54698608e18SIgor Romanov boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
54798608e18SIgor Romanov int rc;
54898608e18SIgor Romanov
54998608e18SIgor Romanov rc = efx_mac_filter_set(sa->nic, requested_all_ucast, B_TRUE,
55098608e18SIgor Romanov requested_all_mcast, B_TRUE);
55198608e18SIgor Romanov if (rc != 0)
55298608e18SIgor Romanov return rc;
55398608e18SIgor Romanov
55498608e18SIgor Romanov return 0;
55598608e18SIgor Romanov }
55698608e18SIgor Romanov
557f3de3840SIvan Malov int
sfc_set_rx_mode(struct sfc_adapter * sa)558f3de3840SIvan Malov sfc_set_rx_mode(struct sfc_adapter *sa)
559f3de3840SIvan Malov {
560f3de3840SIvan Malov struct sfc_port *port = &sa->port;
56198608e18SIgor Romanov boolean_t old_all_ucast;
56298608e18SIgor Romanov boolean_t old_all_mcast;
56398608e18SIgor Romanov boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
56498608e18SIgor Romanov boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
56598608e18SIgor Romanov boolean_t actual_all_ucast;
56698608e18SIgor Romanov boolean_t actual_all_mcast;
567f3de3840SIvan Malov int rc;
568f3de3840SIvan Malov
56998608e18SIgor Romanov efx_mac_filter_get_all_ucast_mcast(sa->nic, &old_all_ucast,
57098608e18SIgor Romanov &old_all_mcast);
571f3de3840SIvan Malov
57298608e18SIgor Romanov rc = sfc_set_rx_mode_unchecked(sa);
57398608e18SIgor Romanov if (rc != 0)
574f3de3840SIvan Malov return rc;
57598608e18SIgor Romanov
57698608e18SIgor Romanov efx_mac_filter_get_all_ucast_mcast(sa->nic, &actual_all_ucast,
57798608e18SIgor Romanov &actual_all_mcast);
57898608e18SIgor Romanov
57998608e18SIgor Romanov if (actual_all_ucast != requested_all_ucast ||
58098608e18SIgor Romanov actual_all_mcast != requested_all_mcast) {
58198608e18SIgor Romanov /*
58298608e18SIgor Romanov * MAC filter set succeeded but not all requested modes
58398608e18SIgor Romanov * were applied. The rollback is necessary to bring back the
58498608e18SIgor Romanov * consistent old state.
58598608e18SIgor Romanov */
58698608e18SIgor Romanov (void)efx_mac_filter_set(sa->nic, old_all_ucast, B_TRUE,
58798608e18SIgor Romanov old_all_mcast, B_TRUE);
58898608e18SIgor Romanov
58998608e18SIgor Romanov return EPERM;
59098608e18SIgor Romanov }
59198608e18SIgor Romanov
59298608e18SIgor Romanov return 0;
593f3de3840SIvan Malov }
594f3de3840SIvan Malov
595886f8d8aSArtem Andreev void
sfc_port_link_mode_to_info(efx_link_mode_t link_mode,struct rte_eth_link * link_info)596886f8d8aSArtem Andreev sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
597886f8d8aSArtem Andreev struct rte_eth_link *link_info)
598886f8d8aSArtem Andreev {
599886f8d8aSArtem Andreev SFC_ASSERT(link_mode < EFX_LINK_NMODES);
600886f8d8aSArtem Andreev
601886f8d8aSArtem Andreev memset(link_info, 0, sizeof(*link_info));
602886f8d8aSArtem Andreev if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN))
603295968d1SFerruh Yigit link_info->link_status = RTE_ETH_LINK_DOWN;
604886f8d8aSArtem Andreev else
605295968d1SFerruh Yigit link_info->link_status = RTE_ETH_LINK_UP;
606886f8d8aSArtem Andreev
607886f8d8aSArtem Andreev switch (link_mode) {
608886f8d8aSArtem Andreev case EFX_LINK_10HDX:
609295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_10M;
610295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
611886f8d8aSArtem Andreev break;
612886f8d8aSArtem Andreev case EFX_LINK_10FDX:
613295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_10M;
614295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
615886f8d8aSArtem Andreev break;
616886f8d8aSArtem Andreev case EFX_LINK_100HDX:
617295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_100M;
618295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
619886f8d8aSArtem Andreev break;
620886f8d8aSArtem Andreev case EFX_LINK_100FDX:
621295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_100M;
622295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
623886f8d8aSArtem Andreev break;
624886f8d8aSArtem Andreev case EFX_LINK_1000HDX:
625295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_1G;
626295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
627886f8d8aSArtem Andreev break;
628886f8d8aSArtem Andreev case EFX_LINK_1000FDX:
629295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_1G;
630295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
631886f8d8aSArtem Andreev break;
632886f8d8aSArtem Andreev case EFX_LINK_10000FDX:
633295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_10G;
634295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
635886f8d8aSArtem Andreev break;
636f82e33afSAndrew Rybchenko case EFX_LINK_25000FDX:
637295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_25G;
638295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
639f82e33afSAndrew Rybchenko break;
640886f8d8aSArtem Andreev case EFX_LINK_40000FDX:
641295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_40G;
642295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
643886f8d8aSArtem Andreev break;
644f82e33afSAndrew Rybchenko case EFX_LINK_50000FDX:
645295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_50G;
646295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
647f82e33afSAndrew Rybchenko break;
648f82e33afSAndrew Rybchenko case EFX_LINK_100000FDX:
649295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_100G;
650295968d1SFerruh Yigit link_info->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
651f82e33afSAndrew Rybchenko break;
652886f8d8aSArtem Andreev default:
653886f8d8aSArtem Andreev SFC_ASSERT(B_FALSE);
654886f8d8aSArtem Andreev /* FALLTHROUGH */
655886f8d8aSArtem Andreev case EFX_LINK_UNKNOWN:
656886f8d8aSArtem Andreev case EFX_LINK_DOWN:
657295968d1SFerruh Yigit link_info->link_speed = RTE_ETH_SPEED_NUM_NONE;
658886f8d8aSArtem Andreev link_info->link_duplex = 0;
659886f8d8aSArtem Andreev break;
660886f8d8aSArtem Andreev }
661886f8d8aSArtem Andreev
662295968d1SFerruh Yigit link_info->link_autoneg = RTE_ETH_LINK_AUTONEG;
663886f8d8aSArtem Andreev }
66421ca2629SIvan Ilchenko
66521ca2629SIvan Ilchenko int
sfc_port_get_mac_stats(struct sfc_adapter * sa,struct rte_eth_xstat * xstats,unsigned int xstats_count,unsigned int * nb_written)66621ca2629SIvan Ilchenko sfc_port_get_mac_stats(struct sfc_adapter *sa, struct rte_eth_xstat *xstats,
66721ca2629SIvan Ilchenko unsigned int xstats_count, unsigned int *nb_written)
66821ca2629SIvan Ilchenko {
66921ca2629SIvan Ilchenko struct sfc_port *port = &sa->port;
67021ca2629SIvan Ilchenko uint64_t *mac_stats;
67121ca2629SIvan Ilchenko unsigned int i;
67221ca2629SIvan Ilchenko int nstats = 0;
67321ca2629SIvan Ilchenko int ret;
67421ca2629SIvan Ilchenko
67521ca2629SIvan Ilchenko sfc_adapter_lock(sa);
67621ca2629SIvan Ilchenko
67721ca2629SIvan Ilchenko ret = sfc_port_update_mac_stats(sa, B_FALSE);
67821ca2629SIvan Ilchenko if (ret != 0) {
67921ca2629SIvan Ilchenko SFC_ASSERT(ret > 0);
68021ca2629SIvan Ilchenko ret = -ret;
68121ca2629SIvan Ilchenko goto unlock;
68221ca2629SIvan Ilchenko }
68321ca2629SIvan Ilchenko
68421ca2629SIvan Ilchenko mac_stats = port->mac_stats_buf;
68521ca2629SIvan Ilchenko
68621ca2629SIvan Ilchenko for (i = 0; i < EFX_MAC_NSTATS; ++i) {
68721ca2629SIvan Ilchenko if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) {
68821ca2629SIvan Ilchenko if (nstats < (int)xstats_count) {
68921ca2629SIvan Ilchenko xstats[nstats].id = nstats;
69021ca2629SIvan Ilchenko xstats[nstats].value = mac_stats[i];
69121ca2629SIvan Ilchenko (*nb_written)++;
69221ca2629SIvan Ilchenko }
69321ca2629SIvan Ilchenko nstats++;
69421ca2629SIvan Ilchenko }
69521ca2629SIvan Ilchenko }
69621ca2629SIvan Ilchenko ret = nstats;
69721ca2629SIvan Ilchenko
69821ca2629SIvan Ilchenko unlock:
69921ca2629SIvan Ilchenko sfc_adapter_unlock(sa);
70021ca2629SIvan Ilchenko
70121ca2629SIvan Ilchenko return ret;
70221ca2629SIvan Ilchenko }
70321ca2629SIvan Ilchenko
70421ca2629SIvan Ilchenko int
sfc_port_get_mac_stats_by_id(struct sfc_adapter * sa,const uint64_t * ids,uint64_t * values,unsigned int n)70521ca2629SIvan Ilchenko sfc_port_get_mac_stats_by_id(struct sfc_adapter *sa, const uint64_t *ids,
70621ca2629SIvan Ilchenko uint64_t *values, unsigned int n)
70721ca2629SIvan Ilchenko {
70821ca2629SIvan Ilchenko struct sfc_port *port = &sa->port;
70921ca2629SIvan Ilchenko uint64_t *mac_stats;
71021ca2629SIvan Ilchenko unsigned int i;
71121ca2629SIvan Ilchenko int ret;
71221ca2629SIvan Ilchenko int rc;
71321ca2629SIvan Ilchenko
71421ca2629SIvan Ilchenko sfc_adapter_lock(sa);
71521ca2629SIvan Ilchenko
71621ca2629SIvan Ilchenko rc = sfc_port_update_mac_stats(sa, B_FALSE);
71721ca2629SIvan Ilchenko if (rc != 0) {
71821ca2629SIvan Ilchenko SFC_ASSERT(rc > 0);
71921ca2629SIvan Ilchenko ret = -rc;
72021ca2629SIvan Ilchenko goto unlock;
72121ca2629SIvan Ilchenko }
72221ca2629SIvan Ilchenko
72321ca2629SIvan Ilchenko mac_stats = port->mac_stats_buf;
72421ca2629SIvan Ilchenko
72521ca2629SIvan Ilchenko SFC_ASSERT(port->mac_stats_nb_supported <=
72621ca2629SIvan Ilchenko RTE_DIM(port->mac_stats_by_id));
72721ca2629SIvan Ilchenko
72821ca2629SIvan Ilchenko for (i = 0; i < n; i++) {
729fdd7719eSIvan Ilchenko if (ids[i] < port->mac_stats_nb_supported)
73021ca2629SIvan Ilchenko values[i] = mac_stats[port->mac_stats_by_id[ids[i]]];
73121ca2629SIvan Ilchenko }
73221ca2629SIvan Ilchenko
733fdd7719eSIvan Ilchenko ret = 0;
73421ca2629SIvan Ilchenko
73521ca2629SIvan Ilchenko unlock:
73621ca2629SIvan Ilchenko sfc_adapter_unlock(sa);
73721ca2629SIvan Ilchenko
73821ca2629SIvan Ilchenko return ret;
73921ca2629SIvan Ilchenko }
740