net/mlx5e: Add ethtool support for rxvlan-offload (vlan stripping)
Use ethtool -K <interface> rxvlan <on/off> to enable/disable C-TAG vlan stripping by hardware. Signed-off-by: Gal Pressman <galp@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bb64143eee
commit
363501145e
|
@ -166,6 +166,7 @@ struct mlx5e_params {
|
|||
u8 rss_hfunc;
|
||||
u8 toeplitz_hash_key[40];
|
||||
u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
|
||||
bool vlan_strip_disable;
|
||||
#ifdef CONFIG_MLX5_CORE_EN_DCB
|
||||
struct ieee_ets ets;
|
||||
#endif
|
||||
|
@ -575,6 +576,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_disable_vlan_filter(struct mlx5e_priv *priv);
|
||||
|
||||
int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd);
|
||||
|
||||
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix);
|
||||
void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
|
||||
|
||||
|
|
|
@ -388,6 +388,7 @@ static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
|
|||
MLX5_SET(rqc, rqc, cqn, rq->cq.mcq.cqn);
|
||||
MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST);
|
||||
MLX5_SET(rqc, rqc, flush_in_error_en, 1);
|
||||
MLX5_SET(rqc, rqc, vsd, priv->params.vlan_strip_disable);
|
||||
MLX5_SET(wq, wq, log_wq_pg_sz, rq->wq_ctrl.buf.page_shift -
|
||||
MLX5_ADAPTER_PAGE_SHIFT);
|
||||
MLX5_SET64(wq, wq, dbr_addr, rq->wq_ctrl.db.dma);
|
||||
|
@ -402,7 +403,8 @@ static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state)
|
||||
static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state,
|
||||
int next_state)
|
||||
{
|
||||
struct mlx5e_channel *c = rq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
|
@ -430,6 +432,36 @@ static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
|
||||
{
|
||||
struct mlx5e_channel *c = rq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
void *in;
|
||||
void *rqc;
|
||||
int inlen;
|
||||
int err;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
|
||||
in = mlx5_vzalloc(inlen);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
|
||||
|
||||
MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY);
|
||||
MLX5_SET64(modify_rq_in, in, modify_bitmask, MLX5_RQ_BITMASK_VSD);
|
||||
MLX5_SET(rqc, rqc, vsd, vsd);
|
||||
MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY);
|
||||
|
||||
err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen);
|
||||
|
||||
kvfree(in);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_disable_rq(struct mlx5e_rq *rq)
|
||||
{
|
||||
mlx5_core_destroy_rq(rq->priv->mdev, rq->rqn);
|
||||
|
@ -468,7 +500,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
|
|||
if (err)
|
||||
goto err_destroy_rq;
|
||||
|
||||
err = mlx5e_modify_rq(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
|
||||
err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
|
||||
if (err)
|
||||
goto err_disable_rq;
|
||||
|
||||
|
@ -493,7 +525,7 @@ static void mlx5e_close_rq(struct mlx5e_rq *rq)
|
|||
clear_bit(MLX5E_RQ_STATE_POST_WQES_ENABLE, &rq->state);
|
||||
napi_synchronize(&rq->channel->napi); /* prevent mlx5e_post_rx_wqes */
|
||||
|
||||
mlx5e_modify_rq(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR);
|
||||
mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR);
|
||||
while (!mlx5_wq_ll_is_empty(&rq->wq))
|
||||
msleep(20);
|
||||
|
||||
|
@ -1963,6 +1995,23 @@ static void mlx5e_destroy_tirs(struct mlx5e_priv *priv)
|
|||
mlx5e_destroy_tir(priv, i);
|
||||
}
|
||||
|
||||
int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < priv->params.num_channels; i++) {
|
||||
err = mlx5e_modify_rq_vsd(&priv->channel[i]->rq, vsd);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
@ -2147,6 +2196,23 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
|
|||
return mlx5_set_port_fcs(mdev, !enable);
|
||||
}
|
||||
|
||||
static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
priv->params.vlan_strip_disable = !enable;
|
||||
err = mlx5e_modify_rqs_vsd(priv, !enable);
|
||||
if (err)
|
||||
priv->params.vlan_strip_disable = enable;
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_handle_feature(struct net_device *netdev,
|
||||
netdev_features_t wanted_features,
|
||||
netdev_features_t feature,
|
||||
|
@ -2184,6 +2250,8 @@ static int mlx5e_set_features(struct net_device *netdev,
|
|||
set_feature_tc_num_filters);
|
||||
err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL,
|
||||
set_feature_rx_all);
|
||||
err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX,
|
||||
set_feature_rx_vlan);
|
||||
|
||||
return err ? -EINVAL : 0;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
#include <linux/mlx5/device.h>
|
||||
#include <linux/mlx5/doorbell.h>
|
||||
|
||||
enum {
|
||||
MLX5_RQ_BITMASK_VSD = 1 << 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_BOARD_ID_LEN = 64,
|
||||
MLX5_MAX_NAME_LEN = 16,
|
||||
|
|
Loading…
Reference in New Issue