summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/ethtool/common.c2
-rw-r--r--net/ethtool/ioctl.c11
-rw-r--r--net/ethtool/rss.c23
3 files changed, 27 insertions, 9 deletions
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index eb253e0fd61b..d62dc56f2f5b 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -707,7 +707,9 @@ static u32 ethtool_get_max_rxfh_channel(struct net_device *dev)
if (!rxfh.indir)
return U32_MAX;
+ mutex_lock(&dev->ethtool->rss_lock);
ret = dev->ethtool_ops->get_rxfh(dev, &rxfh);
+ mutex_unlock(&dev->ethtool->rss_lock);
if (ret) {
current_max = U32_MAX;
goto out_free;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index df376628ba19..b6d96e562c9a 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -1079,16 +1079,17 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
!ops->rxfh_per_ctx_fields)
return -EINVAL;
+ mutex_lock(&dev->ethtool->rss_lock);
if (ops->get_rxfh) {
struct ethtool_rxfh_param rxfh = {};
rc = ops->get_rxfh(dev, &rxfh);
if (rc)
- return rc;
+ goto exit_unlock;
rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data);
if (rc)
- return rc;
+ goto exit_unlock;
}
fields.data = info.data;
@@ -1096,8 +1097,8 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
if (info.flow_type & FLOW_RSS)
fields.rss_context = info.rss_context;
- mutex_lock(&dev->ethtool->rss_lock);
rc = ops->set_rxfh_fields(dev, &fields, NULL);
+exit_unlock:
mutex_unlock(&dev->ethtool->rss_lock);
return rc;
}
@@ -1274,7 +1275,9 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
if (!rxfh.indir)
return -ENOMEM;
+ mutex_lock(&dev->ethtool->rss_lock);
ret = dev->ethtool_ops->get_rxfh(dev, &rxfh);
+ mutex_unlock(&dev->ethtool->rss_lock);
if (ret)
goto out;
if (copy_to_user(useraddr +
@@ -1413,6 +1416,7 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (user_key_size)
rxfh_dev.key = rss_config + indir_bytes;
+ mutex_lock(&dev->ethtool->rss_lock);
if (rxfh.rss_context) {
ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context);
if (!ctx) {
@@ -1458,6 +1462,7 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
ret = -EFAULT;
}
out:
+ mutex_unlock(&dev->ethtool->rss_lock);
kfree(rss_config);
return ret;
diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
index 3adddca7e215..e717f23cbc10 100644
--- a/net/ethtool/rss.c
+++ b/net/ethtool/rss.c
@@ -139,6 +139,15 @@ rss_prepare_ctx(const struct rss_req_info *request, struct net_device *dev,
}
static int
+rss_prepare(const struct rss_req_info *request, struct net_device *dev,
+ struct rss_reply_data *data, const struct genl_info *info)
+{
+ if (request->rss_context)
+ return rss_prepare_ctx(request, dev, data, info);
+ return rss_prepare_get(request, dev, data, info);
+}
+
+static int
rss_prepare_data(const struct ethnl_req_info *req_base,
struct ethnl_reply_data *reply_base,
const struct genl_info *info)
@@ -147,20 +156,22 @@ rss_prepare_data(const struct ethnl_req_info *req_base,
struct rss_req_info *request = RSS_REQINFO(req_base);
struct net_device *dev = reply_base->dev;
const struct ethtool_ops *ops;
+ int ret;
ops = dev->ethtool_ops;
if (!ops->get_rxfh)
return -EOPNOTSUPP;
/* Some drivers don't handle rss_context */
- if (request->rss_context) {
- if (!ops->cap_rss_ctx_supported && !ops->create_rxfh_context)
- return -EOPNOTSUPP;
+ if (request->rss_context &&
+ !ops->cap_rss_ctx_supported && !ops->create_rxfh_context)
+ return -EOPNOTSUPP;
- return rss_prepare_ctx(request, dev, data, info);
- }
+ mutex_lock(&dev->ethtool->rss_lock);
+ ret = rss_prepare(request, dev, data, info);
+ mutex_unlock(&dev->ethtool->rss_lock);
- return rss_prepare_get(request, dev, data, info);
+ return ret;
}
static int