net/mlx5e: Query FW for buffer ownership
authorAlexei Lazar <alazar@nvidia.com>
Wed, 20 Aug 2025 13:32:08 +0000 (16:32 +0300)
committerJakub Kicinski <kuba@kernel.org>
Thu, 21 Aug 2025 14:58:32 +0000 (07:58 -0700)
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: ecdf2dadee8e ("net/mlx5e: Receive buffer support for DCBX")
Signed-off-by: Alexei Lazar <alazar@nvidia.com>
Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-8-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/port.c

index b59aee7..2c98a52 100644 (file)
@@ -26,7 +26,6 @@ struct mlx5e_dcbx {
        u8                         cap;
 
        /* Buffer configuration */
-       bool                       manual_buffer;
        u32                        cable_len;
        u32                        xoff;
        u16                        port_buff_cell_sz;
index 5fe016e..d166c0d 100644 (file)
@@ -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);
index b6d53db..9d3504f 100644 (file)
@@ -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);
 
index 549f106..2d7adf7 100644 (file)
@@ -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);