aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c40
1 files changed, 24 insertions, 16 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index a1280f643bf4..fbbe4b49116b 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -283,18 +283,17 @@ err_out:
283 return ret; 283 return ret;
284} 284}
285 285
286static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, 286static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
287 struct ethtool_rx_ntuple_flow_spec *spec) 287 struct ethtool_rx_ntuple_flow_spec *spec,
288 struct ethtool_rx_ntuple_flow_spec_container *fsc)
288{ 289{
289 struct ethtool_rx_ntuple_flow_spec_container *fsc;
290 290
291 /* don't add filters forever */ 291 /* don't add filters forever */
292 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) 292 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
293 return 0; 293 /* free the container */
294 294 kfree(fsc);
295 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); 295 return;
296 if (!fsc) 296 }
297 return -ENOMEM;
298 297
299 /* Copy the whole filter over */ 298 /* Copy the whole filter over */
300 fsc->fs.flow_type = spec->flow_type; 299 fsc->fs.flow_type = spec->flow_type;
@@ -310,14 +309,13 @@ static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
310 /* add to the list */ 309 /* add to the list */
311 list_add_tail_rcu(&fsc->list, &list->list); 310 list_add_tail_rcu(&fsc->list, &list->list);
312 list->count++; 311 list->count++;
313
314 return 0;
315} 312}
316 313
317static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) 314static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)
318{ 315{
319 struct ethtool_rx_ntuple cmd; 316 struct ethtool_rx_ntuple cmd;
320 const struct ethtool_ops *ops = dev->ethtool_ops; 317 const struct ethtool_ops *ops = dev->ethtool_ops;
318 struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
321 int ret; 319 int ret;
322 320
323 if (!ops->set_rx_ntuple) 321 if (!ops->set_rx_ntuple)
@@ -329,16 +327,26 @@ static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)
329 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 327 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
330 return -EFAULT; 328 return -EFAULT;
331 329
332 ret = ops->set_rx_ntuple(dev, &cmd);
333
334 /* 330 /*
335 * Cache filter in dev struct for GET operation only if 331 * Cache filter in dev struct for GET operation only if
336 * the underlying driver doesn't have its own GET operation, and 332 * the underlying driver doesn't have its own GET operation, and
337 * only if the filter was added successfully. 333 * only if the filter was added successfully. First make sure we
334 * can allocate the filter, then continue if successful.
338 */ 335 */
339 if (!ops->get_rx_ntuple && !ret) 336 if (!ops->get_rx_ntuple) {
340 if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs)) 337 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
338 if (!fsc)
341 return -ENOMEM; 339 return -ENOMEM;
340 }
341
342 ret = ops->set_rx_ntuple(dev, &cmd);
343 if (ret) {
344 kfree(fsc);
345 return ret;
346 }
347
348 if (!ops->get_rx_ntuple)
349 __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
342 350
343 return ret; 351 return ret;
344} 352}