Commit efe28034 authored by Mingming Cao's avatar Mingming Cao Committed by Jakub Kicinski
Browse files

ibmvnic: Use ndo_get_stats64 to fix inaccurate SAR reporting



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: default avatarMingming Cao <mmc@linux.ibm.com>
Reviewed-by: default avatarBrian King <bjking1@linux.ibm.com>
Reviewed-by: default avatarDave Marquardt <davemarq@linux.ibm.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>

----
Changes since v3:
link to v3: https://www.spinics.net/lists/netdev/msg1107999.html
-- keep per queue counters as u64 (this patch) and drop off patch 1 in v3

Link: https://patch.msgid.link/20250716152115.61143-1-mmc@linux.ibm.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0dce6847
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -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;
		adapter->tx_stats_buffers[queue_num].batched_packets--;
		adapter->tx_stats_buffers[queue_num].bytes -=
						tx_buff->skb->len;
@@ -2647,9 +2645,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;
	adapter->tx_stats_buffers[queue_num].batched_packets += tx_bpackets;
@@ -3452,6 +3447,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 += adapter->rx_stats_buffers[i].packets;
		stats->rx_bytes   += adapter->rx_stats_buffers[i].bytes;
	}

	for (i = 0; i < adapter->req_tx_queues; i++) {
		stats->tx_packets += adapter->tx_stats_buffers[i].batched_packets;
		stats->tx_packets += adapter->tx_stats_buffers[i].direct_packets;
		stats->tx_bytes   += adapter->tx_stats_buffers[i].bytes;
		stats->tx_dropped += 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);
@@ -3567,8 +3581,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;
		adapter->rx_stats_buffers[scrq_num].packets++;
		adapter->rx_stats_buffers[scrq_num].bytes += length;
		frames_processed++;
@@ -3678,6 +3690,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,