From: Dmitry Bogdanov <dbogda...@marvell.com> This patch adds additional per-queue stats, these could be useful for debugging and diagnostics.
Signed-off-by: Dmitry Bogdanov <dbogda...@marvell.com> Signed-off-by: Mark Starovoytov <mstarovoi...@marvell.com> Signed-off-by: Igor Russkikh <irussk...@marvell.com> --- .../ethernet/aquantia/atlantic/aq_ethtool.c | 3 ++ .../net/ethernet/aquantia/atlantic/aq_nic.c | 42 ++++++++++++++++- .../net/ethernet/aquantia/atlantic/aq_nic.h | 6 +++ .../net/ethernet/aquantia/atlantic/aq_ring.c | 4 ++ .../net/ethernet/aquantia/atlantic/aq_ring.h | 10 ++-- .../net/ethernet/aquantia/atlantic/aq_vec.c | 46 +++++-------------- .../net/ethernet/aquantia/atlantic/aq_vec.h | 14 ++++-- 7 files changed, 81 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index a8f0fbbbd91a..420fa5b791f9 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -96,6 +96,9 @@ static const char * const aq_ethtool_queue_stat_names[] = { "%sQueue[%d] InJumboPackets", "%sQueue[%d] InLroPackets", "%sQueue[%d] InErrors", + "%sQueue[%d] AllocFails", + "%sQueue[%d] SkbAllocFails", + "%sQueue[%d] Polls", }; #if IS_ENABLED(CONFIG_MACSEC) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 43b8914c3ef5..45d99c1a9635 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -857,6 +857,20 @@ int aq_nic_get_regs_count(struct aq_nic_s *self) return self->aq_nic_cfg.aq_hw_caps->mac_regs_count; } +static int aq_nic_get_tc_stats(struct aq_vec_s *vec, const unsigned int tc, + u64 *data, unsigned int *p_count) +{ + struct aq_ring_stats_rx_s stats_rx; + struct aq_ring_stats_tx_s stats_tx; + + memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); + memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); + + aq_vec_add_stats(vec, tc, &stats_rx, &stats_tx); + + return aq_nic_fill_stats_data(&stats_rx, &stats_tx, data, p_count); +} + u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) { struct aq_vec_s *aq_vec = NULL; @@ -907,13 +921,13 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) aq_vec && self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { data += count; - aq_vec_get_sw_stats(aq_vec, tc, data, &count); + aq_nic_get_tc_stats(aq_vec, tc, data, &count); } } data += count; -err_exit:; +err_exit: return data; } @@ -932,6 +946,30 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self) ndev->stats.multicast = stats->mprc; } +int aq_nic_fill_stats_data(struct aq_ring_stats_rx_s *stats_rx, + struct aq_ring_stats_tx_s *stats_tx, + u64 *data, + unsigned int *p_count) +{ + unsigned int count = 0U; + /* This data should mimic aq_ethtool_queue_stat_names structure + */ + data[count] += stats_rx->packets; + data[++count] += stats_tx->packets; + data[++count] += stats_tx->queue_restarts; + data[++count] += stats_rx->jumbo_packets; + data[++count] += stats_rx->lro_packets; + data[++count] += stats_rx->errors; + data[++count] += stats_rx->alloc_fails; + data[++count] += stats_rx->skb_alloc_fails; + data[++count] += stats_rx->polls; + + if (p_count) + *p_count = ++count; + + return 0; +} + void aq_nic_get_link_ksettings(struct aq_nic_s *self, struct ethtool_link_ksettings *cmd) { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 317bfc646f0a..0c7233d8ecd6 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -15,6 +15,8 @@ #include "aq_hw.h" struct aq_ring_s; +struct aq_ring_stats_rx_s; +struct aq_ring_stats_tx_s; struct aq_hw_ops; struct aq_fw_s; struct aq_vec_s; @@ -175,6 +177,10 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb); int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p); int aq_nic_get_regs_count(struct aq_nic_s *self); u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data); +int aq_nic_fill_stats_data(struct aq_ring_stats_rx_s *stats_rx, + struct aq_ring_stats_tx_s *stats_tx, + u64 *data, + unsigned int *p_count); int aq_nic_stop(struct aq_nic_s *self); void aq_nic_deinit(struct aq_nic_s *self, bool link_down); void aq_nic_set_power(struct aq_nic_s *self); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 8dd59e9fc3aa..20b606aa7974 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -88,6 +88,8 @@ static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf, if (!rxbuf->rxdata.page) { ret = aq_get_rxpage(&rxbuf->rxdata, order, aq_nic_get_dev(self->aq_nic)); + if (ret) + self->stats.rx.alloc_fails++; return ret; } @@ -392,6 +394,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, skb = build_skb(aq_buf_vaddr(&buff->rxdata), AQ_CFG_RX_FRAME_MAX); if (unlikely(!skb)) { + self->stats.rx.skb_alloc_fails++; err = -ENOMEM; goto err_exit; } @@ -405,6 +408,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, } else { skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); if (unlikely(!skb)) { + self->stats.rx.skb_alloc_fails++; err = -ENOMEM; goto err_exit; } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h index 2c96f20f6289..0e40ccbaf19a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* - * aQuantia Corporation Network Driver - * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved +/* Atlantic Network Driver + * + * Copyright (C) 2014-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ @@ -93,6 +94,9 @@ struct aq_ring_stats_rx_s { u64 bytes; u64 lro_packets; u64 jumbo_packets; + u64 alloc_fails; + u64 skb_alloc_fails; + u64 polls; u64 pg_losts; u64 pg_flips; u64 pg_reuses; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c index d1d43c8ce400..eafcb98c274f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +/* Atlantic Network Driver + * + * Copyright (C) 2014-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ /* File aq_vec.c: Definition of common structure for vector of Rx and Tx rings. @@ -44,6 +45,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) } else { for (i = 0U, ring = self->ring[0]; self->tx_rings > i; ++i, ring = self->ring[i]) { + ring[AQ_VEC_RX_ID].stats.rx.polls++; if (self->aq_hw_ops->hw_ring_tx_head_update) { err = self->aq_hw_ops->hw_ring_tx_head_update( self->aq_hw, @@ -349,10 +351,10 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) return &self->aq_ring_param.affinity_mask; } -static void aq_vec_add_stats(struct aq_vec_s *self, - const unsigned int tc, - struct aq_ring_stats_rx_s *stats_rx, - struct aq_ring_stats_tx_s *stats_tx) +void aq_vec_add_stats(struct aq_vec_s *self, + const unsigned int tc, + struct aq_ring_stats_rx_s *stats_rx, + struct aq_ring_stats_tx_s *stats_tx) { struct aq_ring_s *ring = self->ring[tc]; @@ -364,6 +366,9 @@ static void aq_vec_add_stats(struct aq_vec_s *self, stats_rx->errors += rx->errors; stats_rx->jumbo_packets += rx->jumbo_packets; stats_rx->lro_packets += rx->lro_packets; + stats_rx->alloc_fails += rx->alloc_fails; + stats_rx->skb_alloc_fails += rx->skb_alloc_fails; + stats_rx->polls += rx->polls; stats_rx->pg_losts += rx->pg_losts; stats_rx->pg_flips += rx->pg_flips; stats_rx->pg_reuses += rx->pg_reuses; @@ -378,30 +383,3 @@ static void aq_vec_add_stats(struct aq_vec_s *self, stats_tx->queue_restarts += tx->queue_restarts; } } - -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_tx_s stats_tx; - unsigned int count = 0U; - - memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); - memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); - - aq_vec_add_stats(self, tc, &stats_rx, &stats_tx); - - /* This data should mimic aq_ethtool_queue_stat_names structure - */ - data[count] += stats_rx.packets; - data[++count] += stats_tx.packets; - data[++count] += stats_tx.queue_restarts; - data[++count] += stats_rx.jumbo_packets; - data[++count] += stats_rx.lro_packets; - data[++count] += stats_rx.errors; - - if (p_count) - *p_count = ++count; - - return 0; -} diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h index 541af85e6510..876781a1e2b3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* - * aQuantia Corporation Network Driver - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +/* Atlantic Network Driver + * + * Copyright (C) 2014-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ /* File aq_vec.h: Definition of common structures for vector of Rx and Tx rings. @@ -35,7 +36,10 @@ void aq_vec_ring_free(struct aq_vec_s *self); int aq_vec_start(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); -int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, - unsigned int *p_count); + +void aq_vec_add_stats(struct aq_vec_s *self, + const unsigned int tc, + struct aq_ring_stats_rx_s *stats_rx, + struct aq_ring_stats_tx_s *stats_tx); #endif /* AQ_VEC_H */ -- 2.25.1