mlxsw: spectrum: Adjust headroom buffers for 8x ports
authorIdo Schimmel <idosch@mellanox.com>
Tue, 16 Jun 2020 07:14:58 +0000 (10:14 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Jun 2020 20:46:27 +0000 (13:46 -0700)
The port's headroom buffers are used to store packets while they
traverse the device's pipeline and also to store packets that are egress
mirrored.

On Spectrum-3, ports with eight lanes use two headroom buffers between
which the configured headroom size is split.

In order to prevent packet loss, multiply the calculated headroom size
by two for 8x ports.

Fixes: da382875c616 ("mlxsw: spectrum: Extend to support Spectrum-3 ASIC")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c

index 5ffa32b75e5fb93c731d1d07bc98a57e9c8c9c7d..55af877763ed4c1f9b868fb20f8563e7db9c2d33 100644 (file)
@@ -978,8 +978,10 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 
                lossy = !(pfc || pause_en);
                thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &thres_cells);
                delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
                                                        pfc, pause_en);
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &delay_cells);
                total_cells = thres_cells + delay_cells;
 
                taken_headroom_cells += total_cells;
index 6f96ca50c9bab8be632fa179281b02c254456b9e..6e87457dd635bef9a0ee38a88f4801ff3c3f3ac6 100644 (file)
@@ -374,6 +374,19 @@ mlxsw_sp_port_vlan_find_by_vid(const struct mlxsw_sp_port *mlxsw_sp_port,
        return NULL;
 }
 
+static inline void
+mlxsw_sp_port_headroom_8x_adjust(const struct mlxsw_sp_port *mlxsw_sp_port,
+                                u16 *p_size)
+{
+       /* Ports with eight lanes use two headroom buffers between which the
+        * configured headroom size is split. Therefore, multiply the calculated
+        * headroom size by two.
+        */
+       if (mlxsw_sp_port->mapping.width != 8)
+               return;
+       *p_size *= 2;
+}
+
 enum mlxsw_sp_flood_type {
        MLXSW_SP_FLOOD_TYPE_UC,
        MLXSW_SP_FLOOD_TYPE_BC,
index 21bfb2f6a6f0b824981a8109f9958a8b85f8d47f..f25a8b084b4bb3e1b0c871b3349b5fbf0f99ad09 100644 (file)
@@ -312,6 +312,7 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
                if (i == MLXSW_SP_PB_UNUSED)
                        continue;
+               mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, &size);
                mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, size);
        }
        mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl,
index 304eb8c3d8bd744fc91e24c3ab6d59f0a32af614..f843545d3478d6c9cc49041e2cf13feb1ec55a31 100644 (file)
@@ -782,6 +782,7 @@ mlxsw_sp_span_port_buffer_update(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
                speed = 0;
 
        buffsize = mlxsw_sp_span_buffsize_get(mlxsw_sp, speed, mtu);
+       mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, (u16 *) &buffsize);
        mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, buffsize);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
 }