| From 4582f0d0826ed5baae0449d3c6fe5f7824bd4060 Mon Sep 17 00:00:00 2001 |
| From: Petr Machata <petrm@mellanox.com> |
| Date: Wed, 15 Jan 2020 13:53:48 +0200 |
| Subject: [PATCH] mlxsw: spectrum: Wipe xstats.backlog of down ports |
| |
| commit ca7609ff3680c51d6c29897f3117aa2ad904f92a upstream. |
| |
| Per-port counter cache used by Qdiscs is updated periodically, unless the |
| port is down. The fact that the cache is not updated for down ports is no |
| problem for most counters, which are relative in nature. However, backlog |
| is absolute in nature, and if there is a non-zero value in the cache around |
| the time that the port goes down, that value just stays there. This value |
| then leaks to offloaded Qdiscs that report non-zero backlog even if |
| there (obviously) is no traffic. |
| |
| The HW does not keep backlog of a downed port, so do likewise: as the port |
| goes down, wipe the backlog value from xstats. |
| |
| Fixes: 075ab8adaf4e ("mlxsw: spectrum: Collect tclass related stats periodically") |
| Signed-off-by: Petr Machata <petrm@mellanox.com> |
| Acked-by: Jiri Pirko <jiri@mellanox.com> |
| Signed-off-by: Ido Schimmel <idosch@mellanox.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c |
| index da260149c0ad..cca5c9b5a79e 100644 |
| --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c |
| +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c |
| @@ -1087,6 +1087,9 @@ static void update_stats_cache(struct work_struct *work) |
| periodic_hw_stats.update_dw.work); |
| |
| if (!netif_carrier_ok(mlxsw_sp_port->dev)) |
| + /* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as |
| + * necessary when port goes down. |
| + */ |
| goto out; |
| |
| mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev, |
| @@ -3906,6 +3909,15 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port, |
| return 0; |
| } |
| |
| +static void |
| +mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < TC_MAX_QUEUE; i++) |
| + mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0; |
| +} |
| + |
| static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, |
| char *pude_pl, void *priv) |
| { |
| @@ -3926,6 +3938,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, |
| } else { |
| netdev_info(mlxsw_sp_port->dev, "link down\n"); |
| netif_carrier_off(mlxsw_sp_port->dev); |
| + mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port); |
| } |
| } |
| |
| -- |
| 2.7.4 |
| |