Commit 6937693d authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'ethtool-use-the-rss-context-xarray-in-ring-deactivation-safety-check'

Jakub Kicinski says:

====================
ethtool: use the rss context XArray in ring deactivation safety-check

Now that we have an XArray storing information about all extra
RSS contexts - use it to extend checks already performed using
ethtool_get_max_rxfh_channel().
====================

Link: https://patch.msgid.link/20240710174043.754664-1-kuba@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7c826727 24ac7e54
...@@ -171,11 +171,9 @@ ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info) ...@@ -171,11 +171,9 @@ ethnl_set_channels(struct ethnl_req_info *req_info, struct genl_info *info)
*/ */
if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use)) if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use))
max_rxnfc_in_use = 0; max_rxnfc_in_use = 0;
if (!netif_is_rxfh_configured(dev) || max_rxfh_in_use = ethtool_get_max_rxfh_channel(dev);
ethtool_get_max_rxfh_channel(dev, &max_rxfh_in_use))
max_rxfh_in_use = 0;
if (channels.combined_count + channels.rx_count <= max_rxfh_in_use) { if (channels.combined_count + channels.rx_count <= max_rxfh_in_use) {
GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing indirection table settings"); GENL_SET_ERR_MSG_FMT(info, "requested channel counts are too low for existing indirection table (%d)", max_rxfh_in_use);
return -EINVAL; return -EINVAL;
} }
if (channels.combined_count + channels.rx_count <= max_rxnfc_in_use) { if (channels.combined_count + channels.rx_count <= max_rxnfc_in_use) {
......
...@@ -587,35 +587,64 @@ int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max) ...@@ -587,35 +587,64 @@ int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max)
return err; return err;
} }
int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max) static u32 ethtool_get_max_rss_ctx_channel(struct net_device *dev)
{
struct ethtool_rxfh_context *ctx;
unsigned long context;
u32 max_ring = 0;
mutex_lock(&dev->ethtool->rss_lock);
xa_for_each(&dev->ethtool->rss_ctx, context, ctx) {
u32 i, *tbl;
tbl = ethtool_rxfh_context_indir(ctx);
for (i = 0; i < ctx->indir_size; i++)
max_ring = max(max_ring, tbl[i]);
}
mutex_unlock(&dev->ethtool->rss_lock);
return max_ring;
}
u32 ethtool_get_max_rxfh_channel(struct net_device *dev)
{ {
struct ethtool_rxfh_param rxfh = {}; struct ethtool_rxfh_param rxfh = {};
u32 dev_size, current_max = 0; u32 dev_size, current_max;
int ret; int ret;
/* While we do track whether RSS context has an indirection
* table explicitly set by the user, no driver looks at that bit.
* Assume drivers won't auto-regenerate the additional tables,
* to be safe.
*/
current_max = ethtool_get_max_rss_ctx_channel(dev);
if (!netif_is_rxfh_configured(dev))
return current_max;
if (!dev->ethtool_ops->get_rxfh_indir_size || if (!dev->ethtool_ops->get_rxfh_indir_size ||
!dev->ethtool_ops->get_rxfh) !dev->ethtool_ops->get_rxfh)
return -EOPNOTSUPP; return current_max;
dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev); dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
if (dev_size == 0) if (dev_size == 0)
return -EOPNOTSUPP; return current_max;
rxfh.indir = kcalloc(dev_size, sizeof(rxfh.indir[0]), GFP_USER); rxfh.indir = kcalloc(dev_size, sizeof(rxfh.indir[0]), GFP_USER);
if (!rxfh.indir) if (!rxfh.indir)
return -ENOMEM; return U32_MAX;
ret = dev->ethtool_ops->get_rxfh(dev, &rxfh); ret = dev->ethtool_ops->get_rxfh(dev, &rxfh);
if (ret) if (ret) {
goto out; current_max = U32_MAX;
goto out_free;
}
while (dev_size--) while (dev_size--)
current_max = max(current_max, rxfh.indir[dev_size]); current_max = max(current_max, rxfh.indir[dev_size]);
*max = current_max; out_free:
out:
kfree(rxfh.indir); kfree(rxfh.indir);
return ret; return current_max;
} }
int ethtool_check_ops(const struct ethtool_ops *ops) int ethtool_check_ops(const struct ethtool_ops *ops)
......
...@@ -42,7 +42,7 @@ int __ethtool_get_link(struct net_device *dev); ...@@ -42,7 +42,7 @@ int __ethtool_get_link(struct net_device *dev);
bool convert_legacy_settings_to_link_ksettings( bool convert_legacy_settings_to_link_ksettings(
struct ethtool_link_ksettings *link_ksettings, struct ethtool_link_ksettings *link_ksettings,
const struct ethtool_cmd *legacy_settings); const struct ethtool_cmd *legacy_settings);
int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max); u32 ethtool_get_max_rxfh_channel(struct net_device *dev);
int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max); int ethtool_get_max_rxnfc_channel(struct net_device *dev, u64 *max);
int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info); int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info);
......
...@@ -2049,9 +2049,7 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev, ...@@ -2049,9 +2049,7 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
* indirection table/rxnfc settings */ * indirection table/rxnfc settings */
if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use)) if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use))
max_rxnfc_in_use = 0; max_rxnfc_in_use = 0;
if (!netif_is_rxfh_configured(dev) || max_rxfh_in_use = ethtool_get_max_rxfh_channel(dev);
ethtool_get_max_rxfh_channel(dev, &max_rxfh_in_use))
max_rxfh_in_use = 0;
if (channels.combined_count + channels.rx_count <= if (channels.combined_count + channels.rx_count <=
max_t(u64, max_rxnfc_in_use, max_rxfh_in_use)) max_t(u64, max_rxnfc_in_use, max_rxfh_in_use))
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment