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 | } |
