diff options
Diffstat (limited to 'net/ethtool/common.c')
| -rw-r--r-- | net/ethtool/common.c | 61 | 
1 files changed, 49 insertions, 12 deletions
| diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 07032babd1b6..dd345efa114b 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -6,6 +6,7 @@  #include <linux/rtnetlink.h>  #include <linux/ptp_clock_kernel.h> +#include "netlink.h"  #include "common.h"  const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = { @@ -24,8 +25,6 @@ const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {  	[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", @@ -51,7 +50,6 @@ const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {  	[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", @@ -429,6 +427,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = {  	[const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)]  = "option-tx-swhw",  	[const_ilog2(SOF_TIMESTAMPING_BIND_PHC)]     = "bind-phc",  	[const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)]   = "option-id-tcp", +	[const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter",  };  static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT); @@ -539,7 +538,7 @@ static int ethtool_get_rxnfc_rule_count(struct net_device *dev)  	return info.rule_cnt;  } -int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max) +static int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max)  {  	const struct ethtool_ops *ops = dev->ethtool_ops;  	struct ethtool_rxnfc *info; @@ -609,7 +608,7 @@ static u32 ethtool_get_max_rss_ctx_channel(struct net_device *dev)  	return max_ring;  } -u32 ethtool_get_max_rxfh_channel(struct net_device *dev) +static u32 ethtool_get_max_rxfh_channel(struct net_device *dev)  {  	struct ethtool_rxfh_param rxfh = {};  	u32 dev_size, current_max; @@ -650,10 +649,47 @@ out_free:  	return current_max;  } +int ethtool_check_max_channel(struct net_device *dev, +			      struct ethtool_channels channels, +			      struct genl_info *info) +{ +	u64 max_rxnfc_in_use; +	u32 max_rxfh_in_use; +	int max_mp_in_use; + +	/* ensure the new Rx count fits within the configured Rx flow +	 * indirection table/rxnfc settings +	 */ +	if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use)) +		max_rxnfc_in_use = 0; +	max_rxfh_in_use = ethtool_get_max_rxfh_channel(dev); +	if (channels.combined_count + channels.rx_count <= max_rxfh_in_use) { +		if (info) +			GENL_SET_ERR_MSG_FMT(info, "requested channel counts are too low for existing indirection table (%d)", max_rxfh_in_use); +		return -EINVAL; +	} +	if (channels.combined_count + channels.rx_count <= max_rxnfc_in_use) { +		if (info) +			GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing ntuple filter settings"); +		return -EINVAL; +	} + +	max_mp_in_use = dev_get_min_mp_channel_count(dev); +	if (channels.combined_count + channels.rx_count <= max_mp_in_use) { +		if (info) +			GENL_SET_ERR_MSG_FMT(info, "requested channel counts are too low for existing memory provider setting (%d)", max_mp_in_use); +		return -EINVAL; +	} + +	return 0; +} +  int ethtool_check_ops(const struct ethtool_ops *ops)  {  	if (WARN_ON(ops->set_coalesce && !ops->supported_coalesce_params))  		return -EINVAL; +	if (WARN_ON(ops->rxfh_max_num_contexts == 1)) +		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. @@ -665,20 +701,21 @@ int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info  {  	const struct ethtool_ops *ops = dev->ethtool_ops;  	struct phy_device *phydev = dev->phydev; +	int err = 0;  	memset(info, 0, sizeof(*info));  	info->cmd = ETHTOOL_GET_TS_INFO; +	info->phc_index = -1;  	if (phy_is_default_hwtstamp(phydev) && phy_has_tsinfo(phydev)) -		return phy_ts_info(phydev, info); -	if (ops->get_ts_info) -		return ops->get_ts_info(dev, info); +		err = phy_ts_info(phydev, info); +	else if (ops->get_ts_info) +		err = ops->get_ts_info(dev, info); -	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | -				SOF_TIMESTAMPING_SOFTWARE; -	info->phc_index = -1; +	info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE | +				 SOF_TIMESTAMPING_SOFTWARE; -	return 0; +	return err;  }  int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index) | 
