12246cbc2SShay Agroskin // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
21738cd3eSNetanel Belgazal /*
32246cbc2SShay Agroskin * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
41738cd3eSNetanel Belgazal */
51738cd3eSNetanel Belgazal
6cc69837fSJakub Kicinski #include <linux/ethtool.h>
71738cd3eSNetanel Belgazal #include <linux/pci.h>
81738cd3eSNetanel Belgazal
91738cd3eSNetanel Belgazal #include "ena_netdev.h"
10*c891d767SDavid Arinzon #include "ena_xdp.h"
111738cd3eSNetanel Belgazal
121738cd3eSNetanel Belgazal struct ena_stats {
131738cd3eSNetanel Belgazal char name[ETH_GSTRING_LEN];
141738cd3eSNetanel Belgazal int stat_offset;
151738cd3eSNetanel Belgazal };
161738cd3eSNetanel Belgazal
171738cd3eSNetanel Belgazal #define ENA_STAT_ENA_COM_ENTRY(stat) { \
181738cd3eSNetanel Belgazal .name = #stat, \
19f1852d64SSameeh Jubran .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \
201738cd3eSNetanel Belgazal }
211738cd3eSNetanel Belgazal
221738cd3eSNetanel Belgazal #define ENA_STAT_ENTRY(stat, stat_type) { \
231738cd3eSNetanel Belgazal .name = #stat, \
24f1852d64SSameeh Jubran .stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \
251738cd3eSNetanel Belgazal }
261738cd3eSNetanel Belgazal
27713865daSSameeh Jubran #define ENA_STAT_HW_ENTRY(stat, stat_type) { \
28713865daSSameeh Jubran .name = #stat, \
29713865daSSameeh Jubran .stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \
30713865daSSameeh Jubran }
31713865daSSameeh Jubran
321738cd3eSNetanel Belgazal #define ENA_STAT_RX_ENTRY(stat) \
331738cd3eSNetanel Belgazal ENA_STAT_ENTRY(stat, rx)
341738cd3eSNetanel Belgazal
351738cd3eSNetanel Belgazal #define ENA_STAT_TX_ENTRY(stat) \
361738cd3eSNetanel Belgazal ENA_STAT_ENTRY(stat, tx)
371738cd3eSNetanel Belgazal
381738cd3eSNetanel Belgazal #define ENA_STAT_GLOBAL_ENTRY(stat) \
391738cd3eSNetanel Belgazal ENA_STAT_ENTRY(stat, dev)
401738cd3eSNetanel Belgazal
41713865daSSameeh Jubran #define ENA_STAT_ENI_ENTRY(stat) \
42713865daSSameeh Jubran ENA_STAT_HW_ENTRY(stat, eni_stats)
43713865daSSameeh Jubran
441738cd3eSNetanel Belgazal static const struct ena_stats ena_stats_global_strings[] = {
451738cd3eSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(tx_timeout),
468c5c7abdSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(suspend),
478c5c7abdSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(resume),
481738cd3eSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(wd_expired),
491738cd3eSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(interface_up),
501738cd3eSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(interface_down),
511738cd3eSNetanel Belgazal ENA_STAT_GLOBAL_ENTRY(admin_q_pause),
521738cd3eSNetanel Belgazal };
531738cd3eSNetanel Belgazal
54713865daSSameeh Jubran static const struct ena_stats ena_stats_eni_strings[] = {
55713865daSSameeh Jubran ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded),
56713865daSSameeh Jubran ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded),
57713865daSSameeh Jubran ENA_STAT_ENI_ENTRY(pps_allowance_exceeded),
58713865daSSameeh Jubran ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded),
59713865daSSameeh Jubran ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded),
60713865daSSameeh Jubran };
61713865daSSameeh Jubran
621738cd3eSNetanel Belgazal static const struct ena_stats ena_stats_tx_strings[] = {
631738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(cnt),
641738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(bytes),
651738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(queue_stop),
661738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(queue_wakeup),
671738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(dma_mapping_err),
681738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(linearize),
691738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(linearize_failed),
701738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(napi_comp),
711738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(tx_poll),
721738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(doorbells),
731738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(prepare_ctx_err),
741738cd3eSNetanel Belgazal ENA_STAT_TX_ENTRY(bad_req_id),
7538005ca8SArthur Kiyanovski ENA_STAT_TX_ENTRY(llq_buffer_copy),
7611095fdbSNetanel Belgazal ENA_STAT_TX_ENTRY(missed_tx),
77d4a8b3bbSSameeh Jubran ENA_STAT_TX_ENTRY(unmask_interrupt),
781738cd3eSNetanel Belgazal };
791738cd3eSNetanel Belgazal
801738cd3eSNetanel Belgazal static const struct ena_stats ena_stats_rx_strings[] = {
811738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(cnt),
821738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(bytes),
83d2eecc6eSSameeh Jubran ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
84d2eecc6eSSameeh Jubran ENA_STAT_RX_ENTRY(csum_good),
851738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(refil_partial),
86d0e8831dSArthur Kiyanovski ENA_STAT_RX_ENTRY(csum_bad),
871738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(page_alloc_fail),
881738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(skb_alloc_fail),
891738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(dma_mapping_err),
901738cd3eSNetanel Belgazal ENA_STAT_RX_ENTRY(bad_desc_num),
91ad974baeSNetanel Belgazal ENA_STAT_RX_ENTRY(bad_req_id),
92a3af7c18SNetanel Belgazal ENA_STAT_RX_ENTRY(empty_rx_ring),
93cb36bb36SArthur Kiyanovski ENA_STAT_RX_ENTRY(csum_unchecked),
944cd28b21SSameeh Jubran ENA_STAT_RX_ENTRY(xdp_aborted),
954cd28b21SSameeh Jubran ENA_STAT_RX_ENTRY(xdp_drop),
964cd28b21SSameeh Jubran ENA_STAT_RX_ENTRY(xdp_pass),
974cd28b21SSameeh Jubran ENA_STAT_RX_ENTRY(xdp_tx),
984cd28b21SSameeh Jubran ENA_STAT_RX_ENTRY(xdp_invalid),
99a318c70aSShay Agroskin ENA_STAT_RX_ENTRY(xdp_redirect),
1001738cd3eSNetanel Belgazal };
1011738cd3eSNetanel Belgazal
1021738cd3eSNetanel Belgazal static const struct ena_stats ena_stats_ena_com_strings[] = {
1031738cd3eSNetanel Belgazal ENA_STAT_ENA_COM_ENTRY(aborted_cmd),
1041738cd3eSNetanel Belgazal ENA_STAT_ENA_COM_ENTRY(submitted_cmd),
1051738cd3eSNetanel Belgazal ENA_STAT_ENA_COM_ENTRY(completed_cmd),
1061738cd3eSNetanel Belgazal ENA_STAT_ENA_COM_ENTRY(out_of_space),
1071738cd3eSNetanel Belgazal ENA_STAT_ENA_COM_ENTRY(no_completion),
1081738cd3eSNetanel Belgazal };
1091738cd3eSNetanel Belgazal
1101738cd3eSNetanel Belgazal #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings)
1111738cd3eSNetanel Belgazal #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings)
1121738cd3eSNetanel Belgazal #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings)
1131738cd3eSNetanel Belgazal #define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings)
114394c48e0SArthur Kiyanovski #define ENA_STATS_ARRAY_ENI(adapter) ARRAY_SIZE(ena_stats_eni_strings)
1151738cd3eSNetanel Belgazal
ena_safe_update_stat(u64 * src,u64 * dst,struct u64_stats_sync * syncp)1161738cd3eSNetanel Belgazal static void ena_safe_update_stat(u64 *src, u64 *dst,
1171738cd3eSNetanel Belgazal struct u64_stats_sync *syncp)
1181738cd3eSNetanel Belgazal {
1191738cd3eSNetanel Belgazal unsigned int start;
1201738cd3eSNetanel Belgazal
1211738cd3eSNetanel Belgazal do {
122068c38adSThomas Gleixner start = u64_stats_fetch_begin(syncp);
1231738cd3eSNetanel Belgazal *(dst) = *src;
124068c38adSThomas Gleixner } while (u64_stats_fetch_retry(syncp, start));
1251738cd3eSNetanel Belgazal }
1261738cd3eSNetanel Belgazal
ena_queue_stats(struct ena_adapter * adapter,u64 ** data)1271738cd3eSNetanel Belgazal static void ena_queue_stats(struct ena_adapter *adapter, u64 **data)
1281738cd3eSNetanel Belgazal {
1291738cd3eSNetanel Belgazal const struct ena_stats *ena_stats;
1301738cd3eSNetanel Belgazal struct ena_ring *ring;
1311738cd3eSNetanel Belgazal
1321738cd3eSNetanel Belgazal u64 *ptr;
1331738cd3eSNetanel Belgazal int i, j;
1341738cd3eSNetanel Belgazal
1350201bda1SSameeh Jubran for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
1361738cd3eSNetanel Belgazal /* Tx stats */
1371738cd3eSNetanel Belgazal ring = &adapter->tx_ring[i];
1381738cd3eSNetanel Belgazal
1391738cd3eSNetanel Belgazal for (j = 0; j < ENA_STATS_ARRAY_TX; j++) {
1401738cd3eSNetanel Belgazal ena_stats = &ena_stats_tx_strings[j];
1411738cd3eSNetanel Belgazal
142f1852d64SSameeh Jubran ptr = (u64 *)&ring->tx_stats + ena_stats->stat_offset;
1431738cd3eSNetanel Belgazal
1441738cd3eSNetanel Belgazal ena_safe_update_stat(ptr, (*data)++, &ring->syncp);
1451738cd3eSNetanel Belgazal }
1460201bda1SSameeh Jubran /* XDP TX queues don't have a RX queue counterpart */
1470201bda1SSameeh Jubran if (!ENA_IS_XDP_INDEX(adapter, i)) {
1481738cd3eSNetanel Belgazal /* Rx stats */
1491738cd3eSNetanel Belgazal ring = &adapter->rx_ring[i];
1501738cd3eSNetanel Belgazal
1511738cd3eSNetanel Belgazal for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
1521738cd3eSNetanel Belgazal ena_stats = &ena_stats_rx_strings[j];
1531738cd3eSNetanel Belgazal
154f1852d64SSameeh Jubran ptr = (u64 *)&ring->rx_stats +
155f1852d64SSameeh Jubran ena_stats->stat_offset;
1561738cd3eSNetanel Belgazal
1571738cd3eSNetanel Belgazal ena_safe_update_stat(ptr, (*data)++, &ring->syncp);
1581738cd3eSNetanel Belgazal }
1591738cd3eSNetanel Belgazal }
1601738cd3eSNetanel Belgazal }
1610201bda1SSameeh Jubran }
1621738cd3eSNetanel Belgazal
ena_dev_admin_queue_stats(struct ena_adapter * adapter,u64 ** data)1631738cd3eSNetanel Belgazal static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data)
1641738cd3eSNetanel Belgazal {
1651738cd3eSNetanel Belgazal const struct ena_stats *ena_stats;
1660dcec686SArthur Kiyanovski u64 *ptr;
1671738cd3eSNetanel Belgazal int i;
1681738cd3eSNetanel Belgazal
1691738cd3eSNetanel Belgazal for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) {
1701738cd3eSNetanel Belgazal ena_stats = &ena_stats_ena_com_strings[i];
1711738cd3eSNetanel Belgazal
172f1852d64SSameeh Jubran ptr = (u64 *)&adapter->ena_dev->admin_queue.stats +
173f1852d64SSameeh Jubran ena_stats->stat_offset;
1741738cd3eSNetanel Belgazal
1751738cd3eSNetanel Belgazal *(*data)++ = *ptr;
1761738cd3eSNetanel Belgazal }
1771738cd3eSNetanel Belgazal }
1781738cd3eSNetanel Belgazal
ena_get_stats(struct ena_adapter * adapter,u64 * data,bool eni_stats_needed)179713865daSSameeh Jubran static void ena_get_stats(struct ena_adapter *adapter,
180713865daSSameeh Jubran u64 *data,
181713865daSSameeh Jubran bool eni_stats_needed)
1821738cd3eSNetanel Belgazal {
1831738cd3eSNetanel Belgazal const struct ena_stats *ena_stats;
1841738cd3eSNetanel Belgazal u64 *ptr;
1851738cd3eSNetanel Belgazal int i;
1861738cd3eSNetanel Belgazal
1871738cd3eSNetanel Belgazal for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
1881738cd3eSNetanel Belgazal ena_stats = &ena_stats_global_strings[i];
1891738cd3eSNetanel Belgazal
190f1852d64SSameeh Jubran ptr = (u64 *)&adapter->dev_stats + ena_stats->stat_offset;
1911738cd3eSNetanel Belgazal
1921738cd3eSNetanel Belgazal ena_safe_update_stat(ptr, data++, &adapter->syncp);
1931738cd3eSNetanel Belgazal }
1941738cd3eSNetanel Belgazal
195713865daSSameeh Jubran if (eni_stats_needed) {
196713865daSSameeh Jubran ena_update_hw_stats(adapter);
197713865daSSameeh Jubran for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
198713865daSSameeh Jubran ena_stats = &ena_stats_eni_strings[i];
199713865daSSameeh Jubran
200713865daSSameeh Jubran ptr = (u64 *)&adapter->eni_stats +
201713865daSSameeh Jubran ena_stats->stat_offset;
202713865daSSameeh Jubran
203713865daSSameeh Jubran ena_safe_update_stat(ptr, data++, &adapter->syncp);
204713865daSSameeh Jubran }
205713865daSSameeh Jubran }
206713865daSSameeh Jubran
2071738cd3eSNetanel Belgazal ena_queue_stats(adapter, &data);
2081738cd3eSNetanel Belgazal ena_dev_admin_queue_stats(adapter, &data);
2091738cd3eSNetanel Belgazal }
2101738cd3eSNetanel Belgazal
ena_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)211713865daSSameeh Jubran static void ena_get_ethtool_stats(struct net_device *netdev,
212713865daSSameeh Jubran struct ethtool_stats *stats,
213713865daSSameeh Jubran u64 *data)
214713865daSSameeh Jubran {
215713865daSSameeh Jubran struct ena_adapter *adapter = netdev_priv(netdev);
216394c48e0SArthur Kiyanovski struct ena_com_dev *dev = adapter->ena_dev;
217713865daSSameeh Jubran
218394c48e0SArthur Kiyanovski ena_get_stats(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS));
219713865daSSameeh Jubran }
220713865daSSameeh Jubran
ena_get_sw_stats_count(struct ena_adapter * adapter)221713865daSSameeh Jubran static int ena_get_sw_stats_count(struct ena_adapter *adapter)
222713865daSSameeh Jubran {
223713865daSSameeh Jubran return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
2240201bda1SSameeh Jubran + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX
225713865daSSameeh Jubran + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
226713865daSSameeh Jubran }
227713865daSSameeh Jubran
ena_get_hw_stats_count(struct ena_adapter * adapter)228713865daSSameeh Jubran static int ena_get_hw_stats_count(struct ena_adapter *adapter)
229713865daSSameeh Jubran {
230394c48e0SArthur Kiyanovski bool supported = ena_com_get_cap(adapter->ena_dev, ENA_ADMIN_ENI_STATS);
231394c48e0SArthur Kiyanovski
232394c48e0SArthur Kiyanovski return ENA_STATS_ARRAY_ENI(adapter) * supported;
233713865daSSameeh Jubran }
234713865daSSameeh Jubran
ena_get_sset_count(struct net_device * netdev,int sset)2351738cd3eSNetanel Belgazal int ena_get_sset_count(struct net_device *netdev, int sset)
2361738cd3eSNetanel Belgazal {
2371738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
2381738cd3eSNetanel Belgazal
239a01f2cd0SShay Agroskin switch (sset) {
240a01f2cd0SShay Agroskin case ETH_SS_STATS:
241a01f2cd0SShay Agroskin return ena_get_sw_stats_count(adapter) +
242a01f2cd0SShay Agroskin ena_get_hw_stats_count(adapter);
243a01f2cd0SShay Agroskin }
244eb203baeSJakub Kicinski
245a01f2cd0SShay Agroskin return -EOPNOTSUPP;
2461738cd3eSNetanel Belgazal }
2471738cd3eSNetanel Belgazal
ena_queue_strings(struct ena_adapter * adapter,u8 ** data)2481738cd3eSNetanel Belgazal static void ena_queue_strings(struct ena_adapter *adapter, u8 **data)
2491738cd3eSNetanel Belgazal {
2501738cd3eSNetanel Belgazal const struct ena_stats *ena_stats;
2510201bda1SSameeh Jubran bool is_xdp;
2521738cd3eSNetanel Belgazal int i, j;
2531738cd3eSNetanel Belgazal
2540201bda1SSameeh Jubran for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
2550201bda1SSameeh Jubran is_xdp = ENA_IS_XDP_INDEX(adapter, i);
2561738cd3eSNetanel Belgazal /* Tx stats */
2571738cd3eSNetanel Belgazal for (j = 0; j < ENA_STATS_ARRAY_TX; j++) {
2581738cd3eSNetanel Belgazal ena_stats = &ena_stats_tx_strings[j];
2591738cd3eSNetanel Belgazal
260efbbe4fbSAlexander Duyck ethtool_sprintf(data,
2610201bda1SSameeh Jubran "queue_%u_%s_%s", i,
262efbbe4fbSAlexander Duyck is_xdp ? "xdp_tx" : "tx",
263efbbe4fbSAlexander Duyck ena_stats->name);
2641738cd3eSNetanel Belgazal }
2650201bda1SSameeh Jubran
2660201bda1SSameeh Jubran if (!is_xdp) {
2670201bda1SSameeh Jubran /* RX stats, in XDP there isn't a RX queue
2680201bda1SSameeh Jubran * counterpart
2690201bda1SSameeh Jubran */
2701738cd3eSNetanel Belgazal for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
2711738cd3eSNetanel Belgazal ena_stats = &ena_stats_rx_strings[j];
2721738cd3eSNetanel Belgazal
273efbbe4fbSAlexander Duyck ethtool_sprintf(data,
274efbbe4fbSAlexander Duyck "queue_%u_rx_%s", i,
275efbbe4fbSAlexander Duyck ena_stats->name);
2761738cd3eSNetanel Belgazal }
2771738cd3eSNetanel Belgazal }
2781738cd3eSNetanel Belgazal }
2790201bda1SSameeh Jubran }
2801738cd3eSNetanel Belgazal
ena_com_dev_strings(u8 ** data)2811738cd3eSNetanel Belgazal static void ena_com_dev_strings(u8 **data)
2821738cd3eSNetanel Belgazal {
2831738cd3eSNetanel Belgazal const struct ena_stats *ena_stats;
2841738cd3eSNetanel Belgazal int i;
2851738cd3eSNetanel Belgazal
2861738cd3eSNetanel Belgazal for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) {
2871738cd3eSNetanel Belgazal ena_stats = &ena_stats_ena_com_strings[i];
2881738cd3eSNetanel Belgazal
289efbbe4fbSAlexander Duyck ethtool_sprintf(data,
2901738cd3eSNetanel Belgazal "ena_admin_q_%s", ena_stats->name);
2911738cd3eSNetanel Belgazal }
2921738cd3eSNetanel Belgazal }
2931738cd3eSNetanel Belgazal
ena_get_strings(struct ena_adapter * adapter,u8 * data,bool eni_stats_needed)294713865daSSameeh Jubran static void ena_get_strings(struct ena_adapter *adapter,
295713865daSSameeh Jubran u8 *data,
296713865daSSameeh Jubran bool eni_stats_needed)
297315c28d2SArthur Kiyanovski {
298eb203baeSJakub Kicinski const struct ena_stats *ena_stats;
299eb203baeSJakub Kicinski int i;
300315c28d2SArthur Kiyanovski
301eb203baeSJakub Kicinski for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
302eb203baeSJakub Kicinski ena_stats = &ena_stats_global_strings[i];
303efbbe4fbSAlexander Duyck ethtool_sprintf(&data, ena_stats->name);
304315c28d2SArthur Kiyanovski }
305eb203baeSJakub Kicinski
306713865daSSameeh Jubran if (eni_stats_needed) {
307713865daSSameeh Jubran for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
308713865daSSameeh Jubran ena_stats = &ena_stats_eni_strings[i];
309efbbe4fbSAlexander Duyck ethtool_sprintf(&data, ena_stats->name);
310713865daSSameeh Jubran }
311713865daSSameeh Jubran }
312713865daSSameeh Jubran
313eb203baeSJakub Kicinski ena_queue_strings(adapter, &data);
314eb203baeSJakub Kicinski ena_com_dev_strings(&data);
315315c28d2SArthur Kiyanovski }
316315c28d2SArthur Kiyanovski
ena_get_ethtool_strings(struct net_device * netdev,u32 sset,u8 * data)317713865daSSameeh Jubran static void ena_get_ethtool_strings(struct net_device *netdev,
318713865daSSameeh Jubran u32 sset,
319713865daSSameeh Jubran u8 *data)
320713865daSSameeh Jubran {
321713865daSSameeh Jubran struct ena_adapter *adapter = netdev_priv(netdev);
322394c48e0SArthur Kiyanovski struct ena_com_dev *dev = adapter->ena_dev;
323713865daSSameeh Jubran
324a01f2cd0SShay Agroskin switch (sset) {
325a01f2cd0SShay Agroskin case ETH_SS_STATS:
326394c48e0SArthur Kiyanovski ena_get_strings(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS));
327a01f2cd0SShay Agroskin break;
328a01f2cd0SShay Agroskin }
329713865daSSameeh Jubran }
330713865daSSameeh Jubran
ena_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * link_ksettings)3311738cd3eSNetanel Belgazal static int ena_get_link_ksettings(struct net_device *netdev,
3321738cd3eSNetanel Belgazal struct ethtool_link_ksettings *link_ksettings)
3331738cd3eSNetanel Belgazal {
3341738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
3351738cd3eSNetanel Belgazal struct ena_com_dev *ena_dev = adapter->ena_dev;
3361738cd3eSNetanel Belgazal struct ena_admin_get_feature_link_desc *link;
3371738cd3eSNetanel Belgazal struct ena_admin_get_feat_resp feat_resp;
3381738cd3eSNetanel Belgazal int rc;
3391738cd3eSNetanel Belgazal
3401738cd3eSNetanel Belgazal rc = ena_com_get_link_params(ena_dev, &feat_resp);
3411738cd3eSNetanel Belgazal if (rc)
3421738cd3eSNetanel Belgazal return rc;
3431738cd3eSNetanel Belgazal
3441738cd3eSNetanel Belgazal link = &feat_resp.u.link;
3451738cd3eSNetanel Belgazal link_ksettings->base.speed = link->speed;
3461738cd3eSNetanel Belgazal
3471738cd3eSNetanel Belgazal if (link->flags & ENA_ADMIN_GET_FEATURE_LINK_DESC_AUTONEG_MASK) {
3481738cd3eSNetanel Belgazal ethtool_link_ksettings_add_link_mode(link_ksettings,
3491738cd3eSNetanel Belgazal supported, Autoneg);
3501738cd3eSNetanel Belgazal ethtool_link_ksettings_add_link_mode(link_ksettings,
3511738cd3eSNetanel Belgazal supported, Autoneg);
3521738cd3eSNetanel Belgazal }
3531738cd3eSNetanel Belgazal
3541738cd3eSNetanel Belgazal link_ksettings->base.autoneg =
3551738cd3eSNetanel Belgazal (link->flags & ENA_ADMIN_GET_FEATURE_LINK_DESC_AUTONEG_MASK) ?
3561738cd3eSNetanel Belgazal AUTONEG_ENABLE : AUTONEG_DISABLE;
3571738cd3eSNetanel Belgazal
3581738cd3eSNetanel Belgazal link_ksettings->base.duplex = DUPLEX_FULL;
3591738cd3eSNetanel Belgazal
3601738cd3eSNetanel Belgazal return 0;
3611738cd3eSNetanel Belgazal }
3621738cd3eSNetanel Belgazal
ena_get_coalesce(struct net_device * net_dev,struct ethtool_coalesce * coalesce,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)3631738cd3eSNetanel Belgazal static int ena_get_coalesce(struct net_device *net_dev,
364f3ccfda1SYufeng Mo struct ethtool_coalesce *coalesce,
365f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
366f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
3671738cd3eSNetanel Belgazal {
3681738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(net_dev);
3691738cd3eSNetanel Belgazal struct ena_com_dev *ena_dev = adapter->ena_dev;
3701738cd3eSNetanel Belgazal
371f3020447SArthur Kiyanovski if (!ena_com_interrupt_moderation_supported(ena_dev))
3721738cd3eSNetanel Belgazal return -EOPNOTSUPP;
3730eda8479SArthur Kiyanovski
3741738cd3eSNetanel Belgazal coalesce->tx_coalesce_usecs =
3750eda8479SArthur Kiyanovski ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) *
3761738cd3eSNetanel Belgazal ena_dev->intr_delay_resolution;
377b3db86dcSArthur Kiyanovski
3781738cd3eSNetanel Belgazal coalesce->rx_coalesce_usecs =
3791738cd3eSNetanel Belgazal ena_com_get_nonadaptive_moderation_interval_rx(ena_dev)
3800eda8479SArthur Kiyanovski * ena_dev->intr_delay_resolution;
3811738cd3eSNetanel Belgazal
3821738cd3eSNetanel Belgazal coalesce->use_adaptive_rx_coalesce =
3831738cd3eSNetanel Belgazal ena_com_get_adaptive_moderation_enabled(ena_dev);
3841738cd3eSNetanel Belgazal
3851738cd3eSNetanel Belgazal return 0;
3861738cd3eSNetanel Belgazal }
3871738cd3eSNetanel Belgazal
ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter * adapter)38895d0fcb5SArthur Kiyanovski static void ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter)
3891738cd3eSNetanel Belgazal {
3901738cd3eSNetanel Belgazal unsigned int val;
3911738cd3eSNetanel Belgazal int i;
3921738cd3eSNetanel Belgazal
3931738cd3eSNetanel Belgazal val = ena_com_get_nonadaptive_moderation_interval_tx(adapter->ena_dev);
3941738cd3eSNetanel Belgazal
395faa615f9SSameeh Jubran for (i = 0; i < adapter->num_io_queues; i++)
3961738cd3eSNetanel Belgazal adapter->tx_ring[i].smoothed_interval = val;
3971738cd3eSNetanel Belgazal }
3981738cd3eSNetanel Belgazal
ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter * adapter)39995d0fcb5SArthur Kiyanovski static void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter)
400b3db86dcSArthur Kiyanovski {
401b3db86dcSArthur Kiyanovski unsigned int val;
402b3db86dcSArthur Kiyanovski int i;
403b3db86dcSArthur Kiyanovski
404b3db86dcSArthur Kiyanovski val = ena_com_get_nonadaptive_moderation_interval_rx(adapter->ena_dev);
405b3db86dcSArthur Kiyanovski
406faa615f9SSameeh Jubran for (i = 0; i < adapter->num_io_queues; i++)
407b3db86dcSArthur Kiyanovski adapter->rx_ring[i].smoothed_interval = val;
408b3db86dcSArthur Kiyanovski }
409b3db86dcSArthur Kiyanovski
ena_set_coalesce(struct net_device * net_dev,struct ethtool_coalesce * coalesce,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)4101738cd3eSNetanel Belgazal static int ena_set_coalesce(struct net_device *net_dev,
411f3ccfda1SYufeng Mo struct ethtool_coalesce *coalesce,
412f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
413f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
4141738cd3eSNetanel Belgazal {
4151738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(net_dev);
4161738cd3eSNetanel Belgazal struct ena_com_dev *ena_dev = adapter->ena_dev;
4171738cd3eSNetanel Belgazal int rc;
4181738cd3eSNetanel Belgazal
419f3020447SArthur Kiyanovski if (!ena_com_interrupt_moderation_supported(ena_dev))
4201738cd3eSNetanel Belgazal return -EOPNOTSUPP;
4211738cd3eSNetanel Belgazal
4221738cd3eSNetanel Belgazal rc = ena_com_update_nonadaptive_moderation_interval_tx(ena_dev,
4231738cd3eSNetanel Belgazal coalesce->tx_coalesce_usecs);
4241738cd3eSNetanel Belgazal if (rc)
4251738cd3eSNetanel Belgazal return rc;
4261738cd3eSNetanel Belgazal
42795d0fcb5SArthur Kiyanovski ena_update_tx_rings_nonadaptive_intr_moderation(adapter);
4281738cd3eSNetanel Belgazal
4291738cd3eSNetanel Belgazal rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev,
4301738cd3eSNetanel Belgazal coalesce->rx_coalesce_usecs);
431b3db86dcSArthur Kiyanovski if (rc)
4321738cd3eSNetanel Belgazal return rc;
433b3db86dcSArthur Kiyanovski
43495d0fcb5SArthur Kiyanovski ena_update_rx_rings_nonadaptive_intr_moderation(adapter);
435b3db86dcSArthur Kiyanovski
43641c53caaSArthur Kiyanovski if (coalesce->use_adaptive_rx_coalesce &&
43741c53caaSArthur Kiyanovski !ena_com_get_adaptive_moderation_enabled(ena_dev))
43841c53caaSArthur Kiyanovski ena_com_enable_adaptive_moderation(ena_dev);
43941c53caaSArthur Kiyanovski
44041c53caaSArthur Kiyanovski if (!coalesce->use_adaptive_rx_coalesce &&
44141c53caaSArthur Kiyanovski ena_com_get_adaptive_moderation_enabled(ena_dev))
442b3db86dcSArthur Kiyanovski ena_com_disable_adaptive_moderation(ena_dev);
4431738cd3eSNetanel Belgazal
4441738cd3eSNetanel Belgazal return 0;
4451738cd3eSNetanel Belgazal }
4461738cd3eSNetanel Belgazal
ena_get_msglevel(struct net_device * netdev)4471738cd3eSNetanel Belgazal static u32 ena_get_msglevel(struct net_device *netdev)
4481738cd3eSNetanel Belgazal {
4491738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
4501738cd3eSNetanel Belgazal
4511738cd3eSNetanel Belgazal return adapter->msg_enable;
4521738cd3eSNetanel Belgazal }
4531738cd3eSNetanel Belgazal
ena_set_msglevel(struct net_device * netdev,u32 value)4541738cd3eSNetanel Belgazal static void ena_set_msglevel(struct net_device *netdev, u32 value)
4551738cd3eSNetanel Belgazal {
4561738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
4571738cd3eSNetanel Belgazal
4581738cd3eSNetanel Belgazal adapter->msg_enable = value;
4591738cd3eSNetanel Belgazal }
4601738cd3eSNetanel Belgazal
ena_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)4611738cd3eSNetanel Belgazal static void ena_get_drvinfo(struct net_device *dev,
4621738cd3eSNetanel Belgazal struct ethtool_drvinfo *info)
4631738cd3eSNetanel Belgazal {
4641738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(dev);
4651738cd3eSNetanel Belgazal
466f029c781SWolfram Sang strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
467f029c781SWolfram Sang strscpy(info->bus_info, pci_name(adapter->pdev),
4681738cd3eSNetanel Belgazal sizeof(info->bus_info));
4691738cd3eSNetanel Belgazal }
4701738cd3eSNetanel Belgazal
ena_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)4711738cd3eSNetanel Belgazal static void ena_get_ringparam(struct net_device *netdev,
47274624944SHao Chen struct ethtool_ringparam *ring,
47374624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
47474624944SHao Chen struct netlink_ext_ack *extack)
4751738cd3eSNetanel Belgazal {
4761738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
4771738cd3eSNetanel Belgazal
4789f9ae3f9SSameeh Jubran ring->tx_max_pending = adapter->max_tx_ring_size;
4799f9ae3f9SSameeh Jubran ring->rx_max_pending = adapter->max_rx_ring_size;
480b0c59e53SShay Agroskin if (adapter->ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
481b0c59e53SShay Agroskin bool large_llq_supported = adapter->large_llq_header_supported;
482b0c59e53SShay Agroskin
483060cdac2SShay Agroskin kernel_ring->tx_push = true;
484b0c59e53SShay Agroskin kernel_ring->tx_push_buf_len = adapter->ena_dev->tx_max_header_size;
485b0c59e53SShay Agroskin if (large_llq_supported)
486b0c59e53SShay Agroskin kernel_ring->tx_push_buf_max_len = ENA_LLQ_LARGE_HEADER;
487b0c59e53SShay Agroskin else
488b0c59e53SShay Agroskin kernel_ring->tx_push_buf_max_len = ENA_LLQ_HEADER;
489b0c59e53SShay Agroskin } else {
490060cdac2SShay Agroskin kernel_ring->tx_push = false;
491b0c59e53SShay Agroskin kernel_ring->tx_push_buf_max_len = 0;
492b0c59e53SShay Agroskin kernel_ring->tx_push_buf_len = 0;
493b0c59e53SShay Agroskin }
494b0c59e53SShay Agroskin
49513ca32a6SSameeh Jubran ring->tx_pending = adapter->tx_ring[0].ring_size;
49613ca32a6SSameeh Jubran ring->rx_pending = adapter->rx_ring[0].ring_size;
4971738cd3eSNetanel Belgazal }
4981738cd3eSNetanel Belgazal
ena_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)499eece4d2aSSameeh Jubran static int ena_set_ringparam(struct net_device *netdev,
50074624944SHao Chen struct ethtool_ringparam *ring,
50174624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
50274624944SHao Chen struct netlink_ext_ack *extack)
503eece4d2aSSameeh Jubran {
504eece4d2aSSameeh Jubran struct ena_adapter *adapter = netdev_priv(netdev);
505b0c59e53SShay Agroskin u32 new_tx_size, new_rx_size, new_tx_push_buf_len;
506b0c59e53SShay Agroskin bool changed = false;
507eece4d2aSSameeh Jubran
508eece4d2aSSameeh Jubran new_tx_size = ring->tx_pending < ENA_MIN_RING_SIZE ?
509eece4d2aSSameeh Jubran ENA_MIN_RING_SIZE : ring->tx_pending;
510eece4d2aSSameeh Jubran new_tx_size = rounddown_pow_of_two(new_tx_size);
511eece4d2aSSameeh Jubran
512eece4d2aSSameeh Jubran new_rx_size = ring->rx_pending < ENA_MIN_RING_SIZE ?
513eece4d2aSSameeh Jubran ENA_MIN_RING_SIZE : ring->rx_pending;
514eece4d2aSSameeh Jubran new_rx_size = rounddown_pow_of_two(new_rx_size);
515eece4d2aSSameeh Jubran
516b0c59e53SShay Agroskin changed |= new_tx_size != adapter->requested_tx_ring_size ||
517b0c59e53SShay Agroskin new_rx_size != adapter->requested_rx_ring_size;
518b0c59e53SShay Agroskin
519b0c59e53SShay Agroskin /* This value is ignored if LLQ is not supported */
520b0c59e53SShay Agroskin new_tx_push_buf_len = adapter->ena_dev->tx_max_header_size;
521b0c59e53SShay Agroskin
522060cdac2SShay Agroskin if ((adapter->ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) !=
523060cdac2SShay Agroskin kernel_ring->tx_push) {
524060cdac2SShay Agroskin NL_SET_ERR_MSG_MOD(extack, "Push mode state cannot be modified");
525060cdac2SShay Agroskin return -EINVAL;
526060cdac2SShay Agroskin }
527060cdac2SShay Agroskin
528b0c59e53SShay Agroskin /* Validate that the push buffer is supported on the underlying device */
529b0c59e53SShay Agroskin if (kernel_ring->tx_push_buf_len) {
530b0c59e53SShay Agroskin enum ena_admin_placement_policy_type placement;
531b0c59e53SShay Agroskin
532b0c59e53SShay Agroskin new_tx_push_buf_len = kernel_ring->tx_push_buf_len;
533b0c59e53SShay Agroskin
534b0c59e53SShay Agroskin placement = adapter->ena_dev->tx_mem_queue_type;
535b0c59e53SShay Agroskin if (placement == ENA_ADMIN_PLACEMENT_POLICY_HOST)
536b0c59e53SShay Agroskin return -EOPNOTSUPP;
537b0c59e53SShay Agroskin
538b0c59e53SShay Agroskin if (new_tx_push_buf_len != ENA_LLQ_HEADER &&
539b0c59e53SShay Agroskin new_tx_push_buf_len != ENA_LLQ_LARGE_HEADER) {
540b0c59e53SShay Agroskin bool large_llq_sup = adapter->large_llq_header_supported;
541b0c59e53SShay Agroskin char large_llq_size_str[40];
542b0c59e53SShay Agroskin
543b0c59e53SShay Agroskin snprintf(large_llq_size_str, 40, ", %lu", ENA_LLQ_LARGE_HEADER);
544b0c59e53SShay Agroskin
545b0c59e53SShay Agroskin NL_SET_ERR_MSG_FMT_MOD(extack,
546b0c59e53SShay Agroskin "Supported tx push buff values: [%lu%s]",
547b0c59e53SShay Agroskin ENA_LLQ_HEADER,
548b0c59e53SShay Agroskin large_llq_sup ? large_llq_size_str : "");
549b0c59e53SShay Agroskin
550b0c59e53SShay Agroskin return -EINVAL;
551b0c59e53SShay Agroskin }
552b0c59e53SShay Agroskin
553b0c59e53SShay Agroskin changed |= new_tx_push_buf_len != adapter->ena_dev->tx_max_header_size;
554b0c59e53SShay Agroskin }
555b0c59e53SShay Agroskin
556b0c59e53SShay Agroskin if (!changed)
557eece4d2aSSameeh Jubran return 0;
558eece4d2aSSameeh Jubran
559b0c59e53SShay Agroskin return ena_update_queue_params(adapter, new_tx_size, new_rx_size,
560b0c59e53SShay Agroskin new_tx_push_buf_len);
561eece4d2aSSameeh Jubran }
562eece4d2aSSameeh Jubran
ena_flow_hash_to_flow_type(u16 hash_fields)5631738cd3eSNetanel Belgazal static u32 ena_flow_hash_to_flow_type(u16 hash_fields)
5641738cd3eSNetanel Belgazal {
5651738cd3eSNetanel Belgazal u32 data = 0;
5661738cd3eSNetanel Belgazal
5671738cd3eSNetanel Belgazal if (hash_fields & ENA_ADMIN_RSS_L2_DA)
5681738cd3eSNetanel Belgazal data |= RXH_L2DA;
5691738cd3eSNetanel Belgazal
5701738cd3eSNetanel Belgazal if (hash_fields & ENA_ADMIN_RSS_L3_DA)
5711738cd3eSNetanel Belgazal data |= RXH_IP_DST;
5721738cd3eSNetanel Belgazal
5731738cd3eSNetanel Belgazal if (hash_fields & ENA_ADMIN_RSS_L3_SA)
5741738cd3eSNetanel Belgazal data |= RXH_IP_SRC;
5751738cd3eSNetanel Belgazal
5761738cd3eSNetanel Belgazal if (hash_fields & ENA_ADMIN_RSS_L4_DP)
5771738cd3eSNetanel Belgazal data |= RXH_L4_B_2_3;
5781738cd3eSNetanel Belgazal
5791738cd3eSNetanel Belgazal if (hash_fields & ENA_ADMIN_RSS_L4_SP)
5801738cd3eSNetanel Belgazal data |= RXH_L4_B_0_1;
5811738cd3eSNetanel Belgazal
5821738cd3eSNetanel Belgazal return data;
5831738cd3eSNetanel Belgazal }
5841738cd3eSNetanel Belgazal
ena_flow_data_to_flow_hash(u32 hash_fields)5851738cd3eSNetanel Belgazal static u16 ena_flow_data_to_flow_hash(u32 hash_fields)
5861738cd3eSNetanel Belgazal {
5871738cd3eSNetanel Belgazal u16 data = 0;
5881738cd3eSNetanel Belgazal
5891738cd3eSNetanel Belgazal if (hash_fields & RXH_L2DA)
5901738cd3eSNetanel Belgazal data |= ENA_ADMIN_RSS_L2_DA;
5911738cd3eSNetanel Belgazal
5921738cd3eSNetanel Belgazal if (hash_fields & RXH_IP_DST)
5931738cd3eSNetanel Belgazal data |= ENA_ADMIN_RSS_L3_DA;
5941738cd3eSNetanel Belgazal
5951738cd3eSNetanel Belgazal if (hash_fields & RXH_IP_SRC)
5961738cd3eSNetanel Belgazal data |= ENA_ADMIN_RSS_L3_SA;
5971738cd3eSNetanel Belgazal
5981738cd3eSNetanel Belgazal if (hash_fields & RXH_L4_B_2_3)
5991738cd3eSNetanel Belgazal data |= ENA_ADMIN_RSS_L4_DP;
6001738cd3eSNetanel Belgazal
6011738cd3eSNetanel Belgazal if (hash_fields & RXH_L4_B_0_1)
6021738cd3eSNetanel Belgazal data |= ENA_ADMIN_RSS_L4_SP;
6031738cd3eSNetanel Belgazal
6041738cd3eSNetanel Belgazal return data;
6051738cd3eSNetanel Belgazal }
6061738cd3eSNetanel Belgazal
ena_get_rss_hash(struct ena_com_dev * ena_dev,struct ethtool_rxnfc * cmd)6071738cd3eSNetanel Belgazal static int ena_get_rss_hash(struct ena_com_dev *ena_dev,
6081738cd3eSNetanel Belgazal struct ethtool_rxnfc *cmd)
6091738cd3eSNetanel Belgazal {
6101738cd3eSNetanel Belgazal enum ena_admin_flow_hash_proto proto;
6111738cd3eSNetanel Belgazal u16 hash_fields;
6121738cd3eSNetanel Belgazal int rc;
6131738cd3eSNetanel Belgazal
6141738cd3eSNetanel Belgazal cmd->data = 0;
6151738cd3eSNetanel Belgazal
6161738cd3eSNetanel Belgazal switch (cmd->flow_type) {
6171738cd3eSNetanel Belgazal case TCP_V4_FLOW:
6181738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_TCP4;
6191738cd3eSNetanel Belgazal break;
6201738cd3eSNetanel Belgazal case UDP_V4_FLOW:
6211738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_UDP4;
6221738cd3eSNetanel Belgazal break;
6231738cd3eSNetanel Belgazal case TCP_V6_FLOW:
6241738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_TCP6;
6251738cd3eSNetanel Belgazal break;
6261738cd3eSNetanel Belgazal case UDP_V6_FLOW:
6271738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_UDP6;
6281738cd3eSNetanel Belgazal break;
6291738cd3eSNetanel Belgazal case IPV4_FLOW:
6301738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_IP4;
6311738cd3eSNetanel Belgazal break;
6321738cd3eSNetanel Belgazal case IPV6_FLOW:
6331738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_IP6;
6341738cd3eSNetanel Belgazal break;
6351738cd3eSNetanel Belgazal case ETHER_FLOW:
6361738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_NOT_IP;
6371738cd3eSNetanel Belgazal break;
6381738cd3eSNetanel Belgazal case AH_V4_FLOW:
6391738cd3eSNetanel Belgazal case ESP_V4_FLOW:
6401738cd3eSNetanel Belgazal case AH_V6_FLOW:
6411738cd3eSNetanel Belgazal case ESP_V6_FLOW:
6421738cd3eSNetanel Belgazal case SCTP_V4_FLOW:
6431738cd3eSNetanel Belgazal case AH_ESP_V4_FLOW:
6441738cd3eSNetanel Belgazal return -EOPNOTSUPP;
6451738cd3eSNetanel Belgazal default:
6461738cd3eSNetanel Belgazal return -EINVAL;
6471738cd3eSNetanel Belgazal }
6481738cd3eSNetanel Belgazal
6491738cd3eSNetanel Belgazal rc = ena_com_get_hash_ctrl(ena_dev, proto, &hash_fields);
650d1497638SNetanel Belgazal if (rc)
6511738cd3eSNetanel Belgazal return rc;
6521738cd3eSNetanel Belgazal
6531738cd3eSNetanel Belgazal cmd->data = ena_flow_hash_to_flow_type(hash_fields);
6541738cd3eSNetanel Belgazal
6551738cd3eSNetanel Belgazal return 0;
6561738cd3eSNetanel Belgazal }
6571738cd3eSNetanel Belgazal
ena_set_rss_hash(struct ena_com_dev * ena_dev,struct ethtool_rxnfc * cmd)6581738cd3eSNetanel Belgazal static int ena_set_rss_hash(struct ena_com_dev *ena_dev,
6591738cd3eSNetanel Belgazal struct ethtool_rxnfc *cmd)
6601738cd3eSNetanel Belgazal {
6611738cd3eSNetanel Belgazal enum ena_admin_flow_hash_proto proto;
6621738cd3eSNetanel Belgazal u16 hash_fields;
6631738cd3eSNetanel Belgazal
6641738cd3eSNetanel Belgazal switch (cmd->flow_type) {
6651738cd3eSNetanel Belgazal case TCP_V4_FLOW:
6661738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_TCP4;
6671738cd3eSNetanel Belgazal break;
6681738cd3eSNetanel Belgazal case UDP_V4_FLOW:
6691738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_UDP4;
6701738cd3eSNetanel Belgazal break;
6711738cd3eSNetanel Belgazal case TCP_V6_FLOW:
6721738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_TCP6;
6731738cd3eSNetanel Belgazal break;
6741738cd3eSNetanel Belgazal case UDP_V6_FLOW:
6751738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_UDP6;
6761738cd3eSNetanel Belgazal break;
6771738cd3eSNetanel Belgazal case IPV4_FLOW:
6781738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_IP4;
6791738cd3eSNetanel Belgazal break;
6801738cd3eSNetanel Belgazal case IPV6_FLOW:
6811738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_IP6;
6821738cd3eSNetanel Belgazal break;
6831738cd3eSNetanel Belgazal case ETHER_FLOW:
6841738cd3eSNetanel Belgazal proto = ENA_ADMIN_RSS_NOT_IP;
6851738cd3eSNetanel Belgazal break;
6861738cd3eSNetanel Belgazal case AH_V4_FLOW:
6871738cd3eSNetanel Belgazal case ESP_V4_FLOW:
6881738cd3eSNetanel Belgazal case AH_V6_FLOW:
6891738cd3eSNetanel Belgazal case ESP_V6_FLOW:
6901738cd3eSNetanel Belgazal case SCTP_V4_FLOW:
6911738cd3eSNetanel Belgazal case AH_ESP_V4_FLOW:
6921738cd3eSNetanel Belgazal return -EOPNOTSUPP;
6931738cd3eSNetanel Belgazal default:
6941738cd3eSNetanel Belgazal return -EINVAL;
6951738cd3eSNetanel Belgazal }
6961738cd3eSNetanel Belgazal
6971738cd3eSNetanel Belgazal hash_fields = ena_flow_data_to_flow_hash(cmd->data);
6981738cd3eSNetanel Belgazal
6991738cd3eSNetanel Belgazal return ena_com_fill_hash_ctrl(ena_dev, proto, hash_fields);
7001738cd3eSNetanel Belgazal }
7011738cd3eSNetanel Belgazal
ena_set_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * info)7021738cd3eSNetanel Belgazal static int ena_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info)
7031738cd3eSNetanel Belgazal {
7041738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
7051738cd3eSNetanel Belgazal int rc = 0;
7061738cd3eSNetanel Belgazal
7071738cd3eSNetanel Belgazal switch (info->cmd) {
7081738cd3eSNetanel Belgazal case ETHTOOL_SRXFH:
7091738cd3eSNetanel Belgazal rc = ena_set_rss_hash(adapter->ena_dev, info);
7101738cd3eSNetanel Belgazal break;
7111738cd3eSNetanel Belgazal case ETHTOOL_SRXCLSRLDEL:
7121738cd3eSNetanel Belgazal case ETHTOOL_SRXCLSRLINS:
7131738cd3eSNetanel Belgazal default:
7141738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev,
7151738cd3eSNetanel Belgazal "Command parameter %d is not supported\n", info->cmd);
7161738cd3eSNetanel Belgazal rc = -EOPNOTSUPP;
7171738cd3eSNetanel Belgazal }
7181738cd3eSNetanel Belgazal
719d1497638SNetanel Belgazal return rc;
7201738cd3eSNetanel Belgazal }
7211738cd3eSNetanel Belgazal
ena_get_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * info,u32 * rules)7221738cd3eSNetanel Belgazal static int ena_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
7231738cd3eSNetanel Belgazal u32 *rules)
7241738cd3eSNetanel Belgazal {
7251738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
7261738cd3eSNetanel Belgazal int rc = 0;
7271738cd3eSNetanel Belgazal
7281738cd3eSNetanel Belgazal switch (info->cmd) {
7291738cd3eSNetanel Belgazal case ETHTOOL_GRXRINGS:
730faa615f9SSameeh Jubran info->data = adapter->num_io_queues;
7311738cd3eSNetanel Belgazal rc = 0;
7321738cd3eSNetanel Belgazal break;
7331738cd3eSNetanel Belgazal case ETHTOOL_GRXFH:
7341738cd3eSNetanel Belgazal rc = ena_get_rss_hash(adapter->ena_dev, info);
7351738cd3eSNetanel Belgazal break;
7361738cd3eSNetanel Belgazal case ETHTOOL_GRXCLSRLCNT:
7371738cd3eSNetanel Belgazal case ETHTOOL_GRXCLSRULE:
7381738cd3eSNetanel Belgazal case ETHTOOL_GRXCLSRLALL:
7391738cd3eSNetanel Belgazal default:
7401738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev,
7411738cd3eSNetanel Belgazal "Command parameter %d is not supported\n", info->cmd);
7421738cd3eSNetanel Belgazal rc = -EOPNOTSUPP;
7431738cd3eSNetanel Belgazal }
7441738cd3eSNetanel Belgazal
745d1497638SNetanel Belgazal return rc;
7461738cd3eSNetanel Belgazal }
7471738cd3eSNetanel Belgazal
ena_get_rxfh_indir_size(struct net_device * netdev)7481738cd3eSNetanel Belgazal static u32 ena_get_rxfh_indir_size(struct net_device *netdev)
7491738cd3eSNetanel Belgazal {
7501738cd3eSNetanel Belgazal return ENA_RX_RSS_TABLE_SIZE;
7511738cd3eSNetanel Belgazal }
7521738cd3eSNetanel Belgazal
ena_get_rxfh_key_size(struct net_device * netdev)7531738cd3eSNetanel Belgazal static u32 ena_get_rxfh_key_size(struct net_device *netdev)
7541738cd3eSNetanel Belgazal {
7551738cd3eSNetanel Belgazal return ENA_HASH_KEY_SIZE;
7561738cd3eSNetanel Belgazal }
7571738cd3eSNetanel Belgazal
ena_indirection_table_set(struct ena_adapter * adapter,const u32 * indir)75877a651f5SArthur Kiyanovski static int ena_indirection_table_set(struct ena_adapter *adapter,
75977a651f5SArthur Kiyanovski const u32 *indir)
76077a651f5SArthur Kiyanovski {
76177a651f5SArthur Kiyanovski struct ena_com_dev *ena_dev = adapter->ena_dev;
76277a651f5SArthur Kiyanovski int i, rc;
76377a651f5SArthur Kiyanovski
76477a651f5SArthur Kiyanovski for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {
76577a651f5SArthur Kiyanovski rc = ena_com_indirect_table_fill_entry(ena_dev,
76677a651f5SArthur Kiyanovski i,
76777a651f5SArthur Kiyanovski ENA_IO_RXQ_IDX(indir[i]));
76877a651f5SArthur Kiyanovski if (unlikely(rc)) {
76977a651f5SArthur Kiyanovski netif_err(adapter, drv, adapter->netdev,
77077a651f5SArthur Kiyanovski "Cannot fill indirect table (index is too large)\n");
77177a651f5SArthur Kiyanovski return rc;
77277a651f5SArthur Kiyanovski }
77377a651f5SArthur Kiyanovski }
77477a651f5SArthur Kiyanovski
77577a651f5SArthur Kiyanovski rc = ena_com_indirect_table_set(ena_dev);
77677a651f5SArthur Kiyanovski if (rc) {
77777a651f5SArthur Kiyanovski netif_err(adapter, drv, adapter->netdev,
77877a651f5SArthur Kiyanovski "Cannot set indirect table\n");
77977a651f5SArthur Kiyanovski return rc == -EPERM ? -EOPNOTSUPP : rc;
78077a651f5SArthur Kiyanovski }
78177a651f5SArthur Kiyanovski return rc;
78277a651f5SArthur Kiyanovski }
78377a651f5SArthur Kiyanovski
ena_indirection_table_get(struct ena_adapter * adapter,u32 * indir)78492569fd2SArthur Kiyanovski static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir)
78592569fd2SArthur Kiyanovski {
78692569fd2SArthur Kiyanovski struct ena_com_dev *ena_dev = adapter->ena_dev;
78792569fd2SArthur Kiyanovski int i, rc;
78892569fd2SArthur Kiyanovski
78992569fd2SArthur Kiyanovski if (!indir)
79092569fd2SArthur Kiyanovski return 0;
79192569fd2SArthur Kiyanovski
79292569fd2SArthur Kiyanovski rc = ena_com_indirect_table_get(ena_dev, indir);
79392569fd2SArthur Kiyanovski if (rc)
79492569fd2SArthur Kiyanovski return rc;
79592569fd2SArthur Kiyanovski
79692569fd2SArthur Kiyanovski /* Our internal representation of the indices is: even indices
79792569fd2SArthur Kiyanovski * for Tx and uneven indices for Rx. We need to convert the Rx
79892569fd2SArthur Kiyanovski * indices to be consecutive
79992569fd2SArthur Kiyanovski */
80092569fd2SArthur Kiyanovski for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++)
80192569fd2SArthur Kiyanovski indir[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(indir[i]);
80292569fd2SArthur Kiyanovski
80392569fd2SArthur Kiyanovski return rc;
80492569fd2SArthur Kiyanovski }
80592569fd2SArthur Kiyanovski
ena_get_rxfh(struct net_device * netdev,u32 * indir,u8 * key,u8 * hfunc)8061738cd3eSNetanel Belgazal static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
8071738cd3eSNetanel Belgazal u8 *hfunc)
8081738cd3eSNetanel Belgazal {
8091738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
8101738cd3eSNetanel Belgazal enum ena_admin_hash_functions ena_func;
8111738cd3eSNetanel Belgazal u8 func;
8121738cd3eSNetanel Belgazal int rc;
8131738cd3eSNetanel Belgazal
81492569fd2SArthur Kiyanovski rc = ena_indirection_table_get(adapter, indir);
8151738cd3eSNetanel Belgazal if (rc)
8161738cd3eSNetanel Belgazal return rc;
8171738cd3eSNetanel Belgazal
8180c8923c0SSameeh Jubran /* We call this function in order to check if the device
8190c8923c0SSameeh Jubran * supports getting/setting the hash function.
8200c8923c0SSameeh Jubran */
821f66c2ea3SSameeh Jubran rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func);
8220c8923c0SSameeh Jubran if (rc) {
823cac7172fSSameeh Jubran if (rc == -EOPNOTSUPP)
8240c8923c0SSameeh Jubran rc = 0;
8250c8923c0SSameeh Jubran
8260c8923c0SSameeh Jubran return rc;
8270c8923c0SSameeh Jubran }
8280c8923c0SSameeh Jubran
829f66c2ea3SSameeh Jubran rc = ena_com_get_hash_key(adapter->ena_dev, key);
830f66c2ea3SSameeh Jubran if (rc)
831f66c2ea3SSameeh Jubran return rc;
832f66c2ea3SSameeh Jubran
8331738cd3eSNetanel Belgazal switch (ena_func) {
8341738cd3eSNetanel Belgazal case ENA_ADMIN_TOEPLITZ:
8351738cd3eSNetanel Belgazal func = ETH_RSS_HASH_TOP;
8361738cd3eSNetanel Belgazal break;
8371738cd3eSNetanel Belgazal case ENA_ADMIN_CRC32:
838886d2089SSameeh Jubran func = ETH_RSS_HASH_CRC32;
8391738cd3eSNetanel Belgazal break;
8401738cd3eSNetanel Belgazal default:
8411738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev,
8421738cd3eSNetanel Belgazal "Command parameter is not supported\n");
8431738cd3eSNetanel Belgazal return -EOPNOTSUPP;
8441738cd3eSNetanel Belgazal }
8451738cd3eSNetanel Belgazal
8461738cd3eSNetanel Belgazal if (hfunc)
8471738cd3eSNetanel Belgazal *hfunc = func;
8481738cd3eSNetanel Belgazal
849f66c2ea3SSameeh Jubran return 0;
8501738cd3eSNetanel Belgazal }
8511738cd3eSNetanel Belgazal
ena_set_rxfh(struct net_device * netdev,const u32 * indir,const u8 * key,const u8 hfunc)8521738cd3eSNetanel Belgazal static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
8531738cd3eSNetanel Belgazal const u8 *key, const u8 hfunc)
8541738cd3eSNetanel Belgazal {
8551738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
8561738cd3eSNetanel Belgazal struct ena_com_dev *ena_dev = adapter->ena_dev;
857f66c2ea3SSameeh Jubran enum ena_admin_hash_functions func = 0;
85877a651f5SArthur Kiyanovski int rc;
8591738cd3eSNetanel Belgazal
8601738cd3eSNetanel Belgazal if (indir) {
86177a651f5SArthur Kiyanovski rc = ena_indirection_table_set(adapter, indir);
86277a651f5SArthur Kiyanovski if (rc)
8631738cd3eSNetanel Belgazal return rc;
8641738cd3eSNetanel Belgazal }
8651738cd3eSNetanel Belgazal
8661738cd3eSNetanel Belgazal switch (hfunc) {
867470793a7SArthur Kiyanovski case ETH_RSS_HASH_NO_CHANGE:
868470793a7SArthur Kiyanovski func = ena_com_get_current_hash_function(ena_dev);
869470793a7SArthur Kiyanovski break;
8701738cd3eSNetanel Belgazal case ETH_RSS_HASH_TOP:
8711738cd3eSNetanel Belgazal func = ENA_ADMIN_TOEPLITZ;
8721738cd3eSNetanel Belgazal break;
873886d2089SSameeh Jubran case ETH_RSS_HASH_CRC32:
8741738cd3eSNetanel Belgazal func = ENA_ADMIN_CRC32;
8751738cd3eSNetanel Belgazal break;
8761738cd3eSNetanel Belgazal default:
8771738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev, "Unsupported hfunc %d\n",
8781738cd3eSNetanel Belgazal hfunc);
8791738cd3eSNetanel Belgazal return -EOPNOTSUPP;
8801738cd3eSNetanel Belgazal }
8811738cd3eSNetanel Belgazal
882f66c2ea3SSameeh Jubran if (key || func) {
8831738cd3eSNetanel Belgazal rc = ena_com_fill_hash_function(ena_dev, func, key,
8841738cd3eSNetanel Belgazal ENA_HASH_KEY_SIZE,
8851738cd3eSNetanel Belgazal 0xFFFFFFFF);
8861738cd3eSNetanel Belgazal if (unlikely(rc)) {
8871738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev, "Cannot fill key\n");
8881738cd3eSNetanel Belgazal return rc == -EPERM ? -EOPNOTSUPP : rc;
8891738cd3eSNetanel Belgazal }
8901738cd3eSNetanel Belgazal }
8911738cd3eSNetanel Belgazal
8921738cd3eSNetanel Belgazal return 0;
8931738cd3eSNetanel Belgazal }
8941738cd3eSNetanel Belgazal
ena_get_channels(struct net_device * netdev,struct ethtool_channels * channels)8951738cd3eSNetanel Belgazal static void ena_get_channels(struct net_device *netdev,
8961738cd3eSNetanel Belgazal struct ethtool_channels *channels)
8971738cd3eSNetanel Belgazal {
8981738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
8991738cd3eSNetanel Belgazal
900736ce3f4SSameeh Jubran channels->max_combined = adapter->max_num_io_queues;
9019a037b06SSameeh Jubran channels->combined_count = adapter->num_io_queues;
9021738cd3eSNetanel Belgazal }
9031738cd3eSNetanel Belgazal
ena_set_channels(struct net_device * netdev,struct ethtool_channels * channels)9042413ea97SSameeh Jubran static int ena_set_channels(struct net_device *netdev,
9052413ea97SSameeh Jubran struct ethtool_channels *channels)
9062413ea97SSameeh Jubran {
9072413ea97SSameeh Jubran struct ena_adapter *adapter = netdev_priv(netdev);
9082413ea97SSameeh Jubran u32 count = channels->combined_count;
9092413ea97SSameeh Jubran /* The check for max value is already done in ethtool */
9107aa6dc35SLorenzo Bianconi if (count < ENA_MIN_NUM_IO_QUEUES)
9112413ea97SSameeh Jubran return -EINVAL;
9122413ea97SSameeh Jubran
9137aa6dc35SLorenzo Bianconi if (!ena_xdp_legal_queue_count(adapter, count)) {
9147aa6dc35SLorenzo Bianconi if (ena_xdp_present(adapter))
9157aa6dc35SLorenzo Bianconi return -EINVAL;
9167aa6dc35SLorenzo Bianconi
9177aa6dc35SLorenzo Bianconi xdp_clear_features_flag(netdev);
9187aa6dc35SLorenzo Bianconi } else {
9197aa6dc35SLorenzo Bianconi xdp_set_features_flag(netdev,
9207aa6dc35SLorenzo Bianconi NETDEV_XDP_ACT_BASIC |
9217aa6dc35SLorenzo Bianconi NETDEV_XDP_ACT_REDIRECT);
9227aa6dc35SLorenzo Bianconi }
9237aa6dc35SLorenzo Bianconi
9242413ea97SSameeh Jubran return ena_update_queue_count(adapter, count);
9252413ea97SSameeh Jubran }
9262413ea97SSameeh Jubran
ena_get_tunable(struct net_device * netdev,const struct ethtool_tunable * tuna,void * data)9271738cd3eSNetanel Belgazal static int ena_get_tunable(struct net_device *netdev,
9281738cd3eSNetanel Belgazal const struct ethtool_tunable *tuna, void *data)
9291738cd3eSNetanel Belgazal {
9301738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
9311738cd3eSNetanel Belgazal int ret = 0;
9321738cd3eSNetanel Belgazal
9331738cd3eSNetanel Belgazal switch (tuna->id) {
9341738cd3eSNetanel Belgazal case ETHTOOL_RX_COPYBREAK:
9351738cd3eSNetanel Belgazal *(u32 *)data = adapter->rx_copybreak;
9361738cd3eSNetanel Belgazal break;
9371738cd3eSNetanel Belgazal default:
9381738cd3eSNetanel Belgazal ret = -EINVAL;
9391738cd3eSNetanel Belgazal break;
9401738cd3eSNetanel Belgazal }
9411738cd3eSNetanel Belgazal
9421738cd3eSNetanel Belgazal return ret;
9431738cd3eSNetanel Belgazal }
9441738cd3eSNetanel Belgazal
ena_set_tunable(struct net_device * netdev,const struct ethtool_tunable * tuna,const void * data)9451738cd3eSNetanel Belgazal static int ena_set_tunable(struct net_device *netdev,
9461738cd3eSNetanel Belgazal const struct ethtool_tunable *tuna,
9471738cd3eSNetanel Belgazal const void *data)
9481738cd3eSNetanel Belgazal {
9491738cd3eSNetanel Belgazal struct ena_adapter *adapter = netdev_priv(netdev);
9501738cd3eSNetanel Belgazal int ret = 0;
9511738cd3eSNetanel Belgazal u32 len;
9521738cd3eSNetanel Belgazal
9531738cd3eSNetanel Belgazal switch (tuna->id) {
9541738cd3eSNetanel Belgazal case ETHTOOL_RX_COPYBREAK:
9551738cd3eSNetanel Belgazal len = *(u32 *)data;
956c7062aaeSDavid Arinzon ret = ena_set_rx_copybreak(adapter, len);
9571738cd3eSNetanel Belgazal break;
9581738cd3eSNetanel Belgazal default:
9591738cd3eSNetanel Belgazal ret = -EINVAL;
9601738cd3eSNetanel Belgazal break;
9611738cd3eSNetanel Belgazal }
9621738cd3eSNetanel Belgazal
9631738cd3eSNetanel Belgazal return ret;
9641738cd3eSNetanel Belgazal }
9651738cd3eSNetanel Belgazal
9661738cd3eSNetanel Belgazal static const struct ethtool_ops ena_ethtool_ops = {
9678e4f90caSJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
9688e4f90caSJakub Kicinski ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
969060cdac2SShay Agroskin .supported_ring_params = ETHTOOL_RING_USE_TX_PUSH_BUF_LEN |
970060cdac2SShay Agroskin ETHTOOL_RING_USE_TX_PUSH,
9711738cd3eSNetanel Belgazal .get_link_ksettings = ena_get_link_ksettings,
9721738cd3eSNetanel Belgazal .get_drvinfo = ena_get_drvinfo,
9731738cd3eSNetanel Belgazal .get_msglevel = ena_get_msglevel,
9741738cd3eSNetanel Belgazal .set_msglevel = ena_set_msglevel,
9751738cd3eSNetanel Belgazal .get_link = ethtool_op_get_link,
9761738cd3eSNetanel Belgazal .get_coalesce = ena_get_coalesce,
9771738cd3eSNetanel Belgazal .set_coalesce = ena_set_coalesce,
9781738cd3eSNetanel Belgazal .get_ringparam = ena_get_ringparam,
979eece4d2aSSameeh Jubran .set_ringparam = ena_set_ringparam,
9801738cd3eSNetanel Belgazal .get_sset_count = ena_get_sset_count,
981713865daSSameeh Jubran .get_strings = ena_get_ethtool_strings,
9821738cd3eSNetanel Belgazal .get_ethtool_stats = ena_get_ethtool_stats,
9831738cd3eSNetanel Belgazal .get_rxnfc = ena_get_rxnfc,
9841738cd3eSNetanel Belgazal .set_rxnfc = ena_set_rxnfc,
9851738cd3eSNetanel Belgazal .get_rxfh_indir_size = ena_get_rxfh_indir_size,
9861738cd3eSNetanel Belgazal .get_rxfh_key_size = ena_get_rxfh_key_size,
9871738cd3eSNetanel Belgazal .get_rxfh = ena_get_rxfh,
9881738cd3eSNetanel Belgazal .set_rxfh = ena_set_rxfh,
9891738cd3eSNetanel Belgazal .get_channels = ena_get_channels,
9902413ea97SSameeh Jubran .set_channels = ena_set_channels,
9911738cd3eSNetanel Belgazal .get_tunable = ena_get_tunable,
9921738cd3eSNetanel Belgazal .set_tunable = ena_set_tunable,
993cf6d17fdSArthur Kiyanovski .get_ts_info = ethtool_op_get_ts_info,
9941738cd3eSNetanel Belgazal };
9951738cd3eSNetanel Belgazal
ena_set_ethtool_ops(struct net_device * netdev)9961738cd3eSNetanel Belgazal void ena_set_ethtool_ops(struct net_device *netdev)
9971738cd3eSNetanel Belgazal {
9981738cd3eSNetanel Belgazal netdev->ethtool_ops = &ena_ethtool_ops;
9991738cd3eSNetanel Belgazal }
10001738cd3eSNetanel Belgazal
ena_dump_stats_ex(struct ena_adapter * adapter,u8 * buf)10011738cd3eSNetanel Belgazal static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
10021738cd3eSNetanel Belgazal {
10031738cd3eSNetanel Belgazal struct net_device *netdev = adapter->netdev;
10041738cd3eSNetanel Belgazal u8 *strings_buf;
10051738cd3eSNetanel Belgazal u64 *data_buf;
10061738cd3eSNetanel Belgazal int strings_num;
10071738cd3eSNetanel Belgazal int i, rc;
10081738cd3eSNetanel Belgazal
1009713865daSSameeh Jubran strings_num = ena_get_sw_stats_count(adapter);
10101738cd3eSNetanel Belgazal if (strings_num <= 0) {
10111738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev, "Can't get stats num\n");
10121738cd3eSNetanel Belgazal return;
10131738cd3eSNetanel Belgazal }
10141738cd3eSNetanel Belgazal
1015a86854d0SKees Cook strings_buf = devm_kcalloc(&adapter->pdev->dev,
1016a86854d0SKees Cook ETH_GSTRING_LEN, strings_num,
10171738cd3eSNetanel Belgazal GFP_ATOMIC);
10181738cd3eSNetanel Belgazal if (!strings_buf) {
10191738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev,
1020bf2746e8SShay Agroskin "Failed to allocate strings_buf\n");
10211738cd3eSNetanel Belgazal return;
10221738cd3eSNetanel Belgazal }
10231738cd3eSNetanel Belgazal
1024a86854d0SKees Cook data_buf = devm_kcalloc(&adapter->pdev->dev,
1025a86854d0SKees Cook strings_num, sizeof(u64),
10261738cd3eSNetanel Belgazal GFP_ATOMIC);
10271738cd3eSNetanel Belgazal if (!data_buf) {
10281738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev,
1029713865daSSameeh Jubran "Failed to allocate data buf\n");
10301738cd3eSNetanel Belgazal devm_kfree(&adapter->pdev->dev, strings_buf);
10311738cd3eSNetanel Belgazal return;
10321738cd3eSNetanel Belgazal }
10331738cd3eSNetanel Belgazal
1034713865daSSameeh Jubran ena_get_strings(adapter, strings_buf, false);
1035713865daSSameeh Jubran ena_get_stats(adapter, data_buf, false);
10361738cd3eSNetanel Belgazal
10371738cd3eSNetanel Belgazal /* If there is a buffer, dump stats, otherwise print them to dmesg */
10381738cd3eSNetanel Belgazal if (buf)
10391738cd3eSNetanel Belgazal for (i = 0; i < strings_num; i++) {
10401738cd3eSNetanel Belgazal rc = snprintf(buf, ETH_GSTRING_LEN + sizeof(u64),
10411738cd3eSNetanel Belgazal "%s %llu\n",
10421738cd3eSNetanel Belgazal strings_buf + i * ETH_GSTRING_LEN,
10431738cd3eSNetanel Belgazal data_buf[i]);
10441738cd3eSNetanel Belgazal buf += rc;
10451738cd3eSNetanel Belgazal }
10461738cd3eSNetanel Belgazal else
10471738cd3eSNetanel Belgazal for (i = 0; i < strings_num; i++)
10481738cd3eSNetanel Belgazal netif_err(adapter, drv, netdev, "%s: %llu\n",
10491738cd3eSNetanel Belgazal strings_buf + i * ETH_GSTRING_LEN,
10501738cd3eSNetanel Belgazal data_buf[i]);
10511738cd3eSNetanel Belgazal
10521738cd3eSNetanel Belgazal devm_kfree(&adapter->pdev->dev, strings_buf);
10531738cd3eSNetanel Belgazal devm_kfree(&adapter->pdev->dev, data_buf);
10541738cd3eSNetanel Belgazal }
10551738cd3eSNetanel Belgazal
ena_dump_stats_to_buf(struct ena_adapter * adapter,u8 * buf)10561738cd3eSNetanel Belgazal void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf)
10571738cd3eSNetanel Belgazal {
10581738cd3eSNetanel Belgazal if (!buf)
10591738cd3eSNetanel Belgazal return;
10601738cd3eSNetanel Belgazal
10611738cd3eSNetanel Belgazal ena_dump_stats_ex(adapter, buf);
10621738cd3eSNetanel Belgazal }
10631738cd3eSNetanel Belgazal
ena_dump_stats_to_dmesg(struct ena_adapter * adapter)10641738cd3eSNetanel Belgazal void ena_dump_stats_to_dmesg(struct ena_adapter *adapter)
10651738cd3eSNetanel Belgazal {
10661738cd3eSNetanel Belgazal ena_dump_stats_ex(adapter, NULL);
10671738cd3eSNetanel Belgazal }
1068