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. Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sfc/ethtool_common.c | 9 ++------- net/ethtool/ioctl.c | 15 ++++++++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c index 823263969f92..fa303e171d98 100644 --- a/drivers/net/ethernet/sfc/ethtool_common.c +++ b/drivers/net/ethernet/sfc/ethtool_common.c @@ -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; } diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index ce7d720b3c79..df376628ba19 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -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) -- 2.50.0