net/mlx5e: Support ETH_RSS_HASH_XOR

The ConnectX-4 HW implements inverted XOR8.
To make it act as XOR we re-order the HW RSS indirection table.

Set XOR to be the default RSS hash function and add ethtool API to
control it.

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Saeed Mahameed 2015-07-23 23:35:56 +03:00 committed by David S. Miller
parent fda19e83fb
commit 2be6967cdb
4 changed files with 79 additions and 13 deletions

View file

@ -195,6 +195,7 @@ struct mlx5e_params {
u16 rx_hash_log_tbl_sz; u16 rx_hash_log_tbl_sz;
bool lro_en; bool lro_en;
u32 lro_wqe_sz; u32 lro_wqe_sz;
u8 rss_hfunc;
}; };
enum { enum {

View file

@ -662,6 +662,43 @@ out:
return err; return err;
} }
static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
if (hfunc)
*hfunc = priv->params.rss_hfunc;
return 0;
}
static int mlx5e_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
int err = 0;
if (hfunc == ETH_RSS_HASH_NO_CHANGE)
return 0;
if ((hfunc != ETH_RSS_HASH_XOR) &&
(hfunc != ETH_RSS_HASH_TOP))
return -EINVAL;
mutex_lock(&priv->state_lock);
priv->params.rss_hfunc = hfunc;
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
mlx5e_close_locked(priv->netdev);
err = mlx5e_open_locked(priv->netdev);
}
mutex_unlock(&priv->state_lock);
return err;
}
const struct ethtool_ops mlx5e_ethtool_ops = { const struct ethtool_ops mlx5e_ethtool_ops = {
.get_drvinfo = mlx5e_get_drvinfo, .get_drvinfo = mlx5e_get_drvinfo,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
@ -676,4 +713,6 @@ 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 = mlx5e_get_rxfh,
.set_rxfh = mlx5e_set_rxfh,
}; };

View file

@ -1158,6 +1158,24 @@ static void mlx5e_close_tises(struct mlx5e_priv *priv)
mlx5e_close_tis(priv, tc); mlx5e_close_tis(priv, tc);
} }
static int mlx5e_rx_hash_fn(int hfunc)
{
return (hfunc == ETH_RSS_HASH_TOP) ?
MLX5_RX_HASH_FN_TOEPLITZ :
MLX5_RX_HASH_FN_INVERTED_XOR8;
}
static int mlx5e_bits_invert(unsigned long a, int size)
{
int inv = 0;
int i;
for (i = 0; i < size; i++)
inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;
return inv;
}
static int mlx5e_open_rqt(struct mlx5e_priv *priv) static int mlx5e_open_rqt(struct mlx5e_priv *priv)
{ {
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
@ -1166,11 +1184,10 @@ static int mlx5e_open_rqt(struct mlx5e_priv *priv)
void *rqtc; void *rqtc;
int inlen; int inlen;
int err; int err;
int sz; int log_tbl_sz = priv->params.rx_hash_log_tbl_sz;
int sz = 1 << log_tbl_sz;
int i; int i;
sz = 1 << priv->params.rx_hash_log_tbl_sz;
inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz; inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
in = mlx5_vzalloc(inlen); in = mlx5_vzalloc(inlen);
if (!in) if (!in)
@ -1182,8 +1199,12 @@ static int mlx5e_open_rqt(struct mlx5e_priv *priv)
MLX5_SET(rqtc, rqtc, rqt_max_size, sz); MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
int ix = i % priv->params.num_channels; int ix = i;
if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
ix = mlx5e_bits_invert(i, log_tbl_sz);
ix = ix % priv->params.num_channels;
MLX5_SET(rqtc, rqtc, rq_num[i], priv->channel[ix]->rq.rqn); MLX5_SET(rqtc, rqtc, rq_num[i], priv->channel[ix]->rq.rqn);
} }
@ -1254,12 +1275,16 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
MLX5_SET(tirc, tirc, indirect_table, MLX5_SET(tirc, tirc, indirect_table,
priv->rqtn); priv->rqtn);
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_SET(tirc, tirc, rx_hash_fn,
MLX5_TIRC_RX_HASH_FN_HASH_TOEPLITZ); mlx5e_rx_hash_fn(priv->params.rss_hfunc));
MLX5_SET(tirc, tirc, rx_hash_symmetric, 1); if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
netdev_rss_key_fill(MLX5_ADDR_OF(tirc, tirc, void *rss_key = MLX5_ADDR_OF(tirc, tirc,
rx_hash_toeplitz_key), rx_hash_toeplitz_key);
MLX5_FLD_SZ_BYTES(tirc, size_t len = MLX5_FLD_SZ_BYTES(tirc,
rx_hash_toeplitz_key)); rx_hash_toeplitz_key);
MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
netdev_rss_key_fill(rss_key, len);
}
break; break;
} }
@ -1700,6 +1725,7 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
MLX5E_PARAMS_DEFAULT_RX_HASH_LOG_TBL_SZ; MLX5E_PARAMS_DEFAULT_RX_HASH_LOG_TBL_SZ;
priv->params.num_tc = 1; priv->params.num_tc = 1;
priv->params.default_vlan_prio = 0; priv->params.default_vlan_prio = 0;
priv->params.rss_hfunc = ETH_RSS_HASH_XOR;
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 =

View file

@ -1936,9 +1936,9 @@ enum {
}; };
enum { enum {
MLX5_TIRC_RX_HASH_FN_HASH_NONE = 0x0, MLX5_RX_HASH_FN_NONE = 0x0,
MLX5_TIRC_RX_HASH_FN_HASH_INVERTED_XOR8 = 0x1, MLX5_RX_HASH_FN_INVERTED_XOR8 = 0x1,
MLX5_TIRC_RX_HASH_FN_HASH_TOEPLITZ = 0x2, MLX5_RX_HASH_FN_TOEPLITZ = 0x2,
}; };
enum { enum {