diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 64 |
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 | ||
6547 | static void | ||
6548 | bnx2_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 | ||
6563 | static struct net_device_stats * | 6592 | static struct net_device_stats * |
6564 | bnx2_get_stats(struct net_device *dev) | 6593 | bnx2_get_stats(struct net_device *dev) |
@@ -7089,6 +7118,9 @@ static int | |||
7089 | bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) | 7118 | bnx2_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); |