diff options
author | Michal Kubecek <mkubecek@suse.cz> | 2020-03-12 21:08:03 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-12 15:32:33 -0700 |
commit | 9c6451ef4881c2f528c625766e8bb9af5e40941a (patch) | |
tree | ca7ef69adba1907b240efe5eaa3aad6c71d18a11 /net | |
parent | 0980bfcd6954f124e40a000b85335c197764de14 (diff) |
ethtool: add FEATURES_NTF notification
Send ETHTOOL_MSG_FEATURES_NTF notification whenever network device features
are modified using ETHTOOL_MSG_FEATURES_SET netlink message, ethtool ioctl
request or any other way resulting in call to netdev_update_features() or
netdev_change_features()
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ethtool/features.c | 4 | ||||
-rw-r--r-- | net/ethtool/netlink.c | 29 |
2 files changed, 32 insertions, 1 deletions
diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 4ac1e05684ce..4e632dc987d8 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -230,6 +230,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1]; struct ethnl_req_info req_info = {}; struct net_device *dev; + bool mod; int ret; ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, @@ -272,6 +273,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev->wanted_features = ethnl_bitmap_to_features(req_wanted); __netdev_update_features(dev); ethnl_features_to_bitmap(new_active, dev->features); + mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT); ret = 0; if (!(req_info.flags & ETHTOOL_FLAG_OMIT_REPLY)) { @@ -292,6 +294,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) wanted_diff_mask, new_active, active_diff_mask, compact); } + if (mod) + ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL); out_rtnl: rtnl_unlock(); diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 757ea3fc98a0..5c0e361bfd66 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -528,6 +528,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops, [ETHTOOL_MSG_DEBUG_NTF] = ðnl_debug_request_ops, [ETHTOOL_MSG_WOL_NTF] = ðnl_wol_request_ops, + [ETHTOOL_MSG_FEATURES_NTF] = ðnl_features_request_ops, }; /* default notification handler */ @@ -613,6 +614,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = { [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify, [ETHTOOL_MSG_DEBUG_NTF] = ethnl_default_notify, [ETHTOOL_MSG_WOL_NTF] = ethnl_default_notify, + [ETHTOOL_MSG_FEATURES_NTF] = ethnl_default_notify, }; void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) @@ -630,6 +632,29 @@ void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) } EXPORT_SYMBOL(ethtool_notify); +static void ethnl_notify_features(struct netdev_notifier_info *info) +{ + struct net_device *dev = netdev_notifier_info_to_dev(info); + + ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL); +} + +static int ethnl_netdev_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + switch (event) { + case NETDEV_FEAT_CHANGE: + ethnl_notify_features(ptr); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block ethnl_netdev_notifier = { + .notifier_call = ethnl_netdev_event, +}; + /* genetlink setup */ static const struct genl_ops ethtool_genl_ops[] = { @@ -736,7 +761,9 @@ static int __init ethnl_init(void) return ret; ethnl_ok = true; - return 0; + ret = register_netdevice_notifier(ðnl_netdev_notifier); + WARN(ret < 0, "ethtool: net device notifier registration failed"); + return ret; } subsys_initcall(ethnl_init); |