Commit 451d2849 authored by Alexei Lazar's avatar Alexei Lazar Committed by Jakub Kicinski
Browse files

net/mlx5e: Query FW for buffer ownership



The SW currently saves local buffer ownership when setting
the buffer.
This means that the SW assumes it has ownership of the buffer
after the command is set.

If setting the buffer fails and we remain in FW ownership,
the local buffer ownership state incorrectly remains as SW-owned.
This leads to incorrect behavior in subsequent PFC commands,
causing failures.

Instead of saving local buffer ownership in SW,
query the FW for buffer ownership when setting the buffer.
This ensures that the buffer ownership state is accurately
reflected, avoiding the issues caused by incorrect ownership
states.

Fixes: ecdf2dad ("net/mlx5e: Receive buffer support for DCBX")
Signed-off-by: default avatarAlexei Lazar <alazar@nvidia.com>
Reviewed-by: default avatarShahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: default avatarDragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: default avatarMark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-8-mbloch@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 51b17c98
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ struct mlx5e_dcbx {
	u8                         cap;

	/* Buffer configuration */
	bool                       manual_buffer;
	u32                        cable_len;
	u32                        xoff;
	u16                        port_buff_cell_sz;
+9 −3
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
				   struct ieee_pfc *pfc)
{
	u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;
	u32 old_cable_len = priv->dcbx.cable_len;
@@ -389,7 +390,14 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,

	if (MLX5_BUFFER_SUPPORTED(mdev)) {
		pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
		if (priv->dcbx.manual_buffer)
		ret = mlx5_query_port_buffer_ownership(mdev,
						       &buffer_ownership);
		if (ret)
			netdev_err(dev,
				   "%s, Failed to get buffer ownership: %d\n",
				   __func__, ret);

		if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED)
			ret = mlx5e_port_manual_buffer_config(priv, changed,
							      dev->mtu, &pfc_new,
							      NULL, NULL);
@@ -982,7 +990,6 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
	if (!changed)
		return 0;

	priv->dcbx.manual_buffer = true;
	err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
					      buffer_size, prio2buffer);
	return err;
@@ -1252,7 +1259,6 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
		priv->dcbx.cap |= DCB_CAP_DCBX_HOST;

	priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
	priv->dcbx.manual_buffer = false;
	priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;

	mlx5e_ets_init(priv);
+2 −0
Original line number Diff line number Diff line
@@ -367,6 +367,8 @@ int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state);
int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state);
int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev,
				     u8 *buffer_ownership);
int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio);
int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio);

+20 −0
Original line number Diff line number Diff line
@@ -968,6 +968,26 @@ int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
	return err;
}

int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev,
				     u8 *buffer_ownership)
{
	u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {};
	int err;

	if (!MLX5_CAP_PCAM_FEATURE(mdev, buffer_ownership)) {
		*buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
		return 0;
	}

	err = mlx5_query_pfcc_reg(mdev, out, sizeof(out));
	if (err)
		return err;

	*buffer_ownership = MLX5_GET(pfcc_reg, out, buf_ownership);

	return 0;
}

int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio)
{
	int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);