From: Inbar Karmy <inb...@mellanox.com>

Implement set/get functions to configure PFC stall prevention
mode by ethtool.
On default the stall prevention timeout is configured to 8 sec.
Auto mode will set the stall prevention timeout to be 100 msec.

Signed-off-by: Inbar Karmy <inb...@mellanox.com>
Reviewed-by: Eran Ben Elisha <era...@mellanox.com>
---
 .../net/ethernet/mellanox/mlx5/core/en_ethtool.c   | 51 ++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx5/core/port.c     | 56 ++++++++++++++++++----
 include/linux/mlx5/mlx5_ifc.h                      | 22 +++++++--
 include/linux/mlx5/port.h                          |  5 ++
 4 files changed, 121 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 23425f0..74096f1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1180,6 +1180,55 @@ static int mlx5e_set_pauseparam(struct net_device 
*netdev,
        return err;
 }
 
+#define MLX5E_PFC_PREVEN_CRITICAL_AUTO_MSEC    100
+#define MLX5E_PFC_PREVEN_MINOR_AUTO_MSEC       85
+#define MLX5E_PFC_PREVEN_CRITICAL_DEFAULT_MSEC 8000
+#define MLX5E_PFC_PREVEN_MINOR_DEFAULT_MSEC    6800
+
+static int mlx5e_get_pfc_prevention_mode(struct net_device *netdev,
+                                        struct ethtool_pfc_prevention 
*pfc_preven)
+{
+       struct mlx5e_priv *priv    = netdev_priv(netdev);
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u16 pfc_prevention_critical;
+       int err;
+
+       if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask))
+               return -EOPNOTSUPP;
+
+       err = mlx5_query_port_pfc_prevention(mdev, &pfc_prevention_critical);
+
+       pfc_preven->mode = (pfc_prevention_critical ==
+                           MLX5E_PFC_PREVEN_CRITICAL_DEFAULT_MSEC) ?
+                           ETH_PFC_PREVENTION_DEFAULT : 
ETH_PFC_PREVENTION_AUTO;
+       return err;
+}
+
+static int mlx5e_set_pfc_prevention_mode(struct net_device *netdev,
+                                        struct ethtool_pfc_prevention 
*pfc_preven)
+{
+       struct mlx5e_priv *priv    = netdev_priv(netdev);
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u16 pfc_prevention_critical;
+       u16 pfc_prevention_minor;
+       int err;
+
+       if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask))
+               return -EOPNOTSUPP;
+
+       pfc_prevention_critical = (pfc_preven->mode == 
ETH_PFC_PREVENTION_DEFAULT) ?
+                                  MLX5E_PFC_PREVEN_CRITICAL_DEFAULT_MSEC :
+                                  MLX5E_PFC_PREVEN_CRITICAL_AUTO_MSEC;
+       pfc_prevention_minor = (pfc_prevention_critical ==
+                               MLX5E_PFC_PREVEN_CRITICAL_DEFAULT_MSEC) ?
+                               MLX5E_PFC_PREVEN_MINOR_DEFAULT_MSEC :
+                               MLX5E_PFC_PREVEN_MINOR_AUTO_MSEC;
+       err = mlx5_set_port_pfc_prevention(mdev, pfc_prevention_critical,
+                                          pfc_prevention_minor);
+
+       return err;
+}
+
 int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
                              struct ethtool_ts_info *info)
 {
@@ -1696,6 +1745,8 @@ static int mlx5e_flash_device(struct net_device *dev,
        .set_tunable       = mlx5e_set_tunable,
        .get_pauseparam    = mlx5e_get_pauseparam,
        .set_pauseparam    = mlx5e_set_pauseparam,
+       .get_pfc_prevention_mode = mlx5e_get_pfc_prevention_mode,
+       .set_pfc_prevention_mode = mlx5e_set_pfc_prevention_mode,
        .get_ts_info       = mlx5e_get_ts_info,
        .set_phys_id       = mlx5e_set_phys_id,
        .get_wol           = mlx5e_get_wol,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c 
b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index c37d00c..d2f7357 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -483,6 +483,16 @@ int mlx5_core_query_ib_ppcnt(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL_GPL(mlx5_core_query_ib_ppcnt);
 
+static int mlx5_query_pfcc_reg(struct mlx5_core_dev *dev, u32 *out, u32 
out_size)
+{
+       u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
+
+       MLX5_SET(pfcc_reg, in, local_port, 1);
+
+       return mlx5_core_access_reg(dev, in, sizeof(in), out,
+                                   out_size, MLX5_REG_PFCC, 0, 0);
+}
+
 int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause)
 {
        u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
@@ -500,13 +510,10 @@ int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 
rx_pause, u32 tx_pause)
 int mlx5_query_port_pause(struct mlx5_core_dev *dev,
                          u32 *rx_pause, u32 *tx_pause)
 {
-       u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
        u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
        int err;
 
-       MLX5_SET(pfcc_reg, in, local_port, 1);
-       err = mlx5_core_access_reg(dev, in, sizeof(in), out,
-                                  sizeof(out), MLX5_REG_PFCC, 0, 0);
+       err = mlx5_query_pfcc_reg(dev, out, sizeof(out));
        if (err)
                return err;
 
@@ -520,6 +527,42 @@ int mlx5_query_port_pause(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL_GPL(mlx5_query_port_pause);
 
+int mlx5_set_port_pfc_prevention(struct mlx5_core_dev *dev,
+                                u16 pfc_preven_critical, u16 pfc_preven_minor)
+{
+       u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
+       u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
+
+       MLX5_SET(pfcc_reg, in, local_port, 1);
+       MLX5_SET(pfcc_reg, in, pptx_mask_n, 1);
+       MLX5_SET(pfcc_reg, in, pprx_mask_n, 1);
+       MLX5_SET(pfcc_reg, in, ppan_mask_n, 1);
+       MLX5_SET(pfcc_reg, in, critical_stall_mask, 1);
+       MLX5_SET(pfcc_reg, in, minor_stall_mask, 1);
+       MLX5_SET(pfcc_reg, in, device_stall_critical_watermark, 
pfc_preven_critical);
+       MLX5_SET(pfcc_reg, in, device_stall_minor_watermark, pfc_preven_minor);
+
+       return mlx5_core_access_reg(dev, in, sizeof(in), out,
+                                   sizeof(out), MLX5_REG_PFCC, 0, 1);
+}
+
+int mlx5_query_port_pfc_prevention(struct mlx5_core_dev *dev,
+                                  u16 *pfc_preven_critical)
+{
+       u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
+       int err;
+
+       err = mlx5_query_pfcc_reg(dev, out, sizeof(out));
+       if (err)
+               return err;
+
+       if (pfc_preven_critical)
+               *pfc_preven_critical = MLX5_GET(pfcc_reg, out,
+                                               
device_stall_critical_watermark);
+
+       return 0;
+}
+
 int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx)
 {
        u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
@@ -538,13 +581,10 @@ int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 
pfc_en_tx, u8 pfc_en_rx)
 
 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 
*pfc_en_rx)
 {
-       u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
        u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
        int err;
 
-       MLX5_SET(pfcc_reg, in, local_port, 1);
-       err = mlx5_core_access_reg(dev, in, sizeof(in), out,
-                                  sizeof(out), MLX5_REG_PFCC, 0, 0);
+       err = mlx5_query_pfcc_reg(dev, out, sizeof(out));
        if (err)
                return err;
 
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 3e5363f..966cd5f 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -7755,7 +7755,11 @@ struct mlx5_ifc_pifr_reg_bits {
 struct mlx5_ifc_pfcc_reg_bits {
        u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_at_10[0x10];
+       u8         reserved_at_10[0xb];
+       u8         ppan_mask_n[0x1];
+       u8         minor_stall_mask[0x1];
+       u8         critical_stall_mask[0x1];
+       u8         reserved_at_1e[0x2];
 
        u8         ppan[0x4];
        u8         reserved_at_24[0x4];
@@ -7765,17 +7769,22 @@ struct mlx5_ifc_pfcc_reg_bits {
 
        u8         pptx[0x1];
        u8         aptx[0x1];
-       u8         reserved_at_42[0x6];
+       u8         pptx_mask_n[0x1];
+       u8         reserved_at_43[0x5];
        u8         pfctx[0x8];
        u8         reserved_at_50[0x10];
 
        u8         pprx[0x1];
        u8         aprx[0x1];
-       u8         reserved_at_62[0x6];
+       u8         pprx_mask_n[0x1];
+       u8         reserved_at_63[0x5];
        u8         pfcrx[0x8];
        u8         reserved_at_70[0x10];
 
-       u8         reserved_at_80[0x80];
+       u8         device_stall_minor_watermark[0x10];
+       u8         device_stall_critical_watermark[0x10];
+
+       u8         reserved_at_a0[0x60];
 };
 
 struct mlx5_ifc_pelc_reg_bits {
@@ -7816,7 +7825,10 @@ struct mlx5_ifc_peir_reg_bits {
 };
 
 struct mlx5_ifc_pcam_enhanced_features_bits {
-       u8         reserved_at_0[0x7b];
+       u8         reserved_at_0[0x76];
+ 
+       u8         pfcc_mask[0x1];
+       u8         reserved_at_77[0x4];
 
        u8         rx_buffer_fullness_counters[0x1];
        u8         ptys_connector_type[0x1];
diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h
index 035f0d4..139a228 100644
--- a/include/linux/mlx5/port.h
+++ b/include/linux/mlx5/port.h
@@ -147,6 +147,11 @@ int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev,
 int mlx5_query_port_pause(struct mlx5_core_dev *dev,
                          u32 *rx_pause, u32 *tx_pause);
 
+int mlx5_set_port_pfc_prevention(struct mlx5_core_dev *dev, u16 
pfc_preven_critical,
+                                u16 pfc_preven_minor);
+int mlx5_query_port_pfc_prevention(struct mlx5_core_dev *dev,
+                                  u16 *pfc_preven_critical);
+
 int mlx5_set_port_pfc(struct mlx5_core_dev *dev, u8 pfc_en_tx, u8 pfc_en_rx);
 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx,
                        u8 *pfc_en_rx);
-- 
1.8.3.1

Reply via email to