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