Commit afc55a06 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

eth: mlx5: migrate to the *_rxfh_context ops



Convert mlx5 to dedicated RXFH ops. This is a fairly shallow
conversion, TBH, most of the driver code stays as is, but we
let the core allocate the context ID for the driver.

mlx5e_rx_res_rss_get_rxfh() and friends are made void, since
core only calls the driver for context 0. The second call
is right after context creation so it must exist (tm).

Tested with drivers/net/hw/rss_ctx.py on MCX6.

Reviewed-by: default avatarGal Pressman <gal@nvidia.com>
Link: https://patch.msgid.link/20250707184115.2285277-4-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent be78c83a
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -567,7 +567,8 @@ int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss,
	return final_err;
}

int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
void mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc,
			bool *symmetric)
{
	if (indir)
		memcpy(indir, rss->indir.table,
@@ -582,8 +583,6 @@ int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bo

	if (symmetric)
		*symmetric = rss->hash.symmetric;

	return 0;
}

int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,
+2 −1
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ void mlx5e_rss_disable(struct mlx5e_rss *rss);

int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss,
				     struct mlx5e_packet_merge_param *pkt_merge_param);
int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc, bool *symmetric);
void mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc,
			bool *symmetric);
int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir,
		       const u8 *key, const u8 *hfunc, const bool *symmetric,
		       u32 *rqns, u32 *vhca_ids, unsigned int num_rqns);
+11 −19
Original line number Diff line number Diff line
@@ -71,17 +71,12 @@ static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res,
	return 0;
}

int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch)
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 rss_idx, unsigned int init_nch)
{
	bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT;
	struct mlx5e_rss *rss;
	int i;

	for (i = 1; i < MLX5E_MAX_NUM_RSS; i++)
		if (!res->rss[i])
			break;

	if (i == MLX5E_MAX_NUM_RSS)
	if (WARN_ON_ONCE(res->rss[rss_idx]))
		return -ENOSPC;

	rss = mlx5e_rss_init(res->mdev, inner_ft_support, res->drop_rqn,
@@ -97,8 +92,7 @@ int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int i
		mlx5e_rss_enable(rss, res->rss_rqns, vhca_ids, res->rss_nch);
	}

	res->rss[i] = rss;
	*rss_idx = i;
	res->rss[rss_idx] = rss;

	return 0;
}
@@ -193,19 +187,17 @@ void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int n
	mlx5e_rss_set_indir_uniform(res->rss[0], nch);
}

int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
			       u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
{
	struct mlx5e_rss *rss;

	if (rss_idx >= MLX5E_MAX_NUM_RSS)
		return -EINVAL;
	struct mlx5e_rss *rss = NULL;

	if (rss_idx < MLX5E_MAX_NUM_RSS)
		rss = res->rss[rss_idx];
	if (!rss)
		return -ENOENT;
	if (WARN_ON_ONCE(!rss))
		return;

	return mlx5e_rss_get_rxfh(rss, indir, key, hfunc, symmetric);
	mlx5e_rss_get_rxfh(rss, indir, key, hfunc, symmetric);
}

int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
+4 −3
Original line number Diff line number Diff line
@@ -48,8 +48,9 @@ void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *ch

/* Configuration API */
void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch);
int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
			      u32 *indir, u8 *key, u8 *hfunc, bool *symmetric);
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
			       u32 *indir, u8 *key, u8 *hfunc,
			       bool *symmetric);
int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
			      const u32 *indir, const u8 *key, const u8 *hfunc,
			      const bool *symmetric);
@@ -61,7 +62,7 @@ int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res,
					struct mlx5e_packet_merge_param *pkt_merge_param);

int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch);
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 rss_idx, unsigned int init_nch);
int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx);
int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res);
int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss);
+106 −29
Original line number Diff line number Diff line
@@ -1480,61 +1480,121 @@ static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
static int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	u32 rss_context = rxfh->rss_context;
	bool symmetric;
	int err;

	mutex_lock(&priv->state_lock);
	err = mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rss_context,
					rxfh->indir, rxfh->key, &rxfh->hfunc, &symmetric);
	mlx5e_rx_res_rss_get_rxfh(priv->rx_res, 0, rxfh->indir, rxfh->key,
				  &rxfh->hfunc, &symmetric);
	mutex_unlock(&priv->state_lock);

	if (err)
		return err;

	if (symmetric)
		rxfh->input_xfrm = RXH_XFRM_SYM_OR_XOR;

	return 0;
}

static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
			  struct netlink_ext_ack *extack)
static int mlx5e_rxfh_hfunc_check(struct mlx5e_priv *priv,
				  const struct ethtool_rxfh_param *rxfh)
{
	bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
	struct mlx5e_priv *priv = netdev_priv(dev);
	u32 *rss_context = &rxfh->rss_context;
	u8 hfunc = rxfh->hfunc;
	unsigned int count;
	int err;

	mutex_lock(&priv->state_lock);

	count = priv->channels.params.num_channels;

	if (hfunc == ETH_RSS_HASH_XOR) {
	if (rxfh->hfunc == ETH_RSS_HASH_XOR) {
		unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();

		if (count > xor8_max_channels) {
			err = -EINVAL;
			netdev_err(priv->netdev, "%s: Cannot set RSS hash function to XOR, current number of channels (%d) exceeds the maximum allowed for XOR8 RSS hfunc (%d)\n",
				   __func__, count, xor8_max_channels);
			goto unlock;
			return -EINVAL;
		}
	}

	if (*rss_context && rxfh->rss_delete) {
		err = mlx5e_rx_res_rss_destroy(priv->rx_res, *rss_context);
	return 0;
}

static int mlx5e_set_rxfh(struct net_device *dev,
			  struct ethtool_rxfh_param *rxfh,
			  struct netlink_ext_ack *extack)
{
	bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
	struct mlx5e_priv *priv = netdev_priv(dev);
	u8 hfunc = rxfh->hfunc;
	int err;

	mutex_lock(&priv->state_lock);

	err = mlx5e_rxfh_hfunc_check(priv, rxfh);
	if (err)
		goto unlock;

	err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
					rxfh->indir, rxfh->key,
					hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
					rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);

unlock:
	mutex_unlock(&priv->state_lock);
	return err;
}

	if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
		err = mlx5e_rx_res_rss_init(priv->rx_res, rss_context, count);
static int mlx5e_create_rxfh_context(struct net_device *dev,
				     struct ethtool_rxfh_context *ctx,
				     const struct ethtool_rxfh_param *rxfh,
				     struct netlink_ext_ack *extack)
{
	bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
	struct mlx5e_priv *priv = netdev_priv(dev);
	u8 hfunc = rxfh->hfunc;
	int err;

	mutex_lock(&priv->state_lock);

	err = mlx5e_rxfh_hfunc_check(priv, rxfh);
	if (err)
		goto unlock;

	err = mlx5e_rx_res_rss_init(priv->rx_res, rxfh->rss_context,
				    priv->channels.params.num_channels);
	if (err)
		goto unlock;

	err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
					rxfh->indir, rxfh->key,
					hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
					rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
	if (err)
		goto unlock;

	mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rxfh->rss_context,
				  ethtool_rxfh_context_indir(ctx),
				  ethtool_rxfh_context_key(ctx),
				  &ctx->hfunc, &symmetric);
	if (symmetric)
		ctx->input_xfrm = RXH_XFRM_SYM_OR_XOR;

unlock:
	mutex_unlock(&priv->state_lock);
	return err;
}

	err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, *rss_context,
static int mlx5e_modify_rxfh_context(struct net_device *dev,
				     struct ethtool_rxfh_context *ctx,
				     const struct ethtool_rxfh_param *rxfh,
				     struct netlink_ext_ack *extack)
{
	bool symmetric = rxfh->input_xfrm == RXH_XFRM_SYM_OR_XOR;
	struct mlx5e_priv *priv = netdev_priv(dev);
	u8 hfunc = rxfh->hfunc;
	int err;

	mutex_lock(&priv->state_lock);

	err = mlx5e_rxfh_hfunc_check(priv, rxfh);
	if (err)
		goto unlock;

	err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
					rxfh->indir, rxfh->key,
					hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
					rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
@@ -1544,6 +1604,20 @@ static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxf
	return err;
}

static int mlx5e_remove_rxfh_context(struct net_device *dev,
				     struct ethtool_rxfh_context *ctx,
				     u32 rss_context,
				     struct netlink_ext_ack *extack)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	int err;

	mutex_lock(&priv->state_lock);
	err = mlx5e_rx_res_rss_destroy(priv->rx_res, rss_context);
	mutex_unlock(&priv->state_lock);
	return err;
}

#define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC		100
#define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC		8000
#define MLX5E_PFC_PREVEN_MINOR_PRECENT		85
@@ -2654,9 +2728,9 @@ static void mlx5e_get_ts_stats(struct net_device *netdev,

const struct ethtool_ops mlx5e_ethtool_ops = {
	.cap_link_lanes_supported = true,
	.cap_rss_ctx_supported	= true,
	.rxfh_per_ctx_fields	= true,
	.rxfh_per_ctx_key	= true,
	.rxfh_max_num_contexts	= MLX5E_MAX_NUM_RSS,
	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
				     ETHTOOL_COALESCE_MAX_FRAMES |
				     ETHTOOL_COALESCE_USE_ADAPTIVE |
@@ -2685,6 +2759,9 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
	.set_rxfh          = mlx5e_set_rxfh,
	.get_rxfh_fields   = mlx5e_get_rxfh_fields,
	.set_rxfh_fields   = mlx5e_set_rxfh_fields,
	.create_rxfh_context	= mlx5e_create_rxfh_context,
	.modify_rxfh_context	= mlx5e_modify_rxfh_context,
	.remove_rxfh_context	= mlx5e_remove_rxfh_context,
	.get_rxnfc         = mlx5e_get_rxnfc,
	.set_rxnfc         = mlx5e_set_rxnfc,
	.get_tunable       = mlx5e_get_tunable,