forked from Minki/linux
net/mlx4_en: Support for configurable RSS hash function
The ConnectX HW is capable of using one of the following hash functions: Toeplitz and an XOR hash function. This patch extends the implementation of the mlx4_en driver set/get_rxfh callbacks to support getting and setting the RSS hash function used by the device. Signed-off-by: Eyal Perry <eyalpe@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
892311f66f
commit
947cbb0ac2
@ -978,6 +978,27 @@ static u32 mlx4_en_get_rxfh_key_size(struct net_device *netdev)
|
||||
return MLX4_EN_RSS_KEY_SIZE;
|
||||
}
|
||||
|
||||
static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* check if requested function is supported by the device */
|
||||
if ((hfunc == ETH_RSS_HASH_TOP &&
|
||||
!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP)) ||
|
||||
(hfunc == ETH_RSS_HASH_XOR &&
|
||||
!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR)))
|
||||
return -EINVAL;
|
||||
|
||||
priv->rss_hash_fn = hfunc;
|
||||
if (hfunc == ETH_RSS_HASH_TOP && !(dev->features & NETIF_F_RXHASH))
|
||||
en_warn(priv,
|
||||
"Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
|
||||
if (hfunc == ETH_RSS_HASH_XOR && (dev->features & NETIF_F_RXHASH))
|
||||
en_warn(priv,
|
||||
"Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
@ -999,7 +1020,7 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
|
||||
if (key)
|
||||
memcpy(key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE);
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
*hfunc = priv->rss_hash_fn;
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1013,10 +1034,6 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
|
||||
int i;
|
||||
int rss_rings = 0;
|
||||
|
||||
/* We do not allow change in unsupported parameters */
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Calculate RSS table size and make sure flows are spread evenly
|
||||
* between rings
|
||||
*/
|
||||
@ -1037,6 +1054,12 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
|
||||
if (!is_power_of_2(rss_rings))
|
||||
return -EINVAL;
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
|
||||
err = mlx4_en_check_rxfh_func(dev, hfunc);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
mutex_lock(&mdev->state_lock);
|
||||
if (priv->port_up) {
|
||||
port_up = 1;
|
||||
@ -1047,6 +1070,7 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
|
||||
priv->prof->rss_rings = rss_rings;
|
||||
if (key)
|
||||
memcpy(priv->rss_key, key, MLX4_EN_RSS_KEY_SIZE);
|
||||
|
||||
if (port_up) {
|
||||
err = mlx4_en_start_port(dev);
|
||||
if (err)
|
||||
|
@ -2608,6 +2608,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||
if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
|
||||
dev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
/* Setting a default hash function value */
|
||||
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP) {
|
||||
priv->rss_hash_fn = ETH_RSS_HASH_TOP;
|
||||
} else if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR) {
|
||||
priv->rss_hash_fn = ETH_RSS_HASH_XOR;
|
||||
} else {
|
||||
en_warn(priv,
|
||||
"No RSS hash capabilities exposed, using Toeplitz\n");
|
||||
priv->rss_hash_fn = ETH_RSS_HASH_TOP;
|
||||
}
|
||||
|
||||
mdev->pndev[port] = dev;
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
@ -1223,7 +1223,19 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
|
||||
|
||||
rss_context->flags = rss_mask;
|
||||
rss_context->hash_fn = MLX4_RSS_HASH_TOP;
|
||||
memcpy(rss_context->rss_key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE);
|
||||
if (priv->rss_hash_fn == ETH_RSS_HASH_XOR) {
|
||||
rss_context->hash_fn = MLX4_RSS_HASH_XOR;
|
||||
} else if (priv->rss_hash_fn == ETH_RSS_HASH_TOP) {
|
||||
rss_context->hash_fn = MLX4_RSS_HASH_TOP;
|
||||
memcpy(rss_context->rss_key, priv->rss_key,
|
||||
MLX4_EN_RSS_KEY_SIZE);
|
||||
netdev_rss_key_fill(rss_context->rss_key,
|
||||
MLX4_EN_RSS_KEY_SIZE);
|
||||
} else {
|
||||
en_err(priv, "Unknown RSS hash function requested\n");
|
||||
err = -EINVAL;
|
||||
goto indir_err;
|
||||
}
|
||||
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
|
||||
&rss_map->indir_qp, &rss_map->indir_state);
|
||||
if (err)
|
||||
|
@ -376,7 +376,6 @@ struct mlx4_en_port_profile {
|
||||
};
|
||||
|
||||
struct mlx4_en_profile {
|
||||
int rss_xor;
|
||||
int udp_rss;
|
||||
u8 rss_mask;
|
||||
u32 active_ports;
|
||||
@ -619,6 +618,7 @@ struct mlx4_en_priv {
|
||||
|
||||
u32 pflags;
|
||||
u8 rss_key[MLX4_EN_RSS_KEY_SIZE];
|
||||
u8 rss_hash_fn;
|
||||
};
|
||||
|
||||
enum mlx4_en_wol {
|
||||
|
Loading…
Reference in New Issue
Block a user