diff options
Diffstat (limited to 'drivers/net/ethernet/aquantia/atlantic/aq_vec.c')
| -rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 134 |
1 files changed, 53 insertions, 81 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c index d1d43c8ce400..9769ab4f9bef 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. @@ -9,11 +10,6 @@ */ #include "aq_vec.h" -#include "aq_nic.h" -#include "aq_ring.h" -#include "aq_hw.h" - -#include <linux/netdevice.h> struct aq_vec_s { const struct aq_hw_ops *aq_hw_ops; @@ -42,8 +38,11 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) if (!self) { err = -EINVAL; } else { - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; + u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp); + ring[AQ_VEC_RX_ID].stats.rx.polls++; + u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp); if (self->aq_hw_ops->hw_ring_tx_head_update) { err = self->aq_hw_ops->hw_ring_tx_head_update( self->aq_hw, @@ -120,8 +119,7 @@ struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, self->tx_rings = 0; self->rx_rings = 0; - netif_napi_add(aq_nic_get_ndev(aq_nic), &self->napi, - aq_vec_poll, AQ_CFG_NAPI_WEIGHT); + netif_napi_add(aq_nic_get_ndev(aq_nic), &self->napi, aq_vec_poll); err_exit: return self; @@ -138,24 +136,35 @@ int aq_vec_ring_alloc(struct aq_vec_s *self, struct aq_nic_s *aq_nic, const unsigned int idx_ring = AQ_NIC_CFG_TCVEC2RING(aq_nic_cfg, i, idx); - ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic, - idx_ring, aq_nic_cfg); - if (!ring) { - err = -ENOMEM; + ring = &self->ring[i][AQ_VEC_TX_ID]; + err = aq_ring_tx_alloc(ring, aq_nic, idx_ring, aq_nic_cfg); + if (err) goto err_exit; - } ++self->tx_rings; aq_nic_set_tx_ring(aq_nic, idx_ring, ring); - ring = aq_ring_rx_alloc(&self->ring[i][AQ_VEC_RX_ID], aq_nic, - idx_ring, aq_nic_cfg); - if (!ring) { + ring = &self->ring[i][AQ_VEC_RX_ID]; + if (xdp_rxq_info_reg(&ring->xdp_rxq, + aq_nic->ndev, idx, + self->napi.napi_id) < 0) { + err = -ENOMEM; + goto err_exit; + } + if (xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, + MEM_TYPE_PAGE_SHARED, NULL) < 0) { + xdp_rxq_info_unreg(&ring->xdp_rxq); err = -ENOMEM; goto err_exit; } + err = aq_ring_rx_alloc(ring, aq_nic, idx_ring, aq_nic_cfg); + if (err) { + xdp_rxq_info_unreg(&ring->xdp_rxq); + goto err_exit; + } + ++self->rx_rings; } @@ -178,9 +187,9 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, self->aq_hw_ops = aq_hw_ops; self->aq_hw = aq_hw; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { - err = aq_ring_init(&ring[AQ_VEC_TX_ID]); + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; + err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX); if (err < 0) goto err_exit; @@ -190,7 +199,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, if (err < 0) 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) goto err_exit; @@ -220,8 +229,8 @@ int aq_vec_start(struct aq_vec_s *self) unsigned int i = 0U; int err = 0; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; err = self->aq_hw_ops->hw_ring_tx_start(self->aq_hw, &ring[AQ_VEC_TX_ID]); if (err < 0) @@ -244,8 +253,8 @@ void aq_vec_stop(struct aq_vec_s *self) struct aq_ring_s *ring = NULL; unsigned int i = 0U; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; self->aq_hw_ops->hw_ring_tx_stop(self->aq_hw, &ring[AQ_VEC_TX_ID]); @@ -264,8 +273,8 @@ void aq_vec_deinit(struct aq_vec_s *self) if (!self) goto err_exit; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]); } @@ -293,11 +302,13 @@ void aq_vec_ring_free(struct aq_vec_s *self) if (!self) goto err_exit; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; aq_ring_free(&ring[AQ_VEC_TX_ID]); - if (i < self->rx_rings) + if (i < self->rx_rings) { + xdp_rxq_info_unreg(&ring[AQ_VEC_RX_ID].xdp_rxq); aq_ring_free(&ring[AQ_VEC_RX_ID]); + } } self->tx_rings = 0; @@ -349,59 +360,20 @@ 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) +bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc) { - struct aq_ring_s *ring = self->ring[tc]; - - 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; - } + return tc < self->rx_rings && tc < self->tx_rings; } -int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, - unsigned int *p_count) +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; - 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); + unsigned int count; - /* 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 (!aq_vec_is_valid_tc(self, tc)) + return 0; - if (p_count) - *p_count = ++count; + 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); - return 0; + return count; } |
