aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>2011-02-15 11:59:17 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-17 17:16:34 -0500
commit86794881c29a7ea6271644b49ad81518cabda96b (patch)
tree3bdf83a8e665866f32e0326c9e29477ee8791280
parent5455c6998d34dc983a8693500e4dffefc3682dc5 (diff)
net: ethtool: use ndo_fix_features for offload setting
Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/ethtool.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 95773960dc77..65999974f743 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -357,15 +357,21 @@ static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd)
357static int ethtool_get_one_feature(struct net_device *dev, 357static int ethtool_get_one_feature(struct net_device *dev,
358 char __user *useraddr, u32 ethcmd) 358 char __user *useraddr, u32 ethcmd)
359{ 359{
360 u32 mask = ethtool_get_feature_mask(ethcmd);
360 struct ethtool_value edata = { 361 struct ethtool_value edata = {
361 .cmd = ethcmd, 362 .cmd = ethcmd,
362 .data = !!(dev->features & ethtool_get_feature_mask(ethcmd)), 363 .data = !!(dev->features & mask),
363 }; 364 };
364 u32 (*actor)(struct net_device *);
365 365
366 actor = __ethtool_get_one_feature_actor(dev, ethcmd); 366 /* compatibility with discrete get_ ops */
367 if (actor) 367 if (!(dev->hw_features & mask)) {
368 edata.data = actor(dev); 368 u32 (*actor)(struct net_device *);
369
370 actor = __ethtool_get_one_feature_actor(dev, ethcmd);
371
372 if (actor)
373 edata.data = actor(dev);
374 }
369 375
370 if (copy_to_user(useraddr, &edata, sizeof(edata))) 376 if (copy_to_user(useraddr, &edata, sizeof(edata)))
371 return -EFAULT; 377 return -EFAULT;
@@ -386,6 +392,27 @@ static int ethtool_set_one_feature(struct net_device *dev,
386 if (copy_from_user(&edata, useraddr, sizeof(edata))) 392 if (copy_from_user(&edata, useraddr, sizeof(edata)))
387 return -EFAULT; 393 return -EFAULT;
388 394
395 mask = ethtool_get_feature_mask(ethcmd);
396 mask &= dev->hw_features;
397 if (mask) {
398 if (edata.data)
399 dev->wanted_features |= mask;
400 else
401 dev->wanted_features &= ~mask;
402
403 netdev_update_features(dev);
404 return 0;
405 }
406
407 /* Driver is not converted to ndo_fix_features or does not
408 * support changing this offload. In the latter case it won't
409 * have corresponding ethtool_ops field set.
410 *
411 * Following part is to be removed after all drivers advertise
412 * their changeable features in netdev->hw_features and stop
413 * using discrete offload setting ops.
414 */
415
389 switch (ethcmd) { 416 switch (ethcmd) {
390 case ETHTOOL_STXCSUM: 417 case ETHTOOL_STXCSUM:
391 return __ethtool_set_tx_csum(dev, edata.data); 418 return __ethtool_set_tx_csum(dev, edata.data);
@@ -395,14 +422,6 @@ static int ethtool_set_one_feature(struct net_device *dev,
395 return __ethtool_set_tso(dev, edata.data); 422 return __ethtool_set_tso(dev, edata.data);
396 case ETHTOOL_SUFO: 423 case ETHTOOL_SUFO:
397 return __ethtool_set_ufo(dev, edata.data); 424 return __ethtool_set_ufo(dev, edata.data);
398 case ETHTOOL_SGSO:
399 case ETHTOOL_SGRO:
400 mask = ethtool_get_feature_mask(ethcmd);
401 if (edata.data)
402 dev->features |= mask;
403 else
404 dev->features &= ~mask;
405 return 0;
406 default: 425 default:
407 return -EOPNOTSUPP; 426 return -EOPNOTSUPP;
408 } 427 }