net/mlx5e: PFC stall prevention support
Implement set/get functions to configure PFC stall prevention timeout by tunables api through ethtool. By default the stall prevention timeout is configured to 8 sec. Timeout range is: 80-8000 msec. Enabling stall prevention with the auto timeout will set the timeout to 100 msec. Signed-off-by: Inbar Karmy <inbark@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
e1577c1c88
commit
2afa609f5c
|
@ -1066,6 +1066,57 @@ static int mlx5e_get_rxnfc(struct net_device *netdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
#define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC 100
|
||||
#define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC 8000
|
||||
#define MLX5E_PFC_PREVEN_MINOR_PRECENT 85
|
||||
#define MLX5E_PFC_PREVEN_TOUT_MIN_MSEC 80
|
||||
#define MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout) \
|
||||
max_t(u16, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC, \
|
||||
(critical_tout * MLX5E_PFC_PREVEN_MINOR_PRECENT) / 100)
|
||||
|
||||
static int mlx5e_get_pfc_prevention_tout(struct net_device *netdev,
|
||||
u16 *pfc_prevention_tout)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) ||
|
||||
!MLX5_CAP_DEBUG((priv)->mdev, stall_detect))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return mlx5_query_port_stall_watermark(mdev, pfc_prevention_tout, NULL);
|
||||
}
|
||||
|
||||
static int mlx5e_set_pfc_prevention_tout(struct net_device *netdev,
|
||||
u16 pfc_preven)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u16 critical_tout;
|
||||
u16 minor;
|
||||
|
||||
if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) ||
|
||||
!MLX5_CAP_DEBUG((priv)->mdev, stall_detect))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
critical_tout = (pfc_preven == PFC_STORM_PREVENTION_AUTO) ?
|
||||
MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC :
|
||||
pfc_preven;
|
||||
|
||||
if (critical_tout != PFC_STORM_PREVENTION_DISABLE &&
|
||||
(critical_tout > MLX5E_PFC_PREVEN_TOUT_MAX_MSEC ||
|
||||
critical_tout < MLX5E_PFC_PREVEN_TOUT_MIN_MSEC)) {
|
||||
netdev_info(netdev, "%s: pfc prevention tout not in range (%d-%d)\n",
|
||||
__func__, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC,
|
||||
MLX5E_PFC_PREVEN_TOUT_MAX_MSEC);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
minor = MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout);
|
||||
return mlx5_set_port_stall_watermark(mdev, critical_tout,
|
||||
minor);
|
||||
}
|
||||
|
||||
static int mlx5e_get_tunable(struct net_device *dev,
|
||||
const struct ethtool_tunable *tuna,
|
||||
void *data)
|
||||
|
@ -1077,6 +1128,9 @@ static int mlx5e_get_tunable(struct net_device *dev,
|
|||
case ETHTOOL_TX_COPYBREAK:
|
||||
*(u32 *)data = priv->channels.params.tx_max_inline;
|
||||
break;
|
||||
case ETHTOOL_PFC_PREVENTION_TOUT:
|
||||
err = mlx5e_get_pfc_prevention_tout(dev, data);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
|
@ -1118,6 +1172,9 @@ static int mlx5e_set_tunable(struct net_device *dev,
|
|||
break;
|
||||
mlx5e_switch_priv_channels(priv, &new_channels, NULL);
|
||||
|
||||
break;
|
||||
case ETHTOOL_PFC_PREVENTION_TOUT:
|
||||
err = mlx5e_set_pfc_prevention_tout(dev, *(u16 *)data);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
|
|
|
@ -483,6 +483,17 @@ 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 +511,10 @@ EXPORT_SYMBOL_GPL(mlx5_set_port_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 +528,49 @@ int mlx5_query_port_pause(struct mlx5_core_dev *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_pause);
|
||||
|
||||
int mlx5_set_port_stall_watermark(struct mlx5_core_dev *dev,
|
||||
u16 stall_critical_watermark,
|
||||
u16 stall_minor_watermark)
|
||||
{
|
||||
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,
|
||||
stall_critical_watermark);
|
||||
MLX5_SET(pfcc_reg, in, device_stall_minor_watermark, stall_minor_watermark);
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PFCC, 0, 1);
|
||||
}
|
||||
|
||||
int mlx5_query_port_stall_watermark(struct mlx5_core_dev *dev,
|
||||
u16 *stall_critical_watermark,
|
||||
u16 *stall_minor_watermark)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
|
||||
int err;
|
||||
|
||||
err = mlx5_query_pfcc_reg(dev, out, sizeof(out));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (stall_critical_watermark)
|
||||
*stall_critical_watermark = MLX5_GET(pfcc_reg, out,
|
||||
device_stall_critical_watermark);
|
||||
|
||||
if (stall_minor_watermark)
|
||||
*stall_minor_watermark = MLX5_GET(pfcc_reg, out,
|
||||
device_stall_minor_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 +589,10 @@ EXPORT_SYMBOL_GPL(mlx5_set_port_pfc);
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -7833,7 +7833,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];
|
||||
|
@ -7843,17 +7847,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 {
|
||||
|
|
|
@ -151,6 +151,12 @@ 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);
|
||||
|
||||
int mlx5_set_port_stall_watermark(struct mlx5_core_dev *dev,
|
||||
u16 stall_critical_watermark,
|
||||
u16 stall_minor_watermark);
|
||||
int mlx5_query_port_stall_watermark(struct mlx5_core_dev *dev,
|
||||
u16 *stall_critical_watermark, u16 *stall_minor_watermark);
|
||||
|
||||
int mlx5_max_tc(struct mlx5_core_dev *mdev);
|
||||
|
||||
int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc);
|
||||
|
|
Loading…
Reference in New Issue