aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/dev.c23
-rw-r--r--net/core/ethtool.c6
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}
2551u32 netdev_increment_features(u32 all, u32 one, u32 mask); 2551u32 netdev_increment_features(u32 all, u32 one, u32 mask);
2552u32 netdev_fix_features(struct net_device *dev, u32 features); 2552u32 netdev_fix_features(struct net_device *dev, u32 features);
2553int __netdev_update_features(struct net_device *dev);
2553void netdev_update_features(struct net_device *dev); 2554void netdev_update_features(struct net_device *dev);
2554 2555
2555void netif_stacked_transfer_operstate(const struct net_device *rootdev, 2556void 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}
5237EXPORT_SYMBOL(netdev_fix_features); 5237EXPORT_SYMBOL(netdev_fix_features);
5238 5238
5239void netdev_update_features(struct net_device *dev) 5239int __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
5274void netdev_update_features(struct net_device *dev)
5275{
5276 if (__netdev_update_features(dev))
5277 netdev_features_change(dev);
5267} 5278}
5268EXPORT_SYMBOL(netdev_update_features); 5279EXPORT_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}