Commit 508f2e3d authored by Mark Starovoytov's avatar Mark Starovoytov Committed by David S. Miller

net: atlantic: split rx and tx per-queue stats

This patch splits rx and tx per-queue stats.
This change simplifies the follow-up introduction of PTP stats and
u64_stats_update_* usage.
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 b772112c
...@@ -89,15 +89,18 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { ...@@ -89,15 +89,18 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
"InDroppedDma", "InDroppedDma",
}; };
static const char * const aq_ethtool_queue_stat_names[] = { static const char * const aq_ethtool_queue_rx_stat_names[] = {
"%sQueue[%d] InPackets", "%sQueue[%d] InPackets",
"%sQueue[%d] OutPackets",
"%sQueue[%d] Restarts",
"%sQueue[%d] InJumboPackets", "%sQueue[%d] InJumboPackets",
"%sQueue[%d] InLroPackets", "%sQueue[%d] InLroPackets",
"%sQueue[%d] InErrors", "%sQueue[%d] InErrors",
}; };
static const char * const aq_ethtool_queue_tx_stat_names[] = {
"%sQueue[%d] OutPackets",
"%sQueue[%d] Restarts",
};
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = { static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
"MACSec InCtlPackets", "MACSec InCtlPackets",
...@@ -164,11 +167,12 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { ...@@ -164,11 +167,12 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
static u32 aq_ethtool_n_stats(struct net_device *ndev) static u32 aq_ethtool_n_stats(struct net_device *ndev)
{ {
const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
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 * (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
cfg->tcs;
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
if (nic->macsec_cfg) { if (nic->macsec_cfg) {
...@@ -237,7 +241,8 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -237,7 +241,8 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
switch (stringset) { switch (stringset) {
case ETH_SS_STATS: { case ETH_SS_STATS: {
const int stat_cnt = ARRAY_SIZE(aq_ethtool_queue_stat_names); const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
char tc_string[8]; char tc_string[8];
int tc; int tc;
...@@ -251,9 +256,16 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -251,9 +256,16 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
snprintf(tc_string, 8, "TC%d ", tc); snprintf(tc_string, 8, "TC%d ", tc);
for (i = 0; i < cfg->vecs; i++) { for (i = 0; i < cfg->vecs; i++) {
for (si = 0; si < stat_cnt; si++) { for (si = 0; si < rx_stat_cnt; si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_rx_stat_names[si],
tc_string,
AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
p += ETH_GSTRING_LEN;
}
for (si = 0; si < tx_stat_cnt; si++) {
snprintf(p, ETH_GSTRING_LEN, snprintf(p, ETH_GSTRING_LEN,
aq_ethtool_queue_stat_names[si], aq_ethtool_queue_tx_stat_names[si],
tc_string, tc_string,
AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
......
...@@ -844,7 +844,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) ...@@ -844,7 +844,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
if (!aq_ptp) if (!aq_ptp)
return 0; return 0;
err = aq_ring_init(&aq_ptp->ptp_tx); err = aq_ring_init(&aq_ptp->ptp_tx, ATL_RING_TX);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw, err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw,
...@@ -853,7 +853,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) ...@@ -853,7 +853,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
err = aq_ring_init(&aq_ptp->ptp_rx); err = aq_ring_init(&aq_ptp->ptp_rx, ATL_RING_RX);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
...@@ -871,7 +871,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) ...@@ -871,7 +871,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
if (err < 0) if (err < 0)
goto err_rx_free; goto err_rx_free;
err = aq_ring_init(&aq_ptp->hwts_rx); err = aq_ring_init(&aq_ptp->hwts_rx, ATL_RING_RX);
if (err < 0) if (err < 0)
goto err_rx_free; goto err_rx_free;
err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
......
...@@ -206,11 +206,12 @@ aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic, ...@@ -206,11 +206,12 @@ aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic,
return self; return self;
} }
int aq_ring_init(struct aq_ring_s *self) int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type)
{ {
self->hw_head = 0; self->hw_head = 0;
self->sw_head = 0; self->sw_head = 0;
self->sw_tail = 0; self->sw_tail = 0;
self->ring_type = ring_type;
return 0; return 0;
} }
...@@ -538,7 +539,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self) ...@@ -538,7 +539,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self)
void aq_ring_rx_deinit(struct aq_ring_s *self) void aq_ring_rx_deinit(struct aq_ring_s *self)
{ {
if (!self) if (!self)
goto err_exit; return;
for (; self->sw_head != self->sw_tail; for (; self->sw_head != self->sw_tail;
self->sw_head = aq_ring_next_dx(self, self->sw_head)) { self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
...@@ -546,14 +547,12 @@ void aq_ring_rx_deinit(struct aq_ring_s *self) ...@@ -546,14 +547,12 @@ void aq_ring_rx_deinit(struct aq_ring_s *self)
aq_free_rxpage(&buff->rxdata, aq_nic_get_dev(self->aq_nic)); aq_free_rxpage(&buff->rxdata, aq_nic_get_dev(self->aq_nic));
} }
err_exit:;
} }
void aq_ring_free(struct aq_ring_s *self) void aq_ring_free(struct aq_ring_s *self)
{ {
if (!self) if (!self)
goto err_exit; return;
kfree(self->buff_ring); kfree(self->buff_ring);
...@@ -561,6 +560,23 @@ void aq_ring_free(struct aq_ring_s *self) ...@@ -561,6 +560,23 @@ void aq_ring_free(struct aq_ring_s *self)
dma_free_coherent(aq_nic_get_dev(self->aq_nic), dma_free_coherent(aq_nic_get_dev(self->aq_nic),
self->size * self->dx_size, self->dx_ring, self->size * self->dx_size, self->dx_ring,
self->dx_ring_pa); self->dx_ring_pa);
}
unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
{
unsigned int count = 0U;
if (self->ring_type == ATL_RING_RX) {
/* This data should mimic aq_ethtool_queue_rx_stat_names structure */
data[count] = self->stats.rx.packets;
data[++count] = self->stats.rx.jumbo_packets;
data[++count] = self->stats.rx.lro_packets;
data[++count] = self->stats.rx.errors;
} else {
/* This data should mimic aq_ethtool_queue_tx_stat_names structure */
data[count] = self->stats.tx.packets;
data[++count] = self->stats.tx.queue_restarts;
}
err_exit:; return ++count;
} }
...@@ -110,6 +110,11 @@ union aq_ring_stats_s { ...@@ -110,6 +110,11 @@ union aq_ring_stats_s {
struct aq_ring_stats_tx_s tx; struct aq_ring_stats_tx_s tx;
}; };
enum atl_ring_type {
ATL_RING_TX,
ATL_RING_RX,
};
struct aq_ring_s { struct aq_ring_s {
struct aq_ring_buff_s *buff_ring; struct aq_ring_buff_s *buff_ring;
u8 *dx_ring; /* descriptors ring, dma shared mem */ u8 *dx_ring; /* descriptors ring, dma shared mem */
...@@ -124,6 +129,7 @@ struct aq_ring_s { ...@@ -124,6 +129,7 @@ struct aq_ring_s {
unsigned int page_order; unsigned int page_order;
union aq_ring_stats_s stats; union aq_ring_stats_s stats;
dma_addr_t dx_ring_pa; dma_addr_t dx_ring_pa;
enum atl_ring_type ring_type;
}; };
struct aq_ring_param_s { struct aq_ring_param_s {
...@@ -163,7 +169,7 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, ...@@ -163,7 +169,7 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
struct aq_nic_s *aq_nic, struct aq_nic_s *aq_nic,
unsigned int idx, unsigned int idx,
struct aq_nic_cfg_s *aq_nic_cfg); struct aq_nic_cfg_s *aq_nic_cfg);
int aq_ring_init(struct aq_ring_s *self); int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type);
void aq_ring_rx_deinit(struct aq_ring_s *self); void aq_ring_rx_deinit(struct aq_ring_s *self);
void aq_ring_free(struct aq_ring_s *self); void aq_ring_free(struct aq_ring_s *self);
void aq_ring_update_queue_state(struct aq_ring_s *ring); void aq_ring_update_queue_state(struct aq_ring_s *ring);
...@@ -181,4 +187,6 @@ struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self, ...@@ -181,4 +187,6 @@ struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
unsigned int size, unsigned int dx_size); unsigned int size, unsigned int dx_size);
void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic);
unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data);
#endif /* AQ_RING_H */ #endif /* AQ_RING_H */
...@@ -181,7 +181,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, ...@@ -181,7 +181,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops,
for (i = 0U, ring = self->ring[0]; for (i = 0U, ring = self->ring[0];
self->tx_rings > i; ++i, ring = self->ring[i]) { self->tx_rings > i; ++i, ring = self->ring[i]) {
err = aq_ring_init(&ring[AQ_VEC_TX_ID]); err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -191,7 +191,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, ...@@ -191,7 +191,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops,
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
err = aq_ring_init(&ring[AQ_VEC_RX_ID]); err = aq_ring_init(&ring[AQ_VEC_RX_ID], ATL_RING_RX);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -350,55 +350,23 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) ...@@ -350,55 +350,23 @@ 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;
} }
static void aq_vec_get_stats(struct aq_vec_s *self, bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc)
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]; return tc < self->rx_rings && tc < self->tx_rings;
if (tc < self->rx_rings) {
struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx;
stats_rx->packets = rx->packets;
stats_rx->bytes = rx->bytes;
stats_rx->errors = rx->errors;
stats_rx->jumbo_packets = rx->jumbo_packets;
stats_rx->lro_packets = rx->lro_packets;
stats_rx->pg_losts = rx->pg_losts;
stats_rx->pg_flips = rx->pg_flips;
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->bytes = tx->bytes;
stats_tx->errors = tx->errors;
stats_tx->queue_restarts = tx->queue_restarts;
}
} }
unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data) unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data)
{ {
struct aq_ring_stats_rx_s stats_rx; unsigned int count;
struct aq_ring_stats_tx_s stats_tx;
unsigned int count = 0U;
memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); WARN_ONCE(!aq_vec_is_valid_tc(self, tc),
memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); "Invalid tc %u (#rx=%u, #tx=%u)\n",
tc, self->rx_rings, self->tx_rings);
if (!aq_vec_is_valid_tc(self, tc))
return 0;
aq_vec_get_stats(self, tc, &stats_rx, &stats_tx); count = aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_RX_ID], data);
count += aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_TX_ID], data + count);
/* This data should mimic aq_ethtool_queue_stat_names structure return count;
*/
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;
return ++count;
} }
...@@ -36,6 +36,7 @@ void aq_vec_ring_free(struct aq_vec_s *self); ...@@ -36,6 +36,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);
bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc);
unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data); unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data);
#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