18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* ethtool support for ixgbe */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/pci.h> 118c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 128c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 138c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 148c2ecf20Sopenharmony_ci#include <linux/highmem.h> 158c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "ixgbe.h" 188c2ecf20Sopenharmony_ci#include "ixgbe_phy.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define IXGBE_ALL_RAR_ENTRIES 16 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cienum {NETDEV_STATS, IXGBE_STATS}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct ixgbe_stats { 268c2ecf20Sopenharmony_ci char stat_string[ETH_GSTRING_LEN]; 278c2ecf20Sopenharmony_ci int type; 288c2ecf20Sopenharmony_ci int sizeof_stat; 298c2ecf20Sopenharmony_ci int stat_offset; 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define IXGBE_STAT(m) IXGBE_STATS, \ 338c2ecf20Sopenharmony_ci sizeof(((struct ixgbe_adapter *)0)->m), \ 348c2ecf20Sopenharmony_ci offsetof(struct ixgbe_adapter, m) 358c2ecf20Sopenharmony_ci#define IXGBE_NETDEV_STAT(m) NETDEV_STATS, \ 368c2ecf20Sopenharmony_ci sizeof(((struct rtnl_link_stats64 *)0)->m), \ 378c2ecf20Sopenharmony_ci offsetof(struct rtnl_link_stats64, m) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic const struct ixgbe_stats ixgbe_gstrings_stats[] = { 408c2ecf20Sopenharmony_ci {"rx_packets", IXGBE_NETDEV_STAT(rx_packets)}, 418c2ecf20Sopenharmony_ci {"tx_packets", IXGBE_NETDEV_STAT(tx_packets)}, 428c2ecf20Sopenharmony_ci {"rx_bytes", IXGBE_NETDEV_STAT(rx_bytes)}, 438c2ecf20Sopenharmony_ci {"tx_bytes", IXGBE_NETDEV_STAT(tx_bytes)}, 448c2ecf20Sopenharmony_ci {"rx_pkts_nic", IXGBE_STAT(stats.gprc)}, 458c2ecf20Sopenharmony_ci {"tx_pkts_nic", IXGBE_STAT(stats.gptc)}, 468c2ecf20Sopenharmony_ci {"rx_bytes_nic", IXGBE_STAT(stats.gorc)}, 478c2ecf20Sopenharmony_ci {"tx_bytes_nic", IXGBE_STAT(stats.gotc)}, 488c2ecf20Sopenharmony_ci {"lsc_int", IXGBE_STAT(lsc_int)}, 498c2ecf20Sopenharmony_ci {"tx_busy", IXGBE_STAT(tx_busy)}, 508c2ecf20Sopenharmony_ci {"non_eop_descs", IXGBE_STAT(non_eop_descs)}, 518c2ecf20Sopenharmony_ci {"rx_errors", IXGBE_NETDEV_STAT(rx_errors)}, 528c2ecf20Sopenharmony_ci {"tx_errors", IXGBE_NETDEV_STAT(tx_errors)}, 538c2ecf20Sopenharmony_ci {"rx_dropped", IXGBE_NETDEV_STAT(rx_dropped)}, 548c2ecf20Sopenharmony_ci {"tx_dropped", IXGBE_NETDEV_STAT(tx_dropped)}, 558c2ecf20Sopenharmony_ci {"multicast", IXGBE_NETDEV_STAT(multicast)}, 568c2ecf20Sopenharmony_ci {"broadcast", IXGBE_STAT(stats.bprc)}, 578c2ecf20Sopenharmony_ci {"rx_no_buffer_count", IXGBE_STAT(stats.rnbc[0]) }, 588c2ecf20Sopenharmony_ci {"collisions", IXGBE_NETDEV_STAT(collisions)}, 598c2ecf20Sopenharmony_ci {"rx_over_errors", IXGBE_NETDEV_STAT(rx_over_errors)}, 608c2ecf20Sopenharmony_ci {"rx_crc_errors", IXGBE_NETDEV_STAT(rx_crc_errors)}, 618c2ecf20Sopenharmony_ci {"rx_frame_errors", IXGBE_NETDEV_STAT(rx_frame_errors)}, 628c2ecf20Sopenharmony_ci {"hw_rsc_aggregated", IXGBE_STAT(rsc_total_count)}, 638c2ecf20Sopenharmony_ci {"hw_rsc_flushed", IXGBE_STAT(rsc_total_flush)}, 648c2ecf20Sopenharmony_ci {"fdir_match", IXGBE_STAT(stats.fdirmatch)}, 658c2ecf20Sopenharmony_ci {"fdir_miss", IXGBE_STAT(stats.fdirmiss)}, 668c2ecf20Sopenharmony_ci {"fdir_overflow", IXGBE_STAT(fdir_overflow)}, 678c2ecf20Sopenharmony_ci {"rx_fifo_errors", IXGBE_NETDEV_STAT(rx_fifo_errors)}, 688c2ecf20Sopenharmony_ci {"rx_missed_errors", IXGBE_NETDEV_STAT(rx_missed_errors)}, 698c2ecf20Sopenharmony_ci {"tx_aborted_errors", IXGBE_NETDEV_STAT(tx_aborted_errors)}, 708c2ecf20Sopenharmony_ci {"tx_carrier_errors", IXGBE_NETDEV_STAT(tx_carrier_errors)}, 718c2ecf20Sopenharmony_ci {"tx_fifo_errors", IXGBE_NETDEV_STAT(tx_fifo_errors)}, 728c2ecf20Sopenharmony_ci {"tx_heartbeat_errors", IXGBE_NETDEV_STAT(tx_heartbeat_errors)}, 738c2ecf20Sopenharmony_ci {"tx_timeout_count", IXGBE_STAT(tx_timeout_count)}, 748c2ecf20Sopenharmony_ci {"tx_restart_queue", IXGBE_STAT(restart_queue)}, 758c2ecf20Sopenharmony_ci {"rx_length_errors", IXGBE_STAT(stats.rlec)}, 768c2ecf20Sopenharmony_ci {"rx_long_length_errors", IXGBE_STAT(stats.roc)}, 778c2ecf20Sopenharmony_ci {"rx_short_length_errors", IXGBE_STAT(stats.ruc)}, 788c2ecf20Sopenharmony_ci {"tx_flow_control_xon", IXGBE_STAT(stats.lxontxc)}, 798c2ecf20Sopenharmony_ci {"rx_flow_control_xon", IXGBE_STAT(stats.lxonrxc)}, 808c2ecf20Sopenharmony_ci {"tx_flow_control_xoff", IXGBE_STAT(stats.lxofftxc)}, 818c2ecf20Sopenharmony_ci {"rx_flow_control_xoff", IXGBE_STAT(stats.lxoffrxc)}, 828c2ecf20Sopenharmony_ci {"rx_csum_offload_errors", IXGBE_STAT(hw_csum_rx_error)}, 838c2ecf20Sopenharmony_ci {"alloc_rx_page", IXGBE_STAT(alloc_rx_page)}, 848c2ecf20Sopenharmony_ci {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, 858c2ecf20Sopenharmony_ci {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, 868c2ecf20Sopenharmony_ci {"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)}, 878c2ecf20Sopenharmony_ci {"os2bmc_rx_by_bmc", IXGBE_STAT(stats.o2bgptc)}, 888c2ecf20Sopenharmony_ci {"os2bmc_tx_by_bmc", IXGBE_STAT(stats.b2ospc)}, 898c2ecf20Sopenharmony_ci {"os2bmc_tx_by_host", IXGBE_STAT(stats.o2bspc)}, 908c2ecf20Sopenharmony_ci {"os2bmc_rx_by_host", IXGBE_STAT(stats.b2ogprc)}, 918c2ecf20Sopenharmony_ci {"tx_hwtstamp_timeouts", IXGBE_STAT(tx_hwtstamp_timeouts)}, 928c2ecf20Sopenharmony_ci {"tx_hwtstamp_skipped", IXGBE_STAT(tx_hwtstamp_skipped)}, 938c2ecf20Sopenharmony_ci {"rx_hwtstamp_cleared", IXGBE_STAT(rx_hwtstamp_cleared)}, 948c2ecf20Sopenharmony_ci {"tx_ipsec", IXGBE_STAT(tx_ipsec)}, 958c2ecf20Sopenharmony_ci {"rx_ipsec", IXGBE_STAT(rx_ipsec)}, 968c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 978c2ecf20Sopenharmony_ci {"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)}, 988c2ecf20Sopenharmony_ci {"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)}, 998c2ecf20Sopenharmony_ci {"rx_fcoe_packets", IXGBE_STAT(stats.fcoeprc)}, 1008c2ecf20Sopenharmony_ci {"rx_fcoe_dwords", IXGBE_STAT(stats.fcoedwrc)}, 1018c2ecf20Sopenharmony_ci {"fcoe_noddp", IXGBE_STAT(stats.fcoe_noddp)}, 1028c2ecf20Sopenharmony_ci {"fcoe_noddp_ext_buff", IXGBE_STAT(stats.fcoe_noddp_ext_buff)}, 1038c2ecf20Sopenharmony_ci {"tx_fcoe_packets", IXGBE_STAT(stats.fcoeptc)}, 1048c2ecf20Sopenharmony_ci {"tx_fcoe_dwords", IXGBE_STAT(stats.fcoedwtc)}, 1058c2ecf20Sopenharmony_ci#endif /* IXGBE_FCOE */ 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* ixgbe allocates num_tx_queues and num_rx_queues symmetrically so 1098c2ecf20Sopenharmony_ci * we set the num_rx_queues to evaluate to num_tx_queues. This is 1108c2ecf20Sopenharmony_ci * used because we do not have a good way to get the max number of 1118c2ecf20Sopenharmony_ci * rx queues with CONFIG_RPS disabled. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_ci#define IXGBE_NUM_RX_QUEUES netdev->num_tx_queues 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#define IXGBE_QUEUE_STATS_LEN ( \ 1168c2ecf20Sopenharmony_ci (netdev->num_tx_queues + IXGBE_NUM_RX_QUEUES) * \ 1178c2ecf20Sopenharmony_ci (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) 1188c2ecf20Sopenharmony_ci#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) 1198c2ecf20Sopenharmony_ci#define IXGBE_PB_STATS_LEN ( \ 1208c2ecf20Sopenharmony_ci (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \ 1218c2ecf20Sopenharmony_ci sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \ 1228c2ecf20Sopenharmony_ci sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \ 1238c2ecf20Sopenharmony_ci sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \ 1248c2ecf20Sopenharmony_ci / sizeof(u64)) 1258c2ecf20Sopenharmony_ci#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \ 1268c2ecf20Sopenharmony_ci IXGBE_PB_STATS_LEN + \ 1278c2ecf20Sopenharmony_ci IXGBE_QUEUE_STATS_LEN) 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { 1308c2ecf20Sopenharmony_ci "Register test (offline)", "Eeprom test (offline)", 1318c2ecf20Sopenharmony_ci "Interrupt test (offline)", "Loopback test (offline)", 1328c2ecf20Sopenharmony_ci "Link test (on/offline)" 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci#define IXGBE_TEST_LEN sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic const char ixgbe_priv_flags_strings[][ETH_GSTRING_LEN] = { 1378c2ecf20Sopenharmony_ci#define IXGBE_PRIV_FLAGS_LEGACY_RX BIT(0) 1388c2ecf20Sopenharmony_ci "legacy-rx", 1398c2ecf20Sopenharmony_ci#define IXGBE_PRIV_FLAGS_VF_IPSEC_EN BIT(1) 1408c2ecf20Sopenharmony_ci "vf-ipsec", 1418c2ecf20Sopenharmony_ci#define IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF BIT(2) 1428c2ecf20Sopenharmony_ci "mdd-disable-vf", 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define IXGBE_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbe_priv_flags_strings) 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#define ixgbe_isbackplane(type) ((type) == ixgbe_media_type_backplane) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void ixgbe_set_supported_10gtypes(struct ixgbe_hw *hw, 1508c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci if (!ixgbe_isbackplane(hw->phy.media_type)) { 1538c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 1548c2ecf20Sopenharmony_ci 10000baseT_Full); 1558c2ecf20Sopenharmony_ci return; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci switch (hw->device_id) { 1598c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82598: 1608c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4: 1618c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4_MEZZ: 1628c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 1638c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 1648c2ecf20Sopenharmony_ci (cmd, supported, 10000baseKX4_Full); 1658c2ecf20Sopenharmony_ci break; 1668c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82598_BX: 1678c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KR: 1688c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 1698c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 1708c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 1718c2ecf20Sopenharmony_ci (cmd, supported, 10000baseKR_Full); 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci default: 1748c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 1758c2ecf20Sopenharmony_ci (cmd, supported, 10000baseKX4_Full); 1768c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 1778c2ecf20Sopenharmony_ci (cmd, supported, 10000baseKR_Full); 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void ixgbe_set_advertising_10gtypes(struct ixgbe_hw *hw, 1838c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci if (!ixgbe_isbackplane(hw->phy.media_type)) { 1868c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 1878c2ecf20Sopenharmony_ci 10000baseT_Full); 1888c2ecf20Sopenharmony_ci return; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci switch (hw->device_id) { 1928c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82598: 1938c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4: 1948c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KX4_MEZZ: 1958c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KX4: 1968c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 1978c2ecf20Sopenharmony_ci (cmd, advertising, 10000baseKX4_Full); 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82598_BX: 2008c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_82599_KR: 2018c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_KR: 2028c2ecf20Sopenharmony_ci case IXGBE_DEV_ID_X550EM_X_XFI: 2038c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2048c2ecf20Sopenharmony_ci (cmd, advertising, 10000baseKR_Full); 2058c2ecf20Sopenharmony_ci break; 2068c2ecf20Sopenharmony_ci default: 2078c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2088c2ecf20Sopenharmony_ci (cmd, advertising, 10000baseKX4_Full); 2098c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2108c2ecf20Sopenharmony_ci (cmd, advertising, 10000baseKR_Full); 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int ixgbe_get_link_ksettings(struct net_device *netdev, 2168c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 2198c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 2208c2ecf20Sopenharmony_ci ixgbe_link_speed supported_link; 2218c2ecf20Sopenharmony_ci bool autoneg = false; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ethtool_link_ksettings_zero_link_mode(cmd, supported); 2248c2ecf20Sopenharmony_ci ethtool_link_ksettings_zero_link_mode(cmd, advertising); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* set the supported link speeds */ 2298c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) { 2308c2ecf20Sopenharmony_ci ixgbe_set_supported_10gtypes(hw, cmd); 2318c2ecf20Sopenharmony_ci ixgbe_set_advertising_10gtypes(hw, cmd); 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_5GB_FULL) 2348c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2358c2ecf20Sopenharmony_ci 5000baseT_Full); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_2_5GB_FULL) 2388c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2398c2ecf20Sopenharmony_ci 2500baseT_Full); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_1GB_FULL) { 2428c2ecf20Sopenharmony_ci if (ixgbe_isbackplane(hw->phy.media_type)) { 2438c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2448c2ecf20Sopenharmony_ci 1000baseKX_Full); 2458c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2468c2ecf20Sopenharmony_ci 1000baseKX_Full); 2478c2ecf20Sopenharmony_ci } else { 2488c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2498c2ecf20Sopenharmony_ci 1000baseT_Full); 2508c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2518c2ecf20Sopenharmony_ci 1000baseT_Full); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_100_FULL) { 2558c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2568c2ecf20Sopenharmony_ci 100baseT_Full); 2578c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2588c2ecf20Sopenharmony_ci 100baseT_Full); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_10_FULL) { 2618c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 2628c2ecf20Sopenharmony_ci 10baseT_Full); 2638c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2648c2ecf20Sopenharmony_ci 10baseT_Full); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* set the advertised speeds */ 2688c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised) { 2698c2ecf20Sopenharmony_ci ethtool_link_ksettings_zero_link_mode(cmd, advertising); 2708c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL) 2718c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2728c2ecf20Sopenharmony_ci 10baseT_Full); 2738c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) 2748c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2758c2ecf20Sopenharmony_ci 100baseT_Full); 2768c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) 2778c2ecf20Sopenharmony_ci ixgbe_set_advertising_10gtypes(hw, cmd); 2788c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) { 2798c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode 2808c2ecf20Sopenharmony_ci (cmd, supported, 1000baseKX_Full)) 2818c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2828c2ecf20Sopenharmony_ci (cmd, advertising, 1000baseKX_Full); 2838c2ecf20Sopenharmony_ci else 2848c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2858c2ecf20Sopenharmony_ci (cmd, advertising, 1000baseT_Full); 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) 2888c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2898c2ecf20Sopenharmony_ci 5000baseT_Full); 2908c2ecf20Sopenharmony_ci if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) 2918c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 2928c2ecf20Sopenharmony_ci 2500baseT_Full); 2938c2ecf20Sopenharmony_ci } else { 2948c2ecf20Sopenharmony_ci if (hw->phy.multispeed_fiber && !autoneg) { 2958c2ecf20Sopenharmony_ci if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) 2968c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode 2978c2ecf20Sopenharmony_ci (cmd, advertising, 10000baseT_Full); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (autoneg) { 3028c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); 3038c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); 3048c2ecf20Sopenharmony_ci cmd->base.autoneg = AUTONEG_ENABLE; 3058c2ecf20Sopenharmony_ci } else 3068c2ecf20Sopenharmony_ci cmd->base.autoneg = AUTONEG_DISABLE; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci /* Determine the remaining settings based on the PHY type. */ 3098c2ecf20Sopenharmony_ci switch (adapter->hw.phy.type) { 3108c2ecf20Sopenharmony_ci case ixgbe_phy_tn: 3118c2ecf20Sopenharmony_ci case ixgbe_phy_aq: 3128c2ecf20Sopenharmony_ci case ixgbe_phy_x550em_ext_t: 3138c2ecf20Sopenharmony_ci case ixgbe_phy_fw: 3148c2ecf20Sopenharmony_ci case ixgbe_phy_cu_unknown: 3158c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, TP); 3168c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); 3178c2ecf20Sopenharmony_ci cmd->base.port = PORT_TP; 3188c2ecf20Sopenharmony_ci break; 3198c2ecf20Sopenharmony_ci case ixgbe_phy_qt: 3208c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 3218c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); 3228c2ecf20Sopenharmony_ci cmd->base.port = PORT_FIBRE; 3238c2ecf20Sopenharmony_ci break; 3248c2ecf20Sopenharmony_ci case ixgbe_phy_nl: 3258c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_passive_tyco: 3268c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_passive_unknown: 3278c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_ftl: 3288c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_avago: 3298c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_intel: 3308c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_unknown: 3318c2ecf20Sopenharmony_ci case ixgbe_phy_qsfp_passive_unknown: 3328c2ecf20Sopenharmony_ci case ixgbe_phy_qsfp_active_unknown: 3338c2ecf20Sopenharmony_ci case ixgbe_phy_qsfp_intel: 3348c2ecf20Sopenharmony_ci case ixgbe_phy_qsfp_unknown: 3358c2ecf20Sopenharmony_ci /* SFP+ devices, further checking needed */ 3368c2ecf20Sopenharmony_ci switch (adapter->hw.phy.sfp_type) { 3378c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_cu: 3388c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_cu_core0: 3398c2ecf20Sopenharmony_ci case ixgbe_sfp_type_da_cu_core1: 3408c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3418c2ecf20Sopenharmony_ci FIBRE); 3428c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3438c2ecf20Sopenharmony_ci FIBRE); 3448c2ecf20Sopenharmony_ci cmd->base.port = PORT_DA; 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci case ixgbe_sfp_type_sr: 3478c2ecf20Sopenharmony_ci case ixgbe_sfp_type_lr: 3488c2ecf20Sopenharmony_ci case ixgbe_sfp_type_srlr_core0: 3498c2ecf20Sopenharmony_ci case ixgbe_sfp_type_srlr_core1: 3508c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core0: 3518c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_sx_core1: 3528c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core0: 3538c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_lx_core1: 3548c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3558c2ecf20Sopenharmony_ci FIBRE); 3568c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3578c2ecf20Sopenharmony_ci FIBRE); 3588c2ecf20Sopenharmony_ci cmd->base.port = PORT_FIBRE; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci case ixgbe_sfp_type_not_present: 3618c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3628c2ecf20Sopenharmony_ci FIBRE); 3638c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3648c2ecf20Sopenharmony_ci FIBRE); 3658c2ecf20Sopenharmony_ci cmd->base.port = PORT_NONE; 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core0: 3688c2ecf20Sopenharmony_ci case ixgbe_sfp_type_1g_cu_core1: 3698c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3708c2ecf20Sopenharmony_ci TP); 3718c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3728c2ecf20Sopenharmony_ci TP); 3738c2ecf20Sopenharmony_ci cmd->base.port = PORT_TP; 3748c2ecf20Sopenharmony_ci break; 3758c2ecf20Sopenharmony_ci case ixgbe_sfp_type_unknown: 3768c2ecf20Sopenharmony_ci default: 3778c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3788c2ecf20Sopenharmony_ci FIBRE); 3798c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3808c2ecf20Sopenharmony_ci FIBRE); 3818c2ecf20Sopenharmony_ci cmd->base.port = PORT_OTHER; 3828c2ecf20Sopenharmony_ci break; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci case ixgbe_phy_xaui: 3868c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3878c2ecf20Sopenharmony_ci FIBRE); 3888c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3898c2ecf20Sopenharmony_ci FIBRE); 3908c2ecf20Sopenharmony_ci cmd->base.port = PORT_NONE; 3918c2ecf20Sopenharmony_ci break; 3928c2ecf20Sopenharmony_ci case ixgbe_phy_unknown: 3938c2ecf20Sopenharmony_ci case ixgbe_phy_generic: 3948c2ecf20Sopenharmony_ci case ixgbe_phy_sfp_unsupported: 3958c2ecf20Sopenharmony_ci default: 3968c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, 3978c2ecf20Sopenharmony_ci FIBRE); 3988c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 3998c2ecf20Sopenharmony_ci FIBRE); 4008c2ecf20Sopenharmony_ci cmd->base.port = PORT_OTHER; 4018c2ecf20Sopenharmony_ci break; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* Indicate pause support */ 4058c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci switch (hw->fc.requested_mode) { 4088c2ecf20Sopenharmony_ci case ixgbe_fc_full: 4098c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); 4108c2ecf20Sopenharmony_ci break; 4118c2ecf20Sopenharmony_ci case ixgbe_fc_rx_pause: 4128c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); 4138c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 4148c2ecf20Sopenharmony_ci Asym_Pause); 4158c2ecf20Sopenharmony_ci break; 4168c2ecf20Sopenharmony_ci case ixgbe_fc_tx_pause: 4178c2ecf20Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, 4188c2ecf20Sopenharmony_ci Asym_Pause); 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci default: 4218c2ecf20Sopenharmony_ci ethtool_link_ksettings_del_link_mode(cmd, advertising, Pause); 4228c2ecf20Sopenharmony_ci ethtool_link_ksettings_del_link_mode(cmd, advertising, 4238c2ecf20Sopenharmony_ci Asym_Pause); 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (netif_carrier_ok(netdev)) { 4278c2ecf20Sopenharmony_ci switch (adapter->link_speed) { 4288c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 4298c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_10000; 4308c2ecf20Sopenharmony_ci break; 4318c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_5GB_FULL: 4328c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_5000; 4338c2ecf20Sopenharmony_ci break; 4348c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_2_5GB_FULL: 4358c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_2500; 4368c2ecf20Sopenharmony_ci break; 4378c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 4388c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_1000; 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_100_FULL: 4418c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_100; 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10_FULL: 4448c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_10; 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci default: 4478c2ecf20Sopenharmony_ci break; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci cmd->base.duplex = DUPLEX_FULL; 4508c2ecf20Sopenharmony_ci } else { 4518c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_UNKNOWN; 4528c2ecf20Sopenharmony_ci cmd->base.duplex = DUPLEX_UNKNOWN; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci return 0; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic int ixgbe_set_link_ksettings(struct net_device *netdev, 4598c2ecf20Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 4628c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 4638c2ecf20Sopenharmony_ci u32 advertised, old; 4648c2ecf20Sopenharmony_ci s32 err = 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if ((hw->phy.media_type == ixgbe_media_type_copper) || 4678c2ecf20Sopenharmony_ci (hw->phy.multispeed_fiber)) { 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * this function does not support duplex forcing, but can 4708c2ecf20Sopenharmony_ci * limit the advertising of the adapter to the specified speed 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci if (!bitmap_subset(cmd->link_modes.advertising, 4738c2ecf20Sopenharmony_ci cmd->link_modes.supported, 4748c2ecf20Sopenharmony_ci __ETHTOOL_LINK_MODE_MASK_NBITS)) 4758c2ecf20Sopenharmony_ci return -EINVAL; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci /* only allow one speed at a time if no autoneg */ 4788c2ecf20Sopenharmony_ci if (!cmd->base.autoneg && hw->phy.multispeed_fiber) { 4798c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 4808c2ecf20Sopenharmony_ci 10000baseT_Full) && 4818c2ecf20Sopenharmony_ci ethtool_link_ksettings_test_link_mode(cmd, advertising, 4828c2ecf20Sopenharmony_ci 1000baseT_Full)) 4838c2ecf20Sopenharmony_ci return -EINVAL; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci old = hw->phy.autoneg_advertised; 4878c2ecf20Sopenharmony_ci advertised = 0; 4888c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 4898c2ecf20Sopenharmony_ci 10000baseT_Full)) 4908c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_10GB_FULL; 4918c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 4928c2ecf20Sopenharmony_ci 5000baseT_Full)) 4938c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_5GB_FULL; 4948c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 4958c2ecf20Sopenharmony_ci 2500baseT_Full)) 4968c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_2_5GB_FULL; 4978c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 4988c2ecf20Sopenharmony_ci 1000baseT_Full)) 4998c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 5028c2ecf20Sopenharmony_ci 100baseT_Full)) 5038c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_100_FULL; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 5068c2ecf20Sopenharmony_ci 10baseT_Full)) 5078c2ecf20Sopenharmony_ci advertised |= IXGBE_LINK_SPEED_10_FULL; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (old == advertised) 5108c2ecf20Sopenharmony_ci return err; 5118c2ecf20Sopenharmony_ci /* this sets the link speed and restarts auto-neg */ 5128c2ecf20Sopenharmony_ci while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) 5138c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci hw->mac.autotry_restart = true; 5168c2ecf20Sopenharmony_ci err = hw->mac.ops.setup_link(hw, advertised, true); 5178c2ecf20Sopenharmony_ci if (err) { 5188c2ecf20Sopenharmony_ci e_info(probe, "setup link failed with code %d\n", err); 5198c2ecf20Sopenharmony_ci hw->mac.ops.setup_link(hw, old, true); 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); 5228c2ecf20Sopenharmony_ci } else { 5238c2ecf20Sopenharmony_ci /* in this case we currently only support 10Gb/FULL */ 5248c2ecf20Sopenharmony_ci u32 speed = cmd->base.speed; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if ((cmd->base.autoneg == AUTONEG_ENABLE) || 5278c2ecf20Sopenharmony_ci (!ethtool_link_ksettings_test_link_mode(cmd, advertising, 5288c2ecf20Sopenharmony_ci 10000baseT_Full)) || 5298c2ecf20Sopenharmony_ci (speed + cmd->base.duplex != SPEED_10000 + DUPLEX_FULL)) 5308c2ecf20Sopenharmony_ci return -EINVAL; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci return err; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void ixgbe_get_pause_stats(struct net_device *netdev, 5378c2ecf20Sopenharmony_ci struct ethtool_pause_stats *stats) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 5408c2ecf20Sopenharmony_ci struct ixgbe_hw_stats *hwstats = &adapter->stats; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci stats->tx_pause_frames = hwstats->lxontxc + hwstats->lxofftxc; 5438c2ecf20Sopenharmony_ci stats->rx_pause_frames = hwstats->lxonrxc + hwstats->lxoffrxc; 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic void ixgbe_get_pauseparam(struct net_device *netdev, 5478c2ecf20Sopenharmony_ci struct ethtool_pauseparam *pause) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 5508c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (ixgbe_device_supports_autoneg_fc(hw) && 5538c2ecf20Sopenharmony_ci !hw->fc.disable_fc_autoneg) 5548c2ecf20Sopenharmony_ci pause->autoneg = 1; 5558c2ecf20Sopenharmony_ci else 5568c2ecf20Sopenharmony_ci pause->autoneg = 0; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (hw->fc.current_mode == ixgbe_fc_rx_pause) { 5598c2ecf20Sopenharmony_ci pause->rx_pause = 1; 5608c2ecf20Sopenharmony_ci } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) { 5618c2ecf20Sopenharmony_ci pause->tx_pause = 1; 5628c2ecf20Sopenharmony_ci } else if (hw->fc.current_mode == ixgbe_fc_full) { 5638c2ecf20Sopenharmony_ci pause->rx_pause = 1; 5648c2ecf20Sopenharmony_ci pause->tx_pause = 1; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic int ixgbe_set_pauseparam(struct net_device *netdev, 5698c2ecf20Sopenharmony_ci struct ethtool_pauseparam *pause) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 5728c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 5738c2ecf20Sopenharmony_ci struct ixgbe_fc_info fc = hw->fc; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* 82598 does no support link flow control with DCB enabled */ 5768c2ecf20Sopenharmony_ci if ((hw->mac.type == ixgbe_mac_82598EB) && 5778c2ecf20Sopenharmony_ci (adapter->flags & IXGBE_FLAG_DCB_ENABLED)) 5788c2ecf20Sopenharmony_ci return -EINVAL; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* some devices do not support autoneg of link flow control */ 5818c2ecf20Sopenharmony_ci if ((pause->autoneg == AUTONEG_ENABLE) && 5828c2ecf20Sopenharmony_ci !ixgbe_device_supports_autoneg_fc(hw)) 5838c2ecf20Sopenharmony_ci return -EINVAL; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if ((pause->rx_pause && pause->tx_pause) || pause->autoneg) 5888c2ecf20Sopenharmony_ci fc.requested_mode = ixgbe_fc_full; 5898c2ecf20Sopenharmony_ci else if (pause->rx_pause && !pause->tx_pause) 5908c2ecf20Sopenharmony_ci fc.requested_mode = ixgbe_fc_rx_pause; 5918c2ecf20Sopenharmony_ci else if (!pause->rx_pause && pause->tx_pause) 5928c2ecf20Sopenharmony_ci fc.requested_mode = ixgbe_fc_tx_pause; 5938c2ecf20Sopenharmony_ci else 5948c2ecf20Sopenharmony_ci fc.requested_mode = ixgbe_fc_none; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* if the thing changed then we'll update and use new autoneg */ 5978c2ecf20Sopenharmony_ci if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) { 5988c2ecf20Sopenharmony_ci hw->fc = fc; 5998c2ecf20Sopenharmony_ci if (netif_running(netdev)) 6008c2ecf20Sopenharmony_ci ixgbe_reinit_locked(adapter); 6018c2ecf20Sopenharmony_ci else 6028c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci return 0; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic u32 ixgbe_get_msglevel(struct net_device *netdev) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 6118c2ecf20Sopenharmony_ci return adapter->msg_enable; 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cistatic void ixgbe_set_msglevel(struct net_device *netdev, u32 data) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 6178c2ecf20Sopenharmony_ci adapter->msg_enable = data; 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic int ixgbe_get_regs_len(struct net_device *netdev) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci#define IXGBE_REGS_LEN 1145 6238c2ecf20Sopenharmony_ci return IXGBE_REGS_LEN * sizeof(u32); 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci#define IXGBE_GET_STAT(_A_, _R_) _A_->stats._R_ 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_cistatic void ixgbe_get_regs(struct net_device *netdev, 6298c2ecf20Sopenharmony_ci struct ethtool_regs *regs, void *p) 6308c2ecf20Sopenharmony_ci{ 6318c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 6328c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 6338c2ecf20Sopenharmony_ci u32 *regs_buff = p; 6348c2ecf20Sopenharmony_ci u8 i; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci memset(p, 0, IXGBE_REGS_LEN * sizeof(u32)); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci regs->version = hw->mac.type << 24 | hw->revision_id << 16 | 6398c2ecf20Sopenharmony_ci hw->device_id; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* General Registers */ 6428c2ecf20Sopenharmony_ci regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_CTRL); 6438c2ecf20Sopenharmony_ci regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_STATUS); 6448c2ecf20Sopenharmony_ci regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 6458c2ecf20Sopenharmony_ci regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_ESDP); 6468c2ecf20Sopenharmony_ci regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_EODSDP); 6478c2ecf20Sopenharmony_ci regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 6488c2ecf20Sopenharmony_ci regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_FRTIMER); 6498c2ecf20Sopenharmony_ci regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_TCPTIMER); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci /* NVM Register */ 6528c2ecf20Sopenharmony_ci regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); 6538c2ecf20Sopenharmony_ci regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_EERD); 6548c2ecf20Sopenharmony_ci regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_FLA(hw)); 6558c2ecf20Sopenharmony_ci regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_EEMNGCTL); 6568c2ecf20Sopenharmony_ci regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_EEMNGDATA); 6578c2ecf20Sopenharmony_ci regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_FLMNGCTL); 6588c2ecf20Sopenharmony_ci regs_buff[14] = IXGBE_READ_REG(hw, IXGBE_FLMNGDATA); 6598c2ecf20Sopenharmony_ci regs_buff[15] = IXGBE_READ_REG(hw, IXGBE_FLMNGCNT); 6608c2ecf20Sopenharmony_ci regs_buff[16] = IXGBE_READ_REG(hw, IXGBE_FLOP); 6618c2ecf20Sopenharmony_ci regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC(hw)); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* Interrupt */ 6648c2ecf20Sopenharmony_ci /* don't read EICR because it can clear interrupt causes, instead 6658c2ecf20Sopenharmony_ci * read EICS which is a shadow but doesn't clear EICR */ 6668c2ecf20Sopenharmony_ci regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICS); 6678c2ecf20Sopenharmony_ci regs_buff[19] = IXGBE_READ_REG(hw, IXGBE_EICS); 6688c2ecf20Sopenharmony_ci regs_buff[20] = IXGBE_READ_REG(hw, IXGBE_EIMS); 6698c2ecf20Sopenharmony_ci regs_buff[21] = IXGBE_READ_REG(hw, IXGBE_EIMC); 6708c2ecf20Sopenharmony_ci regs_buff[22] = IXGBE_READ_REG(hw, IXGBE_EIAC); 6718c2ecf20Sopenharmony_ci regs_buff[23] = IXGBE_READ_REG(hw, IXGBE_EIAM); 6728c2ecf20Sopenharmony_ci regs_buff[24] = IXGBE_READ_REG(hw, IXGBE_EITR(0)); 6738c2ecf20Sopenharmony_ci regs_buff[25] = IXGBE_READ_REG(hw, IXGBE_IVAR(0)); 6748c2ecf20Sopenharmony_ci regs_buff[26] = IXGBE_READ_REG(hw, IXGBE_MSIXT); 6758c2ecf20Sopenharmony_ci regs_buff[27] = IXGBE_READ_REG(hw, IXGBE_MSIXPBA); 6768c2ecf20Sopenharmony_ci regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL(0)); 6778c2ecf20Sopenharmony_ci regs_buff[29] = IXGBE_READ_REG(hw, IXGBE_GPIE); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci /* Flow Control */ 6808c2ecf20Sopenharmony_ci regs_buff[30] = IXGBE_READ_REG(hw, IXGBE_PFCTOP); 6818c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 6828c2ecf20Sopenharmony_ci regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_FCTTV(i)); 6838c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 6848c2ecf20Sopenharmony_ci switch (hw->mac.type) { 6858c2ecf20Sopenharmony_ci case ixgbe_mac_82598EB: 6868c2ecf20Sopenharmony_ci regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i)); 6878c2ecf20Sopenharmony_ci regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i)); 6888c2ecf20Sopenharmony_ci break; 6898c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 6908c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 6918c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 6928c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 6938c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 6948c2ecf20Sopenharmony_ci regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i)); 6958c2ecf20Sopenharmony_ci regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); 6968c2ecf20Sopenharmony_ci break; 6978c2ecf20Sopenharmony_ci default: 6988c2ecf20Sopenharmony_ci break; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV); 7028c2ecf20Sopenharmony_ci regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci /* Receive DMA */ 7058c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7068c2ecf20Sopenharmony_ci regs_buff[53 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAL(i)); 7078c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7088c2ecf20Sopenharmony_ci regs_buff[117 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAH(i)); 7098c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7108c2ecf20Sopenharmony_ci regs_buff[181 + i] = IXGBE_READ_REG(hw, IXGBE_RDLEN(i)); 7118c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7128c2ecf20Sopenharmony_ci regs_buff[245 + i] = IXGBE_READ_REG(hw, IXGBE_RDH(i)); 7138c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7148c2ecf20Sopenharmony_ci regs_buff[309 + i] = IXGBE_READ_REG(hw, IXGBE_RDT(i)); 7158c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 7168c2ecf20Sopenharmony_ci regs_buff[373 + i] = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 7178c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 7188c2ecf20Sopenharmony_ci regs_buff[437 + i] = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i)); 7198c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 7208c2ecf20Sopenharmony_ci regs_buff[453 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 7218c2ecf20Sopenharmony_ci regs_buff[469] = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); 7228c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7238c2ecf20Sopenharmony_ci regs_buff[470 + i] = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); 7248c2ecf20Sopenharmony_ci regs_buff[478] = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 7258c2ecf20Sopenharmony_ci regs_buff[479] = IXGBE_READ_REG(hw, IXGBE_DROPEN); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci /* Receive */ 7288c2ecf20Sopenharmony_ci regs_buff[480] = IXGBE_READ_REG(hw, IXGBE_RXCSUM); 7298c2ecf20Sopenharmony_ci regs_buff[481] = IXGBE_READ_REG(hw, IXGBE_RFCTL); 7308c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 7318c2ecf20Sopenharmony_ci regs_buff[482 + i] = IXGBE_READ_REG(hw, IXGBE_RAL(i)); 7328c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 7338c2ecf20Sopenharmony_ci regs_buff[498 + i] = IXGBE_READ_REG(hw, IXGBE_RAH(i)); 7348c2ecf20Sopenharmony_ci regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)); 7358c2ecf20Sopenharmony_ci regs_buff[515] = IXGBE_READ_REG(hw, IXGBE_FCTRL); 7368c2ecf20Sopenharmony_ci regs_buff[516] = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); 7378c2ecf20Sopenharmony_ci regs_buff[517] = IXGBE_READ_REG(hw, IXGBE_MCSTCTRL); 7388c2ecf20Sopenharmony_ci regs_buff[518] = IXGBE_READ_REG(hw, IXGBE_MRQC); 7398c2ecf20Sopenharmony_ci regs_buff[519] = IXGBE_READ_REG(hw, IXGBE_VMD_CTL); 7408c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7418c2ecf20Sopenharmony_ci regs_buff[520 + i] = IXGBE_READ_REG(hw, IXGBE_IMIR(i)); 7428c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7438c2ecf20Sopenharmony_ci regs_buff[528 + i] = IXGBE_READ_REG(hw, IXGBE_IMIREXT(i)); 7448c2ecf20Sopenharmony_ci regs_buff[536] = IXGBE_READ_REG(hw, IXGBE_IMIRVP); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* Transmit */ 7478c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7488c2ecf20Sopenharmony_ci regs_buff[537 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAL(i)); 7498c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7508c2ecf20Sopenharmony_ci regs_buff[569 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAH(i)); 7518c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7528c2ecf20Sopenharmony_ci regs_buff[601 + i] = IXGBE_READ_REG(hw, IXGBE_TDLEN(i)); 7538c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7548c2ecf20Sopenharmony_ci regs_buff[633 + i] = IXGBE_READ_REG(hw, IXGBE_TDH(i)); 7558c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7568c2ecf20Sopenharmony_ci regs_buff[665 + i] = IXGBE_READ_REG(hw, IXGBE_TDT(i)); 7578c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7588c2ecf20Sopenharmony_ci regs_buff[697 + i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); 7598c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7608c2ecf20Sopenharmony_ci regs_buff[729 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAL(i)); 7618c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 7628c2ecf20Sopenharmony_ci regs_buff[761 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAH(i)); 7638c2ecf20Sopenharmony_ci regs_buff[793] = IXGBE_READ_REG(hw, IXGBE_DTXCTL); 7648c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 7658c2ecf20Sopenharmony_ci regs_buff[794 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); 7668c2ecf20Sopenharmony_ci regs_buff[810] = IXGBE_READ_REG(hw, IXGBE_TIPG); 7678c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7688c2ecf20Sopenharmony_ci regs_buff[811 + i] = IXGBE_READ_REG(hw, IXGBE_TXPBSIZE(i)); 7698c2ecf20Sopenharmony_ci regs_buff[819] = IXGBE_READ_REG(hw, IXGBE_MNGTXMAP); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci /* Wake Up */ 7728c2ecf20Sopenharmony_ci regs_buff[820] = IXGBE_READ_REG(hw, IXGBE_WUC); 7738c2ecf20Sopenharmony_ci regs_buff[821] = IXGBE_READ_REG(hw, IXGBE_WUFC); 7748c2ecf20Sopenharmony_ci regs_buff[822] = IXGBE_READ_REG(hw, IXGBE_WUS); 7758c2ecf20Sopenharmony_ci regs_buff[823] = IXGBE_READ_REG(hw, IXGBE_IPAV); 7768c2ecf20Sopenharmony_ci regs_buff[824] = IXGBE_READ_REG(hw, IXGBE_IP4AT); 7778c2ecf20Sopenharmony_ci regs_buff[825] = IXGBE_READ_REG(hw, IXGBE_IP6AT); 7788c2ecf20Sopenharmony_ci regs_buff[826] = IXGBE_READ_REG(hw, IXGBE_WUPL); 7798c2ecf20Sopenharmony_ci regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM); 7808c2ecf20Sopenharmony_ci regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT(0)); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci /* DCB */ 7838c2ecf20Sopenharmony_ci regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS); /* same as FCCFG */ 7848c2ecf20Sopenharmony_ci regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS); /* same as RTTPCS */ 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci switch (hw->mac.type) { 7878c2ecf20Sopenharmony_ci case ixgbe_mac_82598EB: 7888c2ecf20Sopenharmony_ci regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS); 7898c2ecf20Sopenharmony_ci regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RUPPBMR); 7908c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7918c2ecf20Sopenharmony_ci regs_buff[833 + i] = 7928c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RT2CR(i)); 7938c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7948c2ecf20Sopenharmony_ci regs_buff[841 + i] = 7958c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RT2SR(i)); 7968c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 7978c2ecf20Sopenharmony_ci regs_buff[849 + i] = 7988c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TDTQ2TCCR(i)); 7998c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8008c2ecf20Sopenharmony_ci regs_buff[857 + i] = 8018c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TDTQ2TCSR(i)); 8028c2ecf20Sopenharmony_ci break; 8038c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 8048c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 8058c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 8068c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 8078c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 8088c2ecf20Sopenharmony_ci regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_RTTDCS); 8098c2ecf20Sopenharmony_ci regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RTRPCS); 8108c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8118c2ecf20Sopenharmony_ci regs_buff[833 + i] = 8128c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RTRPT4C(i)); 8138c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8148c2ecf20Sopenharmony_ci regs_buff[841 + i] = 8158c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RTRPT4S(i)); 8168c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8178c2ecf20Sopenharmony_ci regs_buff[849 + i] = 8188c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RTTDT2C(i)); 8198c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8208c2ecf20Sopenharmony_ci regs_buff[857 + i] = 8218c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_RTTDT2S(i)); 8228c2ecf20Sopenharmony_ci break; 8238c2ecf20Sopenharmony_ci default: 8248c2ecf20Sopenharmony_ci break; 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8288c2ecf20Sopenharmony_ci regs_buff[865 + i] = 8298c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TDPT2TCCR(i)); /* same as RTTPT2C */ 8308c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8318c2ecf20Sopenharmony_ci regs_buff[873 + i] = 8328c2ecf20Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_TDPT2TCSR(i)); /* same as RTTPT2S */ 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Statistics */ 8358c2ecf20Sopenharmony_ci regs_buff[881] = IXGBE_GET_STAT(adapter, crcerrs); 8368c2ecf20Sopenharmony_ci regs_buff[882] = IXGBE_GET_STAT(adapter, illerrc); 8378c2ecf20Sopenharmony_ci regs_buff[883] = IXGBE_GET_STAT(adapter, errbc); 8388c2ecf20Sopenharmony_ci regs_buff[884] = IXGBE_GET_STAT(adapter, mspdc); 8398c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8408c2ecf20Sopenharmony_ci regs_buff[885 + i] = IXGBE_GET_STAT(adapter, mpc[i]); 8418c2ecf20Sopenharmony_ci regs_buff[893] = IXGBE_GET_STAT(adapter, mlfc); 8428c2ecf20Sopenharmony_ci regs_buff[894] = IXGBE_GET_STAT(adapter, mrfc); 8438c2ecf20Sopenharmony_ci regs_buff[895] = IXGBE_GET_STAT(adapter, rlec); 8448c2ecf20Sopenharmony_ci regs_buff[896] = IXGBE_GET_STAT(adapter, lxontxc); 8458c2ecf20Sopenharmony_ci regs_buff[897] = IXGBE_GET_STAT(adapter, lxonrxc); 8468c2ecf20Sopenharmony_ci regs_buff[898] = IXGBE_GET_STAT(adapter, lxofftxc); 8478c2ecf20Sopenharmony_ci regs_buff[899] = IXGBE_GET_STAT(adapter, lxoffrxc); 8488c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8498c2ecf20Sopenharmony_ci regs_buff[900 + i] = IXGBE_GET_STAT(adapter, pxontxc[i]); 8508c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8518c2ecf20Sopenharmony_ci regs_buff[908 + i] = IXGBE_GET_STAT(adapter, pxonrxc[i]); 8528c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8538c2ecf20Sopenharmony_ci regs_buff[916 + i] = IXGBE_GET_STAT(adapter, pxofftxc[i]); 8548c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8558c2ecf20Sopenharmony_ci regs_buff[924 + i] = IXGBE_GET_STAT(adapter, pxoffrxc[i]); 8568c2ecf20Sopenharmony_ci regs_buff[932] = IXGBE_GET_STAT(adapter, prc64); 8578c2ecf20Sopenharmony_ci regs_buff[933] = IXGBE_GET_STAT(adapter, prc127); 8588c2ecf20Sopenharmony_ci regs_buff[934] = IXGBE_GET_STAT(adapter, prc255); 8598c2ecf20Sopenharmony_ci regs_buff[935] = IXGBE_GET_STAT(adapter, prc511); 8608c2ecf20Sopenharmony_ci regs_buff[936] = IXGBE_GET_STAT(adapter, prc1023); 8618c2ecf20Sopenharmony_ci regs_buff[937] = IXGBE_GET_STAT(adapter, prc1522); 8628c2ecf20Sopenharmony_ci regs_buff[938] = IXGBE_GET_STAT(adapter, gprc); 8638c2ecf20Sopenharmony_ci regs_buff[939] = IXGBE_GET_STAT(adapter, bprc); 8648c2ecf20Sopenharmony_ci regs_buff[940] = IXGBE_GET_STAT(adapter, mprc); 8658c2ecf20Sopenharmony_ci regs_buff[941] = IXGBE_GET_STAT(adapter, gptc); 8668c2ecf20Sopenharmony_ci regs_buff[942] = (u32)IXGBE_GET_STAT(adapter, gorc); 8678c2ecf20Sopenharmony_ci regs_buff[943] = (u32)(IXGBE_GET_STAT(adapter, gorc) >> 32); 8688c2ecf20Sopenharmony_ci regs_buff[944] = (u32)IXGBE_GET_STAT(adapter, gotc); 8698c2ecf20Sopenharmony_ci regs_buff[945] = (u32)(IXGBE_GET_STAT(adapter, gotc) >> 32); 8708c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 8718c2ecf20Sopenharmony_ci regs_buff[946 + i] = IXGBE_GET_STAT(adapter, rnbc[i]); 8728c2ecf20Sopenharmony_ci regs_buff[954] = IXGBE_GET_STAT(adapter, ruc); 8738c2ecf20Sopenharmony_ci regs_buff[955] = IXGBE_GET_STAT(adapter, rfc); 8748c2ecf20Sopenharmony_ci regs_buff[956] = IXGBE_GET_STAT(adapter, roc); 8758c2ecf20Sopenharmony_ci regs_buff[957] = IXGBE_GET_STAT(adapter, rjc); 8768c2ecf20Sopenharmony_ci regs_buff[958] = IXGBE_GET_STAT(adapter, mngprc); 8778c2ecf20Sopenharmony_ci regs_buff[959] = IXGBE_GET_STAT(adapter, mngpdc); 8788c2ecf20Sopenharmony_ci regs_buff[960] = IXGBE_GET_STAT(adapter, mngptc); 8798c2ecf20Sopenharmony_ci regs_buff[961] = (u32)IXGBE_GET_STAT(adapter, tor); 8808c2ecf20Sopenharmony_ci regs_buff[962] = (u32)(IXGBE_GET_STAT(adapter, tor) >> 32); 8818c2ecf20Sopenharmony_ci regs_buff[963] = IXGBE_GET_STAT(adapter, tpr); 8828c2ecf20Sopenharmony_ci regs_buff[964] = IXGBE_GET_STAT(adapter, tpt); 8838c2ecf20Sopenharmony_ci regs_buff[965] = IXGBE_GET_STAT(adapter, ptc64); 8848c2ecf20Sopenharmony_ci regs_buff[966] = IXGBE_GET_STAT(adapter, ptc127); 8858c2ecf20Sopenharmony_ci regs_buff[967] = IXGBE_GET_STAT(adapter, ptc255); 8868c2ecf20Sopenharmony_ci regs_buff[968] = IXGBE_GET_STAT(adapter, ptc511); 8878c2ecf20Sopenharmony_ci regs_buff[969] = IXGBE_GET_STAT(adapter, ptc1023); 8888c2ecf20Sopenharmony_ci regs_buff[970] = IXGBE_GET_STAT(adapter, ptc1522); 8898c2ecf20Sopenharmony_ci regs_buff[971] = IXGBE_GET_STAT(adapter, mptc); 8908c2ecf20Sopenharmony_ci regs_buff[972] = IXGBE_GET_STAT(adapter, bptc); 8918c2ecf20Sopenharmony_ci regs_buff[973] = IXGBE_GET_STAT(adapter, xec); 8928c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 8938c2ecf20Sopenharmony_ci regs_buff[974 + i] = IXGBE_GET_STAT(adapter, qprc[i]); 8948c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 8958c2ecf20Sopenharmony_ci regs_buff[990 + i] = IXGBE_GET_STAT(adapter, qptc[i]); 8968c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 8978c2ecf20Sopenharmony_ci regs_buff[1006 + i] = IXGBE_GET_STAT(adapter, qbrc[i]); 8988c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) 8998c2ecf20Sopenharmony_ci regs_buff[1022 + i] = IXGBE_GET_STAT(adapter, qbtc[i]); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci /* MAC */ 9028c2ecf20Sopenharmony_ci regs_buff[1038] = IXGBE_READ_REG(hw, IXGBE_PCS1GCFIG); 9038c2ecf20Sopenharmony_ci regs_buff[1039] = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 9048c2ecf20Sopenharmony_ci regs_buff[1040] = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 9058c2ecf20Sopenharmony_ci regs_buff[1041] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG0); 9068c2ecf20Sopenharmony_ci regs_buff[1042] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG1); 9078c2ecf20Sopenharmony_ci regs_buff[1043] = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 9088c2ecf20Sopenharmony_ci regs_buff[1044] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 9098c2ecf20Sopenharmony_ci regs_buff[1045] = IXGBE_READ_REG(hw, IXGBE_PCS1GANNP); 9108c2ecf20Sopenharmony_ci regs_buff[1046] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLPNP); 9118c2ecf20Sopenharmony_ci regs_buff[1047] = IXGBE_READ_REG(hw, IXGBE_HLREG0); 9128c2ecf20Sopenharmony_ci regs_buff[1048] = IXGBE_READ_REG(hw, IXGBE_HLREG1); 9138c2ecf20Sopenharmony_ci regs_buff[1049] = IXGBE_READ_REG(hw, IXGBE_PAP); 9148c2ecf20Sopenharmony_ci regs_buff[1050] = IXGBE_READ_REG(hw, IXGBE_MACA); 9158c2ecf20Sopenharmony_ci regs_buff[1051] = IXGBE_READ_REG(hw, IXGBE_APAE); 9168c2ecf20Sopenharmony_ci regs_buff[1052] = IXGBE_READ_REG(hw, IXGBE_ARD); 9178c2ecf20Sopenharmony_ci regs_buff[1053] = IXGBE_READ_REG(hw, IXGBE_AIS); 9188c2ecf20Sopenharmony_ci regs_buff[1054] = IXGBE_READ_REG(hw, IXGBE_MSCA); 9198c2ecf20Sopenharmony_ci regs_buff[1055] = IXGBE_READ_REG(hw, IXGBE_MSRWD); 9208c2ecf20Sopenharmony_ci regs_buff[1056] = IXGBE_READ_REG(hw, IXGBE_MLADD); 9218c2ecf20Sopenharmony_ci regs_buff[1057] = IXGBE_READ_REG(hw, IXGBE_MHADD); 9228c2ecf20Sopenharmony_ci regs_buff[1058] = IXGBE_READ_REG(hw, IXGBE_TREG); 9238c2ecf20Sopenharmony_ci regs_buff[1059] = IXGBE_READ_REG(hw, IXGBE_PCSS1); 9248c2ecf20Sopenharmony_ci regs_buff[1060] = IXGBE_READ_REG(hw, IXGBE_PCSS2); 9258c2ecf20Sopenharmony_ci regs_buff[1061] = IXGBE_READ_REG(hw, IXGBE_XPCSS); 9268c2ecf20Sopenharmony_ci regs_buff[1062] = IXGBE_READ_REG(hw, IXGBE_SERDESC); 9278c2ecf20Sopenharmony_ci regs_buff[1063] = IXGBE_READ_REG(hw, IXGBE_MACS); 9288c2ecf20Sopenharmony_ci regs_buff[1064] = IXGBE_READ_REG(hw, IXGBE_AUTOC); 9298c2ecf20Sopenharmony_ci regs_buff[1065] = IXGBE_READ_REG(hw, IXGBE_LINKS); 9308c2ecf20Sopenharmony_ci regs_buff[1066] = IXGBE_READ_REG(hw, IXGBE_AUTOC2); 9318c2ecf20Sopenharmony_ci regs_buff[1067] = IXGBE_READ_REG(hw, IXGBE_AUTOC3); 9328c2ecf20Sopenharmony_ci regs_buff[1068] = IXGBE_READ_REG(hw, IXGBE_ANLP1); 9338c2ecf20Sopenharmony_ci regs_buff[1069] = IXGBE_READ_REG(hw, IXGBE_ANLP2); 9348c2ecf20Sopenharmony_ci regs_buff[1070] = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* Diagnostic */ 9378c2ecf20Sopenharmony_ci regs_buff[1071] = IXGBE_READ_REG(hw, IXGBE_RDSTATCTL); 9388c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 9398c2ecf20Sopenharmony_ci regs_buff[1072 + i] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i)); 9408c2ecf20Sopenharmony_ci regs_buff[1080] = IXGBE_READ_REG(hw, IXGBE_RDHMPN); 9418c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 9428c2ecf20Sopenharmony_ci regs_buff[1081 + i] = IXGBE_READ_REG(hw, IXGBE_RIC_DW(i)); 9438c2ecf20Sopenharmony_ci regs_buff[1085] = IXGBE_READ_REG(hw, IXGBE_RDPROBE); 9448c2ecf20Sopenharmony_ci regs_buff[1086] = IXGBE_READ_REG(hw, IXGBE_TDSTATCTL); 9458c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 9468c2ecf20Sopenharmony_ci regs_buff[1087 + i] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i)); 9478c2ecf20Sopenharmony_ci regs_buff[1095] = IXGBE_READ_REG(hw, IXGBE_TDHMPN); 9488c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 9498c2ecf20Sopenharmony_ci regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i)); 9508c2ecf20Sopenharmony_ci regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE); 9518c2ecf20Sopenharmony_ci regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL); 9528c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 9538c2ecf20Sopenharmony_ci regs_buff[1102 + i] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA(i)); 9548c2ecf20Sopenharmony_ci regs_buff[1106] = IXGBE_READ_REG(hw, IXGBE_RXBUFCTRL); 9558c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 9568c2ecf20Sopenharmony_ci regs_buff[1107 + i] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA(i)); 9578c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 9588c2ecf20Sopenharmony_ci regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i)); 9598c2ecf20Sopenharmony_ci regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL); 9608c2ecf20Sopenharmony_ci regs_buff[1120] = IXGBE_READ_REG(hw, IXGBE_MDFTC1); 9618c2ecf20Sopenharmony_ci regs_buff[1121] = IXGBE_READ_REG(hw, IXGBE_MDFTC2); 9628c2ecf20Sopenharmony_ci regs_buff[1122] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO1); 9638c2ecf20Sopenharmony_ci regs_buff[1123] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO2); 9648c2ecf20Sopenharmony_ci regs_buff[1124] = IXGBE_READ_REG(hw, IXGBE_MDFTS); 9658c2ecf20Sopenharmony_ci regs_buff[1125] = IXGBE_READ_REG(hw, IXGBE_PCIEECCCTL); 9668c2ecf20Sopenharmony_ci regs_buff[1126] = IXGBE_READ_REG(hw, IXGBE_PBTXECC); 9678c2ecf20Sopenharmony_ci regs_buff[1127] = IXGBE_READ_REG(hw, IXGBE_PBRXECC); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* 82599 X540 specific registers */ 9708c2ecf20Sopenharmony_ci regs_buff[1128] = IXGBE_READ_REG(hw, IXGBE_MFLCN); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci /* 82599 X540 specific DCB registers */ 9738c2ecf20Sopenharmony_ci regs_buff[1129] = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 9748c2ecf20Sopenharmony_ci regs_buff[1130] = IXGBE_READ_REG(hw, IXGBE_RTTUP2TC); 9758c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 9768c2ecf20Sopenharmony_ci regs_buff[1131 + i] = IXGBE_READ_REG(hw, IXGBE_TXLLQ(i)); 9778c2ecf20Sopenharmony_ci regs_buff[1135] = IXGBE_READ_REG(hw, IXGBE_RTTBCNRM); 9788c2ecf20Sopenharmony_ci /* same as RTTQCNRM */ 9798c2ecf20Sopenharmony_ci regs_buff[1136] = IXGBE_READ_REG(hw, IXGBE_RTTBCNRD); 9808c2ecf20Sopenharmony_ci /* same as RTTQCNRR */ 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci /* X540 specific DCB registers */ 9838c2ecf20Sopenharmony_ci regs_buff[1137] = IXGBE_READ_REG(hw, IXGBE_RTTQCNCR); 9848c2ecf20Sopenharmony_ci regs_buff[1138] = IXGBE_READ_REG(hw, IXGBE_RTTQCNTG); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci /* Security config registers */ 9878c2ecf20Sopenharmony_ci regs_buff[1139] = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL); 9888c2ecf20Sopenharmony_ci regs_buff[1140] = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT); 9898c2ecf20Sopenharmony_ci regs_buff[1141] = IXGBE_READ_REG(hw, IXGBE_SECTXBUFFAF); 9908c2ecf20Sopenharmony_ci regs_buff[1142] = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG); 9918c2ecf20Sopenharmony_ci regs_buff[1143] = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 9928c2ecf20Sopenharmony_ci regs_buff[1144] = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic int ixgbe_get_eeprom_len(struct net_device *netdev) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 9988c2ecf20Sopenharmony_ci return adapter->hw.eeprom.word_size * 2; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_cistatic int ixgbe_get_eeprom(struct net_device *netdev, 10028c2ecf20Sopenharmony_ci struct ethtool_eeprom *eeprom, u8 *bytes) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 10058c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 10068c2ecf20Sopenharmony_ci u16 *eeprom_buff; 10078c2ecf20Sopenharmony_ci int first_word, last_word, eeprom_len; 10088c2ecf20Sopenharmony_ci int ret_val = 0; 10098c2ecf20Sopenharmony_ci u16 i; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci if (eeprom->len == 0) 10128c2ecf20Sopenharmony_ci return -EINVAL; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci eeprom->magic = hw->vendor_id | (hw->device_id << 16); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci first_word = eeprom->offset >> 1; 10178c2ecf20Sopenharmony_ci last_word = (eeprom->offset + eeprom->len - 1) >> 1; 10188c2ecf20Sopenharmony_ci eeprom_len = last_word - first_word + 1; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci eeprom_buff = kmalloc_array(eeprom_len, sizeof(u16), GFP_KERNEL); 10218c2ecf20Sopenharmony_ci if (!eeprom_buff) 10228c2ecf20Sopenharmony_ci return -ENOMEM; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci ret_val = hw->eeprom.ops.read_buffer(hw, first_word, eeprom_len, 10258c2ecf20Sopenharmony_ci eeprom_buff); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* Device's eeprom is always little-endian, word addressable */ 10288c2ecf20Sopenharmony_ci for (i = 0; i < eeprom_len; i++) 10298c2ecf20Sopenharmony_ci le16_to_cpus(&eeprom_buff[i]); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); 10328c2ecf20Sopenharmony_ci kfree(eeprom_buff); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci return ret_val; 10358c2ecf20Sopenharmony_ci} 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic int ixgbe_set_eeprom(struct net_device *netdev, 10388c2ecf20Sopenharmony_ci struct ethtool_eeprom *eeprom, u8 *bytes) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 10418c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 10428c2ecf20Sopenharmony_ci u16 *eeprom_buff; 10438c2ecf20Sopenharmony_ci void *ptr; 10448c2ecf20Sopenharmony_ci int max_len, first_word, last_word, ret_val = 0; 10458c2ecf20Sopenharmony_ci u16 i; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci if (eeprom->len == 0) 10488c2ecf20Sopenharmony_ci return -EINVAL; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) 10518c2ecf20Sopenharmony_ci return -EINVAL; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci max_len = hw->eeprom.word_size * 2; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci first_word = eeprom->offset >> 1; 10568c2ecf20Sopenharmony_ci last_word = (eeprom->offset + eeprom->len - 1) >> 1; 10578c2ecf20Sopenharmony_ci eeprom_buff = kmalloc(max_len, GFP_KERNEL); 10588c2ecf20Sopenharmony_ci if (!eeprom_buff) 10598c2ecf20Sopenharmony_ci return -ENOMEM; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci ptr = eeprom_buff; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if (eeprom->offset & 1) { 10648c2ecf20Sopenharmony_ci /* 10658c2ecf20Sopenharmony_ci * need read/modify/write of first changed EEPROM word 10668c2ecf20Sopenharmony_ci * only the second byte of the word is being modified 10678c2ecf20Sopenharmony_ci */ 10688c2ecf20Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, first_word, &eeprom_buff[0]); 10698c2ecf20Sopenharmony_ci if (ret_val) 10708c2ecf20Sopenharmony_ci goto err; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci ptr++; 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci if ((eeprom->offset + eeprom->len) & 1) { 10758c2ecf20Sopenharmony_ci /* 10768c2ecf20Sopenharmony_ci * need read/modify/write of last changed EEPROM word 10778c2ecf20Sopenharmony_ci * only the first byte of the word is being modified 10788c2ecf20Sopenharmony_ci */ 10798c2ecf20Sopenharmony_ci ret_val = hw->eeprom.ops.read(hw, last_word, 10808c2ecf20Sopenharmony_ci &eeprom_buff[last_word - first_word]); 10818c2ecf20Sopenharmony_ci if (ret_val) 10828c2ecf20Sopenharmony_ci goto err; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* Device's eeprom is always little-endian, word addressable */ 10868c2ecf20Sopenharmony_ci for (i = 0; i < last_word - first_word + 1; i++) 10878c2ecf20Sopenharmony_ci le16_to_cpus(&eeprom_buff[i]); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci memcpy(ptr, bytes, eeprom->len); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci for (i = 0; i < last_word - first_word + 1; i++) 10928c2ecf20Sopenharmony_ci cpu_to_le16s(&eeprom_buff[i]); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci ret_val = hw->eeprom.ops.write_buffer(hw, first_word, 10958c2ecf20Sopenharmony_ci last_word - first_word + 1, 10968c2ecf20Sopenharmony_ci eeprom_buff); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci /* Update the checksum */ 10998c2ecf20Sopenharmony_ci if (ret_val == 0) 11008c2ecf20Sopenharmony_ci hw->eeprom.ops.update_checksum(hw); 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_cierr: 11038c2ecf20Sopenharmony_ci kfree(eeprom_buff); 11048c2ecf20Sopenharmony_ci return ret_val; 11058c2ecf20Sopenharmony_ci} 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_cistatic void ixgbe_get_drvinfo(struct net_device *netdev, 11088c2ecf20Sopenharmony_ci struct ethtool_drvinfo *drvinfo) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci strlcpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver)); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci strlcpy(drvinfo->fw_version, adapter->eeprom_id, 11158c2ecf20Sopenharmony_ci sizeof(drvinfo->fw_version)); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 11188c2ecf20Sopenharmony_ci sizeof(drvinfo->bus_info)); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci drvinfo->n_priv_flags = IXGBE_PRIV_FLAGS_STR_LEN; 11218c2ecf20Sopenharmony_ci} 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistatic void ixgbe_get_ringparam(struct net_device *netdev, 11248c2ecf20Sopenharmony_ci struct ethtool_ringparam *ring) 11258c2ecf20Sopenharmony_ci{ 11268c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 11278c2ecf20Sopenharmony_ci struct ixgbe_ring *tx_ring = adapter->tx_ring[0]; 11288c2ecf20Sopenharmony_ci struct ixgbe_ring *rx_ring = adapter->rx_ring[0]; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci ring->rx_max_pending = IXGBE_MAX_RXD; 11318c2ecf20Sopenharmony_ci ring->tx_max_pending = IXGBE_MAX_TXD; 11328c2ecf20Sopenharmony_ci ring->rx_pending = rx_ring->count; 11338c2ecf20Sopenharmony_ci ring->tx_pending = tx_ring->count; 11348c2ecf20Sopenharmony_ci} 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_cistatic int ixgbe_set_ringparam(struct net_device *netdev, 11378c2ecf20Sopenharmony_ci struct ethtool_ringparam *ring) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 11408c2ecf20Sopenharmony_ci struct ixgbe_ring *temp_ring; 11418c2ecf20Sopenharmony_ci int i, j, err = 0; 11428c2ecf20Sopenharmony_ci u32 new_rx_count, new_tx_count; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 11458c2ecf20Sopenharmony_ci return -EINVAL; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci new_tx_count = clamp_t(u32, ring->tx_pending, 11488c2ecf20Sopenharmony_ci IXGBE_MIN_TXD, IXGBE_MAX_TXD); 11498c2ecf20Sopenharmony_ci new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci new_rx_count = clamp_t(u32, ring->rx_pending, 11528c2ecf20Sopenharmony_ci IXGBE_MIN_RXD, IXGBE_MAX_RXD); 11538c2ecf20Sopenharmony_ci new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci if ((new_tx_count == adapter->tx_ring_count) && 11568c2ecf20Sopenharmony_ci (new_rx_count == adapter->rx_ring_count)) { 11578c2ecf20Sopenharmony_ci /* nothing to do */ 11588c2ecf20Sopenharmony_ci return 0; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) 11628c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci if (!netif_running(adapter->netdev)) { 11658c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 11668c2ecf20Sopenharmony_ci adapter->tx_ring[i]->count = new_tx_count; 11678c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) 11688c2ecf20Sopenharmony_ci adapter->xdp_ring[i]->count = new_tx_count; 11698c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 11708c2ecf20Sopenharmony_ci adapter->rx_ring[i]->count = new_rx_count; 11718c2ecf20Sopenharmony_ci adapter->tx_ring_count = new_tx_count; 11728c2ecf20Sopenharmony_ci adapter->xdp_ring_count = new_tx_count; 11738c2ecf20Sopenharmony_ci adapter->rx_ring_count = new_rx_count; 11748c2ecf20Sopenharmony_ci goto clear_reset; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci /* allocate temporary buffer to store rings in */ 11788c2ecf20Sopenharmony_ci i = max_t(int, adapter->num_tx_queues + adapter->num_xdp_queues, 11798c2ecf20Sopenharmony_ci adapter->num_rx_queues); 11808c2ecf20Sopenharmony_ci temp_ring = vmalloc(array_size(i, sizeof(struct ixgbe_ring))); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (!temp_ring) { 11838c2ecf20Sopenharmony_ci err = -ENOMEM; 11848c2ecf20Sopenharmony_ci goto clear_reset; 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci ixgbe_down(adapter); 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci /* 11908c2ecf20Sopenharmony_ci * Setup new Tx resources and free the old Tx resources in that order. 11918c2ecf20Sopenharmony_ci * We can then assign the new resources to the rings via a memcpy. 11928c2ecf20Sopenharmony_ci * The advantage to this approach is that we are guaranteed to still 11938c2ecf20Sopenharmony_ci * have resources even in the case of an allocation failure. 11948c2ecf20Sopenharmony_ci */ 11958c2ecf20Sopenharmony_ci if (new_tx_count != adapter->tx_ring_count) { 11968c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 11978c2ecf20Sopenharmony_ci memcpy(&temp_ring[i], adapter->tx_ring[i], 11988c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci temp_ring[i].count = new_tx_count; 12018c2ecf20Sopenharmony_ci err = ixgbe_setup_tx_resources(&temp_ring[i]); 12028c2ecf20Sopenharmony_ci if (err) { 12038c2ecf20Sopenharmony_ci while (i) { 12048c2ecf20Sopenharmony_ci i--; 12058c2ecf20Sopenharmony_ci ixgbe_free_tx_resources(&temp_ring[i]); 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci goto err_setup; 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci for (j = 0; j < adapter->num_xdp_queues; j++, i++) { 12128c2ecf20Sopenharmony_ci memcpy(&temp_ring[i], adapter->xdp_ring[j], 12138c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci temp_ring[i].count = new_tx_count; 12168c2ecf20Sopenharmony_ci err = ixgbe_setup_tx_resources(&temp_ring[i]); 12178c2ecf20Sopenharmony_ci if (err) { 12188c2ecf20Sopenharmony_ci while (i) { 12198c2ecf20Sopenharmony_ci i--; 12208c2ecf20Sopenharmony_ci ixgbe_free_tx_resources(&temp_ring[i]); 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci goto err_setup; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 12278c2ecf20Sopenharmony_ci ixgbe_free_tx_resources(adapter->tx_ring[i]); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci memcpy(adapter->tx_ring[i], &temp_ring[i], 12308c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 12318c2ecf20Sopenharmony_ci } 12328c2ecf20Sopenharmony_ci for (j = 0; j < adapter->num_xdp_queues; j++, i++) { 12338c2ecf20Sopenharmony_ci ixgbe_free_tx_resources(adapter->xdp_ring[j]); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci memcpy(adapter->xdp_ring[j], &temp_ring[i], 12368c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci adapter->tx_ring_count = new_tx_count; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* Repeat the process for the Rx rings if needed */ 12438c2ecf20Sopenharmony_ci if (new_rx_count != adapter->rx_ring_count) { 12448c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 12458c2ecf20Sopenharmony_ci memcpy(&temp_ring[i], adapter->rx_ring[i], 12468c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci /* Clear copied XDP RX-queue info */ 12498c2ecf20Sopenharmony_ci memset(&temp_ring[i].xdp_rxq, 0, 12508c2ecf20Sopenharmony_ci sizeof(temp_ring[i].xdp_rxq)); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci temp_ring[i].count = new_rx_count; 12538c2ecf20Sopenharmony_ci err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]); 12548c2ecf20Sopenharmony_ci if (err) { 12558c2ecf20Sopenharmony_ci while (i) { 12568c2ecf20Sopenharmony_ci i--; 12578c2ecf20Sopenharmony_ci ixgbe_free_rx_resources(&temp_ring[i]); 12588c2ecf20Sopenharmony_ci } 12598c2ecf20Sopenharmony_ci goto err_setup; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 12658c2ecf20Sopenharmony_ci ixgbe_free_rx_resources(adapter->rx_ring[i]); 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci memcpy(adapter->rx_ring[i], &temp_ring[i], 12688c2ecf20Sopenharmony_ci sizeof(struct ixgbe_ring)); 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci adapter->rx_ring_count = new_rx_count; 12728c2ecf20Sopenharmony_ci } 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_cierr_setup: 12758c2ecf20Sopenharmony_ci ixgbe_up(adapter); 12768c2ecf20Sopenharmony_ci vfree(temp_ring); 12778c2ecf20Sopenharmony_ciclear_reset: 12788c2ecf20Sopenharmony_ci clear_bit(__IXGBE_RESETTING, &adapter->state); 12798c2ecf20Sopenharmony_ci return err; 12808c2ecf20Sopenharmony_ci} 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_cistatic int ixgbe_get_sset_count(struct net_device *netdev, int sset) 12838c2ecf20Sopenharmony_ci{ 12848c2ecf20Sopenharmony_ci switch (sset) { 12858c2ecf20Sopenharmony_ci case ETH_SS_TEST: 12868c2ecf20Sopenharmony_ci return IXGBE_TEST_LEN; 12878c2ecf20Sopenharmony_ci case ETH_SS_STATS: 12888c2ecf20Sopenharmony_ci return IXGBE_STATS_LEN; 12898c2ecf20Sopenharmony_ci case ETH_SS_PRIV_FLAGS: 12908c2ecf20Sopenharmony_ci return IXGBE_PRIV_FLAGS_STR_LEN; 12918c2ecf20Sopenharmony_ci default: 12928c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_cistatic void ixgbe_get_ethtool_stats(struct net_device *netdev, 12978c2ecf20Sopenharmony_ci struct ethtool_stats *stats, u64 *data) 12988c2ecf20Sopenharmony_ci{ 12998c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 13008c2ecf20Sopenharmony_ci struct rtnl_link_stats64 temp; 13018c2ecf20Sopenharmony_ci const struct rtnl_link_stats64 *net_stats; 13028c2ecf20Sopenharmony_ci unsigned int start; 13038c2ecf20Sopenharmony_ci struct ixgbe_ring *ring; 13048c2ecf20Sopenharmony_ci int i, j; 13058c2ecf20Sopenharmony_ci char *p = NULL; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci ixgbe_update_stats(adapter); 13088c2ecf20Sopenharmony_ci net_stats = dev_get_stats(netdev, &temp); 13098c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { 13108c2ecf20Sopenharmony_ci switch (ixgbe_gstrings_stats[i].type) { 13118c2ecf20Sopenharmony_ci case NETDEV_STATS: 13128c2ecf20Sopenharmony_ci p = (char *) net_stats + 13138c2ecf20Sopenharmony_ci ixgbe_gstrings_stats[i].stat_offset; 13148c2ecf20Sopenharmony_ci break; 13158c2ecf20Sopenharmony_ci case IXGBE_STATS: 13168c2ecf20Sopenharmony_ci p = (char *) adapter + 13178c2ecf20Sopenharmony_ci ixgbe_gstrings_stats[i].stat_offset; 13188c2ecf20Sopenharmony_ci break; 13198c2ecf20Sopenharmony_ci default: 13208c2ecf20Sopenharmony_ci data[i] = 0; 13218c2ecf20Sopenharmony_ci continue; 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci data[i] = (ixgbe_gstrings_stats[i].sizeof_stat == 13258c2ecf20Sopenharmony_ci sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 13268c2ecf20Sopenharmony_ci } 13278c2ecf20Sopenharmony_ci for (j = 0; j < netdev->num_tx_queues; j++) { 13288c2ecf20Sopenharmony_ci ring = adapter->tx_ring[j]; 13298c2ecf20Sopenharmony_ci if (!ring) { 13308c2ecf20Sopenharmony_ci data[i] = 0; 13318c2ecf20Sopenharmony_ci data[i+1] = 0; 13328c2ecf20Sopenharmony_ci i += 2; 13338c2ecf20Sopenharmony_ci continue; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci do { 13378c2ecf20Sopenharmony_ci start = u64_stats_fetch_begin_irq(&ring->syncp); 13388c2ecf20Sopenharmony_ci data[i] = ring->stats.packets; 13398c2ecf20Sopenharmony_ci data[i+1] = ring->stats.bytes; 13408c2ecf20Sopenharmony_ci } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 13418c2ecf20Sopenharmony_ci i += 2; 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) { 13448c2ecf20Sopenharmony_ci ring = adapter->rx_ring[j]; 13458c2ecf20Sopenharmony_ci if (!ring) { 13468c2ecf20Sopenharmony_ci data[i] = 0; 13478c2ecf20Sopenharmony_ci data[i+1] = 0; 13488c2ecf20Sopenharmony_ci i += 2; 13498c2ecf20Sopenharmony_ci continue; 13508c2ecf20Sopenharmony_ci } 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci do { 13538c2ecf20Sopenharmony_ci start = u64_stats_fetch_begin_irq(&ring->syncp); 13548c2ecf20Sopenharmony_ci data[i] = ring->stats.packets; 13558c2ecf20Sopenharmony_ci data[i+1] = ring->stats.bytes; 13568c2ecf20Sopenharmony_ci } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 13578c2ecf20Sopenharmony_ci i += 2; 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) { 13618c2ecf20Sopenharmony_ci data[i++] = adapter->stats.pxontxc[j]; 13628c2ecf20Sopenharmony_ci data[i++] = adapter->stats.pxofftxc[j]; 13638c2ecf20Sopenharmony_ci } 13648c2ecf20Sopenharmony_ci for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) { 13658c2ecf20Sopenharmony_ci data[i++] = adapter->stats.pxonrxc[j]; 13668c2ecf20Sopenharmony_ci data[i++] = adapter->stats.pxoffrxc[j]; 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci} 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_cistatic void ixgbe_get_strings(struct net_device *netdev, u32 stringset, 13718c2ecf20Sopenharmony_ci u8 *data) 13728c2ecf20Sopenharmony_ci{ 13738c2ecf20Sopenharmony_ci char *p = (char *)data; 13748c2ecf20Sopenharmony_ci unsigned int i; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci switch (stringset) { 13778c2ecf20Sopenharmony_ci case ETH_SS_TEST: 13788c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_TEST_LEN; i++) { 13798c2ecf20Sopenharmony_ci memcpy(data, ixgbe_gstrings_test[i], ETH_GSTRING_LEN); 13808c2ecf20Sopenharmony_ci data += ETH_GSTRING_LEN; 13818c2ecf20Sopenharmony_ci } 13828c2ecf20Sopenharmony_ci break; 13838c2ecf20Sopenharmony_ci case ETH_SS_STATS: 13848c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { 13858c2ecf20Sopenharmony_ci memcpy(p, ixgbe_gstrings_stats[i].stat_string, 13868c2ecf20Sopenharmony_ci ETH_GSTRING_LEN); 13878c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 13888c2ecf20Sopenharmony_ci } 13898c2ecf20Sopenharmony_ci for (i = 0; i < netdev->num_tx_queues; i++) { 13908c2ecf20Sopenharmony_ci sprintf(p, "tx_queue_%u_packets", i); 13918c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 13928c2ecf20Sopenharmony_ci sprintf(p, "tx_queue_%u_bytes", i); 13938c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) { 13968c2ecf20Sopenharmony_ci sprintf(p, "rx_queue_%u_packets", i); 13978c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 13988c2ecf20Sopenharmony_ci sprintf(p, "rx_queue_%u_bytes", i); 13998c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 14008c2ecf20Sopenharmony_ci } 14018c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { 14028c2ecf20Sopenharmony_ci sprintf(p, "tx_pb_%u_pxon", i); 14038c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 14048c2ecf20Sopenharmony_ci sprintf(p, "tx_pb_%u_pxoff", i); 14058c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { 14088c2ecf20Sopenharmony_ci sprintf(p, "rx_pb_%u_pxon", i); 14098c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 14108c2ecf20Sopenharmony_ci sprintf(p, "rx_pb_%u_pxoff", i); 14118c2ecf20Sopenharmony_ci p += ETH_GSTRING_LEN; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ 14148c2ecf20Sopenharmony_ci break; 14158c2ecf20Sopenharmony_ci case ETH_SS_PRIV_FLAGS: 14168c2ecf20Sopenharmony_ci memcpy(data, ixgbe_priv_flags_strings, 14178c2ecf20Sopenharmony_ci IXGBE_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); 14188c2ecf20Sopenharmony_ci } 14198c2ecf20Sopenharmony_ci} 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_cistatic int ixgbe_link_test(struct ixgbe_adapter *adapter, u64 *data) 14228c2ecf20Sopenharmony_ci{ 14238c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 14248c2ecf20Sopenharmony_ci bool link_up; 14258c2ecf20Sopenharmony_ci u32 link_speed = 0; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci if (ixgbe_removed(hw->hw_addr)) { 14288c2ecf20Sopenharmony_ci *data = 1; 14298c2ecf20Sopenharmony_ci return 1; 14308c2ecf20Sopenharmony_ci } 14318c2ecf20Sopenharmony_ci *data = 0; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci hw->mac.ops.check_link(hw, &link_speed, &link_up, true); 14348c2ecf20Sopenharmony_ci if (link_up) 14358c2ecf20Sopenharmony_ci return *data; 14368c2ecf20Sopenharmony_ci else 14378c2ecf20Sopenharmony_ci *data = 1; 14388c2ecf20Sopenharmony_ci return *data; 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci/* ethtool register test data */ 14428c2ecf20Sopenharmony_cistruct ixgbe_reg_test { 14438c2ecf20Sopenharmony_ci u16 reg; 14448c2ecf20Sopenharmony_ci u8 array_len; 14458c2ecf20Sopenharmony_ci u8 test_type; 14468c2ecf20Sopenharmony_ci u32 mask; 14478c2ecf20Sopenharmony_ci u32 write; 14488c2ecf20Sopenharmony_ci}; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci/* In the hardware, registers are laid out either singly, in arrays 14518c2ecf20Sopenharmony_ci * spaced 0x40 bytes apart, or in contiguous tables. We assume 14528c2ecf20Sopenharmony_ci * most tests take place on arrays or single registers (handled 14538c2ecf20Sopenharmony_ci * as a single-element array) and special-case the tables. 14548c2ecf20Sopenharmony_ci * Table tests are always pattern tests. 14558c2ecf20Sopenharmony_ci * 14568c2ecf20Sopenharmony_ci * We also make provision for some required setup steps by specifying 14578c2ecf20Sopenharmony_ci * registers to be written without any read-back testing. 14588c2ecf20Sopenharmony_ci */ 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci#define PATTERN_TEST 1 14618c2ecf20Sopenharmony_ci#define SET_READ_TEST 2 14628c2ecf20Sopenharmony_ci#define WRITE_NO_TEST 3 14638c2ecf20Sopenharmony_ci#define TABLE32_TEST 4 14648c2ecf20Sopenharmony_ci#define TABLE64_TEST_LO 5 14658c2ecf20Sopenharmony_ci#define TABLE64_TEST_HI 6 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci/* default 82599 register test */ 14688c2ecf20Sopenharmony_cistatic const struct ixgbe_reg_test reg_test_82599[] = { 14698c2ecf20Sopenharmony_ci { IXGBE_FCRTL_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 14708c2ecf20Sopenharmony_ci { IXGBE_FCRTH_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 14718c2ecf20Sopenharmony_ci { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14728c2ecf20Sopenharmony_ci { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, 14738c2ecf20Sopenharmony_ci { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, 14748c2ecf20Sopenharmony_ci { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14758c2ecf20Sopenharmony_ci { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 14768c2ecf20Sopenharmony_ci { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, 14778c2ecf20Sopenharmony_ci { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 14788c2ecf20Sopenharmony_ci { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, 14798c2ecf20Sopenharmony_ci { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 14808c2ecf20Sopenharmony_ci { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14818c2ecf20Sopenharmony_ci { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, 14828c2ecf20Sopenharmony_ci { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14838c2ecf20Sopenharmony_ci { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, 14848c2ecf20Sopenharmony_ci { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000001, 0x00000001 }, 14858c2ecf20Sopenharmony_ci { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, 14868c2ecf20Sopenharmony_ci { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x8001FFFF, 0x800CFFFF }, 14878c2ecf20Sopenharmony_ci { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14888c2ecf20Sopenharmony_ci { .reg = 0 } 14898c2ecf20Sopenharmony_ci}; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci/* default 82598 register test */ 14928c2ecf20Sopenharmony_cistatic const struct ixgbe_reg_test reg_test_82598[] = { 14938c2ecf20Sopenharmony_ci { IXGBE_FCRTL(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 14948c2ecf20Sopenharmony_ci { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 14958c2ecf20Sopenharmony_ci { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14968c2ecf20Sopenharmony_ci { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, 14978c2ecf20Sopenharmony_ci { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, 14988c2ecf20Sopenharmony_ci { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 14998c2ecf20Sopenharmony_ci { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 15008c2ecf20Sopenharmony_ci /* Enable all four RX queues before testing. */ 15018c2ecf20Sopenharmony_ci { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, 15028c2ecf20Sopenharmony_ci /* RDH is read-only for 82598, only test RDT. */ 15038c2ecf20Sopenharmony_ci { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 15048c2ecf20Sopenharmony_ci { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, 15058c2ecf20Sopenharmony_ci { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, 15068c2ecf20Sopenharmony_ci { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 15078c2ecf20Sopenharmony_ci { IXGBE_TIPG, 1, PATTERN_TEST, 0x000000FF, 0x000000FF }, 15088c2ecf20Sopenharmony_ci { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, 15098c2ecf20Sopenharmony_ci { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 15108c2ecf20Sopenharmony_ci { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 15118c2ecf20Sopenharmony_ci { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000003, 0x00000003 }, 15128c2ecf20Sopenharmony_ci { IXGBE_DTXCTL, 1, SET_READ_TEST, 0x00000005, 0x00000005 }, 15138c2ecf20Sopenharmony_ci { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, 15148c2ecf20Sopenharmony_ci { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x800CFFFF, 0x800CFFFF }, 15158c2ecf20Sopenharmony_ci { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 15168c2ecf20Sopenharmony_ci { .reg = 0 } 15178c2ecf20Sopenharmony_ci}; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cistatic bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg, 15208c2ecf20Sopenharmony_ci u32 mask, u32 write) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci u32 pat, val, before; 15238c2ecf20Sopenharmony_ci static const u32 test_pattern[] = { 15248c2ecf20Sopenharmony_ci 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci if (ixgbe_removed(adapter->hw.hw_addr)) { 15278c2ecf20Sopenharmony_ci *data = 1; 15288c2ecf20Sopenharmony_ci return true; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) { 15318c2ecf20Sopenharmony_ci before = ixgbe_read_reg(&adapter->hw, reg); 15328c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, test_pattern[pat] & write); 15338c2ecf20Sopenharmony_ci val = ixgbe_read_reg(&adapter->hw, reg); 15348c2ecf20Sopenharmony_ci if (val != (test_pattern[pat] & write & mask)) { 15358c2ecf20Sopenharmony_ci e_err(drv, "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", 15368c2ecf20Sopenharmony_ci reg, val, (test_pattern[pat] & write & mask)); 15378c2ecf20Sopenharmony_ci *data = reg; 15388c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, before); 15398c2ecf20Sopenharmony_ci return true; 15408c2ecf20Sopenharmony_ci } 15418c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, before); 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci return false; 15448c2ecf20Sopenharmony_ci} 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_cistatic bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg, 15478c2ecf20Sopenharmony_ci u32 mask, u32 write) 15488c2ecf20Sopenharmony_ci{ 15498c2ecf20Sopenharmony_ci u32 val, before; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci if (ixgbe_removed(adapter->hw.hw_addr)) { 15528c2ecf20Sopenharmony_ci *data = 1; 15538c2ecf20Sopenharmony_ci return true; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci before = ixgbe_read_reg(&adapter->hw, reg); 15568c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, write & mask); 15578c2ecf20Sopenharmony_ci val = ixgbe_read_reg(&adapter->hw, reg); 15588c2ecf20Sopenharmony_ci if ((write & mask) != (val & mask)) { 15598c2ecf20Sopenharmony_ci e_err(drv, "set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", 15608c2ecf20Sopenharmony_ci reg, (val & mask), (write & mask)); 15618c2ecf20Sopenharmony_ci *data = reg; 15628c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, before); 15638c2ecf20Sopenharmony_ci return true; 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, reg, before); 15668c2ecf20Sopenharmony_ci return false; 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_cistatic int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci const struct ixgbe_reg_test *test; 15728c2ecf20Sopenharmony_ci u32 value, before, after; 15738c2ecf20Sopenharmony_ci u32 i, toggle; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci if (ixgbe_removed(adapter->hw.hw_addr)) { 15768c2ecf20Sopenharmony_ci e_err(drv, "Adapter removed - register test blocked\n"); 15778c2ecf20Sopenharmony_ci *data = 1; 15788c2ecf20Sopenharmony_ci return 1; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci switch (adapter->hw.mac.type) { 15818c2ecf20Sopenharmony_ci case ixgbe_mac_82598EB: 15828c2ecf20Sopenharmony_ci toggle = 0x7FFFF3FF; 15838c2ecf20Sopenharmony_ci test = reg_test_82598; 15848c2ecf20Sopenharmony_ci break; 15858c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 15868c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 15878c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 15888c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 15898c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 15908c2ecf20Sopenharmony_ci toggle = 0x7FFFF30F; 15918c2ecf20Sopenharmony_ci test = reg_test_82599; 15928c2ecf20Sopenharmony_ci break; 15938c2ecf20Sopenharmony_ci default: 15948c2ecf20Sopenharmony_ci *data = 1; 15958c2ecf20Sopenharmony_ci return 1; 15968c2ecf20Sopenharmony_ci } 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci /* 15998c2ecf20Sopenharmony_ci * Because the status register is such a special case, 16008c2ecf20Sopenharmony_ci * we handle it separately from the rest of the register 16018c2ecf20Sopenharmony_ci * tests. Some bits are read-only, some toggle, and some 16028c2ecf20Sopenharmony_ci * are writeable on newer MACs. 16038c2ecf20Sopenharmony_ci */ 16048c2ecf20Sopenharmony_ci before = ixgbe_read_reg(&adapter->hw, IXGBE_STATUS); 16058c2ecf20Sopenharmony_ci value = (ixgbe_read_reg(&adapter->hw, IXGBE_STATUS) & toggle); 16068c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, IXGBE_STATUS, toggle); 16078c2ecf20Sopenharmony_ci after = ixgbe_read_reg(&adapter->hw, IXGBE_STATUS) & toggle; 16088c2ecf20Sopenharmony_ci if (value != after) { 16098c2ecf20Sopenharmony_ci e_err(drv, "failed STATUS register test got: 0x%08X expected: 0x%08X\n", 16108c2ecf20Sopenharmony_ci after, value); 16118c2ecf20Sopenharmony_ci *data = 1; 16128c2ecf20Sopenharmony_ci return 1; 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci /* restore previous status */ 16158c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, IXGBE_STATUS, before); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci /* 16188c2ecf20Sopenharmony_ci * Perform the remainder of the register test, looping through 16198c2ecf20Sopenharmony_ci * the test table until we either fail or reach the null entry. 16208c2ecf20Sopenharmony_ci */ 16218c2ecf20Sopenharmony_ci while (test->reg) { 16228c2ecf20Sopenharmony_ci for (i = 0; i < test->array_len; i++) { 16238c2ecf20Sopenharmony_ci bool b = false; 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci switch (test->test_type) { 16268c2ecf20Sopenharmony_ci case PATTERN_TEST: 16278c2ecf20Sopenharmony_ci b = reg_pattern_test(adapter, data, 16288c2ecf20Sopenharmony_ci test->reg + (i * 0x40), 16298c2ecf20Sopenharmony_ci test->mask, 16308c2ecf20Sopenharmony_ci test->write); 16318c2ecf20Sopenharmony_ci break; 16328c2ecf20Sopenharmony_ci case SET_READ_TEST: 16338c2ecf20Sopenharmony_ci b = reg_set_and_check(adapter, data, 16348c2ecf20Sopenharmony_ci test->reg + (i * 0x40), 16358c2ecf20Sopenharmony_ci test->mask, 16368c2ecf20Sopenharmony_ci test->write); 16378c2ecf20Sopenharmony_ci break; 16388c2ecf20Sopenharmony_ci case WRITE_NO_TEST: 16398c2ecf20Sopenharmony_ci ixgbe_write_reg(&adapter->hw, 16408c2ecf20Sopenharmony_ci test->reg + (i * 0x40), 16418c2ecf20Sopenharmony_ci test->write); 16428c2ecf20Sopenharmony_ci break; 16438c2ecf20Sopenharmony_ci case TABLE32_TEST: 16448c2ecf20Sopenharmony_ci b = reg_pattern_test(adapter, data, 16458c2ecf20Sopenharmony_ci test->reg + (i * 4), 16468c2ecf20Sopenharmony_ci test->mask, 16478c2ecf20Sopenharmony_ci test->write); 16488c2ecf20Sopenharmony_ci break; 16498c2ecf20Sopenharmony_ci case TABLE64_TEST_LO: 16508c2ecf20Sopenharmony_ci b = reg_pattern_test(adapter, data, 16518c2ecf20Sopenharmony_ci test->reg + (i * 8), 16528c2ecf20Sopenharmony_ci test->mask, 16538c2ecf20Sopenharmony_ci test->write); 16548c2ecf20Sopenharmony_ci break; 16558c2ecf20Sopenharmony_ci case TABLE64_TEST_HI: 16568c2ecf20Sopenharmony_ci b = reg_pattern_test(adapter, data, 16578c2ecf20Sopenharmony_ci (test->reg + 4) + (i * 8), 16588c2ecf20Sopenharmony_ci test->mask, 16598c2ecf20Sopenharmony_ci test->write); 16608c2ecf20Sopenharmony_ci break; 16618c2ecf20Sopenharmony_ci } 16628c2ecf20Sopenharmony_ci if (b) 16638c2ecf20Sopenharmony_ci return 1; 16648c2ecf20Sopenharmony_ci } 16658c2ecf20Sopenharmony_ci test++; 16668c2ecf20Sopenharmony_ci } 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci *data = 0; 16698c2ecf20Sopenharmony_ci return 0; 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_cistatic int ixgbe_eeprom_test(struct ixgbe_adapter *adapter, u64 *data) 16738c2ecf20Sopenharmony_ci{ 16748c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 16758c2ecf20Sopenharmony_ci if (hw->eeprom.ops.validate_checksum(hw, NULL)) 16768c2ecf20Sopenharmony_ci *data = 1; 16778c2ecf20Sopenharmony_ci else 16788c2ecf20Sopenharmony_ci *data = 0; 16798c2ecf20Sopenharmony_ci return *data; 16808c2ecf20Sopenharmony_ci} 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_cistatic irqreturn_t ixgbe_test_intr(int irq, void *data) 16838c2ecf20Sopenharmony_ci{ 16848c2ecf20Sopenharmony_ci struct net_device *netdev = (struct net_device *) data; 16858c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci adapter->test_icr |= IXGBE_READ_REG(&adapter->hw, IXGBE_EICR); 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci return IRQ_HANDLED; 16908c2ecf20Sopenharmony_ci} 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_cistatic int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) 16938c2ecf20Sopenharmony_ci{ 16948c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 16958c2ecf20Sopenharmony_ci u32 mask, i = 0, shared_int = true; 16968c2ecf20Sopenharmony_ci u32 irq = adapter->pdev->irq; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci *data = 0; 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci /* Hook up test interrupt handler just for this test */ 17018c2ecf20Sopenharmony_ci if (adapter->msix_entries) { 17028c2ecf20Sopenharmony_ci /* NOTE: we don't test MSI-X interrupts here, yet */ 17038c2ecf20Sopenharmony_ci return 0; 17048c2ecf20Sopenharmony_ci } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { 17058c2ecf20Sopenharmony_ci shared_int = false; 17068c2ecf20Sopenharmony_ci if (request_irq(irq, ixgbe_test_intr, 0, netdev->name, 17078c2ecf20Sopenharmony_ci netdev)) { 17088c2ecf20Sopenharmony_ci *data = 1; 17098c2ecf20Sopenharmony_ci return -1; 17108c2ecf20Sopenharmony_ci } 17118c2ecf20Sopenharmony_ci } else if (!request_irq(irq, ixgbe_test_intr, IRQF_PROBE_SHARED, 17128c2ecf20Sopenharmony_ci netdev->name, netdev)) { 17138c2ecf20Sopenharmony_ci shared_int = false; 17148c2ecf20Sopenharmony_ci } else if (request_irq(irq, ixgbe_test_intr, IRQF_SHARED, 17158c2ecf20Sopenharmony_ci netdev->name, netdev)) { 17168c2ecf20Sopenharmony_ci *data = 1; 17178c2ecf20Sopenharmony_ci return -1; 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci e_info(hw, "testing %s interrupt\n", shared_int ? 17208c2ecf20Sopenharmony_ci "shared" : "unshared"); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci /* Disable all the interrupts */ 17238c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); 17248c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(&adapter->hw); 17258c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci /* Test each interrupt */ 17288c2ecf20Sopenharmony_ci for (; i < 10; i++) { 17298c2ecf20Sopenharmony_ci /* Interrupt to test */ 17308c2ecf20Sopenharmony_ci mask = BIT(i); 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci if (!shared_int) { 17338c2ecf20Sopenharmony_ci /* 17348c2ecf20Sopenharmony_ci * Disable the interrupts to be reported in 17358c2ecf20Sopenharmony_ci * the cause register and then force the same 17368c2ecf20Sopenharmony_ci * interrupt and see if one gets posted. If 17378c2ecf20Sopenharmony_ci * an interrupt was posted to the bus, the 17388c2ecf20Sopenharmony_ci * test failed. 17398c2ecf20Sopenharmony_ci */ 17408c2ecf20Sopenharmony_ci adapter->test_icr = 0; 17418c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 17428c2ecf20Sopenharmony_ci ~mask & 0x00007FFF); 17438c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, 17448c2ecf20Sopenharmony_ci ~mask & 0x00007FFF); 17458c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(&adapter->hw); 17468c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci if (adapter->test_icr & mask) { 17498c2ecf20Sopenharmony_ci *data = 3; 17508c2ecf20Sopenharmony_ci break; 17518c2ecf20Sopenharmony_ci } 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci /* 17558c2ecf20Sopenharmony_ci * Enable the interrupt to be reported in the cause 17568c2ecf20Sopenharmony_ci * register and then force the same interrupt and see 17578c2ecf20Sopenharmony_ci * if one gets posted. If an interrupt was not posted 17588c2ecf20Sopenharmony_ci * to the bus, the test failed. 17598c2ecf20Sopenharmony_ci */ 17608c2ecf20Sopenharmony_ci adapter->test_icr = 0; 17618c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); 17628c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); 17638c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(&adapter->hw); 17648c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (!(adapter->test_icr & mask)) { 17678c2ecf20Sopenharmony_ci *data = 4; 17688c2ecf20Sopenharmony_ci break; 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci if (!shared_int) { 17728c2ecf20Sopenharmony_ci /* 17738c2ecf20Sopenharmony_ci * Disable the other interrupts to be reported in 17748c2ecf20Sopenharmony_ci * the cause register and then force the other 17758c2ecf20Sopenharmony_ci * interrupts and see if any get posted. If 17768c2ecf20Sopenharmony_ci * an interrupt was posted to the bus, the 17778c2ecf20Sopenharmony_ci * test failed. 17788c2ecf20Sopenharmony_ci */ 17798c2ecf20Sopenharmony_ci adapter->test_icr = 0; 17808c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 17818c2ecf20Sopenharmony_ci ~mask & 0x00007FFF); 17828c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, 17838c2ecf20Sopenharmony_ci ~mask & 0x00007FFF); 17848c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(&adapter->hw); 17858c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (adapter->test_icr) { 17888c2ecf20Sopenharmony_ci *data = 5; 17898c2ecf20Sopenharmony_ci break; 17908c2ecf20Sopenharmony_ci } 17918c2ecf20Sopenharmony_ci } 17928c2ecf20Sopenharmony_ci } 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci /* Disable all the interrupts */ 17958c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); 17968c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(&adapter->hw); 17978c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci /* Unhook test interrupt handler */ 18008c2ecf20Sopenharmony_ci free_irq(irq, netdev); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci return *data; 18038c2ecf20Sopenharmony_ci} 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_cistatic void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) 18068c2ecf20Sopenharmony_ci{ 18078c2ecf20Sopenharmony_ci /* Shut down the DMA engines now so they can be reinitialized later, 18088c2ecf20Sopenharmony_ci * since the test rings and normally used rings should overlap on 18098c2ecf20Sopenharmony_ci * queue 0 we can just use the standard disable Rx/Tx calls and they 18108c2ecf20Sopenharmony_ci * will take care of disabling the test rings for us. 18118c2ecf20Sopenharmony_ci */ 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci /* first Rx */ 18148c2ecf20Sopenharmony_ci ixgbe_disable_rx(adapter); 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci /* now Tx */ 18178c2ecf20Sopenharmony_ci ixgbe_disable_tx(adapter); 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci ixgbe_free_tx_resources(&adapter->test_tx_ring); 18228c2ecf20Sopenharmony_ci ixgbe_free_rx_resources(&adapter->test_rx_ring); 18238c2ecf20Sopenharmony_ci} 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_cistatic int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) 18268c2ecf20Sopenharmony_ci{ 18278c2ecf20Sopenharmony_ci struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; 18288c2ecf20Sopenharmony_ci struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; 18298c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 18308c2ecf20Sopenharmony_ci u32 rctl, reg_data; 18318c2ecf20Sopenharmony_ci int ret_val; 18328c2ecf20Sopenharmony_ci int err; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci /* Setup Tx descriptor ring and Tx buffers */ 18358c2ecf20Sopenharmony_ci tx_ring->count = IXGBE_DEFAULT_TXD; 18368c2ecf20Sopenharmony_ci tx_ring->queue_index = 0; 18378c2ecf20Sopenharmony_ci tx_ring->dev = &adapter->pdev->dev; 18388c2ecf20Sopenharmony_ci tx_ring->netdev = adapter->netdev; 18398c2ecf20Sopenharmony_ci tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx; 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci err = ixgbe_setup_tx_resources(tx_ring); 18428c2ecf20Sopenharmony_ci if (err) 18438c2ecf20Sopenharmony_ci return 1; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci switch (adapter->hw.mac.type) { 18468c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 18478c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 18488c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 18498c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 18508c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 18518c2ecf20Sopenharmony_ci reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); 18528c2ecf20Sopenharmony_ci reg_data |= IXGBE_DMATXCTL_TE; 18538c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); 18548c2ecf20Sopenharmony_ci break; 18558c2ecf20Sopenharmony_ci default: 18568c2ecf20Sopenharmony_ci break; 18578c2ecf20Sopenharmony_ci } 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci ixgbe_configure_tx_ring(adapter, tx_ring); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci /* Setup Rx Descriptor ring and Rx buffers */ 18628c2ecf20Sopenharmony_ci rx_ring->count = IXGBE_DEFAULT_RXD; 18638c2ecf20Sopenharmony_ci rx_ring->queue_index = 0; 18648c2ecf20Sopenharmony_ci rx_ring->dev = &adapter->pdev->dev; 18658c2ecf20Sopenharmony_ci rx_ring->netdev = adapter->netdev; 18668c2ecf20Sopenharmony_ci rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci err = ixgbe_setup_rx_resources(adapter, rx_ring); 18698c2ecf20Sopenharmony_ci if (err) { 18708c2ecf20Sopenharmony_ci ret_val = 4; 18718c2ecf20Sopenharmony_ci goto err_nomem; 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci hw->mac.ops.disable_rx(hw); 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci ixgbe_configure_rx_ring(adapter, rx_ring); 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL); 18798c2ecf20Sopenharmony_ci rctl |= IXGBE_RXCTRL_DMBYPS; 18808c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci hw->mac.ops.enable_rx(hw); 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci return 0; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_cierr_nomem: 18878c2ecf20Sopenharmony_ci ixgbe_free_desc_rings(adapter); 18888c2ecf20Sopenharmony_ci return ret_val; 18898c2ecf20Sopenharmony_ci} 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_cistatic int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) 18928c2ecf20Sopenharmony_ci{ 18938c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 18948c2ecf20Sopenharmony_ci u32 reg_data; 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci /* Setup MAC loopback */ 18988c2ecf20Sopenharmony_ci reg_data = IXGBE_READ_REG(hw, IXGBE_HLREG0); 18998c2ecf20Sopenharmony_ci reg_data |= IXGBE_HLREG0_LPBK; 19008c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_data); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci reg_data = IXGBE_READ_REG(hw, IXGBE_FCTRL); 19038c2ecf20Sopenharmony_ci reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; 19048c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_data); 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci /* X540 and X550 needs to set the MACC.FLU bit to force link up */ 19078c2ecf20Sopenharmony_ci switch (adapter->hw.mac.type) { 19088c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 19098c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 19108c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 19118c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 19128c2ecf20Sopenharmony_ci reg_data = IXGBE_READ_REG(hw, IXGBE_MACC); 19138c2ecf20Sopenharmony_ci reg_data |= IXGBE_MACC_FLU; 19148c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data); 19158c2ecf20Sopenharmony_ci break; 19168c2ecf20Sopenharmony_ci default: 19178c2ecf20Sopenharmony_ci if (hw->mac.orig_autoc) { 19188c2ecf20Sopenharmony_ci reg_data = hw->mac.orig_autoc | IXGBE_AUTOC_FLU; 19198c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_data); 19208c2ecf20Sopenharmony_ci } else { 19218c2ecf20Sopenharmony_ci return 10; 19228c2ecf20Sopenharmony_ci } 19238c2ecf20Sopenharmony_ci } 19248c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 19258c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci /* Disable Atlas Tx lanes; re-enabled in reset path */ 19288c2ecf20Sopenharmony_ci if (hw->mac.type == ixgbe_mac_82598EB) { 19298c2ecf20Sopenharmony_ci u8 atlas; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &atlas); 19328c2ecf20Sopenharmony_ci atlas |= IXGBE_ATLAS_PDN_TX_REG_EN; 19338c2ecf20Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, atlas); 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &atlas); 19368c2ecf20Sopenharmony_ci atlas |= IXGBE_ATLAS_PDN_TX_10G_QL_ALL; 19378c2ecf20Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, atlas); 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &atlas); 19408c2ecf20Sopenharmony_ci atlas |= IXGBE_ATLAS_PDN_TX_1G_QL_ALL; 19418c2ecf20Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, atlas); 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &atlas); 19448c2ecf20Sopenharmony_ci atlas |= IXGBE_ATLAS_PDN_TX_AN_QL_ALL; 19458c2ecf20Sopenharmony_ci hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, atlas); 19468c2ecf20Sopenharmony_ci } 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci return 0; 19498c2ecf20Sopenharmony_ci} 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_cistatic void ixgbe_loopback_cleanup(struct ixgbe_adapter *adapter) 19528c2ecf20Sopenharmony_ci{ 19538c2ecf20Sopenharmony_ci u32 reg_data; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); 19568c2ecf20Sopenharmony_ci reg_data &= ~IXGBE_HLREG0_LPBK; 19578c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); 19588c2ecf20Sopenharmony_ci} 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_cistatic void ixgbe_create_lbtest_frame(struct sk_buff *skb, 19618c2ecf20Sopenharmony_ci unsigned int frame_size) 19628c2ecf20Sopenharmony_ci{ 19638c2ecf20Sopenharmony_ci memset(skb->data, 0xFF, frame_size); 19648c2ecf20Sopenharmony_ci frame_size >>= 1; 19658c2ecf20Sopenharmony_ci memset(&skb->data[frame_size], 0xAA, frame_size / 2 - 1); 19668c2ecf20Sopenharmony_ci skb->data[frame_size + 10] = 0xBE; 19678c2ecf20Sopenharmony_ci skb->data[frame_size + 12] = 0xAF; 19688c2ecf20Sopenharmony_ci} 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_cistatic bool ixgbe_check_lbtest_frame(struct ixgbe_rx_buffer *rx_buffer, 19718c2ecf20Sopenharmony_ci unsigned int frame_size) 19728c2ecf20Sopenharmony_ci{ 19738c2ecf20Sopenharmony_ci unsigned char *data; 19748c2ecf20Sopenharmony_ci bool match = true; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci frame_size >>= 1; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci data = kmap(rx_buffer->page) + rx_buffer->page_offset; 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci if (data[3] != 0xFF || 19818c2ecf20Sopenharmony_ci data[frame_size + 10] != 0xBE || 19828c2ecf20Sopenharmony_ci data[frame_size + 12] != 0xAF) 19838c2ecf20Sopenharmony_ci match = false; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci kunmap(rx_buffer->page); 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci return match; 19888c2ecf20Sopenharmony_ci} 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_cistatic u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring, 19918c2ecf20Sopenharmony_ci struct ixgbe_ring *tx_ring, 19928c2ecf20Sopenharmony_ci unsigned int size) 19938c2ecf20Sopenharmony_ci{ 19948c2ecf20Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc; 19958c2ecf20Sopenharmony_ci u16 rx_ntc, tx_ntc, count = 0; 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci /* initialize next to clean and descriptor values */ 19988c2ecf20Sopenharmony_ci rx_ntc = rx_ring->next_to_clean; 19998c2ecf20Sopenharmony_ci tx_ntc = tx_ring->next_to_clean; 20008c2ecf20Sopenharmony_ci rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc); 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci while (tx_ntc != tx_ring->next_to_use) { 20038c2ecf20Sopenharmony_ci union ixgbe_adv_tx_desc *tx_desc; 20048c2ecf20Sopenharmony_ci struct ixgbe_tx_buffer *tx_buffer; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci tx_desc = IXGBE_TX_DESC(tx_ring, tx_ntc); 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci /* if DD is not set transmit has not completed */ 20098c2ecf20Sopenharmony_ci if (!(tx_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) 20108c2ecf20Sopenharmony_ci return count; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci /* unmap buffer on Tx side */ 20138c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[tx_ntc]; 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci /* Free all the Tx ring sk_buffs */ 20168c2ecf20Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci /* unmap skb header data */ 20198c2ecf20Sopenharmony_ci dma_unmap_single(tx_ring->dev, 20208c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 20218c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 20228c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 20238c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci /* increment Tx next to clean counter */ 20268c2ecf20Sopenharmony_ci tx_ntc++; 20278c2ecf20Sopenharmony_ci if (tx_ntc == tx_ring->count) 20288c2ecf20Sopenharmony_ci tx_ntc = 0; 20298c2ecf20Sopenharmony_ci } 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci while (rx_desc->wb.upper.length) { 20328c2ecf20Sopenharmony_ci struct ixgbe_rx_buffer *rx_buffer; 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci /* check Rx buffer */ 20358c2ecf20Sopenharmony_ci rx_buffer = &rx_ring->rx_buffer_info[rx_ntc]; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci /* sync Rx buffer for CPU read */ 20388c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(rx_ring->dev, 20398c2ecf20Sopenharmony_ci rx_buffer->dma, 20408c2ecf20Sopenharmony_ci ixgbe_rx_bufsz(rx_ring), 20418c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci /* verify contents of skb */ 20448c2ecf20Sopenharmony_ci if (ixgbe_check_lbtest_frame(rx_buffer, size)) 20458c2ecf20Sopenharmony_ci count++; 20468c2ecf20Sopenharmony_ci else 20478c2ecf20Sopenharmony_ci break; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci /* sync Rx buffer for device write */ 20508c2ecf20Sopenharmony_ci dma_sync_single_for_device(rx_ring->dev, 20518c2ecf20Sopenharmony_ci rx_buffer->dma, 20528c2ecf20Sopenharmony_ci ixgbe_rx_bufsz(rx_ring), 20538c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci /* increment Rx next to clean counter */ 20568c2ecf20Sopenharmony_ci rx_ntc++; 20578c2ecf20Sopenharmony_ci if (rx_ntc == rx_ring->count) 20588c2ecf20Sopenharmony_ci rx_ntc = 0; 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci /* fetch next descriptor */ 20618c2ecf20Sopenharmony_ci rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc); 20628c2ecf20Sopenharmony_ci } 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci netdev_tx_reset_queue(txring_txq(tx_ring)); 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci /* re-map buffers to ring, store next to clean values */ 20678c2ecf20Sopenharmony_ci ixgbe_alloc_rx_buffers(rx_ring, count); 20688c2ecf20Sopenharmony_ci rx_ring->next_to_clean = rx_ntc; 20698c2ecf20Sopenharmony_ci tx_ring->next_to_clean = tx_ntc; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci return count; 20728c2ecf20Sopenharmony_ci} 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_cistatic int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) 20758c2ecf20Sopenharmony_ci{ 20768c2ecf20Sopenharmony_ci struct ixgbe_ring *tx_ring = &adapter->test_tx_ring; 20778c2ecf20Sopenharmony_ci struct ixgbe_ring *rx_ring = &adapter->test_rx_ring; 20788c2ecf20Sopenharmony_ci int i, j, lc, good_cnt, ret_val = 0; 20798c2ecf20Sopenharmony_ci unsigned int size = 1024; 20808c2ecf20Sopenharmony_ci netdev_tx_t tx_ret_val; 20818c2ecf20Sopenharmony_ci struct sk_buff *skb; 20828c2ecf20Sopenharmony_ci u32 flags_orig = adapter->flags; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci /* DCB can modify the frames on Tx */ 20858c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci /* allocate test skb */ 20888c2ecf20Sopenharmony_ci skb = alloc_skb(size, GFP_KERNEL); 20898c2ecf20Sopenharmony_ci if (!skb) 20908c2ecf20Sopenharmony_ci return 11; 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci /* place data into test skb */ 20938c2ecf20Sopenharmony_ci ixgbe_create_lbtest_frame(skb, size); 20948c2ecf20Sopenharmony_ci skb_put(skb, size); 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci /* 20978c2ecf20Sopenharmony_ci * Calculate the loop count based on the largest descriptor ring 20988c2ecf20Sopenharmony_ci * The idea is to wrap the largest ring a number of times using 64 20998c2ecf20Sopenharmony_ci * send/receive pairs during each loop 21008c2ecf20Sopenharmony_ci */ 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci if (rx_ring->count <= tx_ring->count) 21038c2ecf20Sopenharmony_ci lc = ((tx_ring->count / 64) * 2) + 1; 21048c2ecf20Sopenharmony_ci else 21058c2ecf20Sopenharmony_ci lc = ((rx_ring->count / 64) * 2) + 1; 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci for (j = 0; j <= lc; j++) { 21088c2ecf20Sopenharmony_ci /* reset count of good packets */ 21098c2ecf20Sopenharmony_ci good_cnt = 0; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci /* place 64 packets on the transmit queue*/ 21128c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 21138c2ecf20Sopenharmony_ci skb_get(skb); 21148c2ecf20Sopenharmony_ci tx_ret_val = ixgbe_xmit_frame_ring(skb, 21158c2ecf20Sopenharmony_ci adapter, 21168c2ecf20Sopenharmony_ci tx_ring); 21178c2ecf20Sopenharmony_ci if (tx_ret_val == NETDEV_TX_OK) 21188c2ecf20Sopenharmony_ci good_cnt++; 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci if (good_cnt != 64) { 21228c2ecf20Sopenharmony_ci ret_val = 12; 21238c2ecf20Sopenharmony_ci break; 21248c2ecf20Sopenharmony_ci } 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci /* allow 200 milliseconds for packets to go from Tx to Rx */ 21278c2ecf20Sopenharmony_ci msleep(200); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci good_cnt = ixgbe_clean_test_rings(rx_ring, tx_ring, size); 21308c2ecf20Sopenharmony_ci if (good_cnt != 64) { 21318c2ecf20Sopenharmony_ci ret_val = 13; 21328c2ecf20Sopenharmony_ci break; 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci } 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci /* free the original skb */ 21378c2ecf20Sopenharmony_ci kfree_skb(skb); 21388c2ecf20Sopenharmony_ci adapter->flags = flags_orig; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci return ret_val; 21418c2ecf20Sopenharmony_ci} 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_cistatic int ixgbe_loopback_test(struct ixgbe_adapter *adapter, u64 *data) 21448c2ecf20Sopenharmony_ci{ 21458c2ecf20Sopenharmony_ci *data = ixgbe_setup_desc_rings(adapter); 21468c2ecf20Sopenharmony_ci if (*data) 21478c2ecf20Sopenharmony_ci goto out; 21488c2ecf20Sopenharmony_ci *data = ixgbe_setup_loopback_test(adapter); 21498c2ecf20Sopenharmony_ci if (*data) 21508c2ecf20Sopenharmony_ci goto err_loopback; 21518c2ecf20Sopenharmony_ci *data = ixgbe_run_loopback_test(adapter); 21528c2ecf20Sopenharmony_ci ixgbe_loopback_cleanup(adapter); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_cierr_loopback: 21558c2ecf20Sopenharmony_ci ixgbe_free_desc_rings(adapter); 21568c2ecf20Sopenharmony_ciout: 21578c2ecf20Sopenharmony_ci return *data; 21588c2ecf20Sopenharmony_ci} 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_cistatic void ixgbe_diag_test(struct net_device *netdev, 21618c2ecf20Sopenharmony_ci struct ethtool_test *eth_test, u64 *data) 21628c2ecf20Sopenharmony_ci{ 21638c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 21648c2ecf20Sopenharmony_ci bool if_running = netif_running(netdev); 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci if (ixgbe_removed(adapter->hw.hw_addr)) { 21678c2ecf20Sopenharmony_ci e_err(hw, "Adapter removed - test blocked\n"); 21688c2ecf20Sopenharmony_ci data[0] = 1; 21698c2ecf20Sopenharmony_ci data[1] = 1; 21708c2ecf20Sopenharmony_ci data[2] = 1; 21718c2ecf20Sopenharmony_ci data[3] = 1; 21728c2ecf20Sopenharmony_ci data[4] = 1; 21738c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 21748c2ecf20Sopenharmony_ci return; 21758c2ecf20Sopenharmony_ci } 21768c2ecf20Sopenharmony_ci set_bit(__IXGBE_TESTING, &adapter->state); 21778c2ecf20Sopenharmony_ci if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 21788c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { 21818c2ecf20Sopenharmony_ci int i; 21828c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_vfs; i++) { 21838c2ecf20Sopenharmony_ci if (adapter->vfinfo[i].clear_to_send) { 21848c2ecf20Sopenharmony_ci netdev_warn(netdev, "offline diagnostic is not supported when VFs are present\n"); 21858c2ecf20Sopenharmony_ci data[0] = 1; 21868c2ecf20Sopenharmony_ci data[1] = 1; 21878c2ecf20Sopenharmony_ci data[2] = 1; 21888c2ecf20Sopenharmony_ci data[3] = 1; 21898c2ecf20Sopenharmony_ci data[4] = 1; 21908c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 21918c2ecf20Sopenharmony_ci clear_bit(__IXGBE_TESTING, 21928c2ecf20Sopenharmony_ci &adapter->state); 21938c2ecf20Sopenharmony_ci return; 21948c2ecf20Sopenharmony_ci } 21958c2ecf20Sopenharmony_ci } 21968c2ecf20Sopenharmony_ci } 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci /* Offline tests */ 21998c2ecf20Sopenharmony_ci e_info(hw, "offline testing starting\n"); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci /* Link test performed before hardware reset so autoneg doesn't 22028c2ecf20Sopenharmony_ci * interfere with test result 22038c2ecf20Sopenharmony_ci */ 22048c2ecf20Sopenharmony_ci if (ixgbe_link_test(adapter, &data[4])) 22058c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_ci if (if_running) 22088c2ecf20Sopenharmony_ci /* indicate we're in test mode */ 22098c2ecf20Sopenharmony_ci ixgbe_close(netdev); 22108c2ecf20Sopenharmony_ci else 22118c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci e_info(hw, "register testing starting\n"); 22148c2ecf20Sopenharmony_ci if (ixgbe_reg_test(adapter, &data[0])) 22158c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 22188c2ecf20Sopenharmony_ci e_info(hw, "eeprom testing starting\n"); 22198c2ecf20Sopenharmony_ci if (ixgbe_eeprom_test(adapter, &data[1])) 22208c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 22238c2ecf20Sopenharmony_ci e_info(hw, "interrupt testing starting\n"); 22248c2ecf20Sopenharmony_ci if (ixgbe_intr_test(adapter, &data[2])) 22258c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci /* If SRIOV or VMDq is enabled then skip MAC 22288c2ecf20Sopenharmony_ci * loopback diagnostic. */ 22298c2ecf20Sopenharmony_ci if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED | 22308c2ecf20Sopenharmony_ci IXGBE_FLAG_VMDQ_ENABLED)) { 22318c2ecf20Sopenharmony_ci e_info(hw, "Skip MAC loopback diagnostic in VT mode\n"); 22328c2ecf20Sopenharmony_ci data[3] = 0; 22338c2ecf20Sopenharmony_ci goto skip_loopback; 22348c2ecf20Sopenharmony_ci } 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 22378c2ecf20Sopenharmony_ci e_info(hw, "loopback testing starting\n"); 22388c2ecf20Sopenharmony_ci if (ixgbe_loopback_test(adapter, &data[3])) 22398c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ciskip_loopback: 22428c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci /* clear testing bit and return adapter to previous state */ 22458c2ecf20Sopenharmony_ci clear_bit(__IXGBE_TESTING, &adapter->state); 22468c2ecf20Sopenharmony_ci if (if_running) 22478c2ecf20Sopenharmony_ci ixgbe_open(netdev); 22488c2ecf20Sopenharmony_ci else if (hw->mac.ops.disable_tx_laser) 22498c2ecf20Sopenharmony_ci hw->mac.ops.disable_tx_laser(hw); 22508c2ecf20Sopenharmony_ci } else { 22518c2ecf20Sopenharmony_ci e_info(hw, "online testing starting\n"); 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci /* Online tests */ 22548c2ecf20Sopenharmony_ci if (ixgbe_link_test(adapter, &data[4])) 22558c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci /* Offline tests aren't run; pass by default */ 22588c2ecf20Sopenharmony_ci data[0] = 0; 22598c2ecf20Sopenharmony_ci data[1] = 0; 22608c2ecf20Sopenharmony_ci data[2] = 0; 22618c2ecf20Sopenharmony_ci data[3] = 0; 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci clear_bit(__IXGBE_TESTING, &adapter->state); 22648c2ecf20Sopenharmony_ci } 22658c2ecf20Sopenharmony_ci} 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_cistatic int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, 22688c2ecf20Sopenharmony_ci struct ethtool_wolinfo *wol) 22698c2ecf20Sopenharmony_ci{ 22708c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 22718c2ecf20Sopenharmony_ci int retval = 0; 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci /* WOL not supported for all devices */ 22748c2ecf20Sopenharmony_ci if (!ixgbe_wol_supported(adapter, hw->device_id, 22758c2ecf20Sopenharmony_ci hw->subsystem_device_id)) { 22768c2ecf20Sopenharmony_ci retval = 1; 22778c2ecf20Sopenharmony_ci wol->supported = 0; 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci return retval; 22818c2ecf20Sopenharmony_ci} 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_cistatic void ixgbe_get_wol(struct net_device *netdev, 22848c2ecf20Sopenharmony_ci struct ethtool_wolinfo *wol) 22858c2ecf20Sopenharmony_ci{ 22868c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci wol->supported = WAKE_UCAST | WAKE_MCAST | 22898c2ecf20Sopenharmony_ci WAKE_BCAST | WAKE_MAGIC; 22908c2ecf20Sopenharmony_ci wol->wolopts = 0; 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci if (ixgbe_wol_exclusion(adapter, wol) || 22938c2ecf20Sopenharmony_ci !device_can_wakeup(&adapter->pdev->dev)) 22948c2ecf20Sopenharmony_ci return; 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci if (adapter->wol & IXGBE_WUFC_EX) 22978c2ecf20Sopenharmony_ci wol->wolopts |= WAKE_UCAST; 22988c2ecf20Sopenharmony_ci if (adapter->wol & IXGBE_WUFC_MC) 22998c2ecf20Sopenharmony_ci wol->wolopts |= WAKE_MCAST; 23008c2ecf20Sopenharmony_ci if (adapter->wol & IXGBE_WUFC_BC) 23018c2ecf20Sopenharmony_ci wol->wolopts |= WAKE_BCAST; 23028c2ecf20Sopenharmony_ci if (adapter->wol & IXGBE_WUFC_MAG) 23038c2ecf20Sopenharmony_ci wol->wolopts |= WAKE_MAGIC; 23048c2ecf20Sopenharmony_ci} 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_cistatic int ixgbe_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) 23078c2ecf20Sopenharmony_ci{ 23088c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE | 23118c2ecf20Sopenharmony_ci WAKE_FILTER)) 23128c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci if (ixgbe_wol_exclusion(adapter, wol)) 23158c2ecf20Sopenharmony_ci return wol->wolopts ? -EOPNOTSUPP : 0; 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci adapter->wol = 0; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci if (wol->wolopts & WAKE_UCAST) 23208c2ecf20Sopenharmony_ci adapter->wol |= IXGBE_WUFC_EX; 23218c2ecf20Sopenharmony_ci if (wol->wolopts & WAKE_MCAST) 23228c2ecf20Sopenharmony_ci adapter->wol |= IXGBE_WUFC_MC; 23238c2ecf20Sopenharmony_ci if (wol->wolopts & WAKE_BCAST) 23248c2ecf20Sopenharmony_ci adapter->wol |= IXGBE_WUFC_BC; 23258c2ecf20Sopenharmony_ci if (wol->wolopts & WAKE_MAGIC) 23268c2ecf20Sopenharmony_ci adapter->wol |= IXGBE_WUFC_MAG; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci return 0; 23318c2ecf20Sopenharmony_ci} 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_cistatic int ixgbe_nway_reset(struct net_device *netdev) 23348c2ecf20Sopenharmony_ci{ 23358c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci if (netif_running(netdev)) 23388c2ecf20Sopenharmony_ci ixgbe_reinit_locked(adapter); 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci return 0; 23418c2ecf20Sopenharmony_ci} 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_cistatic int ixgbe_set_phys_id(struct net_device *netdev, 23448c2ecf20Sopenharmony_ci enum ethtool_phys_id_state state) 23458c2ecf20Sopenharmony_ci{ 23468c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 23478c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci if (!hw->mac.ops.led_on || !hw->mac.ops.led_off) 23508c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci switch (state) { 23538c2ecf20Sopenharmony_ci case ETHTOOL_ID_ACTIVE: 23548c2ecf20Sopenharmony_ci adapter->led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 23558c2ecf20Sopenharmony_ci return 2; 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci case ETHTOOL_ID_ON: 23588c2ecf20Sopenharmony_ci hw->mac.ops.led_on(hw, hw->mac.led_link_act); 23598c2ecf20Sopenharmony_ci break; 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci case ETHTOOL_ID_OFF: 23628c2ecf20Sopenharmony_ci hw->mac.ops.led_off(hw, hw->mac.led_link_act); 23638c2ecf20Sopenharmony_ci break; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci case ETHTOOL_ID_INACTIVE: 23668c2ecf20Sopenharmony_ci /* Restore LED settings */ 23678c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(&adapter->hw, IXGBE_LEDCTL, adapter->led_reg); 23688c2ecf20Sopenharmony_ci break; 23698c2ecf20Sopenharmony_ci } 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci return 0; 23728c2ecf20Sopenharmony_ci} 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_cistatic int ixgbe_get_coalesce(struct net_device *netdev, 23758c2ecf20Sopenharmony_ci struct ethtool_coalesce *ec) 23768c2ecf20Sopenharmony_ci{ 23778c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 23788c2ecf20Sopenharmony_ci 23798c2ecf20Sopenharmony_ci /* only valid if in constant ITR mode */ 23808c2ecf20Sopenharmony_ci if (adapter->rx_itr_setting <= 1) 23818c2ecf20Sopenharmony_ci ec->rx_coalesce_usecs = adapter->rx_itr_setting; 23828c2ecf20Sopenharmony_ci else 23838c2ecf20Sopenharmony_ci ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci /* if in mixed tx/rx queues per vector mode, report only rx settings */ 23868c2ecf20Sopenharmony_ci if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) 23878c2ecf20Sopenharmony_ci return 0; 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci /* only valid if in constant ITR mode */ 23908c2ecf20Sopenharmony_ci if (adapter->tx_itr_setting <= 1) 23918c2ecf20Sopenharmony_ci ec->tx_coalesce_usecs = adapter->tx_itr_setting; 23928c2ecf20Sopenharmony_ci else 23938c2ecf20Sopenharmony_ci ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci return 0; 23968c2ecf20Sopenharmony_ci} 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci/* 23998c2ecf20Sopenharmony_ci * this function must be called before setting the new value of 24008c2ecf20Sopenharmony_ci * rx_itr_setting 24018c2ecf20Sopenharmony_ci */ 24028c2ecf20Sopenharmony_cistatic bool ixgbe_update_rsc(struct ixgbe_adapter *adapter) 24038c2ecf20Sopenharmony_ci{ 24048c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci /* nothing to do if LRO or RSC are not enabled */ 24078c2ecf20Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) || 24088c2ecf20Sopenharmony_ci !(netdev->features & NETIF_F_LRO)) 24098c2ecf20Sopenharmony_ci return false; 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci /* check the feature flag value and enable RSC if necessary */ 24128c2ecf20Sopenharmony_ci if (adapter->rx_itr_setting == 1 || 24138c2ecf20Sopenharmony_ci adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR) { 24148c2ecf20Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) { 24158c2ecf20Sopenharmony_ci adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; 24168c2ecf20Sopenharmony_ci e_info(probe, "rx-usecs value high enough to re-enable RSC\n"); 24178c2ecf20Sopenharmony_ci return true; 24188c2ecf20Sopenharmony_ci } 24198c2ecf20Sopenharmony_ci /* if interrupt rate is too high then disable RSC */ 24208c2ecf20Sopenharmony_ci } else if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { 24218c2ecf20Sopenharmony_ci adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; 24228c2ecf20Sopenharmony_ci e_info(probe, "rx-usecs set too low, disabling RSC\n"); 24238c2ecf20Sopenharmony_ci return true; 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci return false; 24268c2ecf20Sopenharmony_ci} 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_cistatic int ixgbe_set_coalesce(struct net_device *netdev, 24298c2ecf20Sopenharmony_ci struct ethtool_coalesce *ec) 24308c2ecf20Sopenharmony_ci{ 24318c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 24328c2ecf20Sopenharmony_ci struct ixgbe_q_vector *q_vector; 24338c2ecf20Sopenharmony_ci int i; 24348c2ecf20Sopenharmony_ci u16 tx_itr_param, rx_itr_param, tx_itr_prev; 24358c2ecf20Sopenharmony_ci bool need_reset = false; 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) { 24388c2ecf20Sopenharmony_ci /* reject Tx specific changes in case of mixed RxTx vectors */ 24398c2ecf20Sopenharmony_ci if (ec->tx_coalesce_usecs) 24408c2ecf20Sopenharmony_ci return -EINVAL; 24418c2ecf20Sopenharmony_ci tx_itr_prev = adapter->rx_itr_setting; 24428c2ecf20Sopenharmony_ci } else { 24438c2ecf20Sopenharmony_ci tx_itr_prev = adapter->tx_itr_setting; 24448c2ecf20Sopenharmony_ci } 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) || 24478c2ecf20Sopenharmony_ci (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2))) 24488c2ecf20Sopenharmony_ci return -EINVAL; 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci if (ec->rx_coalesce_usecs > 1) 24518c2ecf20Sopenharmony_ci adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; 24528c2ecf20Sopenharmony_ci else 24538c2ecf20Sopenharmony_ci adapter->rx_itr_setting = ec->rx_coalesce_usecs; 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci if (adapter->rx_itr_setting == 1) 24568c2ecf20Sopenharmony_ci rx_itr_param = IXGBE_20K_ITR; 24578c2ecf20Sopenharmony_ci else 24588c2ecf20Sopenharmony_ci rx_itr_param = adapter->rx_itr_setting; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci if (ec->tx_coalesce_usecs > 1) 24618c2ecf20Sopenharmony_ci adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; 24628c2ecf20Sopenharmony_ci else 24638c2ecf20Sopenharmony_ci adapter->tx_itr_setting = ec->tx_coalesce_usecs; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci if (adapter->tx_itr_setting == 1) 24668c2ecf20Sopenharmony_ci tx_itr_param = IXGBE_12K_ITR; 24678c2ecf20Sopenharmony_ci else 24688c2ecf20Sopenharmony_ci tx_itr_param = adapter->tx_itr_setting; 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci /* mixed Rx/Tx */ 24718c2ecf20Sopenharmony_ci if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) 24728c2ecf20Sopenharmony_ci adapter->tx_itr_setting = adapter->rx_itr_setting; 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci /* detect ITR changes that require update of TXDCTL.WTHRESH */ 24758c2ecf20Sopenharmony_ci if ((adapter->tx_itr_setting != 1) && 24768c2ecf20Sopenharmony_ci (adapter->tx_itr_setting < IXGBE_100K_ITR)) { 24778c2ecf20Sopenharmony_ci if ((tx_itr_prev == 1) || 24788c2ecf20Sopenharmony_ci (tx_itr_prev >= IXGBE_100K_ITR)) 24798c2ecf20Sopenharmony_ci need_reset = true; 24808c2ecf20Sopenharmony_ci } else { 24818c2ecf20Sopenharmony_ci if ((tx_itr_prev != 1) && 24828c2ecf20Sopenharmony_ci (tx_itr_prev < IXGBE_100K_ITR)) 24838c2ecf20Sopenharmony_ci need_reset = true; 24848c2ecf20Sopenharmony_ci } 24858c2ecf20Sopenharmony_ci 24868c2ecf20Sopenharmony_ci /* check the old value and enable RSC if necessary */ 24878c2ecf20Sopenharmony_ci need_reset |= ixgbe_update_rsc(adapter); 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) { 24908c2ecf20Sopenharmony_ci q_vector = adapter->q_vector[i]; 24918c2ecf20Sopenharmony_ci if (q_vector->tx.count && !q_vector->rx.count) 24928c2ecf20Sopenharmony_ci /* tx only */ 24938c2ecf20Sopenharmony_ci q_vector->itr = tx_itr_param; 24948c2ecf20Sopenharmony_ci else 24958c2ecf20Sopenharmony_ci /* rx only or mixed */ 24968c2ecf20Sopenharmony_ci q_vector->itr = rx_itr_param; 24978c2ecf20Sopenharmony_ci ixgbe_write_eitr(q_vector); 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci /* 25018c2ecf20Sopenharmony_ci * do reset here at the end to make sure EITR==0 case is handled 25028c2ecf20Sopenharmony_ci * correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings 25038c2ecf20Sopenharmony_ci * also locks in RSC enable/disable which requires reset 25048c2ecf20Sopenharmony_ci */ 25058c2ecf20Sopenharmony_ci if (need_reset) 25068c2ecf20Sopenharmony_ci ixgbe_do_reset(netdev); 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ci return 0; 25098c2ecf20Sopenharmony_ci} 25108c2ecf20Sopenharmony_ci 25118c2ecf20Sopenharmony_cistatic int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter, 25128c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 25138c2ecf20Sopenharmony_ci{ 25148c2ecf20Sopenharmony_ci union ixgbe_atr_input *mask = &adapter->fdir_mask; 25158c2ecf20Sopenharmony_ci struct ethtool_rx_flow_spec *fsp = 25168c2ecf20Sopenharmony_ci (struct ethtool_rx_flow_spec *)&cmd->fs; 25178c2ecf20Sopenharmony_ci struct hlist_node *node2; 25188c2ecf20Sopenharmony_ci struct ixgbe_fdir_filter *rule = NULL; 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci /* report total rule count */ 25218c2ecf20Sopenharmony_ci cmd->data = (1024 << adapter->fdir_pballoc) - 2; 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ci hlist_for_each_entry_safe(rule, node2, 25248c2ecf20Sopenharmony_ci &adapter->fdir_filter_list, fdir_node) { 25258c2ecf20Sopenharmony_ci if (fsp->location <= rule->sw_idx) 25268c2ecf20Sopenharmony_ci break; 25278c2ecf20Sopenharmony_ci } 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci if (!rule || fsp->location != rule->sw_idx) 25308c2ecf20Sopenharmony_ci return -EINVAL; 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci /* fill out the flow spec entry */ 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci /* set flow type field */ 25358c2ecf20Sopenharmony_ci switch (rule->filter.formatted.flow_type) { 25368c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_TCPV4: 25378c2ecf20Sopenharmony_ci fsp->flow_type = TCP_V4_FLOW; 25388c2ecf20Sopenharmony_ci break; 25398c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_UDPV4: 25408c2ecf20Sopenharmony_ci fsp->flow_type = UDP_V4_FLOW; 25418c2ecf20Sopenharmony_ci break; 25428c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_SCTPV4: 25438c2ecf20Sopenharmony_ci fsp->flow_type = SCTP_V4_FLOW; 25448c2ecf20Sopenharmony_ci break; 25458c2ecf20Sopenharmony_ci case IXGBE_ATR_FLOW_TYPE_IPV4: 25468c2ecf20Sopenharmony_ci fsp->flow_type = IP_USER_FLOW; 25478c2ecf20Sopenharmony_ci fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4; 25488c2ecf20Sopenharmony_ci fsp->h_u.usr_ip4_spec.proto = 0; 25498c2ecf20Sopenharmony_ci fsp->m_u.usr_ip4_spec.proto = 0; 25508c2ecf20Sopenharmony_ci break; 25518c2ecf20Sopenharmony_ci default: 25528c2ecf20Sopenharmony_ci return -EINVAL; 25538c2ecf20Sopenharmony_ci } 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port; 25568c2ecf20Sopenharmony_ci fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port; 25578c2ecf20Sopenharmony_ci fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port; 25588c2ecf20Sopenharmony_ci fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port; 25598c2ecf20Sopenharmony_ci fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0]; 25608c2ecf20Sopenharmony_ci fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0]; 25618c2ecf20Sopenharmony_ci fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0]; 25628c2ecf20Sopenharmony_ci fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0]; 25638c2ecf20Sopenharmony_ci fsp->h_ext.vlan_tci = rule->filter.formatted.vlan_id; 25648c2ecf20Sopenharmony_ci fsp->m_ext.vlan_tci = mask->formatted.vlan_id; 25658c2ecf20Sopenharmony_ci fsp->h_ext.vlan_etype = rule->filter.formatted.flex_bytes; 25668c2ecf20Sopenharmony_ci fsp->m_ext.vlan_etype = mask->formatted.flex_bytes; 25678c2ecf20Sopenharmony_ci fsp->h_ext.data[1] = htonl(rule->filter.formatted.vm_pool); 25688c2ecf20Sopenharmony_ci fsp->m_ext.data[1] = htonl(mask->formatted.vm_pool); 25698c2ecf20Sopenharmony_ci fsp->flow_type |= FLOW_EXT; 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci /* record action */ 25728c2ecf20Sopenharmony_ci if (rule->action == IXGBE_FDIR_DROP_QUEUE) 25738c2ecf20Sopenharmony_ci fsp->ring_cookie = RX_CLS_FLOW_DISC; 25748c2ecf20Sopenharmony_ci else 25758c2ecf20Sopenharmony_ci fsp->ring_cookie = rule->action; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci return 0; 25788c2ecf20Sopenharmony_ci} 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_cistatic int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter, 25818c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd, 25828c2ecf20Sopenharmony_ci u32 *rule_locs) 25838c2ecf20Sopenharmony_ci{ 25848c2ecf20Sopenharmony_ci struct hlist_node *node2; 25858c2ecf20Sopenharmony_ci struct ixgbe_fdir_filter *rule; 25868c2ecf20Sopenharmony_ci int cnt = 0; 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci /* report total rule count */ 25898c2ecf20Sopenharmony_ci cmd->data = (1024 << adapter->fdir_pballoc) - 2; 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci hlist_for_each_entry_safe(rule, node2, 25928c2ecf20Sopenharmony_ci &adapter->fdir_filter_list, fdir_node) { 25938c2ecf20Sopenharmony_ci if (cnt == cmd->rule_cnt) 25948c2ecf20Sopenharmony_ci return -EMSGSIZE; 25958c2ecf20Sopenharmony_ci rule_locs[cnt] = rule->sw_idx; 25968c2ecf20Sopenharmony_ci cnt++; 25978c2ecf20Sopenharmony_ci } 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_ci cmd->rule_cnt = cnt; 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci return 0; 26028c2ecf20Sopenharmony_ci} 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_cistatic int ixgbe_get_rss_hash_opts(struct ixgbe_adapter *adapter, 26058c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 26068c2ecf20Sopenharmony_ci{ 26078c2ecf20Sopenharmony_ci cmd->data = 0; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci /* Report default options for RSS on ixgbe */ 26108c2ecf20Sopenharmony_ci switch (cmd->flow_type) { 26118c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 26128c2ecf20Sopenharmony_ci cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 26138c2ecf20Sopenharmony_ci fallthrough; 26148c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 26158c2ecf20Sopenharmony_ci if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) 26168c2ecf20Sopenharmony_ci cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 26178c2ecf20Sopenharmony_ci fallthrough; 26188c2ecf20Sopenharmony_ci case SCTP_V4_FLOW: 26198c2ecf20Sopenharmony_ci case AH_ESP_V4_FLOW: 26208c2ecf20Sopenharmony_ci case AH_V4_FLOW: 26218c2ecf20Sopenharmony_ci case ESP_V4_FLOW: 26228c2ecf20Sopenharmony_ci case IPV4_FLOW: 26238c2ecf20Sopenharmony_ci cmd->data |= RXH_IP_SRC | RXH_IP_DST; 26248c2ecf20Sopenharmony_ci break; 26258c2ecf20Sopenharmony_ci case TCP_V6_FLOW: 26268c2ecf20Sopenharmony_ci cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 26278c2ecf20Sopenharmony_ci fallthrough; 26288c2ecf20Sopenharmony_ci case UDP_V6_FLOW: 26298c2ecf20Sopenharmony_ci if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) 26308c2ecf20Sopenharmony_ci cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 26318c2ecf20Sopenharmony_ci fallthrough; 26328c2ecf20Sopenharmony_ci case SCTP_V6_FLOW: 26338c2ecf20Sopenharmony_ci case AH_ESP_V6_FLOW: 26348c2ecf20Sopenharmony_ci case AH_V6_FLOW: 26358c2ecf20Sopenharmony_ci case ESP_V6_FLOW: 26368c2ecf20Sopenharmony_ci case IPV6_FLOW: 26378c2ecf20Sopenharmony_ci cmd->data |= RXH_IP_SRC | RXH_IP_DST; 26388c2ecf20Sopenharmony_ci break; 26398c2ecf20Sopenharmony_ci default: 26408c2ecf20Sopenharmony_ci return -EINVAL; 26418c2ecf20Sopenharmony_ci } 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci return 0; 26448c2ecf20Sopenharmony_ci} 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_cistatic int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter) 26478c2ecf20Sopenharmony_ci{ 26488c2ecf20Sopenharmony_ci if (adapter->hw.mac.type < ixgbe_mac_X550) 26498c2ecf20Sopenharmony_ci return 16; 26508c2ecf20Sopenharmony_ci else 26518c2ecf20Sopenharmony_ci return 64; 26528c2ecf20Sopenharmony_ci} 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_cistatic int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, 26558c2ecf20Sopenharmony_ci u32 *rule_locs) 26568c2ecf20Sopenharmony_ci{ 26578c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 26588c2ecf20Sopenharmony_ci int ret = -EOPNOTSUPP; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci switch (cmd->cmd) { 26618c2ecf20Sopenharmony_ci case ETHTOOL_GRXRINGS: 26628c2ecf20Sopenharmony_ci cmd->data = min_t(int, adapter->num_rx_queues, 26638c2ecf20Sopenharmony_ci ixgbe_rss_indir_tbl_max(adapter)); 26648c2ecf20Sopenharmony_ci ret = 0; 26658c2ecf20Sopenharmony_ci break; 26668c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRLCNT: 26678c2ecf20Sopenharmony_ci cmd->rule_cnt = adapter->fdir_filter_count; 26688c2ecf20Sopenharmony_ci ret = 0; 26698c2ecf20Sopenharmony_ci break; 26708c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRULE: 26718c2ecf20Sopenharmony_ci ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd); 26728c2ecf20Sopenharmony_ci break; 26738c2ecf20Sopenharmony_ci case ETHTOOL_GRXCLSRLALL: 26748c2ecf20Sopenharmony_ci ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, rule_locs); 26758c2ecf20Sopenharmony_ci break; 26768c2ecf20Sopenharmony_ci case ETHTOOL_GRXFH: 26778c2ecf20Sopenharmony_ci ret = ixgbe_get_rss_hash_opts(adapter, cmd); 26788c2ecf20Sopenharmony_ci break; 26798c2ecf20Sopenharmony_ci default: 26808c2ecf20Sopenharmony_ci break; 26818c2ecf20Sopenharmony_ci } 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci return ret; 26848c2ecf20Sopenharmony_ci} 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ciint ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter, 26878c2ecf20Sopenharmony_ci struct ixgbe_fdir_filter *input, 26888c2ecf20Sopenharmony_ci u16 sw_idx) 26898c2ecf20Sopenharmony_ci{ 26908c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 26918c2ecf20Sopenharmony_ci struct hlist_node *node2; 26928c2ecf20Sopenharmony_ci struct ixgbe_fdir_filter *rule, *parent; 26938c2ecf20Sopenharmony_ci int err = -EINVAL; 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci parent = NULL; 26968c2ecf20Sopenharmony_ci rule = NULL; 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci hlist_for_each_entry_safe(rule, node2, 26998c2ecf20Sopenharmony_ci &adapter->fdir_filter_list, fdir_node) { 27008c2ecf20Sopenharmony_ci /* hash found, or no matching entry */ 27018c2ecf20Sopenharmony_ci if (rule->sw_idx >= sw_idx) 27028c2ecf20Sopenharmony_ci break; 27038c2ecf20Sopenharmony_ci parent = rule; 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci /* if there is an old rule occupying our place remove it */ 27078c2ecf20Sopenharmony_ci if (rule && (rule->sw_idx == sw_idx)) { 27088c2ecf20Sopenharmony_ci if (!input || (rule->filter.formatted.bkt_hash != 27098c2ecf20Sopenharmony_ci input->filter.formatted.bkt_hash)) { 27108c2ecf20Sopenharmony_ci err = ixgbe_fdir_erase_perfect_filter_82599(hw, 27118c2ecf20Sopenharmony_ci &rule->filter, 27128c2ecf20Sopenharmony_ci sw_idx); 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci hlist_del(&rule->fdir_node); 27168c2ecf20Sopenharmony_ci kfree(rule); 27178c2ecf20Sopenharmony_ci adapter->fdir_filter_count--; 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci /* 27218c2ecf20Sopenharmony_ci * If no input this was a delete, err should be 0 if a rule was 27228c2ecf20Sopenharmony_ci * successfully found and removed from the list else -EINVAL 27238c2ecf20Sopenharmony_ci */ 27248c2ecf20Sopenharmony_ci if (!input) 27258c2ecf20Sopenharmony_ci return err; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci /* initialize node and set software index */ 27288c2ecf20Sopenharmony_ci INIT_HLIST_NODE(&input->fdir_node); 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci /* add filter to the list */ 27318c2ecf20Sopenharmony_ci if (parent) 27328c2ecf20Sopenharmony_ci hlist_add_behind(&input->fdir_node, &parent->fdir_node); 27338c2ecf20Sopenharmony_ci else 27348c2ecf20Sopenharmony_ci hlist_add_head(&input->fdir_node, 27358c2ecf20Sopenharmony_ci &adapter->fdir_filter_list); 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci /* update counts */ 27388c2ecf20Sopenharmony_ci adapter->fdir_filter_count++; 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci return 0; 27418c2ecf20Sopenharmony_ci} 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_cistatic int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp, 27448c2ecf20Sopenharmony_ci u8 *flow_type) 27458c2ecf20Sopenharmony_ci{ 27468c2ecf20Sopenharmony_ci switch (fsp->flow_type & ~FLOW_EXT) { 27478c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 27488c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; 27498c2ecf20Sopenharmony_ci break; 27508c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 27518c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; 27528c2ecf20Sopenharmony_ci break; 27538c2ecf20Sopenharmony_ci case SCTP_V4_FLOW: 27548c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; 27558c2ecf20Sopenharmony_ci break; 27568c2ecf20Sopenharmony_ci case IP_USER_FLOW: 27578c2ecf20Sopenharmony_ci switch (fsp->h_u.usr_ip4_spec.proto) { 27588c2ecf20Sopenharmony_ci case IPPROTO_TCP: 27598c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; 27608c2ecf20Sopenharmony_ci break; 27618c2ecf20Sopenharmony_ci case IPPROTO_UDP: 27628c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; 27638c2ecf20Sopenharmony_ci break; 27648c2ecf20Sopenharmony_ci case IPPROTO_SCTP: 27658c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; 27668c2ecf20Sopenharmony_ci break; 27678c2ecf20Sopenharmony_ci case 0: 27688c2ecf20Sopenharmony_ci if (!fsp->m_u.usr_ip4_spec.proto) { 27698c2ecf20Sopenharmony_ci *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4; 27708c2ecf20Sopenharmony_ci break; 27718c2ecf20Sopenharmony_ci } 27728c2ecf20Sopenharmony_ci fallthrough; 27738c2ecf20Sopenharmony_ci default: 27748c2ecf20Sopenharmony_ci return 0; 27758c2ecf20Sopenharmony_ci } 27768c2ecf20Sopenharmony_ci break; 27778c2ecf20Sopenharmony_ci default: 27788c2ecf20Sopenharmony_ci return 0; 27798c2ecf20Sopenharmony_ci } 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci return 1; 27828c2ecf20Sopenharmony_ci} 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_cistatic int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter, 27858c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 27868c2ecf20Sopenharmony_ci{ 27878c2ecf20Sopenharmony_ci struct ethtool_rx_flow_spec *fsp = 27888c2ecf20Sopenharmony_ci (struct ethtool_rx_flow_spec *)&cmd->fs; 27898c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 27908c2ecf20Sopenharmony_ci struct ixgbe_fdir_filter *input; 27918c2ecf20Sopenharmony_ci union ixgbe_atr_input mask; 27928c2ecf20Sopenharmony_ci u8 queue; 27938c2ecf20Sopenharmony_ci int err; 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) 27968c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci /* ring_cookie is a masked into a set of queues and ixgbe pools or 27998c2ecf20Sopenharmony_ci * we use the drop index. 28008c2ecf20Sopenharmony_ci */ 28018c2ecf20Sopenharmony_ci if (fsp->ring_cookie == RX_CLS_FLOW_DISC) { 28028c2ecf20Sopenharmony_ci queue = IXGBE_FDIR_DROP_QUEUE; 28038c2ecf20Sopenharmony_ci } else { 28048c2ecf20Sopenharmony_ci u32 ring = ethtool_get_flow_spec_ring(fsp->ring_cookie); 28058c2ecf20Sopenharmony_ci u8 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie); 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci if (!vf && (ring >= adapter->num_rx_queues)) 28088c2ecf20Sopenharmony_ci return -EINVAL; 28098c2ecf20Sopenharmony_ci else if (vf && 28108c2ecf20Sopenharmony_ci ((vf > adapter->num_vfs) || 28118c2ecf20Sopenharmony_ci ring >= adapter->num_rx_queues_per_pool)) 28128c2ecf20Sopenharmony_ci return -EINVAL; 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci /* Map the ring onto the absolute queue index */ 28158c2ecf20Sopenharmony_ci if (!vf) 28168c2ecf20Sopenharmony_ci queue = adapter->rx_ring[ring]->reg_idx; 28178c2ecf20Sopenharmony_ci else 28188c2ecf20Sopenharmony_ci queue = ((vf - 1) * 28198c2ecf20Sopenharmony_ci adapter->num_rx_queues_per_pool) + ring; 28208c2ecf20Sopenharmony_ci } 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_ci /* Don't allow indexes to exist outside of available space */ 28238c2ecf20Sopenharmony_ci if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) { 28248c2ecf20Sopenharmony_ci e_err(drv, "Location out of range\n"); 28258c2ecf20Sopenharmony_ci return -EINVAL; 28268c2ecf20Sopenharmony_ci } 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci input = kzalloc(sizeof(*input), GFP_ATOMIC); 28298c2ecf20Sopenharmony_ci if (!input) 28308c2ecf20Sopenharmony_ci return -ENOMEM; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci memset(&mask, 0, sizeof(union ixgbe_atr_input)); 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci /* set SW index */ 28358c2ecf20Sopenharmony_ci input->sw_idx = fsp->location; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci /* record flow type */ 28388c2ecf20Sopenharmony_ci if (!ixgbe_flowspec_to_flow_type(fsp, 28398c2ecf20Sopenharmony_ci &input->filter.formatted.flow_type)) { 28408c2ecf20Sopenharmony_ci e_err(drv, "Unrecognized flow type\n"); 28418c2ecf20Sopenharmony_ci goto err_out; 28428c2ecf20Sopenharmony_ci } 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK | 28458c2ecf20Sopenharmony_ci IXGBE_ATR_L4TYPE_MASK; 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4) 28488c2ecf20Sopenharmony_ci mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK; 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci /* Copy input into formatted structures */ 28518c2ecf20Sopenharmony_ci input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src; 28528c2ecf20Sopenharmony_ci mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src; 28538c2ecf20Sopenharmony_ci input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst; 28548c2ecf20Sopenharmony_ci mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst; 28558c2ecf20Sopenharmony_ci input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc; 28568c2ecf20Sopenharmony_ci mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc; 28578c2ecf20Sopenharmony_ci input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst; 28588c2ecf20Sopenharmony_ci mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst; 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci if (fsp->flow_type & FLOW_EXT) { 28618c2ecf20Sopenharmony_ci input->filter.formatted.vm_pool = 28628c2ecf20Sopenharmony_ci (unsigned char)ntohl(fsp->h_ext.data[1]); 28638c2ecf20Sopenharmony_ci mask.formatted.vm_pool = 28648c2ecf20Sopenharmony_ci (unsigned char)ntohl(fsp->m_ext.data[1]); 28658c2ecf20Sopenharmony_ci input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci; 28668c2ecf20Sopenharmony_ci mask.formatted.vlan_id = fsp->m_ext.vlan_tci; 28678c2ecf20Sopenharmony_ci input->filter.formatted.flex_bytes = 28688c2ecf20Sopenharmony_ci fsp->h_ext.vlan_etype; 28698c2ecf20Sopenharmony_ci mask.formatted.flex_bytes = fsp->m_ext.vlan_etype; 28708c2ecf20Sopenharmony_ci } 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci /* determine if we need to drop or route the packet */ 28738c2ecf20Sopenharmony_ci if (fsp->ring_cookie == RX_CLS_FLOW_DISC) 28748c2ecf20Sopenharmony_ci input->action = IXGBE_FDIR_DROP_QUEUE; 28758c2ecf20Sopenharmony_ci else 28768c2ecf20Sopenharmony_ci input->action = fsp->ring_cookie; 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_ci spin_lock(&adapter->fdir_perfect_lock); 28798c2ecf20Sopenharmony_ci 28808c2ecf20Sopenharmony_ci if (hlist_empty(&adapter->fdir_filter_list)) { 28818c2ecf20Sopenharmony_ci /* save mask and program input mask into HW */ 28828c2ecf20Sopenharmony_ci memcpy(&adapter->fdir_mask, &mask, sizeof(mask)); 28838c2ecf20Sopenharmony_ci err = ixgbe_fdir_set_input_mask_82599(hw, &mask); 28848c2ecf20Sopenharmony_ci if (err) { 28858c2ecf20Sopenharmony_ci e_err(drv, "Error writing mask\n"); 28868c2ecf20Sopenharmony_ci goto err_out_w_lock; 28878c2ecf20Sopenharmony_ci } 28888c2ecf20Sopenharmony_ci } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) { 28898c2ecf20Sopenharmony_ci e_err(drv, "Only one mask supported per port\n"); 28908c2ecf20Sopenharmony_ci goto err_out_w_lock; 28918c2ecf20Sopenharmony_ci } 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci /* apply mask and compute/store hash */ 28948c2ecf20Sopenharmony_ci ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask); 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_ci /* program filters to filter memory */ 28978c2ecf20Sopenharmony_ci err = ixgbe_fdir_write_perfect_filter_82599(hw, 28988c2ecf20Sopenharmony_ci &input->filter, input->sw_idx, queue); 28998c2ecf20Sopenharmony_ci if (err) 29008c2ecf20Sopenharmony_ci goto err_out_w_lock; 29018c2ecf20Sopenharmony_ci 29028c2ecf20Sopenharmony_ci ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci spin_unlock(&adapter->fdir_perfect_lock); 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_ci return err; 29078c2ecf20Sopenharmony_cierr_out_w_lock: 29088c2ecf20Sopenharmony_ci spin_unlock(&adapter->fdir_perfect_lock); 29098c2ecf20Sopenharmony_cierr_out: 29108c2ecf20Sopenharmony_ci kfree(input); 29118c2ecf20Sopenharmony_ci return -EINVAL; 29128c2ecf20Sopenharmony_ci} 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_cistatic int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter, 29158c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd) 29168c2ecf20Sopenharmony_ci{ 29178c2ecf20Sopenharmony_ci struct ethtool_rx_flow_spec *fsp = 29188c2ecf20Sopenharmony_ci (struct ethtool_rx_flow_spec *)&cmd->fs; 29198c2ecf20Sopenharmony_ci int err; 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci spin_lock(&adapter->fdir_perfect_lock); 29228c2ecf20Sopenharmony_ci err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location); 29238c2ecf20Sopenharmony_ci spin_unlock(&adapter->fdir_perfect_lock); 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci return err; 29268c2ecf20Sopenharmony_ci} 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_ci#define UDP_RSS_FLAGS (IXGBE_FLAG2_RSS_FIELD_IPV4_UDP | \ 29298c2ecf20Sopenharmony_ci IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) 29308c2ecf20Sopenharmony_cistatic int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter, 29318c2ecf20Sopenharmony_ci struct ethtool_rxnfc *nfc) 29328c2ecf20Sopenharmony_ci{ 29338c2ecf20Sopenharmony_ci u32 flags2 = adapter->flags2; 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci /* 29368c2ecf20Sopenharmony_ci * RSS does not support anything other than hashing 29378c2ecf20Sopenharmony_ci * to queues on src and dst IPs and ports 29388c2ecf20Sopenharmony_ci */ 29398c2ecf20Sopenharmony_ci if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | 29408c2ecf20Sopenharmony_ci RXH_L4_B_0_1 | RXH_L4_B_2_3)) 29418c2ecf20Sopenharmony_ci return -EINVAL; 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_ci switch (nfc->flow_type) { 29448c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 29458c2ecf20Sopenharmony_ci case TCP_V6_FLOW: 29468c2ecf20Sopenharmony_ci if (!(nfc->data & RXH_IP_SRC) || 29478c2ecf20Sopenharmony_ci !(nfc->data & RXH_IP_DST) || 29488c2ecf20Sopenharmony_ci !(nfc->data & RXH_L4_B_0_1) || 29498c2ecf20Sopenharmony_ci !(nfc->data & RXH_L4_B_2_3)) 29508c2ecf20Sopenharmony_ci return -EINVAL; 29518c2ecf20Sopenharmony_ci break; 29528c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 29538c2ecf20Sopenharmony_ci if (!(nfc->data & RXH_IP_SRC) || 29548c2ecf20Sopenharmony_ci !(nfc->data & RXH_IP_DST)) 29558c2ecf20Sopenharmony_ci return -EINVAL; 29568c2ecf20Sopenharmony_ci switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 29578c2ecf20Sopenharmony_ci case 0: 29588c2ecf20Sopenharmony_ci flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV4_UDP; 29598c2ecf20Sopenharmony_ci break; 29608c2ecf20Sopenharmony_ci case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 29618c2ecf20Sopenharmony_ci flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV4_UDP; 29628c2ecf20Sopenharmony_ci break; 29638c2ecf20Sopenharmony_ci default: 29648c2ecf20Sopenharmony_ci return -EINVAL; 29658c2ecf20Sopenharmony_ci } 29668c2ecf20Sopenharmony_ci break; 29678c2ecf20Sopenharmony_ci case UDP_V6_FLOW: 29688c2ecf20Sopenharmony_ci if (!(nfc->data & RXH_IP_SRC) || 29698c2ecf20Sopenharmony_ci !(nfc->data & RXH_IP_DST)) 29708c2ecf20Sopenharmony_ci return -EINVAL; 29718c2ecf20Sopenharmony_ci switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 29728c2ecf20Sopenharmony_ci case 0: 29738c2ecf20Sopenharmony_ci flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV6_UDP; 29748c2ecf20Sopenharmony_ci break; 29758c2ecf20Sopenharmony_ci case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 29768c2ecf20Sopenharmony_ci flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV6_UDP; 29778c2ecf20Sopenharmony_ci break; 29788c2ecf20Sopenharmony_ci default: 29798c2ecf20Sopenharmony_ci return -EINVAL; 29808c2ecf20Sopenharmony_ci } 29818c2ecf20Sopenharmony_ci break; 29828c2ecf20Sopenharmony_ci case AH_ESP_V4_FLOW: 29838c2ecf20Sopenharmony_ci case AH_V4_FLOW: 29848c2ecf20Sopenharmony_ci case ESP_V4_FLOW: 29858c2ecf20Sopenharmony_ci case SCTP_V4_FLOW: 29868c2ecf20Sopenharmony_ci case AH_ESP_V6_FLOW: 29878c2ecf20Sopenharmony_ci case AH_V6_FLOW: 29888c2ecf20Sopenharmony_ci case ESP_V6_FLOW: 29898c2ecf20Sopenharmony_ci case SCTP_V6_FLOW: 29908c2ecf20Sopenharmony_ci if (!(nfc->data & RXH_IP_SRC) || 29918c2ecf20Sopenharmony_ci !(nfc->data & RXH_IP_DST) || 29928c2ecf20Sopenharmony_ci (nfc->data & RXH_L4_B_0_1) || 29938c2ecf20Sopenharmony_ci (nfc->data & RXH_L4_B_2_3)) 29948c2ecf20Sopenharmony_ci return -EINVAL; 29958c2ecf20Sopenharmony_ci break; 29968c2ecf20Sopenharmony_ci default: 29978c2ecf20Sopenharmony_ci return -EINVAL; 29988c2ecf20Sopenharmony_ci } 29998c2ecf20Sopenharmony_ci 30008c2ecf20Sopenharmony_ci /* if we changed something we need to update flags */ 30018c2ecf20Sopenharmony_ci if (flags2 != adapter->flags2) { 30028c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 30038c2ecf20Sopenharmony_ci u32 mrqc; 30048c2ecf20Sopenharmony_ci unsigned int pf_pool = adapter->num_vfs; 30058c2ecf20Sopenharmony_ci 30068c2ecf20Sopenharmony_ci if ((hw->mac.type >= ixgbe_mac_X550) && 30078c2ecf20Sopenharmony_ci (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 30088c2ecf20Sopenharmony_ci mrqc = IXGBE_READ_REG(hw, IXGBE_PFVFMRQC(pf_pool)); 30098c2ecf20Sopenharmony_ci else 30108c2ecf20Sopenharmony_ci mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); 30118c2ecf20Sopenharmony_ci 30128c2ecf20Sopenharmony_ci if ((flags2 & UDP_RSS_FLAGS) && 30138c2ecf20Sopenharmony_ci !(adapter->flags2 & UDP_RSS_FLAGS)) 30148c2ecf20Sopenharmony_ci e_warn(drv, "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n"); 30158c2ecf20Sopenharmony_ci 30168c2ecf20Sopenharmony_ci adapter->flags2 = flags2; 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci /* Perform hash on these packet types */ 30198c2ecf20Sopenharmony_ci mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 30208c2ecf20Sopenharmony_ci | IXGBE_MRQC_RSS_FIELD_IPV4_TCP 30218c2ecf20Sopenharmony_ci | IXGBE_MRQC_RSS_FIELD_IPV6 30228c2ecf20Sopenharmony_ci | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci mrqc &= ~(IXGBE_MRQC_RSS_FIELD_IPV4_UDP | 30258c2ecf20Sopenharmony_ci IXGBE_MRQC_RSS_FIELD_IPV6_UDP); 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ci if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) 30288c2ecf20Sopenharmony_ci mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) 30318c2ecf20Sopenharmony_ci mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci if ((hw->mac.type >= ixgbe_mac_X550) && 30348c2ecf20Sopenharmony_ci (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 30358c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), mrqc); 30368c2ecf20Sopenharmony_ci else 30378c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 30388c2ecf20Sopenharmony_ci } 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_ci return 0; 30418c2ecf20Sopenharmony_ci} 30428c2ecf20Sopenharmony_ci 30438c2ecf20Sopenharmony_cistatic int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 30448c2ecf20Sopenharmony_ci{ 30458c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 30468c2ecf20Sopenharmony_ci int ret = -EOPNOTSUPP; 30478c2ecf20Sopenharmony_ci 30488c2ecf20Sopenharmony_ci switch (cmd->cmd) { 30498c2ecf20Sopenharmony_ci case ETHTOOL_SRXCLSRLINS: 30508c2ecf20Sopenharmony_ci ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd); 30518c2ecf20Sopenharmony_ci break; 30528c2ecf20Sopenharmony_ci case ETHTOOL_SRXCLSRLDEL: 30538c2ecf20Sopenharmony_ci ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd); 30548c2ecf20Sopenharmony_ci break; 30558c2ecf20Sopenharmony_ci case ETHTOOL_SRXFH: 30568c2ecf20Sopenharmony_ci ret = ixgbe_set_rss_hash_opt(adapter, cmd); 30578c2ecf20Sopenharmony_ci break; 30588c2ecf20Sopenharmony_ci default: 30598c2ecf20Sopenharmony_ci break; 30608c2ecf20Sopenharmony_ci } 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci return ret; 30638c2ecf20Sopenharmony_ci} 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_cistatic u32 ixgbe_get_rxfh_key_size(struct net_device *netdev) 30668c2ecf20Sopenharmony_ci{ 30678c2ecf20Sopenharmony_ci return IXGBE_RSS_KEY_SIZE; 30688c2ecf20Sopenharmony_ci} 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_cistatic u32 ixgbe_rss_indir_size(struct net_device *netdev) 30718c2ecf20Sopenharmony_ci{ 30728c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 30738c2ecf20Sopenharmony_ci 30748c2ecf20Sopenharmony_ci return ixgbe_rss_indir_tbl_entries(adapter); 30758c2ecf20Sopenharmony_ci} 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_cistatic void ixgbe_get_reta(struct ixgbe_adapter *adapter, u32 *indir) 30788c2ecf20Sopenharmony_ci{ 30798c2ecf20Sopenharmony_ci int i, reta_size = ixgbe_rss_indir_tbl_entries(adapter); 30808c2ecf20Sopenharmony_ci u16 rss_m = adapter->ring_feature[RING_F_RSS].mask; 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) 30838c2ecf20Sopenharmony_ci rss_m = adapter->ring_feature[RING_F_RSS].indices - 1; 30848c2ecf20Sopenharmony_ci 30858c2ecf20Sopenharmony_ci for (i = 0; i < reta_size; i++) 30868c2ecf20Sopenharmony_ci indir[i] = adapter->rss_indir_tbl[i] & rss_m; 30878c2ecf20Sopenharmony_ci} 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_cistatic int ixgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 30908c2ecf20Sopenharmony_ci u8 *hfunc) 30918c2ecf20Sopenharmony_ci{ 30928c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci if (hfunc) 30958c2ecf20Sopenharmony_ci *hfunc = ETH_RSS_HASH_TOP; 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci if (indir) 30988c2ecf20Sopenharmony_ci ixgbe_get_reta(adapter, indir); 30998c2ecf20Sopenharmony_ci 31008c2ecf20Sopenharmony_ci if (key) 31018c2ecf20Sopenharmony_ci memcpy(key, adapter->rss_key, ixgbe_get_rxfh_key_size(netdev)); 31028c2ecf20Sopenharmony_ci 31038c2ecf20Sopenharmony_ci return 0; 31048c2ecf20Sopenharmony_ci} 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_cistatic int ixgbe_set_rxfh(struct net_device *netdev, const u32 *indir, 31078c2ecf20Sopenharmony_ci const u8 *key, const u8 hfunc) 31088c2ecf20Sopenharmony_ci{ 31098c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 31108c2ecf20Sopenharmony_ci int i; 31118c2ecf20Sopenharmony_ci u32 reta_entries = ixgbe_rss_indir_tbl_entries(adapter); 31128c2ecf20Sopenharmony_ci 31138c2ecf20Sopenharmony_ci if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 31148c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 31158c2ecf20Sopenharmony_ci 31168c2ecf20Sopenharmony_ci /* Fill out the redirection table */ 31178c2ecf20Sopenharmony_ci if (indir) { 31188c2ecf20Sopenharmony_ci int max_queues = min_t(int, adapter->num_rx_queues, 31198c2ecf20Sopenharmony_ci ixgbe_rss_indir_tbl_max(adapter)); 31208c2ecf20Sopenharmony_ci 31218c2ecf20Sopenharmony_ci /*Allow at least 2 queues w/ SR-IOV.*/ 31228c2ecf20Sopenharmony_ci if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && 31238c2ecf20Sopenharmony_ci (max_queues < 2)) 31248c2ecf20Sopenharmony_ci max_queues = 2; 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_ci /* Verify user input. */ 31278c2ecf20Sopenharmony_ci for (i = 0; i < reta_entries; i++) 31288c2ecf20Sopenharmony_ci if (indir[i] >= max_queues) 31298c2ecf20Sopenharmony_ci return -EINVAL; 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci for (i = 0; i < reta_entries; i++) 31328c2ecf20Sopenharmony_ci adapter->rss_indir_tbl[i] = indir[i]; 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci ixgbe_store_reta(adapter); 31358c2ecf20Sopenharmony_ci } 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci /* Fill out the rss hash key */ 31388c2ecf20Sopenharmony_ci if (key) { 31398c2ecf20Sopenharmony_ci memcpy(adapter->rss_key, key, ixgbe_get_rxfh_key_size(netdev)); 31408c2ecf20Sopenharmony_ci ixgbe_store_key(adapter); 31418c2ecf20Sopenharmony_ci } 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci return 0; 31448c2ecf20Sopenharmony_ci} 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_cistatic int ixgbe_get_ts_info(struct net_device *dev, 31478c2ecf20Sopenharmony_ci struct ethtool_ts_info *info) 31488c2ecf20Sopenharmony_ci{ 31498c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci /* we always support timestamping disabled */ 31528c2ecf20Sopenharmony_ci info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci switch (adapter->hw.mac.type) { 31558c2ecf20Sopenharmony_ci case ixgbe_mac_X550: 31568c2ecf20Sopenharmony_ci case ixgbe_mac_X550EM_x: 31578c2ecf20Sopenharmony_ci case ixgbe_mac_x550em_a: 31588c2ecf20Sopenharmony_ci info->rx_filters |= BIT(HWTSTAMP_FILTER_ALL); 31598c2ecf20Sopenharmony_ci break; 31608c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 31618c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 31628c2ecf20Sopenharmony_ci info->rx_filters |= 31638c2ecf20Sopenharmony_ci BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | 31648c2ecf20Sopenharmony_ci BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | 31658c2ecf20Sopenharmony_ci BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); 31668c2ecf20Sopenharmony_ci break; 31678c2ecf20Sopenharmony_ci default: 31688c2ecf20Sopenharmony_ci return ethtool_op_get_ts_info(dev, info); 31698c2ecf20Sopenharmony_ci } 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_ci info->so_timestamping = 31728c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_TX_SOFTWARE | 31738c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_RX_SOFTWARE | 31748c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_SOFTWARE | 31758c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_TX_HARDWARE | 31768c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_RX_HARDWARE | 31778c2ecf20Sopenharmony_ci SOF_TIMESTAMPING_RAW_HARDWARE; 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci if (adapter->ptp_clock) 31808c2ecf20Sopenharmony_ci info->phc_index = ptp_clock_index(adapter->ptp_clock); 31818c2ecf20Sopenharmony_ci else 31828c2ecf20Sopenharmony_ci info->phc_index = -1; 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_ci info->tx_types = 31858c2ecf20Sopenharmony_ci BIT(HWTSTAMP_TX_OFF) | 31868c2ecf20Sopenharmony_ci BIT(HWTSTAMP_TX_ON); 31878c2ecf20Sopenharmony_ci 31888c2ecf20Sopenharmony_ci return 0; 31898c2ecf20Sopenharmony_ci} 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_cistatic unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter) 31928c2ecf20Sopenharmony_ci{ 31938c2ecf20Sopenharmony_ci unsigned int max_combined; 31948c2ecf20Sopenharmony_ci u8 tcs = adapter->hw_tcs; 31958c2ecf20Sopenharmony_ci 31968c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { 31978c2ecf20Sopenharmony_ci /* We only support one q_vector without MSI-X */ 31988c2ecf20Sopenharmony_ci max_combined = 1; 31998c2ecf20Sopenharmony_ci } else if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { 32008c2ecf20Sopenharmony_ci /* Limit value based on the queue mask */ 32018c2ecf20Sopenharmony_ci max_combined = adapter->ring_feature[RING_F_RSS].mask + 1; 32028c2ecf20Sopenharmony_ci } else if (tcs > 1) { 32038c2ecf20Sopenharmony_ci /* For DCB report channels per traffic class */ 32048c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 32058c2ecf20Sopenharmony_ci /* 8 TC w/ 4 queues per TC */ 32068c2ecf20Sopenharmony_ci max_combined = 4; 32078c2ecf20Sopenharmony_ci } else if (tcs > 4) { 32088c2ecf20Sopenharmony_ci /* 8 TC w/ 8 queues per TC */ 32098c2ecf20Sopenharmony_ci max_combined = 8; 32108c2ecf20Sopenharmony_ci } else { 32118c2ecf20Sopenharmony_ci /* 4 TC w/ 16 queues per TC */ 32128c2ecf20Sopenharmony_ci max_combined = 16; 32138c2ecf20Sopenharmony_ci } 32148c2ecf20Sopenharmony_ci } else if (adapter->atr_sample_rate) { 32158c2ecf20Sopenharmony_ci /* support up to 64 queues with ATR */ 32168c2ecf20Sopenharmony_ci max_combined = IXGBE_MAX_FDIR_INDICES; 32178c2ecf20Sopenharmony_ci } else { 32188c2ecf20Sopenharmony_ci /* support up to 16 queues with RSS */ 32198c2ecf20Sopenharmony_ci max_combined = ixgbe_max_rss_indices(adapter); 32208c2ecf20Sopenharmony_ci } 32218c2ecf20Sopenharmony_ci 32228c2ecf20Sopenharmony_ci return min_t(int, max_combined, num_online_cpus()); 32238c2ecf20Sopenharmony_ci} 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_cistatic void ixgbe_get_channels(struct net_device *dev, 32268c2ecf20Sopenharmony_ci struct ethtool_channels *ch) 32278c2ecf20Sopenharmony_ci{ 32288c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_ci /* report maximum channels */ 32318c2ecf20Sopenharmony_ci ch->max_combined = ixgbe_max_channels(adapter); 32328c2ecf20Sopenharmony_ci 32338c2ecf20Sopenharmony_ci /* report info for other vector */ 32348c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { 32358c2ecf20Sopenharmony_ci ch->max_other = NON_Q_VECTORS; 32368c2ecf20Sopenharmony_ci ch->other_count = NON_Q_VECTORS; 32378c2ecf20Sopenharmony_ci } 32388c2ecf20Sopenharmony_ci 32398c2ecf20Sopenharmony_ci /* record RSS queues */ 32408c2ecf20Sopenharmony_ci ch->combined_count = adapter->ring_feature[RING_F_RSS].indices; 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci /* nothing else to report if RSS is disabled */ 32438c2ecf20Sopenharmony_ci if (ch->combined_count == 1) 32448c2ecf20Sopenharmony_ci return; 32458c2ecf20Sopenharmony_ci 32468c2ecf20Sopenharmony_ci /* we do not support ATR queueing if SR-IOV is enabled */ 32478c2ecf20Sopenharmony_ci if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) 32488c2ecf20Sopenharmony_ci return; 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci /* same thing goes for being DCB enabled */ 32518c2ecf20Sopenharmony_ci if (adapter->hw_tcs > 1) 32528c2ecf20Sopenharmony_ci return; 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_ci /* if ATR is disabled we can exit */ 32558c2ecf20Sopenharmony_ci if (!adapter->atr_sample_rate) 32568c2ecf20Sopenharmony_ci return; 32578c2ecf20Sopenharmony_ci 32588c2ecf20Sopenharmony_ci /* report flow director queues as maximum channels */ 32598c2ecf20Sopenharmony_ci ch->combined_count = adapter->ring_feature[RING_F_FDIR].indices; 32608c2ecf20Sopenharmony_ci} 32618c2ecf20Sopenharmony_ci 32628c2ecf20Sopenharmony_cistatic int ixgbe_set_channels(struct net_device *dev, 32638c2ecf20Sopenharmony_ci struct ethtool_channels *ch) 32648c2ecf20Sopenharmony_ci{ 32658c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 32668c2ecf20Sopenharmony_ci unsigned int count = ch->combined_count; 32678c2ecf20Sopenharmony_ci u8 max_rss_indices = ixgbe_max_rss_indices(adapter); 32688c2ecf20Sopenharmony_ci 32698c2ecf20Sopenharmony_ci /* verify they are not requesting separate vectors */ 32708c2ecf20Sopenharmony_ci if (!count || ch->rx_count || ch->tx_count) 32718c2ecf20Sopenharmony_ci return -EINVAL; 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci /* verify other_count has not changed */ 32748c2ecf20Sopenharmony_ci if (ch->other_count != NON_Q_VECTORS) 32758c2ecf20Sopenharmony_ci return -EINVAL; 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci /* verify the number of channels does not exceed hardware limits */ 32788c2ecf20Sopenharmony_ci if (count > ixgbe_max_channels(adapter)) 32798c2ecf20Sopenharmony_ci return -EINVAL; 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci /* update feature limits from largest to smallest supported values */ 32828c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_FDIR].limit = count; 32838c2ecf20Sopenharmony_ci 32848c2ecf20Sopenharmony_ci /* cap RSS limit */ 32858c2ecf20Sopenharmony_ci if (count > max_rss_indices) 32868c2ecf20Sopenharmony_ci count = max_rss_indices; 32878c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].limit = count; 32888c2ecf20Sopenharmony_ci 32898c2ecf20Sopenharmony_ci#ifdef IXGBE_FCOE 32908c2ecf20Sopenharmony_ci /* cap FCoE limit at 8 */ 32918c2ecf20Sopenharmony_ci if (count > IXGBE_FCRETA_SIZE) 32928c2ecf20Sopenharmony_ci count = IXGBE_FCRETA_SIZE; 32938c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_FCOE].limit = count; 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci#endif 32968c2ecf20Sopenharmony_ci /* use setup TC to update any traffic class queue mapping */ 32978c2ecf20Sopenharmony_ci return ixgbe_setup_tc(dev, adapter->hw_tcs); 32988c2ecf20Sopenharmony_ci} 32998c2ecf20Sopenharmony_ci 33008c2ecf20Sopenharmony_cistatic int ixgbe_get_module_info(struct net_device *dev, 33018c2ecf20Sopenharmony_ci struct ethtool_modinfo *modinfo) 33028c2ecf20Sopenharmony_ci{ 33038c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 33048c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 33058c2ecf20Sopenharmony_ci s32 status; 33068c2ecf20Sopenharmony_ci u8 sff8472_rev, addr_mode; 33078c2ecf20Sopenharmony_ci bool page_swap = false; 33088c2ecf20Sopenharmony_ci 33098c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_fw) 33108c2ecf20Sopenharmony_ci return -ENXIO; 33118c2ecf20Sopenharmony_ci 33128c2ecf20Sopenharmony_ci /* Check whether we support SFF-8472 or not */ 33138c2ecf20Sopenharmony_ci status = hw->phy.ops.read_i2c_eeprom(hw, 33148c2ecf20Sopenharmony_ci IXGBE_SFF_SFF_8472_COMP, 33158c2ecf20Sopenharmony_ci &sff8472_rev); 33168c2ecf20Sopenharmony_ci if (status) 33178c2ecf20Sopenharmony_ci return -EIO; 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci /* addressing mode is not supported */ 33208c2ecf20Sopenharmony_ci status = hw->phy.ops.read_i2c_eeprom(hw, 33218c2ecf20Sopenharmony_ci IXGBE_SFF_SFF_8472_SWAP, 33228c2ecf20Sopenharmony_ci &addr_mode); 33238c2ecf20Sopenharmony_ci if (status) 33248c2ecf20Sopenharmony_ci return -EIO; 33258c2ecf20Sopenharmony_ci 33268c2ecf20Sopenharmony_ci if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) { 33278c2ecf20Sopenharmony_ci e_err(drv, "Address change required to access page 0xA2, but not supported. Please report the module type to the driver maintainers.\n"); 33288c2ecf20Sopenharmony_ci page_swap = true; 33298c2ecf20Sopenharmony_ci } 33308c2ecf20Sopenharmony_ci 33318c2ecf20Sopenharmony_ci if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap || 33328c2ecf20Sopenharmony_ci !(addr_mode & IXGBE_SFF_DDM_IMPLEMENTED)) { 33338c2ecf20Sopenharmony_ci /* We have a SFP, but it does not support SFF-8472 */ 33348c2ecf20Sopenharmony_ci modinfo->type = ETH_MODULE_SFF_8079; 33358c2ecf20Sopenharmony_ci modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; 33368c2ecf20Sopenharmony_ci } else { 33378c2ecf20Sopenharmony_ci /* We have a SFP which supports a revision of SFF-8472. */ 33388c2ecf20Sopenharmony_ci modinfo->type = ETH_MODULE_SFF_8472; 33398c2ecf20Sopenharmony_ci modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 33408c2ecf20Sopenharmony_ci } 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci return 0; 33438c2ecf20Sopenharmony_ci} 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_cistatic int ixgbe_get_module_eeprom(struct net_device *dev, 33468c2ecf20Sopenharmony_ci struct ethtool_eeprom *ee, 33478c2ecf20Sopenharmony_ci u8 *data) 33488c2ecf20Sopenharmony_ci{ 33498c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(dev); 33508c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 33518c2ecf20Sopenharmony_ci s32 status = -EFAULT; 33528c2ecf20Sopenharmony_ci u8 databyte = 0xFF; 33538c2ecf20Sopenharmony_ci int i = 0; 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_ci if (ee->len == 0) 33568c2ecf20Sopenharmony_ci return -EINVAL; 33578c2ecf20Sopenharmony_ci 33588c2ecf20Sopenharmony_ci if (hw->phy.type == ixgbe_phy_fw) 33598c2ecf20Sopenharmony_ci return -ENXIO; 33608c2ecf20Sopenharmony_ci 33618c2ecf20Sopenharmony_ci for (i = ee->offset; i < ee->offset + ee->len; i++) { 33628c2ecf20Sopenharmony_ci /* I2C reads can take long time */ 33638c2ecf20Sopenharmony_ci if (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) 33648c2ecf20Sopenharmony_ci return -EBUSY; 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci if (i < ETH_MODULE_SFF_8079_LEN) 33678c2ecf20Sopenharmony_ci status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte); 33688c2ecf20Sopenharmony_ci else 33698c2ecf20Sopenharmony_ci status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte); 33708c2ecf20Sopenharmony_ci 33718c2ecf20Sopenharmony_ci if (status) 33728c2ecf20Sopenharmony_ci return -EIO; 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci data[i - ee->offset] = databyte; 33758c2ecf20Sopenharmony_ci } 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci return 0; 33788c2ecf20Sopenharmony_ci} 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_cistatic const struct { 33818c2ecf20Sopenharmony_ci ixgbe_link_speed mac_speed; 33828c2ecf20Sopenharmony_ci u32 supported; 33838c2ecf20Sopenharmony_ci} ixgbe_ls_map[] = { 33848c2ecf20Sopenharmony_ci { IXGBE_LINK_SPEED_10_FULL, SUPPORTED_10baseT_Full }, 33858c2ecf20Sopenharmony_ci { IXGBE_LINK_SPEED_100_FULL, SUPPORTED_100baseT_Full }, 33868c2ecf20Sopenharmony_ci { IXGBE_LINK_SPEED_1GB_FULL, SUPPORTED_1000baseT_Full }, 33878c2ecf20Sopenharmony_ci { IXGBE_LINK_SPEED_2_5GB_FULL, SUPPORTED_2500baseX_Full }, 33888c2ecf20Sopenharmony_ci { IXGBE_LINK_SPEED_10GB_FULL, SUPPORTED_10000baseT_Full }, 33898c2ecf20Sopenharmony_ci}; 33908c2ecf20Sopenharmony_ci 33918c2ecf20Sopenharmony_cistatic const struct { 33928c2ecf20Sopenharmony_ci u32 lp_advertised; 33938c2ecf20Sopenharmony_ci u32 mac_speed; 33948c2ecf20Sopenharmony_ci} ixgbe_lp_map[] = { 33958c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_100M_TX_EEE, SUPPORTED_100baseT_Full }, 33968c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_1G_T_EEE, SUPPORTED_1000baseT_Full }, 33978c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_10G_T_EEE, SUPPORTED_10000baseT_Full }, 33988c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_1G_KX_EEE, SUPPORTED_1000baseKX_Full }, 33998c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_10G_KX4_EEE, SUPPORTED_10000baseKX4_Full }, 34008c2ecf20Sopenharmony_ci { FW_PHY_ACT_UD_2_10G_KR_EEE, SUPPORTED_10000baseKR_Full}, 34018c2ecf20Sopenharmony_ci}; 34028c2ecf20Sopenharmony_ci 34038c2ecf20Sopenharmony_cistatic int 34048c2ecf20Sopenharmony_ciixgbe_get_eee_fw(struct ixgbe_adapter *adapter, struct ethtool_eee *edata) 34058c2ecf20Sopenharmony_ci{ 34068c2ecf20Sopenharmony_ci u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; 34078c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 34088c2ecf20Sopenharmony_ci s32 rc; 34098c2ecf20Sopenharmony_ci u16 i; 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_UD_2, &info); 34128c2ecf20Sopenharmony_ci if (rc) 34138c2ecf20Sopenharmony_ci return rc; 34148c2ecf20Sopenharmony_ci 34158c2ecf20Sopenharmony_ci edata->lp_advertised = 0; 34168c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_lp_map); ++i) { 34178c2ecf20Sopenharmony_ci if (info[0] & ixgbe_lp_map[i].lp_advertised) 34188c2ecf20Sopenharmony_ci edata->lp_advertised |= ixgbe_lp_map[i].mac_speed; 34198c2ecf20Sopenharmony_ci } 34208c2ecf20Sopenharmony_ci 34218c2ecf20Sopenharmony_ci edata->supported = 0; 34228c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) { 34238c2ecf20Sopenharmony_ci if (hw->phy.eee_speeds_supported & ixgbe_ls_map[i].mac_speed) 34248c2ecf20Sopenharmony_ci edata->supported |= ixgbe_ls_map[i].supported; 34258c2ecf20Sopenharmony_ci } 34268c2ecf20Sopenharmony_ci 34278c2ecf20Sopenharmony_ci edata->advertised = 0; 34288c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) { 34298c2ecf20Sopenharmony_ci if (hw->phy.eee_speeds_advertised & ixgbe_ls_map[i].mac_speed) 34308c2ecf20Sopenharmony_ci edata->advertised |= ixgbe_ls_map[i].supported; 34318c2ecf20Sopenharmony_ci } 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci edata->eee_enabled = !!edata->advertised; 34348c2ecf20Sopenharmony_ci edata->tx_lpi_enabled = edata->eee_enabled; 34358c2ecf20Sopenharmony_ci if (edata->advertised & edata->lp_advertised) 34368c2ecf20Sopenharmony_ci edata->eee_active = true; 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci return 0; 34398c2ecf20Sopenharmony_ci} 34408c2ecf20Sopenharmony_ci 34418c2ecf20Sopenharmony_cistatic int ixgbe_get_eee(struct net_device *netdev, struct ethtool_eee *edata) 34428c2ecf20Sopenharmony_ci{ 34438c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 34448c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE)) 34478c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci if (hw->phy.eee_speeds_supported && hw->phy.type == ixgbe_phy_fw) 34508c2ecf20Sopenharmony_ci return ixgbe_get_eee_fw(adapter, edata); 34518c2ecf20Sopenharmony_ci 34528c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 34538c2ecf20Sopenharmony_ci} 34548c2ecf20Sopenharmony_ci 34558c2ecf20Sopenharmony_cistatic int ixgbe_set_eee(struct net_device *netdev, struct ethtool_eee *edata) 34568c2ecf20Sopenharmony_ci{ 34578c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 34588c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 34598c2ecf20Sopenharmony_ci struct ethtool_eee eee_data; 34608c2ecf20Sopenharmony_ci s32 ret_val; 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE)) 34638c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 34648c2ecf20Sopenharmony_ci 34658c2ecf20Sopenharmony_ci memset(&eee_data, 0, sizeof(struct ethtool_eee)); 34668c2ecf20Sopenharmony_ci 34678c2ecf20Sopenharmony_ci ret_val = ixgbe_get_eee(netdev, &eee_data); 34688c2ecf20Sopenharmony_ci if (ret_val) 34698c2ecf20Sopenharmony_ci return ret_val; 34708c2ecf20Sopenharmony_ci 34718c2ecf20Sopenharmony_ci if (eee_data.eee_enabled && !edata->eee_enabled) { 34728c2ecf20Sopenharmony_ci if (eee_data.tx_lpi_enabled != edata->tx_lpi_enabled) { 34738c2ecf20Sopenharmony_ci e_err(drv, "Setting EEE tx-lpi is not supported\n"); 34748c2ecf20Sopenharmony_ci return -EINVAL; 34758c2ecf20Sopenharmony_ci } 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci if (eee_data.tx_lpi_timer != edata->tx_lpi_timer) { 34788c2ecf20Sopenharmony_ci e_err(drv, 34798c2ecf20Sopenharmony_ci "Setting EEE Tx LPI timer is not supported\n"); 34808c2ecf20Sopenharmony_ci return -EINVAL; 34818c2ecf20Sopenharmony_ci } 34828c2ecf20Sopenharmony_ci 34838c2ecf20Sopenharmony_ci if (eee_data.advertised != edata->advertised) { 34848c2ecf20Sopenharmony_ci e_err(drv, 34858c2ecf20Sopenharmony_ci "Setting EEE advertised speeds is not supported\n"); 34868c2ecf20Sopenharmony_ci return -EINVAL; 34878c2ecf20Sopenharmony_ci } 34888c2ecf20Sopenharmony_ci } 34898c2ecf20Sopenharmony_ci 34908c2ecf20Sopenharmony_ci if (eee_data.eee_enabled != edata->eee_enabled) { 34918c2ecf20Sopenharmony_ci if (edata->eee_enabled) { 34928c2ecf20Sopenharmony_ci adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; 34938c2ecf20Sopenharmony_ci hw->phy.eee_speeds_advertised = 34948c2ecf20Sopenharmony_ci hw->phy.eee_speeds_supported; 34958c2ecf20Sopenharmony_ci } else { 34968c2ecf20Sopenharmony_ci adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED; 34978c2ecf20Sopenharmony_ci hw->phy.eee_speeds_advertised = 0; 34988c2ecf20Sopenharmony_ci } 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci /* reset link */ 35018c2ecf20Sopenharmony_ci if (netif_running(netdev)) 35028c2ecf20Sopenharmony_ci ixgbe_reinit_locked(adapter); 35038c2ecf20Sopenharmony_ci else 35048c2ecf20Sopenharmony_ci ixgbe_reset(adapter); 35058c2ecf20Sopenharmony_ci } 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci return 0; 35088c2ecf20Sopenharmony_ci} 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_cistatic u32 ixgbe_get_priv_flags(struct net_device *netdev) 35118c2ecf20Sopenharmony_ci{ 35128c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 35138c2ecf20Sopenharmony_ci u32 priv_flags = 0; 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci if (adapter->flags2 & IXGBE_FLAG2_RX_LEGACY) 35168c2ecf20Sopenharmony_ci priv_flags |= IXGBE_PRIV_FLAGS_LEGACY_RX; 35178c2ecf20Sopenharmony_ci 35188c2ecf20Sopenharmony_ci if (adapter->flags2 & IXGBE_FLAG2_VF_IPSEC_ENABLED) 35198c2ecf20Sopenharmony_ci priv_flags |= IXGBE_PRIV_FLAGS_VF_IPSEC_EN; 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci if (adapter->flags2 & IXGBE_FLAG2_AUTO_DISABLE_VF) 35228c2ecf20Sopenharmony_ci priv_flags |= IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF; 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci return priv_flags; 35258c2ecf20Sopenharmony_ci} 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_cistatic int ixgbe_set_priv_flags(struct net_device *netdev, u32 priv_flags) 35288c2ecf20Sopenharmony_ci{ 35298c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 35308c2ecf20Sopenharmony_ci unsigned int flags2 = adapter->flags2; 35318c2ecf20Sopenharmony_ci unsigned int i; 35328c2ecf20Sopenharmony_ci 35338c2ecf20Sopenharmony_ci flags2 &= ~IXGBE_FLAG2_RX_LEGACY; 35348c2ecf20Sopenharmony_ci if (priv_flags & IXGBE_PRIV_FLAGS_LEGACY_RX) 35358c2ecf20Sopenharmony_ci flags2 |= IXGBE_FLAG2_RX_LEGACY; 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci flags2 &= ~IXGBE_FLAG2_VF_IPSEC_ENABLED; 35388c2ecf20Sopenharmony_ci if (priv_flags & IXGBE_PRIV_FLAGS_VF_IPSEC_EN) 35398c2ecf20Sopenharmony_ci flags2 |= IXGBE_FLAG2_VF_IPSEC_ENABLED; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci flags2 &= ~IXGBE_FLAG2_AUTO_DISABLE_VF; 35428c2ecf20Sopenharmony_ci if (priv_flags & IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF) { 35438c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82599EB) { 35448c2ecf20Sopenharmony_ci /* Reset primary abort counter */ 35458c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_vfs; i++) 35468c2ecf20Sopenharmony_ci adapter->vfinfo[i].primary_abort_count = 0; 35478c2ecf20Sopenharmony_ci 35488c2ecf20Sopenharmony_ci flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF; 35498c2ecf20Sopenharmony_ci } else { 35508c2ecf20Sopenharmony_ci e_info(probe, 35518c2ecf20Sopenharmony_ci "Cannot set private flags: Operation not supported\n"); 35528c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 35538c2ecf20Sopenharmony_ci } 35548c2ecf20Sopenharmony_ci } 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci if (flags2 != adapter->flags2) { 35578c2ecf20Sopenharmony_ci adapter->flags2 = flags2; 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ci /* reset interface to repopulate queues */ 35608c2ecf20Sopenharmony_ci if (netif_running(netdev)) 35618c2ecf20Sopenharmony_ci ixgbe_reinit_locked(adapter); 35628c2ecf20Sopenharmony_ci } 35638c2ecf20Sopenharmony_ci 35648c2ecf20Sopenharmony_ci return 0; 35658c2ecf20Sopenharmony_ci} 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_cistatic const struct ethtool_ops ixgbe_ethtool_ops = { 35688c2ecf20Sopenharmony_ci .supported_coalesce_params = ETHTOOL_COALESCE_USECS, 35698c2ecf20Sopenharmony_ci .get_drvinfo = ixgbe_get_drvinfo, 35708c2ecf20Sopenharmony_ci .get_regs_len = ixgbe_get_regs_len, 35718c2ecf20Sopenharmony_ci .get_regs = ixgbe_get_regs, 35728c2ecf20Sopenharmony_ci .get_wol = ixgbe_get_wol, 35738c2ecf20Sopenharmony_ci .set_wol = ixgbe_set_wol, 35748c2ecf20Sopenharmony_ci .nway_reset = ixgbe_nway_reset, 35758c2ecf20Sopenharmony_ci .get_link = ethtool_op_get_link, 35768c2ecf20Sopenharmony_ci .get_eeprom_len = ixgbe_get_eeprom_len, 35778c2ecf20Sopenharmony_ci .get_eeprom = ixgbe_get_eeprom, 35788c2ecf20Sopenharmony_ci .set_eeprom = ixgbe_set_eeprom, 35798c2ecf20Sopenharmony_ci .get_ringparam = ixgbe_get_ringparam, 35808c2ecf20Sopenharmony_ci .set_ringparam = ixgbe_set_ringparam, 35818c2ecf20Sopenharmony_ci .get_pause_stats = ixgbe_get_pause_stats, 35828c2ecf20Sopenharmony_ci .get_pauseparam = ixgbe_get_pauseparam, 35838c2ecf20Sopenharmony_ci .set_pauseparam = ixgbe_set_pauseparam, 35848c2ecf20Sopenharmony_ci .get_msglevel = ixgbe_get_msglevel, 35858c2ecf20Sopenharmony_ci .set_msglevel = ixgbe_set_msglevel, 35868c2ecf20Sopenharmony_ci .self_test = ixgbe_diag_test, 35878c2ecf20Sopenharmony_ci .get_strings = ixgbe_get_strings, 35888c2ecf20Sopenharmony_ci .set_phys_id = ixgbe_set_phys_id, 35898c2ecf20Sopenharmony_ci .get_sset_count = ixgbe_get_sset_count, 35908c2ecf20Sopenharmony_ci .get_ethtool_stats = ixgbe_get_ethtool_stats, 35918c2ecf20Sopenharmony_ci .get_coalesce = ixgbe_get_coalesce, 35928c2ecf20Sopenharmony_ci .set_coalesce = ixgbe_set_coalesce, 35938c2ecf20Sopenharmony_ci .get_rxnfc = ixgbe_get_rxnfc, 35948c2ecf20Sopenharmony_ci .set_rxnfc = ixgbe_set_rxnfc, 35958c2ecf20Sopenharmony_ci .get_rxfh_indir_size = ixgbe_rss_indir_size, 35968c2ecf20Sopenharmony_ci .get_rxfh_key_size = ixgbe_get_rxfh_key_size, 35978c2ecf20Sopenharmony_ci .get_rxfh = ixgbe_get_rxfh, 35988c2ecf20Sopenharmony_ci .set_rxfh = ixgbe_set_rxfh, 35998c2ecf20Sopenharmony_ci .get_eee = ixgbe_get_eee, 36008c2ecf20Sopenharmony_ci .set_eee = ixgbe_set_eee, 36018c2ecf20Sopenharmony_ci .get_channels = ixgbe_get_channels, 36028c2ecf20Sopenharmony_ci .set_channels = ixgbe_set_channels, 36038c2ecf20Sopenharmony_ci .get_priv_flags = ixgbe_get_priv_flags, 36048c2ecf20Sopenharmony_ci .set_priv_flags = ixgbe_set_priv_flags, 36058c2ecf20Sopenharmony_ci .get_ts_info = ixgbe_get_ts_info, 36068c2ecf20Sopenharmony_ci .get_module_info = ixgbe_get_module_info, 36078c2ecf20Sopenharmony_ci .get_module_eeprom = ixgbe_get_module_eeprom, 36088c2ecf20Sopenharmony_ci .get_link_ksettings = ixgbe_get_link_ksettings, 36098c2ecf20Sopenharmony_ci .set_link_ksettings = ixgbe_set_link_ksettings, 36108c2ecf20Sopenharmony_ci}; 36118c2ecf20Sopenharmony_ci 36128c2ecf20Sopenharmony_civoid ixgbe_set_ethtool_ops(struct net_device *netdev) 36138c2ecf20Sopenharmony_ci{ 36148c2ecf20Sopenharmony_ci netdev->ethtool_ops = &ixgbe_ethtool_ops; 36158c2ecf20Sopenharmony_ci} 3616