diff mbox series

[RFC] net/mlx5e: Temp software stats variable is not required

Message ID 20181103015422.22978-1-saeedm@mellanox.com
State RFC, archived
Delegated to: David Miller
Headers show
Series [RFC] net/mlx5e: Temp software stats variable is not required | expand

Commit Message

Saeed Mahameed Nov. 3, 2018, 1:54 a.m. UTC
mlx5e_grp_sw_update_stats can be called from two threads,
1) ndo_get_stats64
2) get_ethtool_stats

For this reason and to minimize concurrency issue impact on 64bit machines
mlx5e_grp_sw_update_stats folds the software stats into a temporary sw
stats variable and at the end memcopy it to the global driver stats,
both ethtool and ndo will use the global software stats copy to report
whatever stats they need.

Actually ndo_get_stats64 doesn't need to fold the whole software stats
(mlx5e_grp_sw_update_stats), all it needs is five counters to fill the
rtnl_link_stats64 relevant stats paramter.

Hence this patch introduces a simpler helper function to fold software
stats for ndo_get_stats64 mlx5e_fold_sw_stats which will work directly on
rtnl_link_stats64 stats parameter and not on the global or even temporary
mlx5e_sw_stats, And since now ndo_get_stats64 doesn't call
mlx5e_grp_sw_update_stats any more, we can make it static and remove the
temp var.

This patch will fix high stack usage of mlx5e_grp_sw_update_stats on
x86 gcc-4.9 and higher.  And the concurrency issue between mlx5's
ndo_get_stats64 and get_ethtool_stats.

Reported-by: Arnd Bergmann <arnd@arndb.de>
Reported-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 36 ++++++++++++++-----
 .../ethernet/mellanox/mlx5/core/en_stats.c    |  6 ++--
 .../ethernet/mellanox/mlx5/core/en_stats.h    |  2 --
 3 files changed, 29 insertions(+), 15 deletions(-)

Comments

David Miller Nov. 4, 2018, 2:36 a.m. UTC | #1
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Fri,  2 Nov 2018 18:54:22 -0700

> +static void mlx5e_fold_sw_stats(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
> +{
> +	int i;
> +
> +	/* not required ? */
> +	memset(s, 0, sizeof(*s));

Why wouldn't this be required?

I can see that perhaps you can only zero out the statistics that are used in
the ndo_get_stats64() code path, but that's different.
Saeed Mahameed Nov. 5, 2018, 7:13 p.m. UTC | #2
On Sat, 2018-11-03 at 19:36 -0700, David Miller wrote:
> From: Saeed Mahameed <saeedm@mellanox.com>
> Date: Fri,  2 Nov 2018 18:54:22 -0700
> 
> > +static void mlx5e_fold_sw_stats(struct mlx5e_priv *priv, struct
> > rtnl_link_stats64 *s)
> > +{
> > +	int i;
> > +
> > +	/* not required ? */
> > +	memset(s, 0, sizeof(*s));
> 
> Why wouldn't this be required?
> 

I just checked it is already done by the stack @dev_get_stats()

> I can see that perhaps you can only zero out the statistics that are
> used in
> 
> the ndo_get_stats64() code path, but that's different.

mlx5e_fold_sw_stats can only be called from ndo_get_stats64().
The "s" pointer i am trying to zero out here is the same pointer we
receive from ndo_get_stats64().
David Miller Nov. 5, 2018, 7:27 p.m. UTC | #3
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Mon, 5 Nov 2018 19:13:59 +0000

> On Sat, 2018-11-03 at 19:36 -0700, David Miller wrote:
>> From: Saeed Mahameed <saeedm@mellanox.com>
>> Date: Fri,  2 Nov 2018 18:54:22 -0700
>> 
>> > +static void mlx5e_fold_sw_stats(struct mlx5e_priv *priv, struct
>> > rtnl_link_stats64 *s)
>> > +{
>> > +	int i;
>> > +
>> > +	/* not required ? */
>> > +	memset(s, 0, sizeof(*s));
>> 
>> Why wouldn't this be required?
>> 
> 
> I just checked it is already done by the stack @dev_get_stats()

Then please document this in the commit message or similar.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 1243edbedc9e..2d1c5bb81acd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3437,11 +3437,35 @@  static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
 	}
 }
 
+static void mlx5e_fold_sw_stats(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
+{
+	int i;
+
+	/* not required ? */
+	memset(s, 0, sizeof(*s));
+
+	for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+		struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i];
+		struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
+		int j;
+
+		s->rx_packets   += rq_stats->packets;
+		s->rx_bytes     += rq_stats->bytes;
+
+		for (j = 0; j < priv->max_opened_tc; j++) {
+			struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j];
+
+			s->tx_packets    += sq_stats->packets;
+			s->tx_bytes      += sq_stats->bytes;
+			s->tx_dropped    += sq_stats->dropped;
+		}
+	}
+}
+
 static void
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
-	struct mlx5e_sw_stats *sstats = &priv->stats.sw;
 	struct mlx5e_vport_stats *vstats = &priv->stats.vport;
 	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
@@ -3453,14 +3477,8 @@  mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 		stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
 		stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
 		stats->tx_bytes   = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
-	} else {
-		mlx5e_grp_sw_update_stats(priv);
-		stats->rx_packets = sstats->rx_packets;
-		stats->rx_bytes   = sstats->rx_bytes;
-		stats->tx_packets = sstats->tx_packets;
-		stats->tx_bytes   = sstats->tx_bytes;
-		stats->tx_dropped = sstats->tx_queue_dropped;
-	}
+	} else
+		mlx5e_fold_sw_stats(priv, stats);
 
 	stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index 1e55b9c27ffc..8afc2a183a23 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -126,9 +126,9 @@  static int mlx5e_grp_sw_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx)
 	return idx;
 }
 
-void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
+static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 {
-	struct mlx5e_sw_stats temp, *s = &temp;
+	struct mlx5e_sw_stats *s = &priv->stats.sw;
 	int i;
 
 	memset(s, 0, sizeof(*s));
@@ -211,8 +211,6 @@  void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 			s->tx_cqes		+= sq_stats->cqes;
 		}
 	}
-
-	memcpy(&priv->stats.sw, s, sizeof(*s));
 }
 
 static const struct counter_desc q_stats_desc[] = {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
index 77f74ce11280..c628fb43db8c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -277,6 +277,4 @@  struct mlx5e_stats_grp {
 extern const struct mlx5e_stats_grp mlx5e_stats_grps[];
 extern const int mlx5e_num_stats_grps;
 
-void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv);
-
 #endif /* __MLX5_EN_STATS_H__ */