Skip to content

Commit 6977692

Browse files
committed
Merge branch 'mlx5-genl-queue-stats'
Joe Damato says: ==================== mlx5: Add netdev-genl queue stats Welcome to v5. Switched from RFC to just a v5, because I think this is pretty close. Minor changes from v4 summarized below in the changelog. Note that my NIC does not seem to support PTP and I couldn't get the mlnx-tools mlnx_qos script to work, so I was only able to test the following cases: - device up at boot - adjusting queue counts - device down (e.g. ip link set dev eth4 down) Please see the commit message of patch 2/2 for more details on output and test cases. rfcv4 thread: https://lore.kernel.org/linux-kernel/20240604004629.299699-1-jdamato@fastly.com/T/ rfcv4 -> v5: - Patch 1/2: change variable name 'mlx5e_qid' to 'txq_ix'. - Patch 2/2: - remove logic in mlx5e_get_queue_stats_rx for PTP. PTP RX are always reported in base. - report PTP TX in mlx5e_get_base_stats only if: - PTP has ever been opened, and - either PTP is NULL (closed) or the MLX5E_PTP_STATE_TX bit in its state is not set Otherwise, PTP TX will be reported when the txq_ix is passed into mlx5e_get_queue_stats_tx rfcv3 -> rfcv4: - Patch 1/2 now creates a mapping (priv->txq2sq_stats) which maps txq indices to sq_stats structures so stats can be accessed directly. This mapping is kept up to date along side txq2sq. - Patch 2/2: - All mutex_lock/unlock on state_lock has been dropped. - mlx5e_get_queue_stats_rx now uses ASSERT_RTNL() and has a special case for PTP. If PTP was ever opened, is currently opened, and the channel index matches, stats for PTP RX are output. - mlx5e_get_queue_stats_tx rewritten to use priv->txq2sq_stats. No corner cases are needed here because any txq idx (passed in as i) will have an up to date mapping in priv->txq2sq_stats. - mlx5e_get_base_stats: - in the RX case: - iterates from [params.num_channels, stats_nch) collecting stats. - if ptp was ever opened but is currently closed, add the PTP stats. - in the TX case: - handle 2 cases: - the channel is available, so sum only the unavailable TCs [mlx5e_get_dcb_num_tc, max_opened_tc). - the channel is unavailable, so sum all TCs [0, max_opened_tc). - if ptp was ever opened but is currently closed, add the PTP sq stats. v2 -> rfcv3: - Added patch 1/2 which creates some helpers for computing the txq_ix and ch_ix/tc_ix. - Patch 2/2 modified in several ways: - Fixed variable declarations in mlx5e_get_queue_stats_rx to be at the start of the function. - mlx5e_get_queue_stats_tx rewritten to access sq stats directly by using the helpers added in the previous patch. - mlx5e_get_base_stats modified in several ways: - Took the state_lock when accessing priv->channels. - For the base RX stats, code was simplified to call mlx5e_get_queue_stats_rx instead of repeating the same code. - For the base TX stats, I attempted to implement what I think Tariq suggested in the previous thread: - for available channels, only unavailable TC stats are summed - for unavailable channels, all stats for TCs up to max_opened_tc are summed. v1 - > v2: - Essentially a full rewrite after comments from Jakub, Tariq, and Zhu. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 934c299 + 7b66ae5 commit 6977692

File tree

3 files changed

+155
-3
lines changed

3 files changed

+155
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,8 @@ struct mlx5e_priv {
867867
/* priv data path fields - start */
868868
struct mlx5e_selq selq;
869869
struct mlx5e_txqsq **txq2sq;
870+
struct mlx5e_sq_stats **txq2sq_stats;
871+
870872
#ifdef CONFIG_MLX5_CORE_EN_DCB
871873
struct mlx5e_dcbx_dp dcbx_dp;
872874
#endif

drivers/net/ethernet/mellanox/mlx5/core/en/qos.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ int mlx5e_activate_qos_sq(void *data, u16 node_qid, u32 hw_id)
170170
mlx5e_tx_disable_queue(netdev_get_tx_queue(priv->netdev, qid));
171171

172172
priv->txq2sq[qid] = sq;
173+
priv->txq2sq_stats[qid] = sq->stats;
173174

174175
/* Make the change to txq2sq visible before the queue is started.
175176
* As mlx5e_xmit runs under a spinlock, there is an implicit ACQUIRE,
@@ -186,6 +187,7 @@ int mlx5e_activate_qos_sq(void *data, u16 node_qid, u32 hw_id)
186187
void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid)
187188
{
188189
struct mlx5e_txqsq *sq;
190+
u16 txq_ix;
189191

190192
sq = mlx5e_get_qos_sq(priv, qid);
191193
if (!sq) /* Handle the case when the SQ failed to open. */
@@ -194,7 +196,10 @@ void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid)
194196
qos_dbg(sq->mdev, "Deactivate QoS SQ qid %u\n", qid);
195197
mlx5e_deactivate_txqsq(sq);
196198

197-
priv->txq2sq[mlx5e_qid_from_qos(&priv->channels, qid)] = NULL;
199+
txq_ix = mlx5e_qid_from_qos(&priv->channels, qid);
200+
201+
priv->txq2sq[txq_ix] = NULL;
202+
priv->txq2sq_stats[txq_ix] = NULL;
198203

199204
/* Make the change to txq2sq visible before the queue is started again.
200205
* As mlx5e_xmit runs under a spinlock, there is an implicit ACQUIRE,
@@ -325,6 +330,7 @@ void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c)
325330
{
326331
struct mlx5e_params *params = &c->priv->channels.params;
327332
struct mlx5e_txqsq __rcu **qos_sqs;
333+
u16 txq_ix;
328334
int i;
329335

330336
qos_sqs = mlx5e_state_dereference(c->priv, c->qos_sqs);
@@ -342,8 +348,11 @@ void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c)
342348
qos_dbg(c->mdev, "Deactivate QoS SQ qid %u\n", qid);
343349
mlx5e_deactivate_txqsq(sq);
344350

351+
txq_ix = mlx5e_qid_from_qos(&c->priv->channels, qid);
352+
345353
/* The queue is disabled, no synchronization with datapath is needed. */
346-
c->priv->txq2sq[mlx5e_qid_from_qos(&c->priv->channels, qid)] = NULL;
354+
c->priv->txq2sq[txq_ix] = NULL;
355+
c->priv->txq2sq_stats[txq_ix] = NULL;
347356
}
348357
}
349358

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <linux/debugfs.h>
4040
#include <linux/if_bridge.h>
4141
#include <linux/filter.h>
42+
#include <net/netdev_queues.h>
4243
#include <net/page_pool/types.h>
4344
#include <net/pkt_sched.h>
4445
#include <net/xdp_sock_drv.h>
@@ -3125,6 +3126,7 @@ static void mlx5e_build_txq_maps(struct mlx5e_priv *priv)
31253126
struct mlx5e_txqsq *sq = &c->sq[tc];
31263127

31273128
priv->txq2sq[sq->txq_ix] = sq;
3129+
priv->txq2sq_stats[sq->txq_ix] = sq->stats;
31283130
}
31293131
}
31303132

@@ -3139,6 +3141,7 @@ static void mlx5e_build_txq_maps(struct mlx5e_priv *priv)
31393141
struct mlx5e_txqsq *sq = &c->ptpsq[tc].txqsq;
31403142

31413143
priv->txq2sq[sq->txq_ix] = sq;
3144+
priv->txq2sq_stats[sq->txq_ix] = sq->stats;
31423145
}
31433146

31443147
out:
@@ -5296,6 +5299,136 @@ static bool mlx5e_tunnel_any_tx_proto_supported(struct mlx5_core_dev *mdev)
52965299
return (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev));
52975300
}
52985301

5302+
static void mlx5e_get_queue_stats_rx(struct net_device *dev, int i,
5303+
struct netdev_queue_stats_rx *stats)
5304+
{
5305+
struct mlx5e_priv *priv = netdev_priv(dev);
5306+
struct mlx5e_channel_stats *channel_stats;
5307+
struct mlx5e_rq_stats *xskrq_stats;
5308+
struct mlx5e_rq_stats *rq_stats;
5309+
5310+
ASSERT_RTNL();
5311+
if (mlx5e_is_uplink_rep(priv))
5312+
return;
5313+
5314+
channel_stats = priv->channel_stats[i];
5315+
xskrq_stats = &channel_stats->xskrq;
5316+
rq_stats = &channel_stats->rq;
5317+
5318+
stats->packets = rq_stats->packets + xskrq_stats->packets;
5319+
stats->bytes = rq_stats->bytes + xskrq_stats->bytes;
5320+
stats->alloc_fail = rq_stats->buff_alloc_err +
5321+
xskrq_stats->buff_alloc_err;
5322+
}
5323+
5324+
static void mlx5e_get_queue_stats_tx(struct net_device *dev, int i,
5325+
struct netdev_queue_stats_tx *stats)
5326+
{
5327+
struct mlx5e_priv *priv = netdev_priv(dev);
5328+
struct mlx5e_sq_stats *sq_stats;
5329+
5330+
ASSERT_RTNL();
5331+
/* no special case needed for ptp htb etc since txq2sq_stats is kept up
5332+
* to date for active sq_stats, otherwise get_base_stats takes care of
5333+
* inactive sqs.
5334+
*/
5335+
sq_stats = priv->txq2sq_stats[i];
5336+
stats->packets = sq_stats->packets;
5337+
stats->bytes = sq_stats->bytes;
5338+
}
5339+
5340+
static void mlx5e_get_base_stats(struct net_device *dev,
5341+
struct netdev_queue_stats_rx *rx,
5342+
struct netdev_queue_stats_tx *tx)
5343+
{
5344+
struct mlx5e_priv *priv = netdev_priv(dev);
5345+
struct mlx5e_ptp *ptp_channel;
5346+
int i, tc;
5347+
5348+
ASSERT_RTNL();
5349+
if (!mlx5e_is_uplink_rep(priv)) {
5350+
rx->packets = 0;
5351+
rx->bytes = 0;
5352+
rx->alloc_fail = 0;
5353+
5354+
for (i = priv->channels.params.num_channels; i < priv->stats_nch; i++) {
5355+
struct netdev_queue_stats_rx rx_i = {0};
5356+
5357+
mlx5e_get_queue_stats_rx(dev, i, &rx_i);
5358+
5359+
rx->packets += rx_i.packets;
5360+
rx->bytes += rx_i.bytes;
5361+
rx->alloc_fail += rx_i.alloc_fail;
5362+
}
5363+
5364+
/* always report PTP RX stats from base as there is no
5365+
* corresponding channel to report them under in
5366+
* mlx5e_get_queue_stats_rx.
5367+
*/
5368+
if (priv->rx_ptp_opened) {
5369+
struct mlx5e_rq_stats *rq_stats = &priv->ptp_stats.rq;
5370+
5371+
rx->packets += rq_stats->packets;
5372+
rx->bytes += rq_stats->bytes;
5373+
}
5374+
}
5375+
5376+
tx->packets = 0;
5377+
tx->bytes = 0;
5378+
5379+
for (i = 0; i < priv->stats_nch; i++) {
5380+
struct mlx5e_channel_stats *channel_stats = priv->channel_stats[i];
5381+
5382+
/* handle two cases:
5383+
*
5384+
* 1. channels which are active. In this case,
5385+
* report only deactivated TCs on these channels.
5386+
*
5387+
* 2. channels which were deactivated
5388+
* (i > priv->channels.params.num_channels)
5389+
* must have all of their TCs [0 .. priv->max_opened_tc)
5390+
* examined because deactivated channels will not be in the
5391+
* range of [0..real_num_tx_queues) and will not have their
5392+
* stats reported by mlx5e_get_queue_stats_tx.
5393+
*/
5394+
if (i < priv->channels.params.num_channels)
5395+
tc = mlx5e_get_dcb_num_tc(&priv->channels.params);
5396+
else
5397+
tc = 0;
5398+
5399+
for (; tc < priv->max_opened_tc; tc++) {
5400+
struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[tc];
5401+
5402+
tx->packets += sq_stats->packets;
5403+
tx->bytes += sq_stats->bytes;
5404+
}
5405+
}
5406+
5407+
/* if PTP TX was opened at some point and has since either:
5408+
* - been shutdown and set to NULL, or
5409+
* - simply disabled (bit unset)
5410+
*
5411+
* report stats directly from the ptp_stats structures as these queues
5412+
* are now unavailable and there is no txq index to retrieve these
5413+
* stats via calls to mlx5e_get_queue_stats_tx.
5414+
*/
5415+
ptp_channel = priv->channels.ptp;
5416+
if (priv->tx_ptp_opened && (!ptp_channel || !test_bit(MLX5E_PTP_STATE_TX, ptp_channel->state))) {
5417+
for (tc = 0; tc < priv->max_opened_tc; tc++) {
5418+
struct mlx5e_sq_stats *sq_stats = &priv->ptp_stats.sq[tc];
5419+
5420+
tx->packets += sq_stats->packets;
5421+
tx->bytes += sq_stats->bytes;
5422+
}
5423+
}
5424+
}
5425+
5426+
static const struct netdev_stat_ops mlx5e_stat_ops = {
5427+
.get_queue_stats_rx = mlx5e_get_queue_stats_rx,
5428+
.get_queue_stats_tx = mlx5e_get_queue_stats_tx,
5429+
.get_base_stats = mlx5e_get_base_stats,
5430+
};
5431+
52995432
static void mlx5e_build_nic_netdev(struct net_device *netdev)
53005433
{
53015434
struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -5313,6 +5446,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
53135446

53145447
netdev->watchdog_timeo = 15 * HZ;
53155448

5449+
netdev->stat_ops = &mlx5e_stat_ops;
53165450
netdev->ethtool_ops = &mlx5e_ethtool_ops;
53175451

53185452
netdev->vlan_features |= NETIF_F_SG;
@@ -5848,9 +5982,13 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
58485982
if (!priv->txq2sq)
58495983
goto err_destroy_workqueue;
58505984

5985+
priv->txq2sq_stats = kcalloc_node(num_txqs, sizeof(*priv->txq2sq_stats), GFP_KERNEL, node);
5986+
if (!priv->txq2sq_stats)
5987+
goto err_free_txq2sq;
5988+
58515989
priv->tx_rates = kcalloc_node(num_txqs, sizeof(*priv->tx_rates), GFP_KERNEL, node);
58525990
if (!priv->tx_rates)
5853-
goto err_free_txq2sq;
5991+
goto err_free_txq2sq_stats;
58545992

58555993
priv->channel_stats =
58565994
kcalloc_node(nch, sizeof(*priv->channel_stats), GFP_KERNEL, node);
@@ -5861,6 +5999,8 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
58615999

58626000
err_free_tx_rates:
58636001
kfree(priv->tx_rates);
6002+
err_free_txq2sq_stats:
6003+
kfree(priv->txq2sq_stats);
58646004
err_free_txq2sq:
58656005
kfree(priv->txq2sq);
58666006
err_destroy_workqueue:
@@ -5884,6 +6024,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
58846024
kvfree(priv->channel_stats[i]);
58856025
kfree(priv->channel_stats);
58866026
kfree(priv->tx_rates);
6027+
kfree(priv->txq2sq_stats);
58876028
kfree(priv->txq2sq);
58886029
destroy_workqueue(priv->wq);
58896030
mlx5e_selq_cleanup(&priv->selq);

0 commit comments

Comments
 (0)