From e207b7e991768b724f6d216de49c9b800e203eed Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Sun, 27 Nov 2016 17:02:07 +0200 Subject: [PATCH] net/mlx5e: ConnectX-4 firmware support for DCBX DBCX by default is controlled by firmware where dcbx capability bit is set. In this mode, firmware is responsible for reading/sending the TLV packets from/to the remote partner. This patch sets up the infrastructure to move between HOST/FW DCBX control mode. Signed-off-by: Huy Nguyen Signed-off-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 + .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 91 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_main.c | 29 +----- 3 files changed, 94 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 60aa13b2b21f..6c954cddfe66 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -234,6 +234,7 @@ enum { }; struct mlx5e_dcbx { + enum mlx5_dcbx_oper_mode mode; struct mlx5e_cee_config cee_cfg; /* pending configuration */ /* The only setting that cannot be read from FW */ @@ -843,6 +844,7 @@ extern const struct ethtool_ops mlx5e_ethtool_ops; #ifdef CONFIG_MLX5_CORE_EN_DCB 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); #endif #ifndef CONFIG_RFS_ACCEL diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 35e90d16cc66..1753182e8959 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -41,6 +41,45 @@ #define MLX5E_CEE_STATE_UP 1 #define MLX5E_CEE_STATE_DOWN 0 +/* If dcbx mode is non-host set the dcbx mode to host. + */ +static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv, + enum mlx5_dcbx_oper_mode mode) +{ + struct mlx5_core_dev *mdev = priv->mdev; + u32 param[MLX5_ST_SZ_DW(dcbx_param)]; + int err; + + err = mlx5_query_port_dcbx_param(mdev, param); + if (err) + return err; + + MLX5_SET(dcbx_param, param, version_admin, mode); + if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST) + MLX5_SET(dcbx_param, param, willing_admin, 1); + + return mlx5_set_port_dcbx_param(mdev, param); +} + +static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv) +{ + struct mlx5e_dcbx *dcbx = &priv->dcbx; + int err; + + if (!MLX5_CAP_GEN(priv->mdev, dcbx)) + return 0; + + if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST) + return 0; + + err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST); + if (err) + return err; + + dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST; + return 0; +} + static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, struct ieee_ets *ets) { @@ -255,6 +294,9 @@ static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev) static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode) { + if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev))) + return 1; + if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || !(mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE) || @@ -637,3 +679,52 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { .getpfcstate = mlx5e_dcbnl_getpfcstate, .setpfcstate = mlx5e_dcbnl_setpfcstate, }; + +static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv, + enum mlx5_dcbx_oper_mode *mode) +{ + u32 out[MLX5_ST_SZ_DW(dcbx_param)]; + + *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST; + + if (!mlx5_query_port_dcbx_param(priv->mdev, out)) + *mode = MLX5_GET(dcbx_param, out, version_oper); + + /* From driver's point of view, we only care if the mode + * is host (HOST) or non-host (AUTO) + */ + if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST) + *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO; +} + +static void mlx5e_ets_init(struct mlx5e_priv *priv) +{ + int i; + struct ieee_ets ets; + + memset(&ets, 0, sizeof(ets)); + ets.ets_cap = mlx5_max_tc(priv->mdev) + 1; + for (i = 0; i < ets.ets_cap; i++) { + ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC; + ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; + ets.prio_tc[i] = i; + } + + memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa)); + + /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */ + ets.prio_tc[0] = 1; + ets.prio_tc[1] = 0; + + mlx5e_dcbnl_ieee_setets_core(priv, &ets); +} + +void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv) +{ + struct mlx5e_dcbx *dcbx = &priv->dcbx; + + if (MLX5_CAP_GEN(priv->mdev, dcbx)) + mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode); + + mlx5e_ets_init(priv); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index b1e8ec545e79..f5b93c27a884 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3325,33 +3325,6 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev) 2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/; } -#ifdef CONFIG_MLX5_CORE_EN_DCB -static void mlx5e_ets_init(struct mlx5e_priv *priv) -{ - struct ieee_ets ets; - int i; - - if (!MLX5_CAP_GEN(priv->mdev, ets)) - return; - - memset(&ets, 0, sizeof(ets)); - ets.ets_cap = mlx5_max_tc(priv->mdev) + 1; - for (i = 0; i < ets.ets_cap; i++) { - ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC; - ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; - ets.prio_tc[i] = i; - } - - memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa)); - - /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */ - ets.prio_tc[0] = 1; - ets.prio_tc[1] = 0; - - mlx5e_dcbnl_ieee_setets_core(priv, &ets); -} -#endif - void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev, u32 *indirection_rqt, int len, int num_channels) @@ -3794,7 +3767,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) } #ifdef CONFIG_MLX5_CORE_EN_DCB - mlx5e_ets_init(priv); + mlx5e_dcbnl_initialize(priv); #endif return 0; } -- 2.39.5