Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4197aa7b authored by Eric Dumazet's avatar Eric Dumazet Committed by Jeff Kirsher
Browse files

ixgbevf: provide 64 bit statistics



Compute statistics per ring using 64 bits, and provide
network device stats in 64 bits.

It should make this driver multiqueue operations faster (no more cache
line ping pongs on netdev->stats structure)

Use u64_stats_sync infrastructure so that its safe on 32bit arches as
well.

Based on a prior patch from Stephen Hemminger

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: default avatarGreg Rose <gregory.v.rose@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 98b9e48f
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/io.h>
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include <linux/if_vlan.h>
#include <linux/u64_stats_sync.h>


#include "vf.h"
#include "vf.h"


@@ -71,12 +72,13 @@ struct ixgbevf_ring {
		struct ixgbevf_rx_buffer *rx_buffer_info;
		struct ixgbevf_rx_buffer *rx_buffer_info;
	};
	};


	u64			total_bytes;
	u64			total_packets;
	struct u64_stats_sync	syncp;

	u16 head;
	u16 head;
	u16 tail;
	u16 tail;


	unsigned int total_bytes;
	unsigned int total_packets;

	u16 reg_idx; /* holds the special value that gets the hardware register
	u16 reg_idx; /* holds the special value that gets the hardware register
		      * offset associated with this ring, which is different
		      * offset associated with this ring, which is different
		      * for DCB and RSS modes */
		      * for DCB and RSS modes */
+43 −9
Original line number Original line Diff line number Diff line
@@ -270,11 +270,10 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
		IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx);
		IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx);
	}
	}


	u64_stats_update_begin(&tx_ring->syncp);
	tx_ring->total_bytes += total_bytes;
	tx_ring->total_bytes += total_bytes;
	tx_ring->total_packets += total_packets;
	tx_ring->total_packets += total_packets;

	u64_stats_update_end(&tx_ring->syncp);
	netdev->stats.tx_bytes += total_bytes;
	netdev->stats.tx_packets += total_packets;


	return count < tx_ring->work_limit;
	return count < tx_ring->work_limit;
}
}
@@ -597,10 +596,10 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
	if (cleaned_count)
	if (cleaned_count)
		ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
		ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count);


	u64_stats_update_begin(&rx_ring->syncp);
	rx_ring->total_packets += total_rx_packets;
	rx_ring->total_packets += total_rx_packets;
	rx_ring->total_bytes += total_rx_bytes;
	rx_ring->total_bytes += total_rx_bytes;
	adapter->netdev->stats.rx_bytes += total_rx_bytes;
	u64_stats_update_end(&rx_ring->syncp);
	adapter->netdev->stats.rx_packets += total_rx_packets;


	return cleaned;
	return cleaned;
}
}
@@ -2260,10 +2259,6 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
				adapter->stats.vfgotc);
				adapter->stats.vfgotc);
	UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
	UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
				adapter->stats.vfmprc);
				adapter->stats.vfmprc);

	/* Fill out the OS statistics structure */
	adapter->netdev->stats.multicast = adapter->stats.vfmprc -
		adapter->stats.base_vfmprc;
}
}


/**
/**
@@ -3220,11 +3215,50 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
	pci_disable_device(pdev);
	pci_disable_device(pdev);
}
}


static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev,
						struct rtnl_link_stats64 *stats)
{
	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
	unsigned int start;
	u64 bytes, packets;
	const struct ixgbevf_ring *ring;
	int i;

	ixgbevf_update_stats(adapter);

	stats->multicast = adapter->stats.vfmprc - adapter->stats.base_vfmprc;

	for (i = 0; i < adapter->num_rx_queues; i++) {
		ring = &adapter->rx_ring[i];
		do {
			start = u64_stats_fetch_begin_bh(&ring->syncp);
			bytes = ring->total_bytes;
			packets = ring->total_packets;
		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
		stats->rx_bytes += bytes;
		stats->rx_packets += packets;
	}

	for (i = 0; i < adapter->num_tx_queues; i++) {
		ring = &adapter->tx_ring[i];
		do {
			start = u64_stats_fetch_begin_bh(&ring->syncp);
			bytes = ring->total_bytes;
			packets = ring->total_packets;
		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
		stats->tx_bytes += bytes;
		stats->tx_packets += packets;
	}

	return stats;
}

static const struct net_device_ops ixgbe_netdev_ops = {
static const struct net_device_ops ixgbe_netdev_ops = {
	.ndo_open		= ixgbevf_open,
	.ndo_open		= ixgbevf_open,
	.ndo_stop		= ixgbevf_close,
	.ndo_stop		= ixgbevf_close,
	.ndo_start_xmit		= ixgbevf_xmit_frame,
	.ndo_start_xmit		= ixgbevf_xmit_frame,
	.ndo_set_rx_mode	= ixgbevf_set_rx_mode,
	.ndo_set_rx_mode	= ixgbevf_set_rx_mode,
	.ndo_get_stats64	= ixgbevf_get_stats,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= ixgbevf_set_mac,
	.ndo_set_mac_address	= ixgbevf_set_mac,
	.ndo_change_mtu		= ixgbevf_change_mtu,
	.ndo_change_mtu		= ixgbevf_change_mtu,