summaryrefslogtreecommitdiff
path: root/net/ethtool
diff options
context:
space:
mode:
Diffstat (limited to 'net/ethtool')
-rw-r--r--net/ethtool/common.h30
-rw-r--r--net/ethtool/netlink.c9
2 files changed, 37 insertions, 2 deletions
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index 391c41ca56be..e3052972f953 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -95,10 +95,24 @@ ethtool_nl_msg_needs_rtnl(const struct net_device *dev, u8 cmd)
switch (cmd) {
case ETHTOOL_MSG_LINKINFO_GET:
+ case ETHTOOL_MSG_LINKINFO_SET:
case ETHTOOL_MSG_LINKMODES_GET:
+ case ETHTOOL_MSG_LINKMODES_SET:
return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_LINKSETTINGS;
+ case ETHTOOL_MSG_PRIVFLAGS_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SPFLAGS;
+ case ETHTOOL_MSG_RINGS_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM;
+ case ETHTOOL_MSG_CHANNELS_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SCHANNELS;
+ case ETHTOOL_MSG_COALESCE_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SCOALESCE;
case ETHTOOL_MSG_PAUSE_GET:
return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_GPAUSEPARAM;
+ case ETHTOOL_MSG_PAUSE_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM;
+ case ETHTOOL_MSG_RSS_SET:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_RSS;
}
return false;
}
@@ -119,9 +133,25 @@ ethtool_ioctl_needs_rtnl(const struct net_device *dev, u32 ethcmd)
switch (ethcmd) {
case ETHTOOL_GLINKSETTINGS:
case ETHTOOL_GSET:
+ case ETHTOOL_SLINKSETTINGS:
+ case ETHTOOL_SSET:
return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_LINKSETTINGS;
+ case ETHTOOL_SPFLAGS:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SPFLAGS;
+ case ETHTOOL_SRINGPARAM:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM;
+ case ETHTOOL_SCHANNELS:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SCHANNELS;
+ case ETHTOOL_SCOALESCE:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SCOALESCE;
case ETHTOOL_GPAUSEPARAM:
return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_GPAUSEPARAM;
+ case ETHTOOL_SPAUSEPARAM:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM;
+ case ETHTOOL_SRSSH:
+ case ETHTOOL_SRXFH:
+ case ETHTOOL_SRXFHINDIR:
+ return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_RSS;
}
return false;
}
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 2c30eb1f4666..1af395b54330 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -903,6 +903,7 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
const u8 cmd = info->genlhdr->cmd;
struct ethnl_req_info *req_info;
struct net_device *dev;
+ bool need_rtnl;
int ret;
ops = ethnl_default_requests[cmd];
@@ -927,8 +928,11 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
}
dev = req_info->dev;
+ need_rtnl = !netdev_need_ops_lock(dev) ||
+ ethtool_nl_msg_needs_rtnl(dev, cmd);
- rtnl_lock();
+ if (need_rtnl)
+ rtnl_lock();
netdev_lock_ops(dev);
dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg),
GFP_KERNEL_ACCOUNT);
@@ -958,7 +962,8 @@ out_free_cfg:
out_tie_cfg:
dev->cfg_pending = dev->cfg;
netdev_unlock_ops(dev);
- rtnl_unlock();
+ if (need_rtnl)
+ rtnl_unlock();
out_dev:
ethnl_parse_header_dev_put(req_info);
out_free_req: