diff options
-rw-r--r-- | include/linux/netdevice.h | 1 | ||||
-rw-r--r-- | net/core/dev.c | 23 | ||||
-rw-r--r-- | net/core/ethtool.c | 6 |
3 files changed, 21 insertions, 9 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5eeb2cd3631c..423a5447d2ed 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2550,6 +2550,7 @@ static inline u32 netdev_get_wanted_features(struct net_device *dev) | |||
2550 | } | 2550 | } |
2551 | u32 netdev_increment_features(u32 all, u32 one, u32 mask); | 2551 | u32 netdev_increment_features(u32 all, u32 one, u32 mask); |
2552 | u32 netdev_fix_features(struct net_device *dev, u32 features); | 2552 | u32 netdev_fix_features(struct net_device *dev, u32 features); |
2553 | int __netdev_update_features(struct net_device *dev); | ||
2553 | void netdev_update_features(struct net_device *dev); | 2554 | void netdev_update_features(struct net_device *dev); |
2554 | 2555 | ||
2555 | void netif_stacked_transfer_operstate(const struct net_device *rootdev, | 2556 | void netif_stacked_transfer_operstate(const struct net_device *rootdev, |
diff --git a/net/core/dev.c b/net/core/dev.c index 3da9fb06d47a..02f56376fe99 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5236,7 +5236,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5236 | } | 5236 | } |
5237 | EXPORT_SYMBOL(netdev_fix_features); | 5237 | EXPORT_SYMBOL(netdev_fix_features); |
5238 | 5238 | ||
5239 | void netdev_update_features(struct net_device *dev) | 5239 | int __netdev_update_features(struct net_device *dev) |
5240 | { | 5240 | { |
5241 | u32 features; | 5241 | u32 features; |
5242 | int err = 0; | 5242 | int err = 0; |
@@ -5250,7 +5250,7 @@ void netdev_update_features(struct net_device *dev) | |||
5250 | features = netdev_fix_features(dev, features); | 5250 | features = netdev_fix_features(dev, features); |
5251 | 5251 | ||
5252 | if (dev->features == features) | 5252 | if (dev->features == features) |
5253 | return; | 5253 | return 0; |
5254 | 5254 | ||
5255 | netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", | 5255 | netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", |
5256 | dev->features, features); | 5256 | dev->features, features); |
@@ -5258,12 +5258,23 @@ void netdev_update_features(struct net_device *dev) | |||
5258 | if (dev->netdev_ops->ndo_set_features) | 5258 | if (dev->netdev_ops->ndo_set_features) |
5259 | err = dev->netdev_ops->ndo_set_features(dev, features); | 5259 | err = dev->netdev_ops->ndo_set_features(dev, features); |
5260 | 5260 | ||
5261 | if (!err) | 5261 | if (unlikely(err < 0)) { |
5262 | dev->features = features; | ||
5263 | else if (err < 0) | ||
5264 | netdev_err(dev, | 5262 | netdev_err(dev, |
5265 | "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n", | 5263 | "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n", |
5266 | err, features, dev->features); | 5264 | err, features, dev->features); |
5265 | return -1; | ||
5266 | } | ||
5267 | |||
5268 | if (!err) | ||
5269 | dev->features = features; | ||
5270 | |||
5271 | return 1; | ||
5272 | } | ||
5273 | |||
5274 | void netdev_update_features(struct net_device *dev) | ||
5275 | { | ||
5276 | if (__netdev_update_features(dev)) | ||
5277 | netdev_features_change(dev); | ||
5267 | } | 5278 | } |
5268 | EXPORT_SYMBOL(netdev_update_features); | 5279 | EXPORT_SYMBOL(netdev_update_features); |
5269 | 5280 | ||
@@ -5430,7 +5441,7 @@ int register_netdevice(struct net_device *dev) | |||
5430 | goto err_uninit; | 5441 | goto err_uninit; |
5431 | dev->reg_state = NETREG_REGISTERED; | 5442 | dev->reg_state = NETREG_REGISTERED; |
5432 | 5443 | ||
5433 | netdev_update_features(dev); | 5444 | __netdev_update_features(dev); |
5434 | 5445 | ||
5435 | /* | 5446 | /* |
5436 | * Default initial state at registry is that the | 5447 | * Default initial state at registry is that the |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..439e4b0e1312 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -317,7 +317,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) | |||
317 | 317 | ||
318 | dev->wanted_features &= ~features[0].valid; | 318 | dev->wanted_features &= ~features[0].valid; |
319 | dev->wanted_features |= features[0].valid & features[0].requested; | 319 | dev->wanted_features |= features[0].valid & features[0].requested; |
320 | netdev_update_features(dev); | 320 | __netdev_update_features(dev); |
321 | 321 | ||
322 | if ((dev->wanted_features ^ dev->features) & features[0].valid) | 322 | if ((dev->wanted_features ^ dev->features) & features[0].valid) |
323 | ret |= ETHTOOL_F_WISH; | 323 | ret |= ETHTOOL_F_WISH; |
@@ -499,7 +499,7 @@ static int ethtool_set_one_feature(struct net_device *dev, | |||
499 | else | 499 | else |
500 | dev->wanted_features &= ~mask; | 500 | dev->wanted_features &= ~mask; |
501 | 501 | ||
502 | netdev_update_features(dev); | 502 | __netdev_update_features(dev); |
503 | return 0; | 503 | return 0; |
504 | } | 504 | } |
505 | 505 | ||
@@ -551,7 +551,7 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) | |||
551 | dev->wanted_features = | 551 | dev->wanted_features = |
552 | (dev->wanted_features & ~changed) | data; | 552 | (dev->wanted_features & ~changed) | data; |
553 | 553 | ||
554 | netdev_update_features(dev); | 554 | __netdev_update_features(dev); |
555 | 555 | ||
556 | return 0; | 556 | return 0; |
557 | } | 557 | } |