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)
        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;
                        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;
 
 }
 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};
 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;
 
 }
 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};
 
 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;