* @supported_input_xfrm: supported types of input xfrm from %RXH_XFRM_*.
* @cap_link_lanes_supported: indicates if the driver supports lanes
* parameter.
- * @cap_rss_ctx_supported: indicates if the driver supports RSS
- * contexts via legacy API, drivers implementing @create_rxfh_context
- * do not have to set this bit.
* @rxfh_per_ctx_fields: device supports selecting different header fields
* for Rx hash calculation and RSS for each additional context.
* @rxfh_per_ctx_key: device supports setting different RSS key for each
struct ethtool_ops {
u32 supported_input_xfrm:8;
u32 cap_link_lanes_supported:1;
- u32 cap_rss_ctx_supported:1;
u32 rxfh_per_ctx_fields:1;
u32 rxfh_per_ctx_key:1;
u32 cap_rss_rxnfc_adds:1;
mutex_lock(&dev->ethtool->rss_lock);
xa_for_each(&dev->ethtool->rss_ctx, context, ctx) {
- struct ethtool_rxfh_param rxfh;
-
- rxfh.indir = ethtool_rxfh_context_indir(ctx);
- rxfh.key = ethtool_rxfh_context_key(ctx);
- rxfh.hfunc = ctx->hfunc;
- rxfh.input_xfrm = ctx->input_xfrm;
- rxfh.rss_context = context;
- rxfh.rss_delete = true;
-
xa_erase(&dev->ethtool->rss_ctx, context);
- if (dev->ethtool_ops->create_rxfh_context)
- dev->ethtool_ops->remove_rxfh_context(dev, ctx,
- context, NULL);
- else
- dev->ethtool_ops->set_rxfh(dev, &rxfh, NULL);
+ dev->ethtool_ops->remove_rxfh_context(dev, ctx, context, NULL);
kfree(ctx);
}
xa_destroy(&dev->ethtool->rss_ctx);
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
return -EINVAL;
/* Most drivers don't handle rss_context, check it's 0 as well */
- if (rxfh.rss_context && !(ops->cap_rss_ctx_supported ||
- ops->create_rxfh_context))
+ if (rxfh.rss_context && !ops->create_rxfh_context)
return -EOPNOTSUPP;
rxfh.indir_size = rxfh_dev.indir_size;
if (rxfh.rsvd8[0] || rxfh.rsvd8[1] || rxfh.rsvd32)
return -EINVAL;
/* Most drivers don't handle rss_context, check it's 0 as well */
- if (rxfh.rss_context && !(ops->cap_rss_ctx_supported ||
- ops->create_rxfh_context))
+ if (rxfh.rss_context && !ops->create_rxfh_context)
return -EOPNOTSUPP;
/* Check input data transformation capabilities */
if (rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_SYM_XOR &&
}
if (create) {
+ u32 limit, ctx_id;
+
if (rxfh_dev.rss_delete) {
ret = -EINVAL;
goto out_unlock;
goto out_unlock;
}
- if (ops->create_rxfh_context) {
- u32 limit = ops->rxfh_max_num_contexts ?: U32_MAX;
- u32 ctx_id;
-
- /* driver uses new API, core allocates ID */
- ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
- XA_LIMIT(1, limit - 1),
- GFP_KERNEL_ACCOUNT);
- if (ret < 0) {
- kfree(ctx);
- goto out_unlock;
- }
- WARN_ON(!ctx_id); /* can't happen */
- rxfh.rss_context = ctx_id;
+ limit = ops->rxfh_max_num_contexts ?: U32_MAX;
+ ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
+ XA_LIMIT(1, limit - 1), GFP_KERNEL_ACCOUNT);
+ if (ret < 0) {
+ kfree(ctx);
+ goto out_unlock;
}
+ WARN_ON(!ctx_id); /* can't happen */
+ rxfh.rss_context = ctx_id;
} else if (rxfh.rss_context) {
ctx = xa_load(&dev->ethtool->rss_ctx, rxfh.rss_context);
if (!ctx) {
rxfh_dev.rss_context = rxfh.rss_context;
rxfh_dev.input_xfrm = rxfh.input_xfrm;
- if (rxfh.rss_context && ops->create_rxfh_context) {
+ if (rxfh.rss_context) {
if (create) {
ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev,
extack);
if (ret) {
if (create) {
/* failed to create, free our new tracking entry */
- if (ops->create_rxfh_context)
- xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
+ xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
kfree(ctx);
}
goto out_unlock;
dev->priv_flags |= IFF_RXFH_CONFIGURED;
}
/* Update rss_ctx tracking */
- if (create && !ops->create_rxfh_context) {
- /* driver uses old API, it chose context ID */
- if (WARN_ON(xa_load(&dev->ethtool->rss_ctx, rxfh_dev.rss_context))) {
- /* context ID reused, our tracking is screwed */
- kfree(ctx);
- 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_unlock;
- }
-
- /* Fetch the defaults for the old API, in the new API drivers
- * should write defaults into ctx themselves.
- */
- rxfh_dev.indir = (u32 *)rss_config;
- rxfh_dev.indir_size = dev_indir_size;
-
- rxfh_dev.key = rss_config + indir_bytes;
- rxfh_dev.key_size = dev_key_size;
-
- ret = ops->get_rxfh(dev, &rxfh_dev);
- if (WARN_ON(ret)) {
- xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context);
- kfree(ctx);
- goto out_unlock;
- }
- }
if (rxfh_dev.rss_delete) {
WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context) != ctx);
kfree(ctx);