net/mlx5e: ConnectX-4 firmware support for DCBX
authorHuy Nguyen <huyn@mellanox.com>
Sun, 27 Nov 2016 15:02:07 +0000 (17:02 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Nov 2016 20:09:35 +0000 (15:09 -0500)
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 <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index 60aa13b2b21f9c79275fb652875239350ff78674..6c954cddfe662316062fb56b8ef9ff62d39bc9ba 100644 (file)
@@ -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
index 35e90d16cc6665e1a8400231faa5772dbd18fe49..1753182e8959db08c7a03c2a89e78b2bf23b0ccf 100644 (file)
 #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);
+}
index b1e8ec545e79ca6c8cf3054c796addf8c73e8994..f5b93c27a8842750743e00dbd905589ca0eacba1 100644 (file)
@@ -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;
 }