18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/pci.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "ena_netdev.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistruct ena_stats { 118c2ecf20Sopenharmony_ci char name[ETH_GSTRING_LEN]; 128c2ecf20Sopenharmony_ci int stat_offset; 138c2ecf20Sopenharmony_ci}; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define ENA_STAT_ENA_COM_ENTRY(stat) { \ 168c2ecf20Sopenharmony_ci .name = #stat, \ 178c2ecf20Sopenharmony_ci .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \ 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define ENA_STAT_ENTRY(stat, stat_type) { \ 218c2ecf20Sopenharmony_ci .name = #stat, \ 228c2ecf20Sopenharmony_ci .stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \ 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define ENA_STAT_HW_ENTRY(stat, stat_type) { \ 268c2ecf20Sopenharmony_ci .name = #stat, \ 278c2ecf20Sopenharmony_ci .stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \ 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define ENA_STAT_RX_ENTRY(stat) \ 318c2ecf20Sopenharmony_ci ENA_STAT_ENTRY(stat, rx) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define ENA_STAT_TX_ENTRY(stat) \ 348c2ecf20Sopenharmony_ci ENA_STAT_ENTRY(stat, tx) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define ENA_STAT_GLOBAL_ENTRY(stat) \ 378c2ecf20Sopenharmony_ci ENA_STAT_ENTRY(stat, dev) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define ENA_STAT_ENI_ENTRY(stat) \ 408c2ecf20Sopenharmony_ci ENA_STAT_HW_ENTRY(stat, eni_stats) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic const struct ena_stats ena_stats_global_strings[] = { 438c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(tx_timeout), 448c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(suspend), 458c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(resume), 468c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(wd_expired), 478c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(interface_up), 488c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(interface_down), 498c2ecf20Sopenharmony_ci ENA_STAT_GLOBAL_ENTRY(admin_q_pause), 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic const struct ena_stats ena_stats_eni_strings[] = { 538c2ecf20Sopenharmony_ci ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), 548c2ecf20Sopenharmony_ci ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), 558c2ecf20Sopenharmony_ci ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), 568c2ecf20Sopenharmony_ci ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), 578c2ecf20Sopenharmony_ci ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const struct ena_stats ena_stats_tx_strings[] = { 618c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(cnt), 628c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(bytes), 638c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(queue_stop), 648c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(queue_wakeup), 658c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(dma_mapping_err), 668c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(linearize), 678c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(linearize_failed), 688c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(napi_comp), 698c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(tx_poll), 708c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(doorbells), 718c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(prepare_ctx_err), 728c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(bad_req_id), 738c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(llq_buffer_copy), 748c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(missed_tx), 758c2ecf20Sopenharmony_ci ENA_STAT_TX_ENTRY(unmask_interrupt), 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic const struct ena_stats ena_stats_rx_strings[] = { 798c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(cnt), 808c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(bytes), 818c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(rx_copybreak_pkt), 828c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(csum_good), 838c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(refil_partial), 848c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(bad_csum), 858c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(page_alloc_fail), 868c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(skb_alloc_fail), 878c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(dma_mapping_err), 888c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(bad_desc_num), 898c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(bad_req_id), 908c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(empty_rx_ring), 918c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(csum_unchecked), 928c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(xdp_aborted), 938c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(xdp_drop), 948c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(xdp_pass), 958c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(xdp_tx), 968c2ecf20Sopenharmony_ci ENA_STAT_RX_ENTRY(xdp_invalid), 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic const struct ena_stats ena_stats_ena_com_strings[] = { 1008c2ecf20Sopenharmony_ci ENA_STAT_ENA_COM_ENTRY(aborted_cmd), 1018c2ecf20Sopenharmony_ci ENA_STAT_ENA_COM_ENTRY(submitted_cmd), 1028c2ecf20Sopenharmony_ci ENA_STAT_ENA_COM_ENTRY(completed_cmd), 1038c2ecf20Sopenharmony_ci ENA_STAT_ENA_COM_ENTRY(out_of_space), 1048c2ecf20Sopenharmony_ci ENA_STAT_ENA_COM_ENTRY(no_completion), 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) 1088c2ecf20Sopenharmony_ci#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) 1098c2ecf20Sopenharmony_ci#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) 1108c2ecf20Sopenharmony_ci#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings) 1118c2ecf20Sopenharmony_ci#define ENA_STATS_ARRAY_ENI(adapter) \ 1128c2ecf20Sopenharmony_ci (ARRAY_SIZE(ena_stats_eni_strings) * (adapter)->eni_stats_supported) 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic void ena_safe_update_stat(u64 *src, u64 *dst, 1158c2ecf20Sopenharmony_ci struct u64_stats_sync *syncp) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci unsigned int start; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci do { 1208c2ecf20Sopenharmony_ci start = u64_stats_fetch_begin_irq(syncp); 1218c2ecf20Sopenharmony_ci *(dst) = *src; 1228c2ecf20Sopenharmony_ci } while (u64_stats_fetch_retry_irq(syncp, start)); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void ena_queue_stats(struct ena_adapter *adapter, u64 **data) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 1288c2ecf20Sopenharmony_ci struct ena_ring *ring; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci u64 *ptr; 1318c2ecf20Sopenharmony_ci int i, j; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { 1348c2ecf20Sopenharmony_ci /* Tx stats */ 1358c2ecf20Sopenharmony_ci ring = &adapter->tx_ring[i]; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { 1388c2ecf20Sopenharmony_ci ena_stats = &ena_stats_tx_strings[j]; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ptr = (u64 *)&ring->tx_stats + ena_stats->stat_offset; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci ena_safe_update_stat(ptr, (*data)++, &ring->syncp); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci /* XDP TX queues don't have a RX queue counterpart */ 1458c2ecf20Sopenharmony_ci if (!ENA_IS_XDP_INDEX(adapter, i)) { 1468c2ecf20Sopenharmony_ci /* Rx stats */ 1478c2ecf20Sopenharmony_ci ring = &adapter->rx_ring[i]; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { 1508c2ecf20Sopenharmony_ci ena_stats = &ena_stats_rx_strings[j]; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci ptr = (u64 *)&ring->rx_stats + 1538c2ecf20Sopenharmony_ci ena_stats->stat_offset; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci ena_safe_update_stat(ptr, (*data)++, &ring->syncp); 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 1648c2ecf20Sopenharmony_ci u64 *ptr; 1658c2ecf20Sopenharmony_ci int i; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { 1688c2ecf20Sopenharmony_ci ena_stats = &ena_stats_ena_com_strings[i]; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci ptr = (u64 *)&adapter->ena_dev->admin_queue.stats + 1718c2ecf20Sopenharmony_ci ena_stats->stat_offset; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci *(*data)++ = *ptr; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void ena_get_stats(struct ena_adapter *adapter, 1788c2ecf20Sopenharmony_ci u64 *data, 1798c2ecf20Sopenharmony_ci bool eni_stats_needed) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 1828c2ecf20Sopenharmony_ci u64 *ptr; 1838c2ecf20Sopenharmony_ci int i; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) { 1868c2ecf20Sopenharmony_ci ena_stats = &ena_stats_global_strings[i]; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci ptr = (u64 *)&adapter->dev_stats + ena_stats->stat_offset; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci ena_safe_update_stat(ptr, data++, &adapter->syncp); 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (eni_stats_needed) { 1948c2ecf20Sopenharmony_ci ena_update_hw_stats(adapter); 1958c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { 1968c2ecf20Sopenharmony_ci ena_stats = &ena_stats_eni_strings[i]; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci ptr = (u64 *)&adapter->eni_stats + 1998c2ecf20Sopenharmony_ci ena_stats->stat_offset; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci ena_safe_update_stat(ptr, data++, &adapter->syncp); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci ena_queue_stats(adapter, &data); 2068c2ecf20Sopenharmony_ci ena_dev_admin_queue_stats(adapter, &data); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic void ena_get_ethtool_stats(struct net_device *netdev, 2108c2ecf20Sopenharmony_ci struct ethtool_stats *stats, 2118c2ecf20Sopenharmony_ci u64 *data) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci ena_get_stats(adapter, data, adapter->eni_stats_supported); 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic int ena_get_sw_stats_count(struct ena_adapter *adapter) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) 2218c2ecf20Sopenharmony_ci + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX 2228c2ecf20Sopenharmony_ci + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int ena_get_hw_stats_count(struct ena_adapter *adapter) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci return ENA_STATS_ARRAY_ENI(adapter); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ciint ena_get_sset_count(struct net_device *netdev, int sset) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (sset != ETH_SS_STATS) 2358c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci return ena_get_sw_stats_count(adapter) + ena_get_hw_stats_count(adapter); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic void ena_queue_strings(struct ena_adapter *adapter, u8 **data) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 2438c2ecf20Sopenharmony_ci bool is_xdp; 2448c2ecf20Sopenharmony_ci int i, j; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { 2478c2ecf20Sopenharmony_ci is_xdp = ENA_IS_XDP_INDEX(adapter, i); 2488c2ecf20Sopenharmony_ci /* Tx stats */ 2498c2ecf20Sopenharmony_ci for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { 2508c2ecf20Sopenharmony_ci ena_stats = &ena_stats_tx_strings[j]; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci snprintf(*data, ETH_GSTRING_LEN, 2538c2ecf20Sopenharmony_ci "queue_%u_%s_%s", i, 2548c2ecf20Sopenharmony_ci is_xdp ? "xdp_tx" : "tx", ena_stats->name); 2558c2ecf20Sopenharmony_ci (*data) += ETH_GSTRING_LEN; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (!is_xdp) { 2598c2ecf20Sopenharmony_ci /* RX stats, in XDP there isn't a RX queue 2608c2ecf20Sopenharmony_ci * counterpart 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { 2638c2ecf20Sopenharmony_ci ena_stats = &ena_stats_rx_strings[j]; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci snprintf(*data, ETH_GSTRING_LEN, 2668c2ecf20Sopenharmony_ci "queue_%u_rx_%s", i, ena_stats->name); 2678c2ecf20Sopenharmony_ci (*data) += ETH_GSTRING_LEN; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic void ena_com_dev_strings(u8 **data) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 2768c2ecf20Sopenharmony_ci int i; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { 2798c2ecf20Sopenharmony_ci ena_stats = &ena_stats_ena_com_strings[i]; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci snprintf(*data, ETH_GSTRING_LEN, 2828c2ecf20Sopenharmony_ci "ena_admin_q_%s", ena_stats->name); 2838c2ecf20Sopenharmony_ci (*data) += ETH_GSTRING_LEN; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic void ena_get_strings(struct ena_adapter *adapter, 2888c2ecf20Sopenharmony_ci u8 *data, 2898c2ecf20Sopenharmony_ci bool eni_stats_needed) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci const struct ena_stats *ena_stats; 2928c2ecf20Sopenharmony_ci int i; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) { 2958c2ecf20Sopenharmony_ci ena_stats = &ena_stats_global_strings[i]; 2968c2ecf20Sopenharmony_ci memcpy(data, ena_stats->name, ETH_GSTRING_LEN); 2978c2ecf20Sopenharmony_ci data += ETH_GSTRING_LEN; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (eni_stats_needed) { 3018c2ecf20Sopenharmony_ci for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { 3028c2ecf20Sopenharmony_ci ena_stats = &ena_stats_eni_strings[i]; 3038c2ecf20Sopenharmony_ci memcpy(data, ena_stats->name, ETH_GSTRING_LEN); 3048c2ecf20Sopenharmony_ci data += ETH_GSTRING_LEN; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci ena_queue_strings(adapter, &data); 3098c2ecf20Sopenharmony_ci ena_com_dev_strings(&data); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic void ena_get_ethtool_strings(struct net_device *netdev, 3138c2ecf20Sopenharmony_ci u32 sset, 3148c2ecf20Sopenharmony_ci u8 *data) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (sset != ETH_SS_STATS) 3198c2ecf20Sopenharmony_ci return; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci ena_get_strings(adapter, data, adapter->eni_stats_supported); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int ena_get_link_ksettings(struct net_device *netdev, 3258c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *link_ksettings) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 3288c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 3298c2ecf20Sopenharmony_ci struct ena_admin_get_feature_link_desc *link; 3308c2ecf20Sopenharmony_ci struct ena_admin_get_feat_resp feat_resp; 3318c2ecf20Sopenharmony_ci int rc; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci rc = ena_com_get_link_params(ena_dev, &feat_resp); 3348c2ecf20Sopenharmony_ci if (rc) 3358c2ecf20Sopenharmony_ci return rc; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci link = &feat_resp.u.link; 3388c2ecf20Sopenharmony_ci link_ksettings->base.speed = link->speed; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (link->flags & ENA_ADMIN_GET_FEATURE_LINK_DESC_AUTONEG_MASK) { 3418c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(link_ksettings, 3428c2ecf20Sopenharmony_ci supported, Autoneg); 3438c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(link_ksettings, 3448c2ecf20Sopenharmony_ci supported, Autoneg); 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci link_ksettings->base.autoneg = 3488c2ecf20Sopenharmony_ci (link->flags & ENA_ADMIN_GET_FEATURE_LINK_DESC_AUTONEG_MASK) ? 3498c2ecf20Sopenharmony_ci AUTONEG_ENABLE : AUTONEG_DISABLE; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci link_ksettings->base.duplex = DUPLEX_FULL; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci return 0; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic int ena_get_coalesce(struct net_device *net_dev, 3578c2ecf20Sopenharmony_ci struct ethtool_coalesce *coalesce) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(net_dev); 3608c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (!ena_com_interrupt_moderation_supported(ena_dev)) 3638c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci coalesce->tx_coalesce_usecs = 3668c2ecf20Sopenharmony_ci ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) * 3678c2ecf20Sopenharmony_ci ena_dev->intr_delay_resolution; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci coalesce->rx_coalesce_usecs = 3708c2ecf20Sopenharmony_ci ena_com_get_nonadaptive_moderation_interval_rx(ena_dev) 3718c2ecf20Sopenharmony_ci * ena_dev->intr_delay_resolution; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci coalesce->use_adaptive_rx_coalesce = 3748c2ecf20Sopenharmony_ci ena_com_get_adaptive_moderation_enabled(ena_dev); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return 0; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic void ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci unsigned int val; 3828c2ecf20Sopenharmony_ci int i; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci val = ena_com_get_nonadaptive_moderation_interval_tx(adapter->ena_dev); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_io_queues; i++) 3878c2ecf20Sopenharmony_ci adapter->tx_ring[i].smoothed_interval = val; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci unsigned int val; 3938c2ecf20Sopenharmony_ci int i; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci val = ena_com_get_nonadaptive_moderation_interval_rx(adapter->ena_dev); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_io_queues; i++) 3988c2ecf20Sopenharmony_ci adapter->rx_ring[i].smoothed_interval = val; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic int ena_set_coalesce(struct net_device *net_dev, 4028c2ecf20Sopenharmony_ci struct ethtool_coalesce *coalesce) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(net_dev); 4058c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 4068c2ecf20Sopenharmony_ci int rc; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (!ena_com_interrupt_moderation_supported(ena_dev)) 4098c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci rc = ena_com_update_nonadaptive_moderation_interval_tx(ena_dev, 4128c2ecf20Sopenharmony_ci coalesce->tx_coalesce_usecs); 4138c2ecf20Sopenharmony_ci if (rc) 4148c2ecf20Sopenharmony_ci return rc; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci ena_update_tx_rings_nonadaptive_intr_moderation(adapter); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev, 4198c2ecf20Sopenharmony_ci coalesce->rx_coalesce_usecs); 4208c2ecf20Sopenharmony_ci if (rc) 4218c2ecf20Sopenharmony_ci return rc; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci ena_update_rx_rings_nonadaptive_intr_moderation(adapter); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (coalesce->use_adaptive_rx_coalesce && 4268c2ecf20Sopenharmony_ci !ena_com_get_adaptive_moderation_enabled(ena_dev)) 4278c2ecf20Sopenharmony_ci ena_com_enable_adaptive_moderation(ena_dev); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (!coalesce->use_adaptive_rx_coalesce && 4308c2ecf20Sopenharmony_ci ena_com_get_adaptive_moderation_enabled(ena_dev)) 4318c2ecf20Sopenharmony_ci ena_com_disable_adaptive_moderation(ena_dev); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci return 0; 4348c2ecf20Sopenharmony_ci} 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistatic u32 ena_get_msglevel(struct net_device *netdev) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci return adapter->msg_enable; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic void ena_set_msglevel(struct net_device *netdev, u32 value) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci adapter->msg_enable = value; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic void ena_get_drvinfo(struct net_device *dev, 4518c2ecf20Sopenharmony_ci struct ethtool_drvinfo *info) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(dev); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); 4568c2ecf20Sopenharmony_ci strlcpy(info->bus_info, pci_name(adapter->pdev), 4578c2ecf20Sopenharmony_ci sizeof(info->bus_info)); 4588c2ecf20Sopenharmony_ci} 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_cistatic void ena_get_ringparam(struct net_device *netdev, 4618c2ecf20Sopenharmony_ci struct ethtool_ringparam *ring) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci ring->tx_max_pending = adapter->max_tx_ring_size; 4668c2ecf20Sopenharmony_ci ring->rx_max_pending = adapter->max_rx_ring_size; 4678c2ecf20Sopenharmony_ci ring->tx_pending = adapter->tx_ring[0].ring_size; 4688c2ecf20Sopenharmony_ci ring->rx_pending = adapter->rx_ring[0].ring_size; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic int ena_set_ringparam(struct net_device *netdev, 4728c2ecf20Sopenharmony_ci struct ethtool_ringparam *ring) 4738c2ecf20Sopenharmony_ci{ 4748c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 4758c2ecf20Sopenharmony_ci u32 new_tx_size, new_rx_size; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci new_tx_size = ring->tx_pending < ENA_MIN_RING_SIZE ? 4788c2ecf20Sopenharmony_ci ENA_MIN_RING_SIZE : ring->tx_pending; 4798c2ecf20Sopenharmony_ci new_tx_size = rounddown_pow_of_two(new_tx_size); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci new_rx_size = ring->rx_pending < ENA_MIN_RING_SIZE ? 4828c2ecf20Sopenharmony_ci ENA_MIN_RING_SIZE : ring->rx_pending; 4838c2ecf20Sopenharmony_ci new_rx_size = rounddown_pow_of_two(new_rx_size); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (new_tx_size == adapter->requested_tx_ring_size && 4868c2ecf20Sopenharmony_ci new_rx_size == adapter->requested_rx_ring_size) 4878c2ecf20Sopenharmony_ci return 0; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci return ena_update_queue_sizes(adapter, new_tx_size, new_rx_size); 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic u32 ena_flow_hash_to_flow_type(u16 hash_fields) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci u32 data = 0; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (hash_fields & ENA_ADMIN_RSS_L2_DA) 4978c2ecf20Sopenharmony_ci data |= RXH_L2DA; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (hash_fields & ENA_ADMIN_RSS_L3_DA) 5008c2ecf20Sopenharmony_ci data |= RXH_IP_DST; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci if (hash_fields & ENA_ADMIN_RSS_L3_SA) 5038c2ecf20Sopenharmony_ci data |= RXH_IP_SRC; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (hash_fields & ENA_ADMIN_RSS_L4_DP) 5068c2ecf20Sopenharmony_ci data |= RXH_L4_B_2_3; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (hash_fields & ENA_ADMIN_RSS_L4_SP) 5098c2ecf20Sopenharmony_ci data |= RXH_L4_B_0_1; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci return data; 5128c2ecf20Sopenharmony_ci} 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic u16 ena_flow_data_to_flow_hash(u32 hash_fields) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci u16 data = 0; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (hash_fields & RXH_L2DA) 5198c2ecf20Sopenharmony_ci data |= ENA_ADMIN_RSS_L2_DA; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci if (hash_fields & RXH_IP_DST) 5228c2ecf20Sopenharmony_ci data |= ENA_ADMIN_RSS_L3_DA; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (hash_fields & RXH_IP_SRC) 5258c2ecf20Sopenharmony_ci data |= ENA_ADMIN_RSS_L3_SA; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci if (hash_fields & RXH_L4_B_2_3) 5288c2ecf20Sopenharmony_ci data |= ENA_ADMIN_RSS_L4_DP; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (hash_fields & RXH_L4_B_0_1) 5318c2ecf20Sopenharmony_ci data |= ENA_ADMIN_RSS_L4_SP; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci return data; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic int ena_get_rss_hash(struct ena_com_dev *ena_dev, 5378c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci enum ena_admin_flow_hash_proto proto; 5408c2ecf20Sopenharmony_ci u16 hash_fields; 5418c2ecf20Sopenharmony_ci int rc; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci cmd->data = 0; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci switch (cmd->flow_type) { 5468c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 5478c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_TCP4; 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 5508c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_UDP4; 5518c2ecf20Sopenharmony_ci break; 5528c2ecf20Sopenharmony_ci case TCP_V6_FLOW: 5538c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_TCP6; 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci case UDP_V6_FLOW: 5568c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_UDP6; 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case IPV4_FLOW: 5598c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_IP4; 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci case IPV6_FLOW: 5628c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_IP6; 5638c2ecf20Sopenharmony_ci break; 5648c2ecf20Sopenharmony_ci case ETHER_FLOW: 5658c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_NOT_IP; 5668c2ecf20Sopenharmony_ci break; 5678c2ecf20Sopenharmony_ci case AH_V4_FLOW: 5688c2ecf20Sopenharmony_ci case ESP_V4_FLOW: 5698c2ecf20Sopenharmony_ci case AH_V6_FLOW: 5708c2ecf20Sopenharmony_ci case ESP_V6_FLOW: 5718c2ecf20Sopenharmony_ci case SCTP_V4_FLOW: 5728c2ecf20Sopenharmony_ci case AH_ESP_V4_FLOW: 5738c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 5748c2ecf20Sopenharmony_ci default: 5758c2ecf20Sopenharmony_ci return -EINVAL; 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rc = ena_com_get_hash_ctrl(ena_dev, proto, &hash_fields); 5798c2ecf20Sopenharmony_ci if (rc) 5808c2ecf20Sopenharmony_ci return rc; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci cmd->data = ena_flow_hash_to_flow_type(hash_fields); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci return 0; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic int ena_set_rss_hash(struct ena_com_dev *ena_dev, 5888c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci enum ena_admin_flow_hash_proto proto; 5918c2ecf20Sopenharmony_ci u16 hash_fields; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci switch (cmd->flow_type) { 5948c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 5958c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_TCP4; 5968c2ecf20Sopenharmony_ci break; 5978c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 5988c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_UDP4; 5998c2ecf20Sopenharmony_ci break; 6008c2ecf20Sopenharmony_ci case TCP_V6_FLOW: 6018c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_TCP6; 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci case UDP_V6_FLOW: 6048c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_UDP6; 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci case IPV4_FLOW: 6078c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_IP4; 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci case IPV6_FLOW: 6108c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_IP6; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci case ETHER_FLOW: 6138c2ecf20Sopenharmony_ci proto = ENA_ADMIN_RSS_NOT_IP; 6148c2ecf20Sopenharmony_ci break; 6158c2ecf20Sopenharmony_ci case AH_V4_FLOW: 6168c2ecf20Sopenharmony_ci case ESP_V4_FLOW: 6178c2ecf20Sopenharmony_ci case AH_V6_FLOW: 6188c2ecf20Sopenharmony_ci case ESP_V6_FLOW: 6198c2ecf20Sopenharmony_ci case SCTP_V4_FLOW: 6208c2ecf20Sopenharmony_ci case AH_ESP_V4_FLOW: 6218c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 6228c2ecf20Sopenharmony_ci default: 6238c2ecf20Sopenharmony_ci return -EINVAL; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci hash_fields = ena_flow_data_to_flow_hash(cmd->data); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return ena_com_fill_hash_ctrl(ena_dev, proto, hash_fields); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int ena_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 6348c2ecf20Sopenharmony_ci int rc = 0; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci switch (info->cmd) { 6378c2ecf20Sopenharmony_ci case ETHTOOL_SRXFH: 6388c2ecf20Sopenharmony_ci rc = ena_set_rss_hash(adapter->ena_dev, info); 6398c2ecf20Sopenharmony_ci break; 6408c2ecf20Sopenharmony_ci case ETHTOOL_SRXCLSRLDEL: 6418c2ecf20Sopenharmony_ci case ETHTOOL_SRXCLSRLINS: 6428c2ecf20Sopenharmony_ci default: 6438c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, 6448c2ecf20Sopenharmony_ci "Command parameter %d is not supported\n", info->cmd); 6458c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci return rc; 6498c2ecf20Sopenharmony_ci} 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_cistatic int ena_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, 6528c2ecf20Sopenharmony_ci u32 *rules) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 6558c2ecf20Sopenharmony_ci int rc = 0; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci switch (info->cmd) { 6588c2ecf20Sopenharmony_ci case ETHTOOL_GRXRINGS: 6598c2ecf20Sopenharmony_ci info->data = adapter->num_io_queues; 6608c2ecf20Sopenharmony_ci rc = 0; 6618c2ecf20Sopenharmony_ci break; 6628c2ecf20Sopenharmony_ci case ETHTOOL_GRXFH: 6638c2ecf20Sopenharmony_ci rc = ena_get_rss_hash(adapter->ena_dev, info); 6648c2ecf20Sopenharmony_ci break; 6658c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRLCNT: 6668c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRULE: 6678c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRLALL: 6688c2ecf20Sopenharmony_ci default: 6698c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, 6708c2ecf20Sopenharmony_ci "Command parameter %d is not supported\n", info->cmd); 6718c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci return rc; 6758c2ecf20Sopenharmony_ci} 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_cistatic u32 ena_get_rxfh_indir_size(struct net_device *netdev) 6788c2ecf20Sopenharmony_ci{ 6798c2ecf20Sopenharmony_ci return ENA_RX_RSS_TABLE_SIZE; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic u32 ena_get_rxfh_key_size(struct net_device *netdev) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci return ENA_HASH_KEY_SIZE; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cistatic int ena_indirection_table_set(struct ena_adapter *adapter, 6888c2ecf20Sopenharmony_ci const u32 *indir) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 6918c2ecf20Sopenharmony_ci int i, rc; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) { 6948c2ecf20Sopenharmony_ci rc = ena_com_indirect_table_fill_entry(ena_dev, 6958c2ecf20Sopenharmony_ci i, 6968c2ecf20Sopenharmony_ci ENA_IO_RXQ_IDX(indir[i])); 6978c2ecf20Sopenharmony_ci if (unlikely(rc)) { 6988c2ecf20Sopenharmony_ci netif_err(adapter, drv, adapter->netdev, 6998c2ecf20Sopenharmony_ci "Cannot fill indirect table (index is too large)\n"); 7008c2ecf20Sopenharmony_ci return rc; 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci rc = ena_com_indirect_table_set(ena_dev); 7058c2ecf20Sopenharmony_ci if (rc) { 7068c2ecf20Sopenharmony_ci netif_err(adapter, drv, adapter->netdev, 7078c2ecf20Sopenharmony_ci "Cannot set indirect table\n"); 7088c2ecf20Sopenharmony_ci return rc == -EPERM ? -EOPNOTSUPP : rc; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci return rc; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 7168c2ecf20Sopenharmony_ci int i, rc; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (!indir) 7198c2ecf20Sopenharmony_ci return 0; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci rc = ena_com_indirect_table_get(ena_dev, indir); 7228c2ecf20Sopenharmony_ci if (rc) 7238c2ecf20Sopenharmony_ci return rc; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci /* Our internal representation of the indices is: even indices 7268c2ecf20Sopenharmony_ci * for Tx and uneven indices for Rx. We need to convert the Rx 7278c2ecf20Sopenharmony_ci * indices to be consecutive 7288c2ecf20Sopenharmony_ci */ 7298c2ecf20Sopenharmony_ci for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) 7308c2ecf20Sopenharmony_ci indir[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(indir[i]); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci return rc; 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_cistatic int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 7368c2ecf20Sopenharmony_ci u8 *hfunc) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 7398c2ecf20Sopenharmony_ci enum ena_admin_hash_functions ena_func; 7408c2ecf20Sopenharmony_ci u8 func; 7418c2ecf20Sopenharmony_ci int rc; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci rc = ena_indirection_table_get(adapter, indir); 7448c2ecf20Sopenharmony_ci if (rc) 7458c2ecf20Sopenharmony_ci return rc; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci /* We call this function in order to check if the device 7488c2ecf20Sopenharmony_ci * supports getting/setting the hash function. 7498c2ecf20Sopenharmony_ci */ 7508c2ecf20Sopenharmony_ci rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func); 7518c2ecf20Sopenharmony_ci if (rc) { 7528c2ecf20Sopenharmony_ci if (rc == -EOPNOTSUPP) 7538c2ecf20Sopenharmony_ci rc = 0; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci return rc; 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci rc = ena_com_get_hash_key(adapter->ena_dev, key); 7598c2ecf20Sopenharmony_ci if (rc) 7608c2ecf20Sopenharmony_ci return rc; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci switch (ena_func) { 7638c2ecf20Sopenharmony_ci case ENA_ADMIN_TOEPLITZ: 7648c2ecf20Sopenharmony_ci func = ETH_RSS_HASH_TOP; 7658c2ecf20Sopenharmony_ci break; 7668c2ecf20Sopenharmony_ci case ENA_ADMIN_CRC32: 7678c2ecf20Sopenharmony_ci func = ETH_RSS_HASH_CRC32; 7688c2ecf20Sopenharmony_ci break; 7698c2ecf20Sopenharmony_ci default: 7708c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, 7718c2ecf20Sopenharmony_ci "Command parameter is not supported\n"); 7728c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci if (hfunc) 7768c2ecf20Sopenharmony_ci *hfunc = func; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci return 0; 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic int ena_set_rxfh(struct net_device *netdev, const u32 *indir, 7828c2ecf20Sopenharmony_ci const u8 *key, const u8 hfunc) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 7858c2ecf20Sopenharmony_ci struct ena_com_dev *ena_dev = adapter->ena_dev; 7868c2ecf20Sopenharmony_ci enum ena_admin_hash_functions func = 0; 7878c2ecf20Sopenharmony_ci int rc; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci if (indir) { 7908c2ecf20Sopenharmony_ci rc = ena_indirection_table_set(adapter, indir); 7918c2ecf20Sopenharmony_ci if (rc) 7928c2ecf20Sopenharmony_ci return rc; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci switch (hfunc) { 7968c2ecf20Sopenharmony_ci case ETH_RSS_HASH_NO_CHANGE: 7978c2ecf20Sopenharmony_ci func = ena_com_get_current_hash_function(ena_dev); 7988c2ecf20Sopenharmony_ci break; 7998c2ecf20Sopenharmony_ci case ETH_RSS_HASH_TOP: 8008c2ecf20Sopenharmony_ci func = ENA_ADMIN_TOEPLITZ; 8018c2ecf20Sopenharmony_ci break; 8028c2ecf20Sopenharmony_ci case ETH_RSS_HASH_CRC32: 8038c2ecf20Sopenharmony_ci func = ENA_ADMIN_CRC32; 8048c2ecf20Sopenharmony_ci break; 8058c2ecf20Sopenharmony_ci default: 8068c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, "Unsupported hfunc %d\n", 8078c2ecf20Sopenharmony_ci hfunc); 8088c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci if (key || func) { 8128c2ecf20Sopenharmony_ci rc = ena_com_fill_hash_function(ena_dev, func, key, 8138c2ecf20Sopenharmony_ci ENA_HASH_KEY_SIZE, 8148c2ecf20Sopenharmony_ci 0xFFFFFFFF); 8158c2ecf20Sopenharmony_ci if (unlikely(rc)) { 8168c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, "Cannot fill key\n"); 8178c2ecf20Sopenharmony_ci return rc == -EPERM ? -EOPNOTSUPP : rc; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci return 0; 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_cistatic void ena_get_channels(struct net_device *netdev, 8258c2ecf20Sopenharmony_ci struct ethtool_channels *channels) 8268c2ecf20Sopenharmony_ci{ 8278c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci channels->max_combined = adapter->max_num_io_queues; 8308c2ecf20Sopenharmony_ci channels->combined_count = adapter->num_io_queues; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic int ena_set_channels(struct net_device *netdev, 8348c2ecf20Sopenharmony_ci struct ethtool_channels *channels) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 8378c2ecf20Sopenharmony_ci u32 count = channels->combined_count; 8388c2ecf20Sopenharmony_ci /* The check for max value is already done in ethtool */ 8398c2ecf20Sopenharmony_ci if (count < ENA_MIN_NUM_IO_QUEUES || 8408c2ecf20Sopenharmony_ci (ena_xdp_present(adapter) && 8418c2ecf20Sopenharmony_ci !ena_xdp_legal_queue_count(adapter, channels->combined_count))) 8428c2ecf20Sopenharmony_ci return -EINVAL; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci return ena_update_queue_count(adapter, count); 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_cistatic int ena_get_tunable(struct net_device *netdev, 8488c2ecf20Sopenharmony_ci const struct ethtool_tunable *tuna, void *data) 8498c2ecf20Sopenharmony_ci{ 8508c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 8518c2ecf20Sopenharmony_ci int ret = 0; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci switch (tuna->id) { 8548c2ecf20Sopenharmony_ci case ETHTOOL_RX_COPYBREAK: 8558c2ecf20Sopenharmony_ci *(u32 *)data = adapter->rx_copybreak; 8568c2ecf20Sopenharmony_ci break; 8578c2ecf20Sopenharmony_ci default: 8588c2ecf20Sopenharmony_ci ret = -EINVAL; 8598c2ecf20Sopenharmony_ci break; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return ret; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_cistatic int ena_set_tunable(struct net_device *netdev, 8668c2ecf20Sopenharmony_ci const struct ethtool_tunable *tuna, 8678c2ecf20Sopenharmony_ci const void *data) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct ena_adapter *adapter = netdev_priv(netdev); 8708c2ecf20Sopenharmony_ci int ret = 0; 8718c2ecf20Sopenharmony_ci u32 len; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci switch (tuna->id) { 8748c2ecf20Sopenharmony_ci case ETHTOOL_RX_COPYBREAK: 8758c2ecf20Sopenharmony_ci len = *(u32 *)data; 8768c2ecf20Sopenharmony_ci if (len > adapter->netdev->mtu) { 8778c2ecf20Sopenharmony_ci ret = -EINVAL; 8788c2ecf20Sopenharmony_ci break; 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci adapter->rx_copybreak = len; 8818c2ecf20Sopenharmony_ci break; 8828c2ecf20Sopenharmony_ci default: 8838c2ecf20Sopenharmony_ci ret = -EINVAL; 8848c2ecf20Sopenharmony_ci break; 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci return ret; 8888c2ecf20Sopenharmony_ci} 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic const struct ethtool_ops ena_ethtool_ops = { 8918c2ecf20Sopenharmony_ci .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 8928c2ecf20Sopenharmony_ci ETHTOOL_COALESCE_USE_ADAPTIVE_RX, 8938c2ecf20Sopenharmony_ci .get_link_ksettings = ena_get_link_ksettings, 8948c2ecf20Sopenharmony_ci .get_drvinfo = ena_get_drvinfo, 8958c2ecf20Sopenharmony_ci .get_msglevel = ena_get_msglevel, 8968c2ecf20Sopenharmony_ci .set_msglevel = ena_set_msglevel, 8978c2ecf20Sopenharmony_ci .get_link = ethtool_op_get_link, 8988c2ecf20Sopenharmony_ci .get_coalesce = ena_get_coalesce, 8998c2ecf20Sopenharmony_ci .set_coalesce = ena_set_coalesce, 9008c2ecf20Sopenharmony_ci .get_ringparam = ena_get_ringparam, 9018c2ecf20Sopenharmony_ci .set_ringparam = ena_set_ringparam, 9028c2ecf20Sopenharmony_ci .get_sset_count = ena_get_sset_count, 9038c2ecf20Sopenharmony_ci .get_strings = ena_get_ethtool_strings, 9048c2ecf20Sopenharmony_ci .get_ethtool_stats = ena_get_ethtool_stats, 9058c2ecf20Sopenharmony_ci .get_rxnfc = ena_get_rxnfc, 9068c2ecf20Sopenharmony_ci .set_rxnfc = ena_set_rxnfc, 9078c2ecf20Sopenharmony_ci .get_rxfh_indir_size = ena_get_rxfh_indir_size, 9088c2ecf20Sopenharmony_ci .get_rxfh_key_size = ena_get_rxfh_key_size, 9098c2ecf20Sopenharmony_ci .get_rxfh = ena_get_rxfh, 9108c2ecf20Sopenharmony_ci .set_rxfh = ena_set_rxfh, 9118c2ecf20Sopenharmony_ci .get_channels = ena_get_channels, 9128c2ecf20Sopenharmony_ci .set_channels = ena_set_channels, 9138c2ecf20Sopenharmony_ci .get_tunable = ena_get_tunable, 9148c2ecf20Sopenharmony_ci .set_tunable = ena_set_tunable, 9158c2ecf20Sopenharmony_ci .get_ts_info = ethtool_op_get_ts_info, 9168c2ecf20Sopenharmony_ci}; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_civoid ena_set_ethtool_ops(struct net_device *netdev) 9198c2ecf20Sopenharmony_ci{ 9208c2ecf20Sopenharmony_ci netdev->ethtool_ops = &ena_ethtool_ops; 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_cistatic void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 9268c2ecf20Sopenharmony_ci u8 *strings_buf; 9278c2ecf20Sopenharmony_ci u64 *data_buf; 9288c2ecf20Sopenharmony_ci int strings_num; 9298c2ecf20Sopenharmony_ci int i, rc; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci strings_num = ena_get_sw_stats_count(adapter); 9328c2ecf20Sopenharmony_ci if (strings_num <= 0) { 9338c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, "Can't get stats num\n"); 9348c2ecf20Sopenharmony_ci return; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci strings_buf = devm_kcalloc(&adapter->pdev->dev, 9388c2ecf20Sopenharmony_ci ETH_GSTRING_LEN, strings_num, 9398c2ecf20Sopenharmony_ci GFP_ATOMIC); 9408c2ecf20Sopenharmony_ci if (!strings_buf) { 9418c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, 9428c2ecf20Sopenharmony_ci "Failed to allocate strings_buf\n"); 9438c2ecf20Sopenharmony_ci return; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci data_buf = devm_kcalloc(&adapter->pdev->dev, 9478c2ecf20Sopenharmony_ci strings_num, sizeof(u64), 9488c2ecf20Sopenharmony_ci GFP_ATOMIC); 9498c2ecf20Sopenharmony_ci if (!data_buf) { 9508c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, 9518c2ecf20Sopenharmony_ci "Failed to allocate data buf\n"); 9528c2ecf20Sopenharmony_ci devm_kfree(&adapter->pdev->dev, strings_buf); 9538c2ecf20Sopenharmony_ci return; 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci ena_get_strings(adapter, strings_buf, false); 9578c2ecf20Sopenharmony_ci ena_get_stats(adapter, data_buf, false); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* If there is a buffer, dump stats, otherwise print them to dmesg */ 9608c2ecf20Sopenharmony_ci if (buf) 9618c2ecf20Sopenharmony_ci for (i = 0; i < strings_num; i++) { 9628c2ecf20Sopenharmony_ci rc = snprintf(buf, ETH_GSTRING_LEN + sizeof(u64), 9638c2ecf20Sopenharmony_ci "%s %llu\n", 9648c2ecf20Sopenharmony_ci strings_buf + i * ETH_GSTRING_LEN, 9658c2ecf20Sopenharmony_ci data_buf[i]); 9668c2ecf20Sopenharmony_ci buf += rc; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci else 9698c2ecf20Sopenharmony_ci for (i = 0; i < strings_num; i++) 9708c2ecf20Sopenharmony_ci netif_err(adapter, drv, netdev, "%s: %llu\n", 9718c2ecf20Sopenharmony_ci strings_buf + i * ETH_GSTRING_LEN, 9728c2ecf20Sopenharmony_ci data_buf[i]); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci devm_kfree(&adapter->pdev->dev, strings_buf); 9758c2ecf20Sopenharmony_ci devm_kfree(&adapter->pdev->dev, data_buf); 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_civoid ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci if (!buf) 9818c2ecf20Sopenharmony_ci return; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci ena_dump_stats_ex(adapter, buf); 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_civoid ena_dump_stats_to_dmesg(struct ena_adapter *adapter) 9878c2ecf20Sopenharmony_ci{ 9888c2ecf20Sopenharmony_ci ena_dump_stats_ex(adapter, NULL); 9898c2ecf20Sopenharmony_ci} 990