@@ -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,
@@ -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;
@@ -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];
@@ -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);