ethtool: Fix filter addition when caching n-tuple filters
We can allow a filter to be added successfully to the underlying hardware, but still return an error if the cached list memory allocation fails. This patch fixes that condition. Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									02b1bae5e1
								
							
						
					
					
						commit
						e858911804
					
				| @ -283,18 +283,17 @@ err_out: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | ||||
|                                   struct ethtool_rx_ntuple_flow_spec *spec) | ||||
| static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | ||||
|                               struct ethtool_rx_ntuple_flow_spec *spec, | ||||
|                               struct ethtool_rx_ntuple_flow_spec_container *fsc) | ||||
| { | ||||
| 	struct ethtool_rx_ntuple_flow_spec_container *fsc; | ||||
| 
 | ||||
| 	/* don't add filters forever */ | ||||
| 	if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); | ||||
| 	if (!fsc) | ||||
| 		return -ENOMEM; | ||||
| 	if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) { | ||||
| 		/* free the container */ | ||||
| 		kfree(fsc); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Copy the whole filter over */ | ||||
| 	fsc->fs.flow_type = spec->flow_type; | ||||
| @ -310,14 +309,13 @@ static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | ||||
| 	/* add to the list */ | ||||
| 	list_add_tail_rcu(&fsc->list, &list->list); | ||||
| 	list->count++; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||||
| { | ||||
| 	struct ethtool_rx_ntuple cmd; | ||||
| 	const struct ethtool_ops *ops = dev->ethtool_ops; | ||||
| 	struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!ops->set_rx_ntuple) | ||||
| @ -329,16 +327,26 @@ static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||||
| 	if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	ret = ops->set_rx_ntuple(dev, &cmd); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Cache filter in dev struct for GET operation only if | ||||
| 	 * the underlying driver doesn't have its own GET operation, and | ||||
| 	 * only if the filter was added successfully. | ||||
| 	 * only if the filter was added successfully.  First make sure we | ||||
| 	 * can allocate the filter, then continue if successful. | ||||
| 	 */ | ||||
| 	if (!ops->get_rx_ntuple && !ret) | ||||
| 		if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs)) | ||||
| 	if (!ops->get_rx_ntuple) { | ||||
| 		fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); | ||||
| 		if (!fsc) | ||||
| 			return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = ops->set_rx_ntuple(dev, &cmd); | ||||
| 	if (ret) { | ||||
| 		kfree(fsc); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!ops->get_rx_ntuple) | ||||
| 		__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user