Add basic driver framework for the Alibaba Elastic Ethernet Adapter(EEA). This commit introduces ndo_get_stats64 support. Reviewed-by: Dust Li Reviewed-by: Philo Lu Signed-off-by: Wen Gu Signed-off-by: Xuan Zhuo --- drivers/net/ethernet/alibaba/eea/eea_net.c | 51 ++++++++++++++++++++++ drivers/net/ethernet/alibaba/eea/eea_net.h | 5 +++ 2 files changed, 56 insertions(+) diff --git a/drivers/net/ethernet/alibaba/eea/eea_net.c b/drivers/net/ethernet/alibaba/eea/eea_net.c index 89a1521d772f..d05c6b5acd14 100644 --- a/drivers/net/ethernet/alibaba/eea/eea_net.c +++ b/drivers/net/ethernet/alibaba/eea/eea_net.c @@ -27,8 +27,10 @@ static void enet_bind_new_q_and_cfg(struct eea_net *enet, enet->cfg = ctx->cfg; + spin_lock(&enet->stats_lock); enet->rx = ctx->rx; enet->tx = ctx->tx; + spin_unlock(&enet->stats_lock); for (i = 0; i < ctx->cfg.rx_ring_num; i++) { rx = ctx->rx[i]; @@ -54,11 +56,13 @@ static void eea_free_rxtx_q_mem(struct eea_net *enet) struct eea_net_tx *tx, *tx_array; int i; + spin_lock(&enet->stats_lock); rx_array = enet->rx; tx_array = enet->tx; enet->rx = NULL; enet->tx = NULL; + spin_unlock(&enet->stats_lock); for (i = 0; i < enet->cfg.rx_ring_num; i++) { rx = rx_array[i]; @@ -264,6 +268,50 @@ static int eea_netdev_open(struct net_device *netdev) return err; } +static void eea_stats(struct net_device *netdev, struct rtnl_link_stats64 *tot) +{ + struct eea_net *enet = netdev_priv(netdev); + u64 packets, bytes; + u32 start; + int i; + + spin_lock_bh(&enet->stats_lock); + + if (enet->rx) { + for (i = 0; i < enet->cfg.rx_ring_num; i++) { + struct eea_net_rx *rx = enet->rx[i]; + + do { + start = u64_stats_fetch_begin(&rx->stats.syncp); + packets = u64_stats_read(&rx->stats.packets); + bytes = u64_stats_read(&rx->stats.bytes); + } while (u64_stats_fetch_retry(&rx->stats.syncp, + start)); + + tot->rx_packets += packets; + tot->rx_bytes += bytes; + } + } + + if (enet->tx) { + for (i = 0; i < enet->cfg.tx_ring_num; i++) { + struct eea_net_tx *tx = &enet->tx[i]; + + do { + start = u64_stats_fetch_begin(&tx->stats.syncp); + packets = u64_stats_read(&tx->stats.packets); + bytes = u64_stats_read(&tx->stats.bytes); + } while (u64_stats_fetch_retry(&tx->stats.syncp, + start)); + + tot->tx_packets += packets; + tot->tx_bytes += bytes; + } + } + + spin_unlock_bh(&enet->stats_lock); +} + /* resources: ring, buffers, irq */ int eea_reset_hw_resources(struct eea_net *enet, struct eea_net_init_ctx *ctx) { @@ -455,6 +503,7 @@ static const struct net_device_ops eea_netdev = { .ndo_stop = eea_netdev_stop, .ndo_start_xmit = eea_tx_xmit, .ndo_validate_addr = eth_validate_addr, + .ndo_get_stats64 = eea_stats, .ndo_features_check = passthru_features_check, .ndo_tx_timeout = eea_tx_timeout, }; @@ -480,6 +529,8 @@ static struct eea_net *eea_netdev_alloc(struct eea_device *edev, u32 pairs) enet->edev = edev; edev->enet = enet; + spin_lock_init(&enet->stats_lock); + return enet; } diff --git a/drivers/net/ethernet/alibaba/eea/eea_net.h b/drivers/net/ethernet/alibaba/eea/eea_net.h index 78a621c2ce4c..f32d26e156ab 100644 --- a/drivers/net/ethernet/alibaba/eea/eea_net.h +++ b/drivers/net/ethernet/alibaba/eea/eea_net.h @@ -157,6 +157,11 @@ struct eea_net { u32 speed; u64 hw_ts_offset; + + /* Protect the tx and rx of struct eea_net, when eea_stats accesses the + * stats from rx and tx queues. + */ + spinlock_t stats_lock; }; int eea_tx_resize(struct eea_net *enet, struct eea_net_tx *tx, u32 ring_num); -- 2.32.0.3.g01195cf9f