]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: ethtool: move rxfh_fields callbacks under the rss_lock
authorJakub Kicinski <kuba@kernel.org>
Thu, 26 Jun 2025 20:28:47 +0000 (13:28 -0700)
committerJakub Kicinski <kuba@kernel.org>
Mon, 30 Jun 2025 15:41:24 +0000 (08:41 -0700)
Netlink code will want to perform the RSS_SET operation atomically
under the rss_lock. sfc wants to hold the rss_lock in rxfh_fields_get,
which makes that difficult. Lets move the locking up to the core
so that for all driver-facing callbacks rss_lock is taken consistently
by the core.

Link: https://patch.msgid.link/20250626202848.104457-3-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/sfc/ethtool_common.c
net/ethtool/ioctl.c

index 823263969f92a25bc29d96c88f46701f696838dd..fa303e171d98bda1a39428e77935b1c0b2569c16 100644 (file)
@@ -810,13 +810,10 @@ int efx_ethtool_get_rxfh_fields(struct net_device *net_dev,
 
        ctx = &efx->rss_context.priv;
 
-       mutex_lock(&net_dev->ethtool->rss_lock);
        if (info->rss_context) {
                ctx = efx_find_rss_context_entry(efx, info->rss_context);
-               if (!ctx) {
-                       rc = -ENOENT;
-                       goto out_unlock;
-               }
+               if (!ctx)
+                       return -ENOENT;
        }
 
        data = 0;
@@ -850,8 +847,6 @@ int efx_ethtool_get_rxfh_fields(struct net_device *net_dev,
        }
 out_setdata_unlock:
        info->data = data;
-out_unlock:
-       mutex_unlock(&net_dev->ethtool->rss_lock);
        return rc;
 }
 
index ce7d720b3c791bc42f524760006fb59778c10300..df376628ba191de03eb7f560400eed82e90d6b6d 100644 (file)
@@ -1096,7 +1096,10 @@ 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;
 
-       return ops->set_rxfh_fields(dev, &fields, NULL);
+       mutex_lock(&dev->ethtool->rss_lock);
+       rc = ops->set_rxfh_fields(dev, &fields, NULL);
+       mutex_unlock(&dev->ethtool->rss_lock);
+       return rc;
 }
 
 static noinline_for_stack int
@@ -1123,7 +1126,9 @@ ethtool_get_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);
        ret = ops->get_rxfh_fields(dev, &fields);
+       mutex_unlock(&dev->ethtool->rss_lock);
        if (ret < 0)
                return ret;
 
@@ -1553,10 +1558,6 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
             rxfh.input_xfrm == RXH_XFRM_NO_CHANGE))
                return -EINVAL;
 
-       ret = ethtool_check_flow_types(dev, rxfh.input_xfrm);
-       if (ret)
-               return ret;
-
        indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]);
 
        /* Check settings which may be global rather than per RSS-context */
@@ -1617,6 +1618,10 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
 
        mutex_lock(&dev->ethtool->rss_lock);
 
+       ret = ethtool_check_flow_types(dev, rxfh.input_xfrm);
+       if (ret)
+               goto out_unlock;
+
        if (rxfh.rss_context && rxfh_dev.rss_delete) {
                ret = ethtool_check_rss_ctx_busy(dev, rxfh.rss_context);
                if (ret)