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

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

Merge tag 'mlx5-updates-2017-11-04' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5-updates-2017-11-04

This series includes:

From Huy: dscp to priority mapping for Ethernet packet.

===================================================
First six patches enable differentiated services code point (dscp) to
priority mapping for Ethernet packet. Once this feature is
enabled, the packet is routed to the corresponding priority based on its
dscp. User can combine this feature with priority flow control (pfc)
feature to have priority flow control based on the dscp.

Firmware interface:
Mellanox firmware provides two control knobs for this feature:
  QPTS register allow changing the trust state between dscp and
  pcp mode. The default is pcp mode. Once in dscp mode, firmware will
  route the packet based on its dscp value if the dscp field exists.

  QPDPM register allow mapping a specific dscp (0 to 63) to a
  specific priority (0 to 7). By default, all the dscps are mapped to
  priority zero.

Software interface:
This feature is controlled via application priority TLV. IEEE
specification P802.1Qcd/D2.1 defines priority selector id 5 for
application priority TLV. This APP TLV selector defines DSCP to priority
map. This APP TLV can be sent by the switch or can be set locally using
software such as lldptool. In mlx5 drivers, we add the support for net
dcb's getapp and setapp call back. Mlx5 driver only handles the selector
id 5 application entry (dscp application priority application entry).
If user sends multiple dscp to priority APP TLV entries on the same
dscp, the last sent one will take effect. All the previous sent will be
deleted.

The firmware trust state (in QPTS register) is changed based on the
number of dscp to priority application entries. When the first dscp to
priority application entry is added by the user, the trust state is
changed to dscp. When the last dscp to priority application entry is
deleted by the user, the trust state is changed to pcp.

When the port is in DSCP trust state, the transmit queue is selected
based on the dscp of the skb.

When the port is in DSCP trust state and vport inline mode is not NONE,
firmware requires mlx5 driver to copy the IP header to the
wqe ethernet segment inline header if the skb has it.
This is done by changing the transmit queue sq's min inline mode to L3.
Note that the min inline mode of sqs that belong to other features
such as xdpsq, icosq are not modified.
===================================================

Plus to the dscp series, some small misc changes are include as well:

From Inbar, Ethtool msglvl support and some debug prints in DCBNL logic
From Or Gerlitz, Enlarge the NIC TC offload table size
From Rabie, Initialize destination_flow struct to 0
From Feras, Add inner TTC table to IPoIB flow steering
From Tal, Enable CQE based moderation on TX CQ
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bfe26ba9 0088cbbc
Loading
Loading
Loading
Loading
+36 −3
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#define MLX5E_HW2SW_MTU(priv, hwmtu) ((hwmtu) - ((priv)->hard_mtu))
#define MLX5E_SW2HW_MTU(priv, swmtu) ((swmtu) + ((priv)->hard_mtu))

#define MLX5E_MAX_DSCP          64
#define MLX5E_MAX_NUM_TC	8

#define MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE                0x6
@@ -105,6 +106,7 @@
#define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE 0x3
#define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS      0x20
#define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC      0x10
#define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC_FROM_CQE 0x10
#define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS      0x20
#define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES                0x80
#define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES_MPW            0x2
@@ -126,6 +128,16 @@

#define MLX5E_NUM_MAIN_GROUPS 9

#define MLX5E_MSG_LEVEL			NETIF_MSG_LINK

#define mlx5e_dbg(mlevel, priv, format, ...)                    \
do {                                                            \
	if (NETIF_MSG_##mlevel & (priv)->msglevel)              \
		netdev_warn(priv->netdev, format,               \
			    ##__VA_ARGS__);                     \
} while (0)


static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
{
	switch (wq_type) {
@@ -187,12 +199,14 @@ extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];

static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
	"rx_cqe_moder",
	"tx_cqe_moder",
	"rx_cqe_compress",
};

enum mlx5e_priv_flag {
	MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
	MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 1),
	MLX5E_PFLAG_TX_CQE_BASED_MODER = (1 << 1),
	MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 2),
};

#define MLX5E_SET_PFLAG(params, pflag, enable)			\
@@ -212,6 +226,7 @@ enum mlx5e_priv_flag {
struct mlx5e_cq_moder {
	u16 usec;
	u16 pkts;
	u8 cq_period_mode;
};

struct mlx5e_params {
@@ -223,7 +238,6 @@ struct mlx5e_params {
	u8  log_rq_size;
	u16 num_channels;
	u8  num_tc;
	u8  rx_cq_period_mode;
	bool rx_cqe_compress_def;
	struct mlx5e_cq_moder rx_cq_moderation;
	struct mlx5e_cq_moder tx_cq_moderation;
@@ -260,11 +274,17 @@ enum {
struct mlx5e_dcbx {
	enum mlx5_dcbx_oper_mode   mode;
	struct mlx5e_cee_config    cee_cfg; /* pending configuration */
	u8                         dscp_app_cnt;

	/* The only setting that cannot be read from FW */
	u8                         tc_tsa[IEEE_8021QAZ_MAX_TCS];
	u8                         cap;
};

struct mlx5e_dcbx_dp {
	u8                         dscp2prio[MLX5E_MAX_DSCP];
	u8                         trust_state;
};
#endif

enum {
@@ -742,8 +762,12 @@ struct mlx5e_priv {
	/* priv data path fields - start */
	struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
	int channel_tc2txq[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC];
#ifdef CONFIG_MLX5_CORE_EN_DCB
	struct mlx5e_dcbx_dp       dcbx_dp;
#endif
	/* priv data path fields - end */

	u32                        msglevel;
	unsigned long              state;
	struct mutex               state_lock; /* Protects Interface state */
	struct mlx5e_rq            drop_rq;
@@ -800,6 +824,8 @@ struct mlx5e_profile {
		mlx5e_fp_handle_rx_cqe handle_rx_cqe;
		mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
	} rx_handlers;
	void	(*netdev_registered_init)(struct mlx5e_priv *priv);
	void    (*netdev_registered_remove)(struct mlx5e_priv *priv);
	int	max_tc;
};

@@ -903,6 +929,8 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
				   int num_channels);
int mlx5e_get_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);

void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params,
				 u8 cq_period_mode);
void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params,
				 u8 cq_period_mode);
void mlx5e_set_rq_type_params(struct mlx5_core_dev *mdev,
@@ -968,6 +996,8 @@ extern const struct ethtool_ops mlx5e_ethtool_ops;
extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops;
int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets);
void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv);
void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv);
void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv);
#endif

#ifndef CONFIG_RFS_ACCEL
@@ -1020,6 +1050,9 @@ void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);

int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv);
void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv);

int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
		     u32 underlay_qpn, u32 *tisn);
void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn);
@@ -1069,5 +1102,5 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
			    struct mlx5e_params *params,
			    u16 max_channels);

u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev);
#endif /* __MLX5_EN_H__ */
+5 −5
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ static enum mlx5e_traffic_types arfs_get_tt(enum arfs_type type)

static int arfs_disable(struct mlx5e_priv *priv)
{
	struct mlx5_flow_destination dest;
	struct mlx5_flow_destination dest = {};
	struct mlx5e_tir *tir = priv->indir_tir;
	int err = 0;
	int tt;
@@ -126,7 +126,7 @@ int mlx5e_arfs_disable(struct mlx5e_priv *priv)

int mlx5e_arfs_enable(struct mlx5e_priv *priv)
{
	struct mlx5_flow_destination dest;
	struct mlx5_flow_destination dest = {};
	int err = 0;
	int tt;
	int i;
@@ -175,7 +175,7 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
{
	struct arfs_table *arfs_t = &priv->fs.arfs.arfs_tables[type];
	struct mlx5e_tir *tir = priv->indir_tir;
	struct mlx5_flow_destination dest;
	struct mlx5_flow_destination dest = {};
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_spec *spec;
	enum mlx5e_traffic_types tt;
@@ -466,7 +466,7 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
	struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
	struct arfs_tuple *tuple = &arfs_rule->tuple;
	struct mlx5_flow_handle *rule = NULL;
	struct mlx5_flow_destination dest;
	struct mlx5_flow_destination dest = {};
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct arfs_table *arfs_table;
	struct mlx5_flow_spec *spec;
@@ -557,7 +557,7 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
static void arfs_modify_rule_rq(struct mlx5e_priv *priv,
				struct mlx5_flow_handle *rule, u16 rxq)
{
	struct mlx5_flow_destination dst;
	struct mlx5_flow_destination dst = {};
	int err = 0;

	dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
+12 −0
Original line number Diff line number Diff line
@@ -171,3 +171,15 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb)

	return err;
}

u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev)
{
	u8 min_inline_mode;

	mlx5_query_min_inline(mdev, &min_inline_mode);
	if (min_inline_mode == MLX5_INLINE_MODE_NONE &&
	    !MLX5_CAP_ETH(mdev, wqe_vlan_insert))
		min_inline_mode = MLX5_INLINE_MODE_L2;

	return min_inline_mode;
}
+264 −1
Original line number Diff line number Diff line
@@ -46,6 +46,13 @@ enum {
	MLX5E_LOWEST_PRIO_GROUP   = 0,
};

#define MLX5_DSCP_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, qcam_reg)  && \
				   MLX5_CAP_QCAM_REG(mdev, qpts) && \
				   MLX5_CAP_QCAM_REG(mdev, qpdpm))

static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state);
static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio);

/* If dcbx mode is non-host set the dcbx mode to host.
 */
static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
@@ -234,7 +241,7 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
	u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
	u8 tc_group[IEEE_8021QAZ_MAX_TCS];
	int max_tc = mlx5_max_tc(mdev);
	int err;
	int err, i;

	mlx5e_build_tc_group(ets, tc_group, max_tc);
	mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
@@ -253,6 +260,14 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
		return err;

	memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));

	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
		mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n",
			  __func__, i, ets->prio_tc[i]);
		mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
			  __func__, i, tc_tx_bw[i], tc_group[i]);
	}

	return err;
}

@@ -338,6 +353,11 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
	ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
	mlx5_toggle_port_link(mdev);

	if (!ret) {
		mlx5e_dbg(HW, priv,
			  "%s: PFC per priority bit mask: 0x%x\n",
			  __func__, pfc->pfc_en);
	}
	return ret;
}

@@ -381,6 +401,113 @@ static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
	return 0;
}

static int mlx5e_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct dcb_app temp;
	bool is_new;
	int err;

	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
		return -EINVAL;

	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
		return -EINVAL;

	if (!MLX5_DSCP_SUPPORTED(priv->mdev))
		return -EINVAL;

	if (app->protocol >= MLX5E_MAX_DSCP)
		return -EINVAL;

	/* Save the old entry info */
	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
	temp.protocol = app->protocol;
	temp.priority = priv->dcbx_dp.dscp2prio[app->protocol];

	/* Check if need to switch to dscp trust state */
	if (!priv->dcbx.dscp_app_cnt) {
		err =  mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_DSCP);
		if (err)
			return err;
	}

	/* Skip the fw command if new and old mapping are the same */
	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) {
		err = mlx5e_set_dscp2prio(priv, app->protocol, app->priority);
		if (err)
			goto fw_err;
	}

	/* Delete the old entry if exists */
	is_new = false;
	err = dcb_ieee_delapp(dev, &temp);
	if (err)
		is_new = true;

	/* Add new entry and update counter */
	err = dcb_ieee_setapp(dev, app);
	if (err)
		return err;

	if (is_new)
		priv->dcbx.dscp_app_cnt++;

	return err;

fw_err:
	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
	return err;
}

static int mlx5e_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	int err;

	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
		return -EINVAL;

	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
		return -EINVAL;

	if (!MLX5_DSCP_SUPPORTED(priv->mdev))
		return -EINVAL;

	if (app->protocol >= MLX5E_MAX_DSCP)
		return -EINVAL;

	/* Skip if no dscp app entry */
	if (!priv->dcbx.dscp_app_cnt)
		return -ENOENT;

	/* Check if the entry matches fw setting */
	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol])
		return -ENOENT;

	/* Delete the app entry */
	err = dcb_ieee_delapp(dev, app);
	if (err)
		return err;

	/* Reset the priority mapping back to zero */
	err = mlx5e_set_dscp2prio(priv, app->protocol, 0);
	if (err)
		goto fw_err;

	priv->dcbx.dscp_app_cnt--;

	/* Check if need to switch to pcp trust state */
	if (!priv->dcbx.dscp_app_cnt)
		err = mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);

	return err;

fw_err:
	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
	return err;
}

static int mlx5e_dcbnl_ieee_getmaxrate(struct net_device *netdev,
				       struct ieee_maxrate *maxrate)
{
@@ -446,6 +573,11 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
		}
	}

	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
		mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n",
			  __func__, i, max_bw_value[i]);
	}

	return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
}

@@ -471,6 +603,10 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
		ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
		ets.tc_tsa[i]   = IEEE_8021QAZ_TSA_ETS;
		ets.prio_tc[i]  = cee_cfg->prio_to_pg_map[i];
		mlx5e_dbg(HW, priv,
			  "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
			  __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
			  ets.prio_tc[i]);
	}

	err = mlx5e_dbcnl_validate_ets(netdev, &ets);
@@ -740,6 +876,8 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
	.ieee_setmaxrate = mlx5e_dcbnl_ieee_setmaxrate,
	.ieee_getpfc	= mlx5e_dcbnl_ieee_getpfc,
	.ieee_setpfc	= mlx5e_dcbnl_ieee_setpfc,
	.ieee_setapp    = mlx5e_dcbnl_ieee_setapp,
	.ieee_delapp    = mlx5e_dcbnl_ieee_delapp,
	.getdcbx	= mlx5e_dcbnl_getdcbx,
	.setdcbx	= mlx5e_dcbnl_setdcbx,

@@ -801,10 +939,135 @@ static void mlx5e_ets_init(struct mlx5e_priv *priv)
	mlx5e_dcbnl_ieee_setets_core(priv, &ets);
}

enum {
	INIT,
	DELETE,
};

static void mlx5e_dcbnl_dscp_app(struct mlx5e_priv *priv, int action)
{
	struct dcb_app temp;
	int i;

	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
		return;

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

	/* No SEL_DSCP entry in non DSCP state */
	if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_DSCP)
		return;

	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
	for (i = 0; i < MLX5E_MAX_DSCP; i++) {
		temp.protocol = i;
		temp.priority = priv->dcbx_dp.dscp2prio[i];
		if (action == INIT)
			dcb_ieee_setapp(priv->netdev, &temp);
		else
			dcb_ieee_delapp(priv->netdev, &temp);
	}

	priv->dcbx.dscp_app_cnt = (action == INIT) ? MLX5E_MAX_DSCP : 0;
}

void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
{
	mlx5e_dcbnl_dscp_app(priv, INIT);
}

void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
{
	mlx5e_dcbnl_dscp_app(priv, DELETE);
}

static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv,
						  struct mlx5e_params *params)
{
	params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev);
	if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP &&
	    params->tx_min_inline_mode == MLX5_INLINE_MODE_L2)
		params->tx_min_inline_mode = MLX5_INLINE_MODE_IP;
}

static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv)
{
	struct mlx5e_channels new_channels = {};

	mutex_lock(&priv->state_lock);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		goto out;

	new_channels.params = priv->channels.params;
	mlx5e_trust_update_tx_min_inline_mode(priv, &new_channels.params);

	/* Skip if tx_min_inline is the same */
	if (new_channels.params.tx_min_inline_mode ==
	    priv->channels.params.tx_min_inline_mode)
		goto out;

	if (mlx5e_open_channels(priv, &new_channels))
		goto out;
	mlx5e_switch_priv_channels(priv, &new_channels, NULL);

out:
	mutex_unlock(&priv->state_lock);
}

static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
{
	int err;

	err =  mlx5_set_trust_state(priv->mdev, trust_state);
	if (err)
		return err;
	priv->dcbx_dp.trust_state = trust_state;
	mlx5e_trust_update_sq_inline_mode(priv);

	return err;
}

static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio)
{
	int err;

	err = mlx5_set_dscp2prio(priv->mdev, dscp, prio);
	if (err)
		return err;

	priv->dcbx_dp.dscp2prio[dscp] = prio;
	return err;
}

static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	int err;

	if (!MLX5_DSCP_SUPPORTED(mdev))
		return 0;

	err = mlx5_query_trust_state(priv->mdev, &priv->dcbx_dp.trust_state);
	if (err)
		return err;

	mlx5e_trust_update_tx_min_inline_mode(priv, &priv->channels.params);

	err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio);
	if (err)
		return err;

	return 0;
}

void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
{
	struct mlx5e_dcbx *dcbx = &priv->dcbx;

	mlx5e_trust_initialize(priv);

	if (!MLX5_CAP_GEN(priv->mdev, qos))
		return;

+44 −8
Original line number Diff line number Diff line
@@ -1340,6 +1340,16 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
	return mlx5_set_port_wol(mdev, mlx5_wol_mode);
}

static u32 mlx5e_get_msglevel(struct net_device *dev)
{
	return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel;
}

static void mlx5e_set_msglevel(struct net_device *dev, u32 val)
{
	((struct mlx5e_priv *)netdev_priv(dev))->msglevel = val;
}

static int mlx5e_set_phys_id(struct net_device *dev,
			     enum ethtool_phys_id_state state)
{
@@ -1444,29 +1454,36 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,

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

static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
				     bool is_rx_cq)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5_core_dev *mdev = priv->mdev;
	struct mlx5e_channels new_channels = {};
	bool rx_mode_changed;
	u8 rx_cq_period_mode;
	bool mode_changed;
	u8 cq_period_mode, current_cq_period_mode;
	int err = 0;

	rx_cq_period_mode = enable ?
	cq_period_mode = enable ?
		MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
		MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
	rx_mode_changed = rx_cq_period_mode != priv->channels.params.rx_cq_period_mode;
	current_cq_period_mode = is_rx_cq ?
		priv->channels.params.rx_cq_moderation.cq_period_mode :
		priv->channels.params.tx_cq_moderation.cq_period_mode;
	mode_changed = cq_period_mode != current_cq_period_mode;

	if (rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE &&
	if (cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE &&
	    !MLX5_CAP_GEN(mdev, cq_period_start_from_cqe))
		return -EOPNOTSUPP;

	if (!rx_mode_changed)
	if (!mode_changed)
		return 0;

	new_channels.params = priv->channels.params;
	mlx5e_set_rx_cq_mode_params(&new_channels.params, rx_cq_period_mode);
	if (is_rx_cq)
		mlx5e_set_rx_cq_mode_params(&new_channels.params, cq_period_mode);
	else
		mlx5e_set_tx_cq_mode_params(&new_channels.params, cq_period_mode);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
		priv->channels.params = new_channels.params;
@@ -1481,6 +1498,16 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
	return 0;
}

static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
{
	return set_pflag_cqe_based_moder(netdev, enable, false);
}

static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
{
	return set_pflag_cqe_based_moder(netdev, enable, true);
}

int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val)
{
	bool curr_val = MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS);
@@ -1568,6 +1595,12 @@ static int mlx5e_set_priv_flags(struct net_device *netdev, u32 pflags)
	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);
@@ -1672,4 +1705,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
	.get_priv_flags    = mlx5e_get_priv_flags,
	.set_priv_flags    = mlx5e_set_priv_flags,
	.self_test         = mlx5e_self_test,
	.get_msglevel      = mlx5e_get_msglevel,
	.set_msglevel      = mlx5e_set_msglevel,

};
Loading