Commit 2d75b2bc authored by Achiad Shochat's avatar Achiad Shochat Committed by David S. Miller
Browse files

net/mlx5e: Add ethtool RSS configuration options



- get_rxfh_key_size
- get_rxfh_indir_size
- get/set_rxfh indirection table and RSS Toeplitz hash key
- get_rxnfc

Signed-off-by: default avatarAchiad Shochat <achiad@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 936896e9
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -272,9 +272,10 @@ struct mlx5e_params {
	u16 min_rx_wqes;
	u16 min_rx_wqes;
	bool lro_en;
	bool lro_en;
	u32 lro_wqe_sz;
	u32 lro_wqe_sz;
	u8  rss_hfunc;
	u16 tx_max_inline;
	u16 tx_max_inline;
	u8  rss_hfunc;
	u8  toeplitz_hash_key[40];
	u8  toeplitz_hash_key[40];
	u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
};
};


enum {
enum {
@@ -571,6 +572,8 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);


int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix);

int mlx5e_open_locked(struct net_device *netdev);
int mlx5e_open_locked(struct net_device *netdev);
int mlx5e_close_locked(struct net_device *netdev);
int mlx5e_close_locked(struct net_device *netdev);


+63 −8
Original line number Original line Diff line number Diff line
@@ -684,11 +684,31 @@ out:
	return err;
	return err;
}
}


static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

	return sizeof(priv->params.toeplitz_hash_key);
}

static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
{
	return MLX5E_INDIR_RQT_SIZE;
}

static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
			  u8 *hfunc)
			  u8 *hfunc)
{
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5e_priv *priv = netdev_priv(netdev);


	if (indir)
		memcpy(indir, priv->params.indirection_rqt,
		       sizeof(priv->params.indirection_rqt));

	if (key)
		memcpy(key, priv->params.toeplitz_hash_key,
		       sizeof(priv->params.toeplitz_hash_key));

	if (hfunc)
	if (hfunc)
		*hfunc = priv->params.rss_hfunc;
		*hfunc = priv->params.rss_hfunc;


@@ -699,28 +719,60 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
			  const u8 *key, const u8 hfunc)
			  const u8 *key, const u8 hfunc)
{
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5e_priv *priv = netdev_priv(dev);
	bool close_open;
	int err = 0;
	int err = 0;


	if (hfunc == ETH_RSS_HASH_NO_CHANGE)
	if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
		return 0;
	    (hfunc != ETH_RSS_HASH_XOR) &&

	if ((hfunc != ETH_RSS_HASH_XOR) &&
	    (hfunc != ETH_RSS_HASH_TOP))
	    (hfunc != ETH_RSS_HASH_TOP))
		return -EINVAL;
		return -EINVAL;


	mutex_lock(&priv->state_lock);
	mutex_lock(&priv->state_lock);


	priv->params.rss_hfunc = hfunc;
	if (indir) {
	if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
		memcpy(priv->params.indirection_rqt, indir,
		mlx5e_close_locked(dev);
		       sizeof(priv->params.indirection_rqt));
		err = mlx5e_open_locked(dev);
		mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
	}
	}


	close_open = (key || (hfunc != ETH_RSS_HASH_NO_CHANGE)) &&
		     test_bit(MLX5E_STATE_OPENED, &priv->state);
	if (close_open)
		mlx5e_close_locked(dev);

	if (key)
		memcpy(priv->params.toeplitz_hash_key, key,
		       sizeof(priv->params.toeplitz_hash_key));

	if (hfunc != ETH_RSS_HASH_NO_CHANGE)
		priv->params.rss_hfunc = hfunc;

	if (close_open)
		err = mlx5e_open_locked(priv->netdev);

	mutex_unlock(&priv->state_lock);
	mutex_unlock(&priv->state_lock);


	return err;
	return err;
}
}


static int mlx5e_get_rxnfc(struct net_device *netdev,
			   struct ethtool_rxnfc *info, u32 *rule_locs)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err = 0;

	switch (info->cmd) {
	case ETHTOOL_GRXRINGS:
		info->data = priv->params.num_channels;
		break;
	default:
		err = -EOPNOTSUPP;
		break;
	}

	return err;
}

static int mlx5e_get_tunable(struct net_device *dev,
static int mlx5e_get_tunable(struct net_device *dev,
			     const struct ethtool_tunable *tuna,
			     const struct ethtool_tunable *tuna,
			     void *data)
			     void *data)
@@ -793,8 +845,11 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
	.set_coalesce      = mlx5e_set_coalesce,
	.set_coalesce      = mlx5e_set_coalesce,
	.get_settings      = mlx5e_get_settings,
	.get_settings      = mlx5e_get_settings,
	.set_settings      = mlx5e_set_settings,
	.set_settings      = mlx5e_set_settings,
	.get_rxfh_key_size   = mlx5e_get_rxfh_key_size,
	.get_rxfh_indir_size = mlx5e_get_rxfh_indir_size,
	.get_rxfh          = mlx5e_get_rxfh,
	.get_rxfh          = mlx5e_get_rxfh,
	.set_rxfh          = mlx5e_set_rxfh,
	.set_rxfh          = mlx5e_set_rxfh,
	.get_rxnfc         = mlx5e_get_rxnfc,
	.get_tunable       = mlx5e_get_tunable,
	.get_tunable       = mlx5e_get_tunable,
	.set_tunable       = mlx5e_set_tunable,
	.set_tunable       = mlx5e_set_tunable,
};
};
+6 −1
Original line number Original line Diff line number Diff line
@@ -1184,6 +1184,7 @@ static void mlx5e_fill_indir_rqt_rqns(struct mlx5e_priv *priv, void *rqtc)
		if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
		if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
			ix = mlx5e_bits_invert(i, MLX5E_LOG_INDIR_RQT_SIZE);
			ix = mlx5e_bits_invert(i, MLX5E_LOG_INDIR_RQT_SIZE);


		ix = priv->params.indirection_rqt[ix];
		ix = ix % priv->params.num_channels;
		ix = ix % priv->params.num_channels;
		MLX5_SET(rqtc, rqtc, rq_num[i],
		MLX5_SET(rqtc, rqtc, rq_num[i],
			 test_bit(MLX5E_STATE_OPENED, &priv->state) ?
			 test_bit(MLX5E_STATE_OPENED, &priv->state) ?
@@ -1242,7 +1243,7 @@ static int mlx5e_create_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
	return err;
	return err;
}
}


static int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
{
{
	struct mlx5_core_dev *mdev = priv->mdev;
	struct mlx5_core_dev *mdev = priv->mdev;
	u32 *in;
	u32 *in;
@@ -1912,6 +1913,7 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
				    int num_channels)
				    int num_channels)
{
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int i;


	priv->params.log_sq_size           =
	priv->params.log_sq_size           =
		MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
		MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
@@ -1935,6 +1937,9 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
	netdev_rss_key_fill(priv->params.toeplitz_hash_key,
	netdev_rss_key_fill(priv->params.toeplitz_hash_key,
			    sizeof(priv->params.toeplitz_hash_key));
			    sizeof(priv->params.toeplitz_hash_key));


	for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
		priv->params.indirection_rqt[i] = i % num_channels;

	priv->params.lro_en = false && !!MLX5_CAP_ETH(priv->mdev, lro_cap);
	priv->params.lro_en = false && !!MLX5_CAP_ETH(priv->mdev, lro_cap);
	priv->params.lro_wqe_sz            =
	priv->params.lro_wqe_sz            =
		MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
		MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;