diff options
author | Michał Mirosław <mirq-linux@rere.qmqm.pl> | 2011-02-15 11:59:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-17 17:16:34 -0500 |
commit | 86794881c29a7ea6271644b49ad81518cabda96b (patch) | |
tree | 3bdf83a8e665866f32e0326c9e29477ee8791280 | |
parent | 5455c6998d34dc983a8693500e4dffefc3682dc5 (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.c | 45 |
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) | |||
357 | static int ethtool_get_one_feature(struct net_device *dev, | 357 | static 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 | } |