Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba5dfaff authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5e-updates-2018-12-04' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5e-updates-2018-12-04

This series includes updates to mlx5e netdevice driver

From Saeed, Remove trailing space of tx_pause ethtool stat
From Gal, Cleanup unused defines
From Aya, ethtool Support for configuring of RX hash fields
From Tariq, Improve ethtool private-flags code structure
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7127f2fe 8ff57c18
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#include <net/switchdev.h>
#include <net/xdp.h>
#include <linux/net_dim.h>
#include <linux/bits.h>
#include "wq.h"
#include "mlx5_core.h"
#include "en_stats.h"
@@ -147,9 +148,6 @@ struct page_pool;
	       MLX5_UMR_MTT_ALIGNMENT))
#define MLX5E_UMR_WQEBBS \
	(DIV_ROUND_UP(MLX5E_UMR_WQE_INLINE_SZ, MLX5_SEND_WQE_BB))
#define MLX5E_ICOSQ_MAX_WQEBBS MLX5E_UMR_WQEBBS

#define MLX5E_NUM_MAIN_GROUPS 9

#define MLX5E_MSG_LEVEL			NETIF_MSG_LINK

@@ -214,22 +212,23 @@ struct mlx5e_umr_wqe {
extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];

enum mlx5e_priv_flag {
	MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
	MLX5E_PFLAG_TX_CQE_BASED_MODER = (1 << 1),
	MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 2),
	MLX5E_PFLAG_RX_STRIDING_RQ = (1 << 3),
	MLX5E_PFLAG_RX_NO_CSUM_COMPLETE = (1 << 4),
	MLX5E_PFLAG_RX_CQE_BASED_MODER,
	MLX5E_PFLAG_TX_CQE_BASED_MODER,
	MLX5E_PFLAG_RX_CQE_COMPRESS,
	MLX5E_PFLAG_RX_STRIDING_RQ,
	MLX5E_PFLAG_RX_NO_CSUM_COMPLETE,
	MLX5E_NUM_PFLAGS, /* Keep last */
};

#define MLX5E_SET_PFLAG(params, pflag, enable)			\
	do {							\
		if (enable)					\
			(params)->pflags |= (pflag);		\
			(params)->pflags |= BIT(pflag);		\
		else						\
			(params)->pflags &= ~(pflag);		\
			(params)->pflags &= ~(BIT(pflag));	\
	} while (0)

#define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (pflag)))
#define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (BIT(pflag))))

#ifdef CONFIG_MLX5_CORE_EN_DCB
#define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
@@ -247,9 +246,6 @@ struct mlx5e_params {
	bool lro_en;
	u32 lro_wqe_sz;
	u8  tx_min_inline_mode;
	u8  rss_hfunc;
	u8  toeplitz_hash_key[40];
	u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
	bool vlan_strip_disable;
	bool scatter_fcs_en;
	bool rx_dim_enabled;
@@ -654,6 +650,13 @@ enum {
	MLX5E_NIC_PRIO
};

struct mlx5e_rss_params {
	u32	indirection_rqt[MLX5E_INDIR_RQT_SIZE];
	u32	rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
	u8	toeplitz_hash_key[40];
	u8	hfunc;
};

struct mlx5e_priv {
	/* priv data path fields - start */
	struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
@@ -674,6 +677,7 @@ struct mlx5e_priv {
	struct mlx5e_tir           indir_tir[MLX5E_NUM_INDIR_TIRS];
	struct mlx5e_tir           inner_indir_tir[MLX5E_NUM_INDIR_TIRS];
	struct mlx5e_tir           direct_tir[MLX5E_MAX_NUM_CHANNELS];
	struct mlx5e_rss_params    rss_params;
	u32                        tx_rates[MLX5E_MAX_NUM_SQS];

	struct mlx5e_flow_steering fs;
@@ -799,9 +803,11 @@ struct mlx5e_redirect_rqt_param {

int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz,
		       struct mlx5e_redirect_rqt_param rrp);
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
				    enum mlx5e_traffic_types tt,
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
				    const struct mlx5e_tirc_config *ttconfig,
				    void *tirc, bool inner);
void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen);
struct mlx5e_tirc_config mlx5e_tirc_get_default_config(enum mlx5e_traffic_types tt);

int mlx5e_open_locked(struct net_device *netdev);
int mlx5e_close_locked(struct net_device *netdev);
@@ -983,11 +989,13 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv);
void mlx5e_detach_netdev(struct mlx5e_priv *priv);
void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
			    struct mlx5e_rss_params *rss_params,
			    struct mlx5e_params *params,
			    u16 max_channels, u16 mtu);
void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
			   struct mlx5e_params *params);
void mlx5e_build_rss_params(struct mlx5e_params *params);
void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
			    u16 num_channels);
u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev);
void mlx5e_rx_dim_work(struct work_struct *work);
void mlx5e_tx_dim_work(struct work_struct *work);
+16 −0
Original line number Diff line number Diff line
@@ -73,6 +73,22 @@ enum mlx5e_traffic_types {
	MLX5E_NUM_INDIR_TIRS = MLX5E_TT_ANY,
};

struct mlx5e_tirc_config {
	u8 l3_prot_type;
	u8 l4_prot_type;
	u32 rx_hash_fields;
};

#define MLX5_HASH_IP		(MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP)
#define MLX5_HASH_IP_L4PORTS	(MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_L4_SPORT |\
				 MLX5_HASH_FIELD_SEL_L4_DPORT)
#define MLX5_HASH_IP_IPSEC_SPI	(MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_IPSEC_SPI)

enum mlx5e_tunnel_types {
	MLX5E_TT_IPV4_GRE,
	MLX5E_TT_IPV6_GRE,
+48 −87
Original line number Diff line number Diff line
@@ -135,14 +135,15 @@ void mlx5e_build_ptys2ethtool_map(void)
				       ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT);
}

static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
	"rx_cqe_moder",
	"tx_cqe_moder",
	"rx_cqe_compress",
	"rx_striding_rq",
	"rx_no_csum_complete",
typedef int (*mlx5e_pflag_handler)(struct net_device *netdev, bool enable);

struct pflag_desc {
	char name[ETH_GSTRING_LEN];
	mlx5e_pflag_handler handler;
};

static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS];

int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset)
{
	int i, num_stats = 0;
@@ -153,7 +154,7 @@ int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset)
			num_stats += mlx5e_stats_grps[i].get_num_stats(priv);
		return num_stats;
	case ETH_SS_PRIV_FLAGS:
		return ARRAY_SIZE(mlx5e_priv_flags);
		return MLX5E_NUM_PFLAGS;
	case ETH_SS_TEST:
		return mlx5e_self_test_num(priv);
	/* fallthrough */
@@ -183,8 +184,9 @@ void mlx5e_ethtool_get_strings(struct mlx5e_priv *priv, u32 stringset, u8 *data)

	switch (stringset) {
	case ETH_SS_PRIV_FLAGS:
		for (i = 0; i < ARRAY_SIZE(mlx5e_priv_flags); i++)
			strcpy(data + i * ETH_GSTRING_LEN, mlx5e_priv_flags[i]);
		for (i = 0; i < MLX5E_NUM_PFLAGS; i++)
			strcpy(data + i * ETH_GSTRING_LEN,
			       mlx5e_priv_flags[i].name);
		break;

	case ETH_SS_TEST:
@@ -353,7 +355,7 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
	new_channels.params = priv->channels.params;
	new_channels.params.num_channels = count;
	if (!netif_is_rxfh_configured(priv->netdev))
		mlx5e_build_default_indir_rqt(new_channels.params.indirection_rqt,
		mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
					      MLX5E_INDIR_RQT_SIZE, count);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
@@ -931,7 +933,7 @@ static int mlx5e_set_link_ksettings(struct net_device *netdev,

u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv)
{
	return sizeof(priv->channels.params.toeplitz_hash_key);
	return sizeof(priv->rss_params.toeplitz_hash_key);
}

static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev)
@@ -957,50 +959,27 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
			  u8 *hfunc)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5e_rss_params *rss = &priv->rss_params;

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

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

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

	return 0;
}

static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
{
	void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
	struct mlx5_core_dev *mdev = priv->mdev;
	int ctxlen = MLX5_ST_SZ_BYTES(tirc);
	int tt;

	MLX5_SET(modify_tir_in, in, bitmask.hash, 1);

	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(tirc, 0, ctxlen);
		mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, false);
		mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
	}

	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
		return;

	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(tirc, 0, ctxlen);
		mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, true);
		mlx5_core_modify_tir(mdev, priv->inner_indir_tir[tt].tirn, in, inlen);
	}
}

static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
			  const u8 *key, const u8 hfunc)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5e_rss_params *rss = &priv->rss_params;
	int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
	bool hash_changed = false;
	void *in;
@@ -1016,15 +995,14 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,

	mutex_lock(&priv->state_lock);

	if (hfunc != ETH_RSS_HASH_NO_CHANGE &&
	    hfunc != priv->channels.params.rss_hfunc) {
		priv->channels.params.rss_hfunc = hfunc;
	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != rss->hfunc) {
		rss->hfunc = hfunc;
		hash_changed = true;
	}

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

		if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
			u32 rqtn = priv->indir_rqt.rqtn;
@@ -1032,7 +1010,7 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
				.is_rss = true,
				{
					.rss = {
						.hfunc = priv->channels.params.rss_hfunc,
						.hfunc = rss->hfunc,
						.channels  = &priv->channels,
					},
				},
@@ -1043,10 +1021,9 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
	}

	if (key) {
		memcpy(priv->channels.params.toeplitz_hash_key, key,
		       sizeof(priv->channels.params.toeplitz_hash_key));
		hash_changed = hash_changed ||
			       priv->channels.params.rss_hfunc == ETH_RSS_HASH_TOP;
		memcpy(rss->toeplitz_hash_key, key,
		       sizeof(rss->toeplitz_hash_key));
		hash_changed = hash_changed || rss->hfunc == ETH_RSS_HASH_TOP;
	}

	if (hash_changed)
@@ -1510,8 +1487,6 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
	return 0;
}

typedef int (*mlx5e_pflag_handler)(struct net_device *netdev, bool enable);

static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
				     bool is_rx_cq)
{
@@ -1674,23 +1649,30 @@ static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
	return 0;
}

static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = {
	{ "rx_cqe_moder",        set_pflag_rx_cqe_based_moder },
	{ "tx_cqe_moder",        set_pflag_tx_cqe_based_moder },
	{ "rx_cqe_compress",     set_pflag_rx_cqe_compress },
	{ "rx_striding_rq",      set_pflag_rx_striding_rq },
	{ "rx_no_csum_complete", set_pflag_rx_no_csum_complete },
};

static int mlx5e_handle_pflag(struct net_device *netdev,
			      u32 wanted_flags,
			      enum mlx5e_priv_flag flag,
			      mlx5e_pflag_handler pflag_handler)
			      enum mlx5e_priv_flag flag)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	bool enable = !!(wanted_flags & flag);
	bool enable = !!(wanted_flags & BIT(flag));
	u32 changes = wanted_flags ^ priv->channels.params.pflags;
	int err;

	if (!(changes & flag))
	if (!(changes & BIT(flag)))
		return 0;

	err = pflag_handler(netdev, enable);
	err = mlx5e_priv_flags[flag].handler(netdev, enable);
	if (err) {
		netdev_err(netdev, "%s private flag 0x%x failed err %d\n",
			   enable ? "Enable" : "Disable", flag, err);
		netdev_err(netdev, "%s private flag '%s' failed err %d\n",
			   enable ? "Enable" : "Disable", mlx5e_priv_flags[flag].name, err);
		return err;
	}

@@ -1701,38 +1683,17 @@ static int mlx5e_handle_pflag(struct net_device *netdev,
static int mlx5e_set_priv_flags(struct net_device *netdev, u32 pflags)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	enum mlx5e_priv_flag pflag;
	int err;

	mutex_lock(&priv->state_lock);
	err = mlx5e_handle_pflag(netdev, pflags,
				 MLX5E_PFLAG_RX_CQE_BASED_MODER,
				 set_pflag_rx_cqe_based_moder);
	if (err)
		goto out;

	err = mlx5e_handle_pflag(netdev, pflags,
				 MLX5E_PFLAG_TX_CQE_BASED_MODER,
				 set_pflag_tx_cqe_based_moder);
	if (err)
		goto out;

	err = mlx5e_handle_pflag(netdev, pflags,
				 MLX5E_PFLAG_RX_CQE_COMPRESS,
				 set_pflag_rx_cqe_compress);
	for (pflag = 0; pflag < MLX5E_NUM_PFLAGS; pflag++) {
		err = mlx5e_handle_pflag(netdev, pflags, pflag);
		if (err)
		goto out;

	err = mlx5e_handle_pflag(netdev, pflags,
				 MLX5E_PFLAG_RX_STRIDING_RQ,
				 set_pflag_rx_striding_rq);
	if (err)
		goto out;

	err = mlx5e_handle_pflag(netdev, pflags,
				 MLX5E_PFLAG_RX_NO_CSUM_COMPLETE,
				 set_pflag_rx_no_csum_complete);
			break;
	}

out:
	mutex_unlock(&priv->state_lock);

	/* Need to fix some features.. */
+112 −0
Original line number Diff line number Diff line
@@ -771,6 +771,112 @@ void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)
	INIT_LIST_HEAD(&priv->fs.ethtool.rules);
}

static enum mlx5e_traffic_types flow_type_to_traffic_type(u32 flow_type)
{
	switch (flow_type) {
	case TCP_V4_FLOW:
		return  MLX5E_TT_IPV4_TCP;
	case TCP_V6_FLOW:
		return MLX5E_TT_IPV6_TCP;
	case UDP_V4_FLOW:
		return MLX5E_TT_IPV4_UDP;
	case UDP_V6_FLOW:
		return MLX5E_TT_IPV6_UDP;
	case AH_V4_FLOW:
		return MLX5E_TT_IPV4_IPSEC_AH;
	case AH_V6_FLOW:
		return MLX5E_TT_IPV6_IPSEC_AH;
	case ESP_V4_FLOW:
		return MLX5E_TT_IPV4_IPSEC_ESP;
	case ESP_V6_FLOW:
		return MLX5E_TT_IPV6_IPSEC_ESP;
	case IPV4_FLOW:
		return MLX5E_TT_IPV4;
	case IPV6_FLOW:
		return MLX5E_TT_IPV6;
	default:
		return MLX5E_NUM_INDIR_TIRS;
	}
}

static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
				  struct ethtool_rxnfc *nfc)
{
	int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
	enum mlx5e_traffic_types tt;
	u8 rx_hash_field = 0;
	void *in;

	tt = flow_type_to_traffic_type(nfc->flow_type);
	if (tt == MLX5E_NUM_INDIR_TIRS)
		return -EINVAL;

	/*  RSS does not support anything other than hashing to queues
	 *  on src IP, dest IP, TCP/UDP src port and TCP/UDP dest
	 *  port.
	 */
	if (nfc->flow_type != TCP_V4_FLOW &&
	    nfc->flow_type != TCP_V6_FLOW &&
	    nfc->flow_type != UDP_V4_FLOW &&
	    nfc->flow_type != UDP_V6_FLOW)
		return -EOPNOTSUPP;

	if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
			  RXH_L4_B_0_1 | RXH_L4_B_2_3))
		return -EOPNOTSUPP;

	if (nfc->data & RXH_IP_SRC)
		rx_hash_field |= MLX5_HASH_FIELD_SEL_SRC_IP;
	if (nfc->data & RXH_IP_DST)
		rx_hash_field |= MLX5_HASH_FIELD_SEL_DST_IP;
	if (nfc->data & RXH_L4_B_0_1)
		rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_SPORT;
	if (nfc->data & RXH_L4_B_2_3)
		rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_DPORT;

	in = kvzalloc(inlen, GFP_KERNEL);
	if (!in)
		return -ENOMEM;

	mutex_lock(&priv->state_lock);

	if (rx_hash_field == priv->rss_params.rx_hash_fields[tt])
		goto out;

	priv->rss_params.rx_hash_fields[tt] = rx_hash_field;
	mlx5e_modify_tirs_hash(priv, in, inlen);

out:
	mutex_unlock(&priv->state_lock);
	kvfree(in);
	return 0;
}

static int mlx5e_get_rss_hash_opt(struct mlx5e_priv *priv,
				  struct ethtool_rxnfc *nfc)
{
	enum mlx5e_traffic_types tt;
	u32 hash_field = 0;

	tt = flow_type_to_traffic_type(nfc->flow_type);
	if (tt == MLX5E_NUM_INDIR_TIRS)
		return -EINVAL;

	hash_field = priv->rss_params.rx_hash_fields[tt];
	nfc->data = 0;

	if (hash_field & MLX5_HASH_FIELD_SEL_SRC_IP)
		nfc->data |= RXH_IP_SRC;
	if (hash_field & MLX5_HASH_FIELD_SEL_DST_IP)
		nfc->data |= RXH_IP_DST;
	if (hash_field & MLX5_HASH_FIELD_SEL_L4_SPORT)
		nfc->data |= RXH_L4_B_0_1;
	if (hash_field & MLX5_HASH_FIELD_SEL_L4_DPORT)
		nfc->data |= RXH_L4_B_2_3;

	return 0;
}

int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
	int err = 0;
@@ -783,6 +889,9 @@ int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
	case ETHTOOL_SRXCLSRLDEL:
		err = mlx5e_ethtool_flow_remove(priv, cmd->fs.location);
		break;
	case ETHTOOL_SRXFH:
		err = mlx5e_set_rss_hash_opt(priv, cmd);
		break;
	default:
		err = -EOPNOTSUPP;
		break;
@@ -810,6 +919,9 @@ int mlx5e_get_rxnfc(struct net_device *dev,
	case ETHTOOL_GRXCLSRLALL:
		err = mlx5e_ethtool_get_all_flows(priv, info, rule_locs);
		break;
	case ETHTOOL_GRXFH:
		err =  mlx5e_get_rss_hash_opt(priv, info);
		break;
	default:
		err = -EOPNOTSUPP;
		break;
+118 −105
Original line number Diff line number Diff line
@@ -2504,7 +2504,7 @@ static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, int sz,
			if (rrp.rss.hfunc == ETH_RSS_HASH_XOR)
				ix = mlx5e_bits_invert(i, ilog2(sz));

			ix = priv->channels.params.indirection_rqt[ix];
			ix = priv->rss_params.indirection_rqt[ix];
			rqn = rrp.rss.channels->c[ix]->rq.rqn;
		} else {
			rqn = rrp.rqn;
@@ -2587,7 +2587,7 @@ static void mlx5e_redirect_rqts_to_channels(struct mlx5e_priv *priv,
		{
			.rss = {
				.channels  = chs,
				.hfunc     = chs->params.rss_hfunc,
				.hfunc     = priv->rss_params.hfunc,
			}
		},
	};
@@ -2607,6 +2607,54 @@ static void mlx5e_redirect_rqts_to_drop(struct mlx5e_priv *priv)
	mlx5e_redirect_rqts(priv, drop_rrp);
}

static const struct mlx5e_tirc_config tirc_default_config[MLX5E_NUM_INDIR_TIRS] = {
	[MLX5E_TT_IPV4_TCP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
				.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
				.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
	},
	[MLX5E_TT_IPV6_TCP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
				.l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
				.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
	},
	[MLX5E_TT_IPV4_UDP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
				.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
				.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
	},
	[MLX5E_TT_IPV6_UDP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
				.l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
				.rx_hash_fields = MLX5_HASH_IP_L4PORTS,
	},
	[MLX5E_TT_IPV4_IPSEC_AH] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
				     .l4_prot_type = 0,
				     .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
	},
	[MLX5E_TT_IPV6_IPSEC_AH] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
				     .l4_prot_type = 0,
				     .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
	},
	[MLX5E_TT_IPV4_IPSEC_ESP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
				      .l4_prot_type = 0,
				      .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
	},
	[MLX5E_TT_IPV6_IPSEC_ESP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
				      .l4_prot_type = 0,
				      .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
	},
	[MLX5E_TT_IPV4] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
			    .l4_prot_type = 0,
			    .rx_hash_fields = MLX5_HASH_IP,
	},
	[MLX5E_TT_IPV6] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
			    .l4_prot_type = 0,
			    .rx_hash_fields = MLX5_HASH_IP,
	},
};

struct mlx5e_tirc_config mlx5e_tirc_get_default_config(enum mlx5e_traffic_types tt)
{
	return tirc_default_config[tt];
}

static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
{
	if (!params->lro_en)
@@ -2622,116 +2670,68 @@ static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
	MLX5_SET(tirc, tirc, lro_timeout_period_usecs, params->lro_timeout);
}

void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
				    enum mlx5e_traffic_types tt,
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
				    const struct mlx5e_tirc_config *ttconfig,
				    void *tirc, bool inner)
{
	void *hfso = inner ? MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner) :
			     MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);

#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP)

#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_L4_SPORT |\
				 MLX5_HASH_FIELD_SEL_L4_DPORT)

#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_IPSEC_SPI)

	MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_rx_hash_fn(params->rss_hfunc));
	if (params->rss_hfunc == ETH_RSS_HASH_TOP) {
	MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_rx_hash_fn(rss_params->hfunc));
	if (rss_params->hfunc == ETH_RSS_HASH_TOP) {
		void *rss_key = MLX5_ADDR_OF(tirc, tirc,
					     rx_hash_toeplitz_key);
		size_t len = MLX5_FLD_SZ_BYTES(tirc,
					       rx_hash_toeplitz_key);

		MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
		memcpy(rss_key, params->toeplitz_hash_key, len);
		memcpy(rss_key, rss_params->toeplitz_hash_key, len);
	}

	switch (tt) {
	case MLX5E_TT_IPV4_TCP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_TCP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV6_TCP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_TCP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV4_UDP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_UDP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV6_UDP:
	MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		 ttconfig->l3_prot_type);
	MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_UDP);
		 ttconfig->l4_prot_type);
	MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;
		 ttconfig->rx_hash_fields);
}

	case MLX5E_TT_IPV4_IPSEC_AH:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;
static void mlx5e_update_rx_hash_fields(struct mlx5e_tirc_config *ttconfig,
					enum mlx5e_traffic_types tt,
					u32 rx_hash_fields)
{
	*ttconfig                = tirc_default_config[tt];
	ttconfig->rx_hash_fields = rx_hash_fields;
}

	case MLX5E_TT_IPV6_IPSEC_AH:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;
void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
{
	void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
	struct mlx5e_rss_params *rss = &priv->rss_params;
	struct mlx5_core_dev *mdev = priv->mdev;
	int ctxlen = MLX5_ST_SZ_BYTES(tirc);
	struct mlx5e_tirc_config ttconfig;
	int tt;

	case MLX5E_TT_IPV4_IPSEC_ESP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;
	MLX5_SET(modify_tir_in, in, bitmask.hash, 1);

	case MLX5E_TT_IPV6_IPSEC_ESP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(tirc, 0, ctxlen);
		mlx5e_update_rx_hash_fields(&ttconfig, tt,
					    rss->rx_hash_fields[tt]);
		mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, false);
		mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
	}

	case MLX5E_TT_IPV4:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP);
		break;
	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
		return;

	case MLX5E_TT_IPV6:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP);
		break;
	default:
		WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(tirc, 0, ctxlen);
		mlx5e_update_rx_hash_fields(&ttconfig, tt,
					    rss->rx_hash_fields[tt]);
		mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, true);
		mlx5_core_modify_tir(mdev, priv->inner_indir_tir[tt].tirn, in,
				     inlen);
	}
}

@@ -2788,7 +2788,8 @@ static void mlx5e_build_inner_indir_tir_ctx(struct mlx5e_priv *priv,
	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
	MLX5_SET(tirc, tirc, tunneled_offload_en, 0x1);

	mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, true);
	mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
				       &tirc_default_config[tt], tirc, true);
}

static int mlx5e_set_mtu(struct mlx5_core_dev *mdev,
@@ -3180,7 +3181,9 @@ static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv,

	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
	mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, false);

	mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
				       &tirc_default_config[tt], tirc, false);
}

static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 rqtn, u32 *tirc)
@@ -4518,15 +4521,23 @@ void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
	mlx5e_init_rq_type_params(mdev, params);
}

void mlx5e_build_rss_params(struct mlx5e_params *params)
void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
			    u16 num_channels)
{
	params->rss_hfunc = ETH_RSS_HASH_XOR;
	netdev_rss_key_fill(params->toeplitz_hash_key, sizeof(params->toeplitz_hash_key));
	mlx5e_build_default_indir_rqt(params->indirection_rqt,
				      MLX5E_INDIR_RQT_SIZE, params->num_channels);
	enum mlx5e_traffic_types tt;

	rss_params->hfunc = ETH_RSS_HASH_XOR;
	netdev_rss_key_fill(rss_params->toeplitz_hash_key,
			    sizeof(rss_params->toeplitz_hash_key));
	mlx5e_build_default_indir_rqt(rss_params->indirection_rqt,
				      MLX5E_INDIR_RQT_SIZE, num_channels);
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
		rss_params->rx_hash_fields[tt] =
			tirc_default_config[tt].rx_hash_fields;
}

void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
			    struct mlx5e_rss_params *rss_params,
			    struct mlx5e_params *params,
			    u16 max_channels, u16 mtu)
{
@@ -4575,7 +4586,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
	params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(mdev);

	/* RSS */
	mlx5e_build_rss_params(params);
	mlx5e_build_rss_params(rss_params, params->num_channels);
}

static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
@@ -4748,14 +4759,16 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
			  void *ppriv)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5e_rss_params *rss = &priv->rss_params;
	int err;

	err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv);
	if (err)
		return err;

	mlx5e_build_nic_params(mdev, &priv->channels.params,
			       mlx5e_get_netdev_max_channels(netdev), netdev->mtu);
	mlx5e_build_nic_params(mdev, rss, &priv->channels.params,
			       mlx5e_get_netdev_max_channels(netdev),
			       netdev->mtu);

	mlx5e_timestamp_init(priv);

@@ -5030,7 +5043,7 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv)
	if (priv->channels.params.num_channels > max_nch) {
		mlx5_core_warn(priv->mdev, "MLX5E: Reducing number of channels to %d\n", max_nch);
		priv->channels.params.num_channels = max_nch;
		mlx5e_build_default_indir_rqt(priv->channels.params.indirection_rqt,
		mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
					      MLX5E_INDIR_RQT_SIZE, max_nch);
	}

Loading