}
 
        rxfh_dev.hfunc = ETH_RSS_HASH_NO_CHANGE;
+
+       mutex_lock(&dev->ethtool->rss_lock);
        ret = ops->set_rxfh(dev, &rxfh_dev, extack);
        if (ret)
-               goto out;
+               goto out_unlock;
 
        /* indicate whether rxfh was set to default */
        if (user_size == 0)
        else
                dev->priv_flags |= IFF_RXFH_CONFIGURED;
 
+out_unlock:
+       mutex_unlock(&dev->ethtool->rss_lock);
 out:
        kfree(rxfh_dev.indir);
        return ret;
        struct netlink_ext_ack *extack = NULL;
        struct ethtool_rxnfc rx_rings;
        struct ethtool_rxfh rxfh;
-       bool locked = false; /* dev->ethtool->rss_lock taken */
        bool create = false;
        bool mod = false;
        u8 *rss_config;
        rx_rings.cmd = ETHTOOL_GRXRINGS;
        ret = ops->get_rxnfc(dev, &rx_rings, NULL);
        if (ret)
-               goto out;
+               goto out_free;
 
        /* rxfh.indir_size == 0 means reset the indir table to default (master
         * context) or delete the context (other RSS contexts).
                                                  &rx_rings,
                                                  rxfh.indir_size);
                if (ret)
-                       goto out;
+                       goto out_free;
        } else if (rxfh.indir_size == 0) {
                if (rxfh.rss_context == 0) {
                        u32 *indir;
                                   useraddr + rss_cfg_offset + user_indir_len,
                                   rxfh.key_size)) {
                        ret = -EFAULT;
-                       goto out;
+                       goto out_free;
                }
        }
 
-       if (rxfh.rss_context) {
-               mutex_lock(&dev->ethtool->rss_lock);
-               locked = true;
-       }
+       mutex_lock(&dev->ethtool->rss_lock);
 
        if (rxfh.rss_context && rxfh_dev.rss_delete) {
                ret = ethtool_check_rss_ctx_busy(dev, rxfh.rss_context);
                if (ret)
-                       goto out;
+                       goto out_unlock;
        }
 
        if (create) {
                if (rxfh_dev.rss_delete) {
                        ret = -EINVAL;
-                       goto out;
+                       goto out_unlock;
                }
                ctx = ethtool_rxfh_ctx_alloc(ops, dev_indir_size, dev_key_size);
                if (!ctx) {
                        ret = -ENOMEM;
-                       goto out;
+                       goto out_unlock;
                }
 
                if (ops->create_rxfh_context) {
                                       GFP_KERNEL_ACCOUNT);
                        if (ret < 0) {
                                kfree(ctx);
-                               goto out;
+                               goto out_unlock;
                        }
                        WARN_ON(!ctx_id); /* can't happen */
                        rxfh.rss_context = ctx_id;
                ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context);
                if (!ctx) {
                        ret = -ENOENT;
-                       goto out;
+                       goto out_unlock;
                }
        }
        rxfh_dev.hfunc = rxfh.hfunc;
                                xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
                        kfree(ctx);
                }
-               goto out;
+               goto out_unlock;
        }
        mod = !create && !rxfh_dev.rss_delete;
 
                if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh_dev.rss_context))) {
                        /* context ID reused, our tracking is screwed */
                        kfree(ctx);
-                       goto out;
+                       goto out_unlock;
                }
                /* Allocate the exact ID the driver gave us */
                if (xa_is_err(xa_store(&dev->ethtool->rss_ctx, rxfh_dev.rss_context,
                                       ctx, GFP_KERNEL))) {
                        kfree(ctx);
-                       goto out;
+                       goto out_unlock;
                }
 
                /* Fetch the defaults for the old API, in the new API drivers
                if (WARN_ON(ret)) {
                        xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
                        kfree(ctx);
-                       goto out;
+                       goto out_unlock;
                }
        }
        if (rxfh_dev.rss_delete) {
                        ctx->input_xfrm = rxfh_dev.input_xfrm;
        }
 
-out:
-       if (locked)
-               mutex_unlock(&dev->ethtool->rss_lock);
+out_unlock:
+       mutex_unlock(&dev->ethtool->rss_lock);
+out_free:
        kfree(rss_config);
        if (mod)
                ethtool_rss_notify(dev, rxfh.rss_context);