aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2010-01-17 02:30:44 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-17 22:16:03 -0500
commit354fcd7774a00809ebefdba75e747364cb22a940 (patch)
tree5608a763f03b1af9ba8650c9a1e99f5546eb0797 /drivers/net/bnx2.c
parenta47430583dab67b23161b0e75226781deed50138 (diff)
bnx2: Save statistics during reset.
MTU changes, ring size changes, etc cause the chip to be reset and the statisctics flushed. To keep track of the accumulated statistics, we add code to save the whole statistics block before reset. We also modify the macros and statistics functions to return the sum of the saved and current counters. Based on original patch by Breno Leitao <leitao@linux.vnet.ibm.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 47fb5086cf56..d83512d3e02f 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6231,6 +6231,8 @@ bnx2_open(struct net_device *dev)
6231 6231
6232 atomic_set(&bp->intr_sem, 0); 6232 atomic_set(&bp->intr_sem, 0);
6233 6233
6234 memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block));
6235
6234 bnx2_enable_int(bp); 6236 bnx2_enable_int(bp);
6235 6237
6236 if (bp->flags & BNX2_FLAG_USING_MSI) { 6238 if (bp->flags & BNX2_FLAG_USING_MSI) {
@@ -6542,6 +6544,30 @@ bnx2_close(struct net_device *dev)
6542 return 0; 6544 return 0;
6543} 6545}
6544 6546
6547static void
6548bnx2_save_stats(struct bnx2 *bp)
6549{
6550 u32 *hw_stats = (u32 *) bp->stats_blk;
6551 u32 *temp_stats = (u32 *) bp->temp_stats_blk;
6552 int i;
6553
6554 /* The 1st 10 counters are 64-bit counters */
6555 for (i = 0; i < 20; i += 2) {
6556 u32 hi;
6557 u64 lo;
6558
6559 hi = *(temp_stats + i) + *(hw_stats + i);
6560 lo = *(temp_stats + i + 1) + *(hw_stats + i + 1);
6561 if (lo > 0xffffffff)
6562 hi++;
6563 *(temp_stats + i) = hi;
6564 *(temp_stats + i + 1) = lo & 0xffffffff;
6565 }
6566
6567 for ( ; i < sizeof(struct statistics_block) / 4; i++)
6568 *(temp_stats + i) = *(temp_stats + i) + *(hw_stats + i);
6569}
6570
6545#define GET_64BIT_NET_STATS64(ctr) \ 6571#define GET_64BIT_NET_STATS64(ctr) \
6546 (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ 6572 (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \
6547 (unsigned long) (ctr##_lo) 6573 (unsigned long) (ctr##_lo)
@@ -6551,14 +6577,17 @@ bnx2_close(struct net_device *dev)
6551 6577
6552#if (BITS_PER_LONG == 64) 6578#if (BITS_PER_LONG == 64)
6553#define GET_64BIT_NET_STATS(ctr) \ 6579#define GET_64BIT_NET_STATS(ctr) \
6554 GET_64BIT_NET_STATS64(bp->stats_blk->ctr) 6580 GET_64BIT_NET_STATS64(bp->stats_blk->ctr) + \
6581 GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr)
6555#else 6582#else
6556#define GET_64BIT_NET_STATS(ctr) \ 6583#define GET_64BIT_NET_STATS(ctr) \
6557 GET_64BIT_NET_STATS32(bp->stats_blk->ctr) 6584 GET_64BIT_NET_STATS32(bp->stats_blk->ctr) + \
6585 GET_64BIT_NET_STATS32(bp->temp_stats_blk->ctr)
6558#endif 6586#endif
6559 6587
6560#define GET_32BIT_NET_STATS(ctr) \ 6588#define GET_32BIT_NET_STATS(ctr) \
6561 (unsigned long) (bp->stats_blk->ctr) 6589 (unsigned long) (bp->stats_blk->ctr + \
6590 bp->temp_stats_blk->ctr)
6562 6591
6563static struct net_device_stats * 6592static struct net_device_stats *
6564bnx2_get_stats(struct net_device *dev) 6593bnx2_get_stats(struct net_device *dev)
@@ -7089,6 +7118,9 @@ static int
7089bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) 7118bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7090{ 7119{
7091 if (netif_running(bp->dev)) { 7120 if (netif_running(bp->dev)) {
7121 /* Reset will erase chipset stats; save them */
7122 bnx2_save_stats(bp);
7123
7092 bnx2_netif_stop(bp); 7124 bnx2_netif_stop(bp);
7093 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); 7125 bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
7094 bnx2_free_skbs(bp); 7126 bnx2_free_skbs(bp);
@@ -7433,6 +7465,7 @@ bnx2_get_ethtool_stats(struct net_device *dev,
7433 struct bnx2 *bp = netdev_priv(dev); 7465 struct bnx2 *bp = netdev_priv(dev);
7434 int i; 7466 int i;
7435 u32 *hw_stats = (u32 *) bp->stats_blk; 7467 u32 *hw_stats = (u32 *) bp->stats_blk;
7468 u32 *temp_stats = (u32 *) bp->temp_stats_blk;
7436 u8 *stats_len_arr = NULL; 7469 u8 *stats_len_arr = NULL;
7437 7470
7438 if (hw_stats == NULL) { 7471 if (hw_stats == NULL) {
@@ -7449,21 +7482,26 @@ bnx2_get_ethtool_stats(struct net_device *dev,
7449 stats_len_arr = bnx2_5708_stats_len_arr; 7482 stats_len_arr = bnx2_5708_stats_len_arr;
7450 7483
7451 for (i = 0; i < BNX2_NUM_STATS; i++) { 7484 for (i = 0; i < BNX2_NUM_STATS; i++) {
7485 unsigned long offset;
7486
7452 if (stats_len_arr[i] == 0) { 7487 if (stats_len_arr[i] == 0) {
7453 /* skip this counter */ 7488 /* skip this counter */
7454 buf[i] = 0; 7489 buf[i] = 0;
7455 continue; 7490 continue;
7456 } 7491 }
7492
7493 offset = bnx2_stats_offset_arr[i];
7457 if (stats_len_arr[i] == 4) { 7494 if (stats_len_arr[i] == 4) {
7458 /* 4-byte counter */ 7495 /* 4-byte counter */
7459 buf[i] = (u64) 7496 buf[i] = (u64) *(hw_stats + offset) +
7460 *(hw_stats + bnx2_stats_offset_arr[i]); 7497 *(temp_stats + offset);
7461 continue; 7498 continue;
7462 } 7499 }
7463 /* 8-byte counter */ 7500 /* 8-byte counter */
7464 buf[i] = (((u64) *(hw_stats + 7501 buf[i] = (((u64) *(hw_stats + offset)) << 32) +
7465 bnx2_stats_offset_arr[i])) << 32) + 7502 *(hw_stats + offset + 1) +
7466 *(hw_stats + bnx2_stats_offset_arr[i] + 1); 7503 (((u64) *(temp_stats + offset)) << 32) +
7504 *(temp_stats + offset + 1);
7467 } 7505 }
7468} 7506}
7469 7507
@@ -7831,6 +7869,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
7831 bp->flags = 0; 7869 bp->flags = 0;
7832 bp->phy_flags = 0; 7870 bp->phy_flags = 0;
7833 7871
7872 bp->temp_stats_blk =
7873 kzalloc(sizeof(struct statistics_block), GFP_KERNEL);
7874
7875 if (bp->temp_stats_blk == NULL) {
7876 rc = -ENOMEM;
7877 goto err_out;
7878 }
7879
7834 /* enable device (incl. PCI PM wakeup), and bus-mastering */ 7880 /* enable device (incl. PCI PM wakeup), and bus-mastering */
7835 rc = pci_enable_device(pdev); 7881 rc = pci_enable_device(pdev);
7836 if (rc) { 7882 if (rc) {
@@ -8352,6 +8398,8 @@ bnx2_remove_one(struct pci_dev *pdev)
8352 if (bp->regview) 8398 if (bp->regview)
8353 iounmap(bp->regview); 8399 iounmap(bp->regview);
8354 8400
8401 kfree(bp->temp_stats_blk);
8402
8355 free_netdev(dev); 8403 free_netdev(dev);
8356 pci_release_regions(pdev); 8404 pci_release_regions(pdev);
8357 pci_disable_device(pdev); 8405 pci_disable_device(pdev);