aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-12-08 02:22:03 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-08 23:10:12 -0500
commit60d51134281fbeb352013d782a440fb338d31f01 (patch)
tree36df3a263cf024612e1c62c8210bfbfe2d67a0d3
parent3421eecdee750bafc78b12ac25b3e980195265eb (diff)
ixgbe: Fix TX stats accounting
Here is an updated version, because ixgbe_get_ethtool_stats() needs to call dev_get_stats() or "ethtool -S" wont give correct tx_bytes/tx_packets values. Several cpus can update netdev->stats.tx_bytes & netdev->stats.tx_packets in parallel. In this case, TX stats are under estimated and false sharing takes place. After a pktgen session sending exactly 200000000 packets : # ifconfig fiber0 | grep TX TX packets:198501982 errors:0 dropped:0 overruns:0 carrier:0 Multi queue devices should instead use txq->tx_bytes & txq->tx_packets in their xmit() method (appropriate txq lock already held by caller, no cache line miss), or use appropriate locking. After patch, same pktgen session gives : # ifconfig fiber0 | grep TX TX packets:200000000 errors:0 dropped:0 overruns:0 carrier:0 Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c1
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c20
2 files changed, 5 insertions, 16 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 06a9d18bbdbc..0bd49d3b9f65 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -990,6 +990,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
990 char *p = NULL; 990 char *p = NULL;
991 991
992 ixgbe_update_stats(adapter); 992 ixgbe_update_stats(adapter);
993 dev_get_stats(netdev);
993 for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { 994 for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
994 switch (ixgbe_gstrings_stats[i].type) { 995 switch (ixgbe_gstrings_stats[i].type) {
995 case NETDEV_STATS: 996 case NETDEV_STATS:
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 247ed2a24769..4374f441c426 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -435,8 +435,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
435 tx_ring->total_packets += total_packets; 435 tx_ring->total_packets += total_packets;
436 tx_ring->stats.packets += total_packets; 436 tx_ring->stats.packets += total_packets;
437 tx_ring->stats.bytes += total_bytes; 437 tx_ring->stats.bytes += total_bytes;
438 netdev->stats.tx_bytes += total_bytes;
439 netdev->stats.tx_packets += total_packets;
440 return (count < tx_ring->work_limit); 438 return (count < tx_ring->work_limit);
441} 439}
442 440
@@ -5327,6 +5325,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
5327{ 5325{
5328 struct ixgbe_adapter *adapter = netdev_priv(netdev); 5326 struct ixgbe_adapter *adapter = netdev_priv(netdev);
5329 struct ixgbe_ring *tx_ring; 5327 struct ixgbe_ring *tx_ring;
5328 struct netdev_queue *txq;
5330 unsigned int first; 5329 unsigned int first;
5331 unsigned int tx_flags = 0; 5330 unsigned int tx_flags = 0;
5332 u8 hdr_len = 0; 5331 u8 hdr_len = 0;
@@ -5424,6 +5423,9 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
5424 tx_ring->atr_count = 0; 5423 tx_ring->atr_count = 0;
5425 } 5424 }
5426 } 5425 }
5426 txq = netdev_get_tx_queue(netdev, tx_ring->queue_index);
5427 txq->tx_bytes += skb->len;
5428 txq->tx_packets++;
5427 ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len, 5429 ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
5428 hdr_len); 5430 hdr_len);
5429 ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); 5431 ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
@@ -5438,19 +5440,6 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
5438} 5440}
5439 5441
5440/** 5442/**
5441 * ixgbe_get_stats - Get System Network Statistics
5442 * @netdev: network interface device structure
5443 *
5444 * Returns the address of the device statistics structure.
5445 * The statistics are actually updated from the timer callback.
5446 **/
5447static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev)
5448{
5449 /* only return the current stats */
5450 return &netdev->stats;
5451}
5452
5453/**
5454 * ixgbe_set_mac - Change the Ethernet Address of the NIC 5443 * ixgbe_set_mac - Change the Ethernet Address of the NIC
5455 * @netdev: network interface device structure 5444 * @netdev: network interface device structure
5456 * @p: pointer to an address structure 5445 * @p: pointer to an address structure
@@ -5580,7 +5569,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
5580 .ndo_stop = ixgbe_close, 5569 .ndo_stop = ixgbe_close,
5581 .ndo_start_xmit = ixgbe_xmit_frame, 5570 .ndo_start_xmit = ixgbe_xmit_frame,
5582 .ndo_select_queue = ixgbe_select_queue, 5571 .ndo_select_queue = ixgbe_select_queue,
5583 .ndo_get_stats = ixgbe_get_stats,
5584 .ndo_set_rx_mode = ixgbe_set_rx_mode, 5572 .ndo_set_rx_mode = ixgbe_set_rx_mode,
5585 .ndo_set_multicast_list = ixgbe_set_rx_mode, 5573 .ndo_set_multicast_list = ixgbe_set_rx_mode,
5586 .ndo_validate_addr = eth_validate_addr, 5574 .ndo_validate_addr = eth_validate_addr,