Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2afa609f authored by Inbar Karmy's avatar Inbar Karmy Committed by Saeed Mahameed
Browse files

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: default avatarInbar Karmy <inbark@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent e1577c1c
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -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;
+56 −8
Original line number Diff line number Diff line
@@ -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;

+13 −4
Original line number Diff line number Diff line
@@ -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 {
+6 −0
Original line number Diff line number Diff line
@@ -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);