forked from mirrors/linux
		
	ethtool: check if there is at least one channel for TX/RX in the core
Having a channel config with no ability to RX or TX traffic is clearly wrong. Check for this in the core so the drivers don't have to. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Reviewed-by: Michal Kubecek <mkubecek@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									a0c1d0eafd
								
							
						
					
					
						commit
						7be92514b9
					
				
					 2 changed files with 23 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -129,13 +129,13 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
 | 
			
		|||
{
 | 
			
		||||
	struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1];
 | 
			
		||||
	unsigned int from_channel, old_total, i;
 | 
			
		||||
	bool mod = false, mod_combined = false;
 | 
			
		||||
	struct ethtool_channels channels = {};
 | 
			
		||||
	struct ethnl_req_info req_info = {};
 | 
			
		||||
	const struct nlattr *err_attr;
 | 
			
		||||
	const struct ethtool_ops *ops;
 | 
			
		||||
	struct net_device *dev;
 | 
			
		||||
	u32 max_rx_in_use = 0;
 | 
			
		||||
	bool mod = false;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
 | 
			
		||||
| 
						 | 
				
			
			@ -170,7 +170,8 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
 | 
			
		|||
	ethnl_update_u32(&channels.other_count,
 | 
			
		||||
			 tb[ETHTOOL_A_CHANNELS_OTHER_COUNT], &mod);
 | 
			
		||||
	ethnl_update_u32(&channels.combined_count,
 | 
			
		||||
			 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], &mod);
 | 
			
		||||
			 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], &mod_combined);
 | 
			
		||||
	mod |= mod_combined;
 | 
			
		||||
	ret = 0;
 | 
			
		||||
	if (!mod)
 | 
			
		||||
		goto out_ops;
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +194,21 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
 | 
			
		|||
		goto out_ops;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ensure there is at least one RX and one TX channel */
 | 
			
		||||
	if (!channels.combined_count && !channels.rx_count)
 | 
			
		||||
		err_attr = tb[ETHTOOL_A_CHANNELS_RX_COUNT];
 | 
			
		||||
	else if (!channels.combined_count && !channels.tx_count)
 | 
			
		||||
		err_attr = tb[ETHTOOL_A_CHANNELS_TX_COUNT];
 | 
			
		||||
	else
 | 
			
		||||
		err_attr = NULL;
 | 
			
		||||
	if (err_attr) {
 | 
			
		||||
		if (mod_combined)
 | 
			
		||||
			err_attr = tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT];
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		NL_SET_ERR_MSG_ATTR(info->extack, err_attr, "requested channel counts would result in no RX or TX channel being configured");
 | 
			
		||||
		goto out_ops;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ensure the new Rx count fits within the configured Rx flow
 | 
			
		||||
	 * indirection table settings
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1676,6 +1676,11 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
 | 
			
		|||
	    channels.other_count > curr.max_other)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* ensure there is at least one RX and one TX channel */
 | 
			
		||||
	if (!channels.combined_count &&
 | 
			
		||||
	    (!channels.rx_count || !channels.tx_count))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* ensure the new Rx count fits within the configured Rx flow
 | 
			
		||||
	 * indirection table settings */
 | 
			
		||||
	if (netif_is_rxfh_configured(dev) &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue