diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 124 |
1 files changed, 89 insertions, 35 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 65df1de447e4..d83512d3e02f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -6145,6 +6145,10 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) | |||
6145 | REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); | 6145 | REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); |
6146 | REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); | 6146 | REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); |
6147 | 6147 | ||
6148 | /* Need to flush the previous three writes to ensure MSI-X | ||
6149 | * is setup properly */ | ||
6150 | REG_RD(bp, BNX2_PCI_MSIX_CONTROL); | ||
6151 | |||
6148 | for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { | 6152 | for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { |
6149 | msix_ent[i].entry = i; | 6153 | msix_ent[i].entry = i; |
6150 | msix_ent[i].vector = 0; | 6154 | msix_ent[i].vector = 0; |
@@ -6227,6 +6231,8 @@ bnx2_open(struct net_device *dev) | |||
6227 | 6231 | ||
6228 | atomic_set(&bp->intr_sem, 0); | 6232 | atomic_set(&bp->intr_sem, 0); |
6229 | 6233 | ||
6234 | memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block)); | ||
6235 | |||
6230 | bnx2_enable_int(bp); | 6236 | bnx2_enable_int(bp); |
6231 | 6237 | ||
6232 | if (bp->flags & BNX2_FLAG_USING_MSI) { | 6238 | if (bp->flags & BNX2_FLAG_USING_MSI) { |
@@ -6538,92 +6544,121 @@ bnx2_close(struct net_device *dev) | |||
6538 | return 0; | 6544 | return 0; |
6539 | } | 6545 | } |
6540 | 6546 | ||
6541 | #define GET_NET_STATS64(ctr) \ | 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 | |||
6571 | #define GET_64BIT_NET_STATS64(ctr) \ | ||
6542 | (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ | 6572 | (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ |
6543 | (unsigned long) (ctr##_lo) | 6573 | (unsigned long) (ctr##_lo) |
6544 | 6574 | ||
6545 | #define GET_NET_STATS32(ctr) \ | 6575 | #define GET_64BIT_NET_STATS32(ctr) \ |
6546 | (ctr##_lo) | 6576 | (ctr##_lo) |
6547 | 6577 | ||
6548 | #if (BITS_PER_LONG == 64) | 6578 | #if (BITS_PER_LONG == 64) |
6549 | #define GET_NET_STATS GET_NET_STATS64 | 6579 | #define GET_64BIT_NET_STATS(ctr) \ |
6580 | GET_64BIT_NET_STATS64(bp->stats_blk->ctr) + \ | ||
6581 | GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr) | ||
6550 | #else | 6582 | #else |
6551 | #define GET_NET_STATS GET_NET_STATS32 | 6583 | #define GET_64BIT_NET_STATS(ctr) \ |
6584 | GET_64BIT_NET_STATS32(bp->stats_blk->ctr) + \ | ||
6585 | GET_64BIT_NET_STATS32(bp->temp_stats_blk->ctr) | ||
6552 | #endif | 6586 | #endif |
6553 | 6587 | ||
6588 | #define GET_32BIT_NET_STATS(ctr) \ | ||
6589 | (unsigned long) (bp->stats_blk->ctr + \ | ||
6590 | bp->temp_stats_blk->ctr) | ||
6591 | |||
6554 | static struct net_device_stats * | 6592 | static struct net_device_stats * |
6555 | bnx2_get_stats(struct net_device *dev) | 6593 | bnx2_get_stats(struct net_device *dev) |
6556 | { | 6594 | { |
6557 | struct bnx2 *bp = netdev_priv(dev); | 6595 | struct bnx2 *bp = netdev_priv(dev); |
6558 | struct statistics_block *stats_blk = bp->stats_blk; | ||
6559 | struct net_device_stats *net_stats = &dev->stats; | 6596 | struct net_device_stats *net_stats = &dev->stats; |
6560 | 6597 | ||
6561 | if (bp->stats_blk == NULL) { | 6598 | if (bp->stats_blk == NULL) { |
6562 | return net_stats; | 6599 | return net_stats; |
6563 | } | 6600 | } |
6564 | net_stats->rx_packets = | 6601 | net_stats->rx_packets = |
6565 | GET_NET_STATS(stats_blk->stat_IfHCInUcastPkts) + | 6602 | GET_64BIT_NET_STATS(stat_IfHCInUcastPkts) + |
6566 | GET_NET_STATS(stats_blk->stat_IfHCInMulticastPkts) + | 6603 | GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts) + |
6567 | GET_NET_STATS(stats_blk->stat_IfHCInBroadcastPkts); | 6604 | GET_64BIT_NET_STATS(stat_IfHCInBroadcastPkts); |
6568 | 6605 | ||
6569 | net_stats->tx_packets = | 6606 | net_stats->tx_packets = |
6570 | GET_NET_STATS(stats_blk->stat_IfHCOutUcastPkts) + | 6607 | GET_64BIT_NET_STATS(stat_IfHCOutUcastPkts) + |
6571 | GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts) + | 6608 | GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts) + |
6572 | GET_NET_STATS(stats_blk->stat_IfHCOutBroadcastPkts); | 6609 | GET_64BIT_NET_STATS(stat_IfHCOutBroadcastPkts); |
6573 | 6610 | ||
6574 | net_stats->rx_bytes = | 6611 | net_stats->rx_bytes = |
6575 | GET_NET_STATS(stats_blk->stat_IfHCInOctets); | 6612 | GET_64BIT_NET_STATS(stat_IfHCInOctets); |
6576 | 6613 | ||
6577 | net_stats->tx_bytes = | 6614 | net_stats->tx_bytes = |
6578 | GET_NET_STATS(stats_blk->stat_IfHCOutOctets); | 6615 | GET_64BIT_NET_STATS(stat_IfHCOutOctets); |
6579 | 6616 | ||
6580 | net_stats->multicast = | 6617 | net_stats->multicast = |
6581 | GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts); | 6618 | GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts); |
6582 | 6619 | ||
6583 | net_stats->collisions = | 6620 | net_stats->collisions = |
6584 | (unsigned long) stats_blk->stat_EtherStatsCollisions; | 6621 | GET_32BIT_NET_STATS(stat_EtherStatsCollisions); |
6585 | 6622 | ||
6586 | net_stats->rx_length_errors = | 6623 | net_stats->rx_length_errors = |
6587 | (unsigned long) (stats_blk->stat_EtherStatsUndersizePkts + | 6624 | GET_32BIT_NET_STATS(stat_EtherStatsUndersizePkts) + |
6588 | stats_blk->stat_EtherStatsOverrsizePkts); | 6625 | GET_32BIT_NET_STATS(stat_EtherStatsOverrsizePkts); |
6589 | 6626 | ||
6590 | net_stats->rx_over_errors = | 6627 | net_stats->rx_over_errors = |
6591 | (unsigned long) (stats_blk->stat_IfInFTQDiscards + | 6628 | GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + |
6592 | stats_blk->stat_IfInMBUFDiscards); | 6629 | GET_32BIT_NET_STATS(stat_IfInMBUFDiscards); |
6593 | 6630 | ||
6594 | net_stats->rx_frame_errors = | 6631 | net_stats->rx_frame_errors = |
6595 | (unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors; | 6632 | GET_32BIT_NET_STATS(stat_Dot3StatsAlignmentErrors); |
6596 | 6633 | ||
6597 | net_stats->rx_crc_errors = | 6634 | net_stats->rx_crc_errors = |
6598 | (unsigned long) stats_blk->stat_Dot3StatsFCSErrors; | 6635 | GET_32BIT_NET_STATS(stat_Dot3StatsFCSErrors); |
6599 | 6636 | ||
6600 | net_stats->rx_errors = net_stats->rx_length_errors + | 6637 | net_stats->rx_errors = net_stats->rx_length_errors + |
6601 | net_stats->rx_over_errors + net_stats->rx_frame_errors + | 6638 | net_stats->rx_over_errors + net_stats->rx_frame_errors + |
6602 | net_stats->rx_crc_errors; | 6639 | net_stats->rx_crc_errors; |
6603 | 6640 | ||
6604 | net_stats->tx_aborted_errors = | 6641 | net_stats->tx_aborted_errors = |
6605 | (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + | 6642 | GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) + |
6606 | stats_blk->stat_Dot3StatsLateCollisions); | 6643 | GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions); |
6607 | 6644 | ||
6608 | if ((CHIP_NUM(bp) == CHIP_NUM_5706) || | 6645 | if ((CHIP_NUM(bp) == CHIP_NUM_5706) || |
6609 | (CHIP_ID(bp) == CHIP_ID_5708_A0)) | 6646 | (CHIP_ID(bp) == CHIP_ID_5708_A0)) |
6610 | net_stats->tx_carrier_errors = 0; | 6647 | net_stats->tx_carrier_errors = 0; |
6611 | else { | 6648 | else { |
6612 | net_stats->tx_carrier_errors = | 6649 | net_stats->tx_carrier_errors = |
6613 | (unsigned long) | 6650 | GET_32BIT_NET_STATS(stat_Dot3StatsCarrierSenseErrors); |
6614 | stats_blk->stat_Dot3StatsCarrierSenseErrors; | ||
6615 | } | 6651 | } |
6616 | 6652 | ||
6617 | net_stats->tx_errors = | 6653 | net_stats->tx_errors = |
6618 | (unsigned long) | 6654 | GET_32BIT_NET_STATS(stat_emac_tx_stat_dot3statsinternalmactransmiterrors) + |
6619 | stats_blk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors | ||
6620 | + | ||
6621 | net_stats->tx_aborted_errors + | 6655 | net_stats->tx_aborted_errors + |
6622 | net_stats->tx_carrier_errors; | 6656 | net_stats->tx_carrier_errors; |
6623 | 6657 | ||
6624 | net_stats->rx_missed_errors = | 6658 | net_stats->rx_missed_errors = |
6625 | (unsigned long) (stats_blk->stat_IfInFTQDiscards + | 6659 | GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + |
6626 | stats_blk->stat_IfInMBUFDiscards + stats_blk->stat_FwRxDrop); | 6660 | GET_32BIT_NET_STATS(stat_IfInMBUFDiscards) + |
6661 | GET_32BIT_NET_STATS(stat_FwRxDrop); | ||
6627 | 6662 | ||
6628 | return net_stats; | 6663 | return net_stats; |
6629 | } | 6664 | } |
@@ -7083,6 +7118,9 @@ static int | |||
7083 | bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) | 7118 | bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) |
7084 | { | 7119 | { |
7085 | 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 | |||
7086 | bnx2_netif_stop(bp); | 7124 | bnx2_netif_stop(bp); |
7087 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); | 7125 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); |
7088 | bnx2_free_skbs(bp); | 7126 | bnx2_free_skbs(bp); |
@@ -7427,6 +7465,7 @@ bnx2_get_ethtool_stats(struct net_device *dev, | |||
7427 | struct bnx2 *bp = netdev_priv(dev); | 7465 | struct bnx2 *bp = netdev_priv(dev); |
7428 | int i; | 7466 | int i; |
7429 | u32 *hw_stats = (u32 *) bp->stats_blk; | 7467 | u32 *hw_stats = (u32 *) bp->stats_blk; |
7468 | u32 *temp_stats = (u32 *) bp->temp_stats_blk; | ||
7430 | u8 *stats_len_arr = NULL; | 7469 | u8 *stats_len_arr = NULL; |
7431 | 7470 | ||
7432 | if (hw_stats == NULL) { | 7471 | if (hw_stats == NULL) { |
@@ -7443,21 +7482,26 @@ bnx2_get_ethtool_stats(struct net_device *dev, | |||
7443 | stats_len_arr = bnx2_5708_stats_len_arr; | 7482 | stats_len_arr = bnx2_5708_stats_len_arr; |
7444 | 7483 | ||
7445 | for (i = 0; i < BNX2_NUM_STATS; i++) { | 7484 | for (i = 0; i < BNX2_NUM_STATS; i++) { |
7485 | unsigned long offset; | ||
7486 | |||
7446 | if (stats_len_arr[i] == 0) { | 7487 | if (stats_len_arr[i] == 0) { |
7447 | /* skip this counter */ | 7488 | /* skip this counter */ |
7448 | buf[i] = 0; | 7489 | buf[i] = 0; |
7449 | continue; | 7490 | continue; |
7450 | } | 7491 | } |
7492 | |||
7493 | offset = bnx2_stats_offset_arr[i]; | ||
7451 | if (stats_len_arr[i] == 4) { | 7494 | if (stats_len_arr[i] == 4) { |
7452 | /* 4-byte counter */ | 7495 | /* 4-byte counter */ |
7453 | buf[i] = (u64) | 7496 | buf[i] = (u64) *(hw_stats + offset) + |
7454 | *(hw_stats + bnx2_stats_offset_arr[i]); | 7497 | *(temp_stats + offset); |
7455 | continue; | 7498 | continue; |
7456 | } | 7499 | } |
7457 | /* 8-byte counter */ | 7500 | /* 8-byte counter */ |
7458 | buf[i] = (((u64) *(hw_stats + | 7501 | buf[i] = (((u64) *(hw_stats + offset)) << 32) + |
7459 | bnx2_stats_offset_arr[i])) << 32) + | 7502 | *(hw_stats + offset + 1) + |
7460 | *(hw_stats + bnx2_stats_offset_arr[i] + 1); | 7503 | (((u64) *(temp_stats + offset)) << 32) + |
7504 | *(temp_stats + offset + 1); | ||
7461 | } | 7505 | } |
7462 | } | 7506 | } |
7463 | 7507 | ||
@@ -7825,6 +7869,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
7825 | bp->flags = 0; | 7869 | bp->flags = 0; |
7826 | bp->phy_flags = 0; | 7870 | bp->phy_flags = 0; |
7827 | 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 | |||
7828 | /* enable device (incl. PCI PM wakeup), and bus-mastering */ | 7880 | /* enable device (incl. PCI PM wakeup), and bus-mastering */ |
7829 | rc = pci_enable_device(pdev); | 7881 | rc = pci_enable_device(pdev); |
7830 | if (rc) { | 7882 | if (rc) { |
@@ -8346,6 +8398,8 @@ bnx2_remove_one(struct pci_dev *pdev) | |||
8346 | if (bp->regview) | 8398 | if (bp->regview) |
8347 | iounmap(bp->regview); | 8399 | iounmap(bp->regview); |
8348 | 8400 | ||
8401 | kfree(bp->temp_stats_blk); | ||
8402 | |||
8349 | free_netdev(dev); | 8403 | free_netdev(dev); |
8350 | pci_release_regions(pdev); | 8404 | pci_release_regions(pdev); |
8351 | pci_disable_device(pdev); | 8405 | pci_disable_device(pdev); |