forked from Minki/linux
c7d759eb7b
Add an interface to report offloaded UDP ports via ethtool netlink. Now that core takes care of tracking which UDP tunnel ports the NICs are aware of we can quite easily export this information out to user space. The responsibility of writing the netlink dumps is split between ethtool code and udp_tunnel_nic.c - since udp_tunnel module may not always be loaded, yet we should always report the capabilities of the NIC. $ ethtool --show-tunnels eth0 Tunnel information for eth0: UDP port table 0: Size: 4 Types: vxlan No entries UDP port table 1: Size: 4 Types: geneve, vxlan-gpe Entries (1): port 1230, vxlan-gpe v4: - back to v2, build fix is now directly in udp_tunnel.h v3: - don't compile ETHTOOL_MSG_TUNNEL_INFO_GET in if CONFIG_INET not set. v2: - fix string set count, - reorder enums in the uAPI, - fix type of ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES to bitset in docs and comments. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
411 lines
15 KiB
C
411 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
#include <linux/ethtool_netlink.h>
|
|
#include <linux/net_tstamp.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/rtnetlink.h>
|
|
|
|
#include "common.h"
|
|
|
|
const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
|
|
[NETIF_F_SG_BIT] = "tx-scatter-gather",
|
|
[NETIF_F_IP_CSUM_BIT] = "tx-checksum-ipv4",
|
|
[NETIF_F_HW_CSUM_BIT] = "tx-checksum-ip-generic",
|
|
[NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6",
|
|
[NETIF_F_HIGHDMA_BIT] = "highdma",
|
|
[NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist",
|
|
[NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert",
|
|
|
|
[NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse",
|
|
[NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter",
|
|
[NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert",
|
|
[NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse",
|
|
[NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter",
|
|
[NETIF_F_VLAN_CHALLENGED_BIT] = "vlan-challenged",
|
|
[NETIF_F_GSO_BIT] = "tx-generic-segmentation",
|
|
[NETIF_F_LLTX_BIT] = "tx-lockless",
|
|
[NETIF_F_NETNS_LOCAL_BIT] = "netns-local",
|
|
[NETIF_F_GRO_BIT] = "rx-gro",
|
|
[NETIF_F_GRO_HW_BIT] = "rx-gro-hw",
|
|
[NETIF_F_LRO_BIT] = "rx-lro",
|
|
|
|
[NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
|
|
[NETIF_F_GSO_ROBUST_BIT] = "tx-gso-robust",
|
|
[NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation",
|
|
[NETIF_F_TSO_MANGLEID_BIT] = "tx-tcp-mangleid-segmentation",
|
|
[NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation",
|
|
[NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
|
|
[NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
|
|
[NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
|
|
[NETIF_F_GSO_IPXIP4_BIT] = "tx-ipxip4-segmentation",
|
|
[NETIF_F_GSO_IPXIP6_BIT] = "tx-ipxip6-segmentation",
|
|
[NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
|
|
[NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
|
|
[NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
|
|
[NETIF_F_GSO_TUNNEL_REMCSUM_BIT] = "tx-tunnel-remcsum-segmentation",
|
|
[NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation",
|
|
[NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation",
|
|
[NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation",
|
|
[NETIF_F_GSO_FRAGLIST_BIT] = "tx-gso-list",
|
|
|
|
[NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
|
|
[NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
|
|
[NETIF_F_FCOE_MTU_BIT] = "fcoe-mtu",
|
|
[NETIF_F_NTUPLE_BIT] = "rx-ntuple-filter",
|
|
[NETIF_F_RXHASH_BIT] = "rx-hashing",
|
|
[NETIF_F_RXCSUM_BIT] = "rx-checksum",
|
|
[NETIF_F_NOCACHE_COPY_BIT] = "tx-nocache-copy",
|
|
[NETIF_F_LOOPBACK_BIT] = "loopback",
|
|
[NETIF_F_RXFCS_BIT] = "rx-fcs",
|
|
[NETIF_F_RXALL_BIT] = "rx-all",
|
|
[NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload",
|
|
[NETIF_F_HW_TC_BIT] = "hw-tc-offload",
|
|
[NETIF_F_HW_ESP_BIT] = "esp-hw-offload",
|
|
[NETIF_F_HW_ESP_TX_CSUM_BIT] = "esp-tx-csum-hw-offload",
|
|
[NETIF_F_RX_UDP_TUNNEL_PORT_BIT] = "rx-udp_tunnel-port-offload",
|
|
[NETIF_F_HW_TLS_RECORD_BIT] = "tls-hw-record",
|
|
[NETIF_F_HW_TLS_TX_BIT] = "tls-hw-tx-offload",
|
|
[NETIF_F_HW_TLS_RX_BIT] = "tls-hw-rx-offload",
|
|
[NETIF_F_GRO_FRAGLIST_BIT] = "rx-gro-list",
|
|
[NETIF_F_HW_MACSEC_BIT] = "macsec-hw-offload",
|
|
};
|
|
|
|
const char
|
|
rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
|
|
[ETH_RSS_HASH_TOP_BIT] = "toeplitz",
|
|
[ETH_RSS_HASH_XOR_BIT] = "xor",
|
|
[ETH_RSS_HASH_CRC32_BIT] = "crc32",
|
|
};
|
|
|
|
const char
|
|
tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
|
|
[ETHTOOL_ID_UNSPEC] = "Unspec",
|
|
[ETHTOOL_RX_COPYBREAK] = "rx-copybreak",
|
|
[ETHTOOL_TX_COPYBREAK] = "tx-copybreak",
|
|
[ETHTOOL_PFC_PREVENTION_TOUT] = "pfc-prevention-tout",
|
|
};
|
|
|
|
const char
|
|
phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
|
|
[ETHTOOL_ID_UNSPEC] = "Unspec",
|
|
[ETHTOOL_PHY_DOWNSHIFT] = "phy-downshift",
|
|
[ETHTOOL_PHY_FAST_LINK_DOWN] = "phy-fast-link-down",
|
|
[ETHTOOL_PHY_EDPD] = "phy-energy-detect-power-down",
|
|
};
|
|
|
|
#define __LINK_MODE_NAME(speed, type, duplex) \
|
|
#speed "base" #type "/" #duplex
|
|
#define __DEFINE_LINK_MODE_NAME(speed, type, duplex) \
|
|
[ETHTOOL_LINK_MODE(speed, type, duplex)] = \
|
|
__LINK_MODE_NAME(speed, type, duplex)
|
|
#define __DEFINE_SPECIAL_MODE_NAME(_mode, _name) \
|
|
[ETHTOOL_LINK_MODE_ ## _mode ## _BIT] = _name
|
|
|
|
const char link_mode_names[][ETH_GSTRING_LEN] = {
|
|
__DEFINE_LINK_MODE_NAME(10, T, Half),
|
|
__DEFINE_LINK_MODE_NAME(10, T, Full),
|
|
__DEFINE_LINK_MODE_NAME(100, T, Half),
|
|
__DEFINE_LINK_MODE_NAME(100, T, Full),
|
|
__DEFINE_LINK_MODE_NAME(1000, T, Half),
|
|
__DEFINE_LINK_MODE_NAME(1000, T, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(Autoneg, "Autoneg"),
|
|
__DEFINE_SPECIAL_MODE_NAME(TP, "TP"),
|
|
__DEFINE_SPECIAL_MODE_NAME(AUI, "AUI"),
|
|
__DEFINE_SPECIAL_MODE_NAME(MII, "MII"),
|
|
__DEFINE_SPECIAL_MODE_NAME(FIBRE, "FIBRE"),
|
|
__DEFINE_SPECIAL_MODE_NAME(BNC, "BNC"),
|
|
__DEFINE_LINK_MODE_NAME(10000, T, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(Pause, "Pause"),
|
|
__DEFINE_SPECIAL_MODE_NAME(Asym_Pause, "Asym_Pause"),
|
|
__DEFINE_LINK_MODE_NAME(2500, X, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(Backplane, "Backplane"),
|
|
__DEFINE_LINK_MODE_NAME(1000, KX, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, KX4, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, KR, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(10000baseR_FEC, "10000baseR_FEC"),
|
|
__DEFINE_LINK_MODE_NAME(20000, MLD2, Full),
|
|
__DEFINE_LINK_MODE_NAME(20000, KR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(40000, KR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(40000, CR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(40000, SR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(40000, LR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(56000, KR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(56000, CR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(56000, SR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(56000, LR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(25000, CR, Full),
|
|
__DEFINE_LINK_MODE_NAME(25000, KR, Full),
|
|
__DEFINE_LINK_MODE_NAME(25000, SR, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, CR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, KR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, KR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, SR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, CR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, LR4_ER4, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, SR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(1000, X, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, CR, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, SR, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, LR, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, LRM, Full),
|
|
__DEFINE_LINK_MODE_NAME(10000, ER, Full),
|
|
__DEFINE_LINK_MODE_NAME(2500, T, Full),
|
|
__DEFINE_LINK_MODE_NAME(5000, T, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(FEC_NONE, "None"),
|
|
__DEFINE_SPECIAL_MODE_NAME(FEC_RS, "RS"),
|
|
__DEFINE_SPECIAL_MODE_NAME(FEC_BASER, "BASER"),
|
|
__DEFINE_LINK_MODE_NAME(50000, KR, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, SR, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, CR, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, LR_ER_FR, Full),
|
|
__DEFINE_LINK_MODE_NAME(50000, DR, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, KR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, SR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, CR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, LR2_ER2_FR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, DR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, KR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, SR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, LR4_ER4_FR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, DR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, CR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(100, T1, Full),
|
|
__DEFINE_LINK_MODE_NAME(1000, T1, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, KR8, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, SR8, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, LR8_ER8_FR8, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, DR8, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, CR8, Full),
|
|
__DEFINE_SPECIAL_MODE_NAME(FEC_LLRS, "LLRS"),
|
|
__DEFINE_LINK_MODE_NAME(100000, KR, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, SR, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, LR_ER_FR, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, DR, Full),
|
|
__DEFINE_LINK_MODE_NAME(100000, CR, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, KR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, SR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, LR2_ER2_FR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, DR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(200000, CR2, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, KR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, SR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, LR4_ER4_FR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, DR4, Full),
|
|
__DEFINE_LINK_MODE_NAME(400000, CR4, Full),
|
|
};
|
|
static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
|
|
|
|
const char netif_msg_class_names[][ETH_GSTRING_LEN] = {
|
|
[NETIF_MSG_DRV_BIT] = "drv",
|
|
[NETIF_MSG_PROBE_BIT] = "probe",
|
|
[NETIF_MSG_LINK_BIT] = "link",
|
|
[NETIF_MSG_TIMER_BIT] = "timer",
|
|
[NETIF_MSG_IFDOWN_BIT] = "ifdown",
|
|
[NETIF_MSG_IFUP_BIT] = "ifup",
|
|
[NETIF_MSG_RX_ERR_BIT] = "rx_err",
|
|
[NETIF_MSG_TX_ERR_BIT] = "tx_err",
|
|
[NETIF_MSG_TX_QUEUED_BIT] = "tx_queued",
|
|
[NETIF_MSG_INTR_BIT] = "intr",
|
|
[NETIF_MSG_TX_DONE_BIT] = "tx_done",
|
|
[NETIF_MSG_RX_STATUS_BIT] = "rx_status",
|
|
[NETIF_MSG_PKTDATA_BIT] = "pktdata",
|
|
[NETIF_MSG_HW_BIT] = "hw",
|
|
[NETIF_MSG_WOL_BIT] = "wol",
|
|
};
|
|
static_assert(ARRAY_SIZE(netif_msg_class_names) == NETIF_MSG_CLASS_COUNT);
|
|
|
|
const char wol_mode_names[][ETH_GSTRING_LEN] = {
|
|
[const_ilog2(WAKE_PHY)] = "phy",
|
|
[const_ilog2(WAKE_UCAST)] = "ucast",
|
|
[const_ilog2(WAKE_MCAST)] = "mcast",
|
|
[const_ilog2(WAKE_BCAST)] = "bcast",
|
|
[const_ilog2(WAKE_ARP)] = "arp",
|
|
[const_ilog2(WAKE_MAGIC)] = "magic",
|
|
[const_ilog2(WAKE_MAGICSECURE)] = "magicsecure",
|
|
[const_ilog2(WAKE_FILTER)] = "filter",
|
|
};
|
|
static_assert(ARRAY_SIZE(wol_mode_names) == WOL_MODE_COUNT);
|
|
|
|
const char sof_timestamping_names[][ETH_GSTRING_LEN] = {
|
|
[const_ilog2(SOF_TIMESTAMPING_TX_HARDWARE)] = "hardware-transmit",
|
|
[const_ilog2(SOF_TIMESTAMPING_TX_SOFTWARE)] = "software-transmit",
|
|
[const_ilog2(SOF_TIMESTAMPING_RX_HARDWARE)] = "hardware-receive",
|
|
[const_ilog2(SOF_TIMESTAMPING_RX_SOFTWARE)] = "software-receive",
|
|
[const_ilog2(SOF_TIMESTAMPING_SOFTWARE)] = "software-system-clock",
|
|
[const_ilog2(SOF_TIMESTAMPING_SYS_HARDWARE)] = "hardware-legacy-clock",
|
|
[const_ilog2(SOF_TIMESTAMPING_RAW_HARDWARE)] = "hardware-raw-clock",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_ID)] = "option-id",
|
|
[const_ilog2(SOF_TIMESTAMPING_TX_SCHED)] = "sched-transmit",
|
|
[const_ilog2(SOF_TIMESTAMPING_TX_ACK)] = "ack-transmit",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_CMSG)] = "option-cmsg",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_TSONLY)] = "option-tsonly",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_STATS)] = "option-stats",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_PKTINFO)] = "option-pktinfo",
|
|
[const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw",
|
|
};
|
|
static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);
|
|
|
|
const char ts_tx_type_names[][ETH_GSTRING_LEN] = {
|
|
[HWTSTAMP_TX_OFF] = "off",
|
|
[HWTSTAMP_TX_ON] = "on",
|
|
[HWTSTAMP_TX_ONESTEP_SYNC] = "onestep-sync",
|
|
[HWTSTAMP_TX_ONESTEP_P2P] = "onestep-p2p",
|
|
};
|
|
static_assert(ARRAY_SIZE(ts_tx_type_names) == __HWTSTAMP_TX_CNT);
|
|
|
|
const char ts_rx_filter_names[][ETH_GSTRING_LEN] = {
|
|
[HWTSTAMP_FILTER_NONE] = "none",
|
|
[HWTSTAMP_FILTER_ALL] = "all",
|
|
[HWTSTAMP_FILTER_SOME] = "some",
|
|
[HWTSTAMP_FILTER_PTP_V1_L4_EVENT] = "ptpv1-l4-event",
|
|
[HWTSTAMP_FILTER_PTP_V1_L4_SYNC] = "ptpv1-l4-sync",
|
|
[HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ] = "ptpv1-l4-delay-req",
|
|
[HWTSTAMP_FILTER_PTP_V2_L4_EVENT] = "ptpv2-l4-event",
|
|
[HWTSTAMP_FILTER_PTP_V2_L4_SYNC] = "ptpv2-l4-sync",
|
|
[HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ] = "ptpv2-l4-delay-req",
|
|
[HWTSTAMP_FILTER_PTP_V2_L2_EVENT] = "ptpv2-l2-event",
|
|
[HWTSTAMP_FILTER_PTP_V2_L2_SYNC] = "ptpv2-l2-sync",
|
|
[HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ] = "ptpv2-l2-delay-req",
|
|
[HWTSTAMP_FILTER_PTP_V2_EVENT] = "ptpv2-event",
|
|
[HWTSTAMP_FILTER_PTP_V2_SYNC] = "ptpv2-sync",
|
|
[HWTSTAMP_FILTER_PTP_V2_DELAY_REQ] = "ptpv2-delay-req",
|
|
[HWTSTAMP_FILTER_NTP_ALL] = "ntp-all",
|
|
};
|
|
static_assert(ARRAY_SIZE(ts_rx_filter_names) == __HWTSTAMP_FILTER_CNT);
|
|
|
|
const char udp_tunnel_type_names[][ETH_GSTRING_LEN] = {
|
|
[ETHTOOL_UDP_TUNNEL_TYPE_VXLAN] = "vxlan",
|
|
[ETHTOOL_UDP_TUNNEL_TYPE_GENEVE] = "geneve",
|
|
[ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE] = "vxlan-gpe",
|
|
};
|
|
static_assert(ARRAY_SIZE(udp_tunnel_type_names) ==
|
|
__ETHTOOL_UDP_TUNNEL_TYPE_CNT);
|
|
|
|
/* return false if legacy contained non-0 deprecated fields
|
|
* maxtxpkt/maxrxpkt. rest of ksettings always updated
|
|
*/
|
|
bool
|
|
convert_legacy_settings_to_link_ksettings(
|
|
struct ethtool_link_ksettings *link_ksettings,
|
|
const struct ethtool_cmd *legacy_settings)
|
|
{
|
|
bool retval = true;
|
|
|
|
memset(link_ksettings, 0, sizeof(*link_ksettings));
|
|
|
|
/* This is used to tell users that driver is still using these
|
|
* deprecated legacy fields, and they should not use
|
|
* %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS
|
|
*/
|
|
if (legacy_settings->maxtxpkt ||
|
|
legacy_settings->maxrxpkt)
|
|
retval = false;
|
|
|
|
ethtool_convert_legacy_u32_to_link_mode(
|
|
link_ksettings->link_modes.supported,
|
|
legacy_settings->supported);
|
|
ethtool_convert_legacy_u32_to_link_mode(
|
|
link_ksettings->link_modes.advertising,
|
|
legacy_settings->advertising);
|
|
ethtool_convert_legacy_u32_to_link_mode(
|
|
link_ksettings->link_modes.lp_advertising,
|
|
legacy_settings->lp_advertising);
|
|
link_ksettings->base.speed
|
|
= ethtool_cmd_speed(legacy_settings);
|
|
link_ksettings->base.duplex
|
|
= legacy_settings->duplex;
|
|
link_ksettings->base.port
|
|
= legacy_settings->port;
|
|
link_ksettings->base.phy_address
|
|
= legacy_settings->phy_address;
|
|
link_ksettings->base.autoneg
|
|
= legacy_settings->autoneg;
|
|
link_ksettings->base.mdio_support
|
|
= legacy_settings->mdio_support;
|
|
link_ksettings->base.eth_tp_mdix
|
|
= legacy_settings->eth_tp_mdix;
|
|
link_ksettings->base.eth_tp_mdix_ctrl
|
|
= legacy_settings->eth_tp_mdix_ctrl;
|
|
return retval;
|
|
}
|
|
|
|
int __ethtool_get_link(struct net_device *dev)
|
|
{
|
|
if (!dev->ethtool_ops->get_link)
|
|
return -EOPNOTSUPP;
|
|
|
|
return netif_running(dev) && dev->ethtool_ops->get_link(dev);
|
|
}
|
|
|
|
int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max)
|
|
{
|
|
u32 dev_size, current_max = 0;
|
|
u32 *indir;
|
|
int ret;
|
|
|
|
if (!dev->ethtool_ops->get_rxfh_indir_size ||
|
|
!dev->ethtool_ops->get_rxfh)
|
|
return -EOPNOTSUPP;
|
|
dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
|
|
if (dev_size == 0)
|
|
return -EOPNOTSUPP;
|
|
|
|
indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER);
|
|
if (!indir)
|
|
return -ENOMEM;
|
|
|
|
ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL, NULL);
|
|
if (ret)
|
|
goto out;
|
|
|
|
while (dev_size--)
|
|
current_max = max(current_max, indir[dev_size]);
|
|
|
|
*max = current_max;
|
|
|
|
out:
|
|
kfree(indir);
|
|
return ret;
|
|
}
|
|
|
|
int ethtool_check_ops(const struct ethtool_ops *ops)
|
|
{
|
|
if (WARN_ON(ops->set_coalesce && !ops->supported_coalesce_params))
|
|
return -EINVAL;
|
|
/* NOTE: sufficiently insane drivers may swap ethtool_ops at runtime,
|
|
* the fact that ops are checked at registration time does not
|
|
* mean the ops attached to a netdev later on are sane.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
|
|
{
|
|
const struct ethtool_ops *ops = dev->ethtool_ops;
|
|
struct phy_device *phydev = dev->phydev;
|
|
|
|
memset(info, 0, sizeof(*info));
|
|
info->cmd = ETHTOOL_GET_TS_INFO;
|
|
|
|
if (phy_has_tsinfo(phydev))
|
|
return phy_ts_info(phydev, info);
|
|
if (ops->get_ts_info)
|
|
return ops->get_ts_info(dev, info);
|
|
|
|
info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
|
|
SOF_TIMESTAMPING_SOFTWARE;
|
|
info->phc_index = -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct ethtool_phy_ops *ethtool_phy_ops;
|
|
|
|
void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops)
|
|
{
|
|
rtnl_lock();
|
|
ethtool_phy_ops = ops;
|
|
rtnl_unlock();
|
|
}
|
|
EXPORT_SYMBOL_GPL(ethtool_set_ethtool_phy_ops);
|