VNIC testing on multi-core Power systems showed SAR stats drift and packet rate inconsistencies under load. Implements ndo_get_stats64 to provide safe aggregation of queue-level atomic64 counters into rtnl_link_stats64 for use by tools like 'ip -s', 'ifconfig', and 'sar'. Switch to ndo_get_stats64 to align SAR reporting with the standard kernel interface for retrieving netdev stats. This removes redundant per-adapter stat updates, reduces overhead, eliminates cacheline bouncing from hot path updates, and improves the accuracy of reported packet rates. Signed-off-by: Mingming Cao Reviewed by: Brian King Reviewed by: Dave Marquardt --- drivers/net/ethernet/ibm/ibmvnic.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 79fdba4293a4..6dd7809b1bc7 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2312,8 +2312,6 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, tx_pool->num_buffers - 1 : tx_pool->consumer_index - 1; tx_buff = &tx_pool->tx_buff[index]; - adapter->netdev->stats.tx_packets--; - adapter->netdev->stats.tx_bytes -= tx_buff->skb->len; atomic64_dec(&adapter->tx_stats_buffers[queue_num].batched_packets); if (atomic64_sub_return(tx_buff->skb->len, &adapter->tx_stats_buffers[queue_num].bytes) < 0) { @@ -2325,9 +2323,9 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, atomic64_read(&adapter->tx_stats_buffers[queue_num].bytes), tx_buff->skb->len); } + atomic64_inc(&adapter->tx_stats_buffers[queue_num].dropped_packets); dev_kfree_skb_any(tx_buff->skb); tx_buff->skb = NULL; - adapter->netdev->stats.tx_dropped++; } ind_bufp->index = 0; @@ -2655,9 +2653,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) } out: rcu_read_unlock(); - netdev->stats.tx_dropped += tx_dropped; - netdev->stats.tx_bytes += tx_bytes; - netdev->stats.tx_packets += tx_bpackets + tx_dpackets; adapter->tx_send_failed += tx_send_failed; adapter->tx_map_failed += tx_map_failed; atomic64_add(tx_bpackets, &adapter->tx_stats_buffers[queue_num].batched_packets); @@ -3460,6 +3455,25 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, return -ret; } +static void ibmvnic_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct ibmvnic_adapter *adapter = netdev_priv(netdev); + int i; + + for (i = 0; i < adapter->req_rx_queues; i++) { + stats->rx_packets += atomic64_read(&adapter->rx_stats_buffers[i].packets); + stats->rx_bytes += atomic64_read(&adapter->rx_stats_buffers[i].bytes); + } + + for (i = 0; i < adapter->req_tx_queues; i++) { + stats->tx_packets += atomic64_read(&adapter->tx_stats_buffers[i].batched_packets); + stats->tx_packets += atomic64_read(&adapter->tx_stats_buffers[i].direct_packets); + stats->tx_bytes += atomic64_read(&adapter->tx_stats_buffers[i].bytes); + stats->tx_dropped += atomic64_read(&adapter->tx_stats_buffers[i].dropped_packets); + } +} + static void ibmvnic_tx_timeout(struct net_device *dev, unsigned int txqueue) { struct ibmvnic_adapter *adapter = netdev_priv(dev); @@ -3575,8 +3589,6 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget) length = skb->len; napi_gro_receive(napi, skb); /* send it up */ - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += length; atomic64_inc(&adapter->rx_stats_buffers[scrq_num].packets); atomic64_add(length, &adapter->rx_stats_buffers[scrq_num].bytes); frames_processed++; @@ -3686,6 +3698,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = { .ndo_set_rx_mode = ibmvnic_set_multi, .ndo_set_mac_address = ibmvnic_set_mac, .ndo_validate_addr = eth_validate_addr, + .ndo_get_stats64 = ibmvnic_get_stats64, .ndo_tx_timeout = ibmvnic_tx_timeout, .ndo_change_mtu = ibmvnic_change_mtu, .ndo_features_check = ibmvnic_features_check, -- 2.39.3 (Apple Git-146)