Commit 4272ba8b authored by Mark Starovoytov's avatar Mark Starovoytov Committed by David S. Miller

net: atlantic: per-TC queue statistics

This patch adds support for per-TC queue statistics.

By default (single TC), the output is the same as it used to be, e.g.:
     Queue[0] InPackets: 2
     Queue[0] OutPackets: 8
     Queue[0] Restarts: 0
     Queue[0] InJumboPackets: 0
     Queue[0] InLroPackets: 0
     Queue[0] InErrors: 0

If several TCs are enabled, then each queue statistics line is prefixed
with TC number, e.g.:
     TC0 Queue[0] InPackets: 6
     TC0 Queue[0] OutPackets: 11
Queue numbering is end-to-end, so:
     TC1 Queue[4] InPackets: 0
     TC1 Queue[4] OutPackets: 22
Signed-off-by: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a83fe6b6
...@@ -88,13 +88,13 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { ...@@ -88,13 +88,13 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"InDroppedDma", "InDroppedDma",
}; };
static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { static const char * const aq_ethtool_queue_stat_names[] = {
"Queue[%d] InPackets", "%sQueue[%d] InPackets",
"Queue[%d] OutPackets", "%sQueue[%d] OutPackets",
"Queue[%d] Restarts", "%sQueue[%d] Restarts",
"Queue[%d] InJumboPackets", "%sQueue[%d] InJumboPackets",
"Queue[%d] InLroPackets", "%sQueue[%d] InLroPackets",
"Queue[%d] InErrors", "%sQueue[%d] InErrors",
}; };
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
...@@ -166,7 +166,8 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev) ...@@ -166,7 +166,8 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev)
struct aq_nic_s *nic = netdev_priv(ndev); struct aq_nic_s *nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic); struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs; ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs *
cfg->tcs;
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
if (nic->macsec_cfg) { if (nic->macsec_cfg) {
...@@ -223,7 +224,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, ...@@ -223,7 +224,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
static void aq_ethtool_get_strings(struct net_device *ndev, static void aq_ethtool_get_strings(struct net_device *ndev,
u32 stringset, u8 *data) u32 stringset, u8 *data)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg; struct aq_nic_cfg_s *cfg;
u8 *p = data; u8 *p = data;
int i, si; int i, si;
...@@ -231,24 +232,35 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -231,24 +232,35 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
int sa; int sa;
#endif #endif
cfg = aq_nic_get_cfg(aq_nic); cfg = aq_nic_get_cfg(nic);
switch (stringset) { switch (stringset) {
case ETH_SS_STATS: case ETH_SS_STATS: {
const int stat_cnt = ARRAY_SIZE(aq_ethtool_queue_stat_names);
char tc_string[8];
int tc;
memset(tc_string, 0, sizeof(tc_string));
memcpy(p, aq_ethtool_stat_names, memcpy(p, aq_ethtool_stat_names,
sizeof(aq_ethtool_stat_names)); sizeof(aq_ethtool_stat_names));
p = p + sizeof(aq_ethtool_stat_names); p = p + sizeof(aq_ethtool_stat_names);
for (i = 0; i < cfg->vecs; i++) {
for (si = 0; for (tc = 0; tc < cfg->tcs; tc++) {
si < ARRAY_SIZE(aq_ethtool_queue_stat_names); if (cfg->is_qos)
si++) { snprintf(tc_string, 8, "TC%d ", tc);
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si], i); for (i = 0; i < cfg->vecs; i++) {
p += ETH_GSTRING_LEN; for (si = 0; si < stat_cnt; si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si],
tc_string,
AQ_NIC_TCVEC2RING(nic, tc, i));
p += ETH_GSTRING_LEN;
}
} }
} }
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
if (!aq_nic->macsec_cfg) if (!nic->macsec_cfg)
break; break;
memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names)); memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
...@@ -256,7 +268,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -256,7 +268,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_txsc *aq_txsc; struct aq_macsec_txsc *aq_txsc;
if (!(test_bit(i, &aq_nic->macsec_cfg->txsc_idx_busy))) if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
continue; continue;
for (si = 0; for (si = 0;
...@@ -266,7 +278,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -266,7 +278,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
aq_macsec_txsc_stat_names[si], i); aq_macsec_txsc_stat_names[si], i);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
aq_txsc = &aq_nic->macsec_cfg->aq_txsc[i]; aq_txsc = &nic->macsec_cfg->aq_txsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) { for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy))) if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
continue; continue;
...@@ -283,10 +295,10 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -283,10 +295,10 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_rxsc *aq_rxsc; struct aq_macsec_rxsc *aq_rxsc;
if (!(test_bit(i, &aq_nic->macsec_cfg->rxsc_idx_busy))) if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
continue; continue;
aq_rxsc = &aq_nic->macsec_cfg->aq_rxsc[i]; aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) { for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy))) if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
continue; continue;
...@@ -302,6 +314,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -302,6 +314,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
} }
#endif #endif
break; break;
}
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
memcpy(p, aq_ethtool_priv_flag_names, memcpy(p, aq_ethtool_priv_flag_names,
sizeof(aq_ethtool_priv_flag_names)); sizeof(aq_ethtool_priv_flag_names));
......
...@@ -855,6 +855,7 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) ...@@ -855,6 +855,7 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
struct aq_stats_s *stats; struct aq_stats_s *stats;
unsigned int count = 0U; unsigned int count = 0U;
unsigned int i = 0U; unsigned int i = 0U;
unsigned int tc;
if (self->aq_fw_ops->update_stats) { if (self->aq_fw_ops->update_stats) {
mutex_lock(&self->fwreq_mutex); mutex_lock(&self->fwreq_mutex);
...@@ -893,10 +894,13 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) ...@@ -893,10 +894,13 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
data += i; data += i;
for (i = 0U, aq_vec = self->aq_vec[0]; for (tc = 0U; tc < self->aq_nic_cfg.tcs; tc++) {
aq_vec && self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { for (i = 0U, aq_vec = self->aq_vec[0];
data += count; aq_vec && self->aq_vecs > i;
aq_vec_get_sw_stats(aq_vec, data, &count); ++i, aq_vec = self->aq_vec[i]) {
data += count;
aq_vec_get_sw_stats(aq_vec, tc, data, &count);
}
} }
data += count; data += count;
......
...@@ -348,16 +348,14 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) ...@@ -348,16 +348,14 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self)
return &self->aq_ring_param.affinity_mask; return &self->aq_ring_param.affinity_mask;
} }
void aq_vec_add_stats(struct aq_vec_s *self, static void aq_vec_add_stats(struct aq_vec_s *self,
struct aq_ring_stats_rx_s *stats_rx, const unsigned int tc,
struct aq_ring_stats_tx_s *stats_tx) struct aq_ring_stats_rx_s *stats_rx,
struct aq_ring_stats_tx_s *stats_tx)
{ {
struct aq_ring_s *ring = NULL; struct aq_ring_s *ring = self->ring[tc];
unsigned int r = 0U;
for (r = 0U, ring = self->ring[0]; if (tc < self->rx_rings) {
self->tx_rings > r; ++r, ring = self->ring[r]) {
struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx;
struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx; struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx;
stats_rx->packets += rx->packets; stats_rx->packets += rx->packets;
...@@ -368,6 +366,10 @@ void aq_vec_add_stats(struct aq_vec_s *self, ...@@ -368,6 +366,10 @@ void aq_vec_add_stats(struct aq_vec_s *self,
stats_rx->pg_losts += rx->pg_losts; stats_rx->pg_losts += rx->pg_losts;
stats_rx->pg_flips += rx->pg_flips; stats_rx->pg_flips += rx->pg_flips;
stats_rx->pg_reuses += rx->pg_reuses; stats_rx->pg_reuses += rx->pg_reuses;
}
if (tc < self->tx_rings) {
struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx;
stats_tx->packets += tx->packets; stats_tx->packets += tx->packets;
stats_tx->bytes += tx->bytes; stats_tx->bytes += tx->bytes;
...@@ -376,7 +378,8 @@ void aq_vec_add_stats(struct aq_vec_s *self, ...@@ -376,7 +378,8 @@ void aq_vec_add_stats(struct aq_vec_s *self,
} }
} }
int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data,
unsigned int *p_count)
{ {
struct aq_ring_stats_rx_s stats_rx; struct aq_ring_stats_rx_s stats_rx;
struct aq_ring_stats_tx_s stats_tx; struct aq_ring_stats_tx_s stats_tx;
...@@ -384,7 +387,8 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) ...@@ -384,7 +387,8 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count)
memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
aq_vec_add_stats(self, &stats_rx, &stats_tx);
aq_vec_add_stats(self, tc, &stats_rx, &stats_tx);
/* This data should mimic aq_ethtool_queue_stat_names structure /* This data should mimic aq_ethtool_queue_stat_names structure
*/ */
......
...@@ -35,10 +35,7 @@ void aq_vec_ring_free(struct aq_vec_s *self); ...@@ -35,10 +35,7 @@ void aq_vec_ring_free(struct aq_vec_s *self);
int aq_vec_start(struct aq_vec_s *self); int aq_vec_start(struct aq_vec_s *self);
void aq_vec_stop(struct aq_vec_s *self); void aq_vec_stop(struct aq_vec_s *self);
cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self); cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self);
int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data,
unsigned int *p_count); unsigned int *p_count);
void aq_vec_add_stats(struct aq_vec_s *self,
struct aq_ring_stats_rx_s *stats_rx,
struct aq_ring_stats_tx_s *stats_tx);
#endif /* AQ_VEC_H */ #endif /* AQ_VEC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment