summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSathya Perla <sathya.perla@emulex.com>2011-06-26 16:40:48 -0400
committerDavid S. Miller <davem@davemloft.net>2011-06-27 03:09:31 -0400
commit6e53391cb4f9491182e7fbd280966ebe2aca07dc (patch)
treed2e920a3b86e8d58903e051c98071da646eabb1e /drivers/net
parentc6af9c406ceb3434281cf230938453931dcbab75 (diff)
be2net: fix netdev_stats_update
Problem initially reproted and fixed by Eric Dumazet <eric.dumazet@gmail.com> netdev_stats_update() resets netdev->stats and then accumulates stats from various rings. This is wrong as stats readers can sometimes catch zero values. Use temporary variables instead for accumulating per-ring values. Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/benet/be_main.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index c4f564cd745b..5ca06b0d2d0c 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -428,33 +428,38 @@ void netdev_stats_update(struct be_adapter *adapter)
428 struct net_device_stats *dev_stats = &adapter->netdev->stats; 428 struct net_device_stats *dev_stats = &adapter->netdev->stats;
429 struct be_rx_obj *rxo; 429 struct be_rx_obj *rxo;
430 struct be_tx_obj *txo; 430 struct be_tx_obj *txo;
431 unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
431 int i; 432 int i;
432 433
433 memset(dev_stats, 0, sizeof(*dev_stats));
434 for_all_rx_queues(adapter, rxo, i) { 434 for_all_rx_queues(adapter, rxo, i) {
435 dev_stats->rx_packets += rx_stats(rxo)->rx_pkts; 435 pkts += rx_stats(rxo)->rx_pkts;
436 dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes; 436 bytes += rx_stats(rxo)->rx_bytes;
437 dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts; 437 mcast += rx_stats(rxo)->rx_mcast_pkts;
438 /* no space in linux buffers: best possible approximation */ 438 /* no space in linux buffers: best possible approximation */
439 if (adapter->generation == BE_GEN3) { 439 if (adapter->generation == BE_GEN3) {
440 if (!(lancer_chip(adapter))) { 440 if (!(lancer_chip(adapter))) {
441 struct be_erx_stats_v1 *erx_stats = 441 struct be_erx_stats_v1 *erx =
442 be_erx_stats_from_cmd(adapter); 442 be_erx_stats_from_cmd(adapter);
443 dev_stats->rx_dropped += 443 drops += erx->rx_drops_no_fragments[rxo->q.id];
444 erx_stats->rx_drops_no_fragments[rxo->q.id];
445 } 444 }
446 } else { 445 } else {
447 struct be_erx_stats_v0 *erx_stats = 446 struct be_erx_stats_v0 *erx =
448 be_erx_stats_from_cmd(adapter); 447 be_erx_stats_from_cmd(adapter);
449 dev_stats->rx_dropped += 448 drops += erx->rx_drops_no_fragments[rxo->q.id];
450 erx_stats->rx_drops_no_fragments[rxo->q.id];
451 } 449 }
452 } 450 }
451 dev_stats->rx_packets = pkts;
452 dev_stats->rx_bytes = bytes;
453 dev_stats->multicast = mcast;
454 dev_stats->rx_dropped = drops;
453 455
456 pkts = bytes = 0;
454 for_all_tx_queues(adapter, txo, i) { 457 for_all_tx_queues(adapter, txo, i) {
455 dev_stats->tx_packets += tx_stats(txo)->be_tx_pkts; 458 pkts += tx_stats(txo)->be_tx_pkts;
456 dev_stats->tx_bytes += tx_stats(txo)->be_tx_bytes; 459 bytes += tx_stats(txo)->be_tx_bytes;
457 } 460 }
461 dev_stats->tx_packets = pkts;
462 dev_stats->tx_bytes = bytes;
458 463
459 /* bad pkts received */ 464 /* bad pkts received */
460 dev_stats->rx_errors = drvs->rx_crc_errors + 465 dev_stats->rx_errors = drvs->rx_crc_errors +