net/ethtool/common.c

Source file repositories/reference/linux-study-clean/net/ethtool/common.c

File Facts

System
Linux kernel
Corpus path
net/ethtool/common.c
Extension
.c
Size
47211 bytes
Lines
1403
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rule_info.flow_type & FLOW_RSS) {
				struct ethtool_rxfh_context *ctx;

				ctx = xa_load(&dev->ethtool->rss_ctx,
					      rule_info.rss_context);
				ring += ethtool_get_rss_ctx_max_channel(ctx);
			}
			max_ring = max_t(u64, max_ring, ring);
		}
	}

	kvfree(info);
	*max = max_ring;
	return 0;

err_free_info:
	kvfree(info);
	return err;
}

/* Max offset across all of a device's RSS contexts */
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)
		max_ring = max(max_ring, ethtool_get_rss_ctx_max_channel(ctx));
	mutex_unlock(&dev->ethtool->rss_lock);

	return max_ring;
}

static u32 ethtool_get_max_rxfh_channel(struct net_device *dev)
{
	struct ethtool_rxfh_param rxfh = {};
	u32 dev_size, current_max = 0;
	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 ||
	    !dev->ethtool_ops->get_rxfh)
		return current_max;
	dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
	if (dev_size == 0)
		return current_max;

	rxfh.indir = kzalloc_objs(rxfh.indir[0], dev_size, GFP_USER);
	if (!rxfh.indir)
		return U32_MAX;

	mutex_lock(&dev->ethtool->rss_lock);
	ret = dev->ethtool_ops->get_rxfh(dev, &rxfh);
	mutex_unlock(&dev->ethtool->rss_lock);
	if (ret) {
		current_max = U32_MAX;
		goto out_free;
	}

	while (dev_size--)
		current_max = max(current_max, rxfh.indir[dev_size]);

out_free:
	kfree(rxfh.indir);
	return current_max;
}

int ethtool_check_max_channel(struct net_device *dev,
			      struct ethtool_channels channels,
			      struct genl_info *info)
{
	u64 max_rxnfc_in_use;
	u32 max_rxfh_in_use;
	int max_mp_in_use;

	/* ensure the new Rx count fits within the configured Rx flow
	 * indirection table/rxnfc settings
	 */
	if (ethtool_get_max_rxnfc_channel(dev, &max_rxnfc_in_use))

Annotation

Implementation Notes