diff options
author | Michał Mirosław <mirq-linux@rere.qmqm.pl> | 2011-02-15 11:59:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-17 17:16:34 -0500 |
commit | da8ac86c4a56a14bf8deea7d2f92d0a453c67f91 (patch) | |
tree | 9ccb11cb01f7917240efe014cae22f5ff3ce9d43 /net/core/ethtool.c | |
parent | 86794881c29a7ea6271644b49ad81518cabda96b (diff) |
net: use ndo_fix_features for ethtool_ops->set_flags
Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r-- | net/core/ethtool.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 65999974f743..65b3d50a6df2 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -427,6 +427,34 @@ static int ethtool_set_one_feature(struct net_device *dev, | |||
427 | } | 427 | } |
428 | } | 428 | } |
429 | 429 | ||
430 | static int __ethtool_set_flags(struct net_device *dev, u32 data) | ||
431 | { | ||
432 | u32 changed; | ||
433 | |||
434 | if (data & ~flags_dup_features) | ||
435 | return -EINVAL; | ||
436 | |||
437 | /* legacy set_flags() op */ | ||
438 | if (dev->ethtool_ops->set_flags) { | ||
439 | if (unlikely(dev->hw_features & flags_dup_features)) | ||
440 | netdev_warn(dev, | ||
441 | "driver BUG: mixed hw_features and set_flags()\n"); | ||
442 | return dev->ethtool_ops->set_flags(dev, data); | ||
443 | } | ||
444 | |||
445 | /* allow changing only bits set in hw_features */ | ||
446 | changed = (data ^ dev->wanted_features) & flags_dup_features; | ||
447 | if (changed & ~dev->hw_features) | ||
448 | return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; | ||
449 | |||
450 | dev->wanted_features = | ||
451 | (dev->wanted_features & ~changed) | data; | ||
452 | |||
453 | netdev_update_features(dev); | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
430 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 458 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) |
431 | { | 459 | { |
432 | struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; | 460 | struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; |
@@ -1768,8 +1796,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1768 | ethtool_op_get_flags)); | 1796 | ethtool_op_get_flags)); |
1769 | break; | 1797 | break; |
1770 | case ETHTOOL_SFLAGS: | 1798 | case ETHTOOL_SFLAGS: |
1771 | rc = ethtool_set_value(dev, useraddr, | 1799 | rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags); |
1772 | dev->ethtool_ops->set_flags); | ||
1773 | break; | 1800 | break; |
1774 | case ETHTOOL_GPFLAGS: | 1801 | case ETHTOOL_GPFLAGS: |
1775 | rc = ethtool_get_value(dev, useraddr, ethcmd, | 1802 | rc = ethtool_get_value(dev, useraddr, ethcmd, |