diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2010-06-16 09:26:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-19 01:12:15 -0400 |
commit | 8c7bbb925337705dd1459070ac620aeec6a29666 (patch) | |
tree | 688e5310b27bc0a276a578eeacf8b9b272bc0504 /drivers/net/e1000e | |
parent | 3f0c16e84438d657d29446f85fe375794a93f159 (diff) |
e1000e: separate out PHY statistics register updates
The 82577/82578 parts have half-duplex statistics in PHY registers. These
need only be read when in half-duplex and should all be read at once rather
than one at a time to prevent excessive cycles of acquiring/releasing the
PHY semaphore.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r-- | drivers/net/e1000e/e1000.h | 1 | ||||
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 1 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 171 |
3 files changed, 126 insertions, 47 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index c0b3db40bd73..79e7c4c18719 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -421,6 +421,7 @@ struct e1000_info { | |||
421 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) | 421 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) |
422 | #define FLAG2_IS_DISCARDING (1 << 2) | 422 | #define FLAG2_IS_DISCARDING (1 << 2) |
423 | #define FLAG2_DISABLE_ASPM_L1 (1 << 3) | 423 | #define FLAG2_DISABLE_ASPM_L1 (1 << 3) |
424 | #define FLAG2_HAS_PHY_STATS (1 << 4) | ||
424 | 425 | ||
425 | #define E1000_RX_DESC_PS(R, i) \ | 426 | #define E1000_RX_DESC_PS(R, i) \ |
426 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 427 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 5d8fad3bb203..70cd681fd1ce 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -3503,6 +3503,7 @@ struct e1000_info e1000_pch_info = { | |||
3503 | | FLAG_HAS_JUMBO_FRAMES | 3503 | | FLAG_HAS_JUMBO_FRAMES |
3504 | | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ | 3504 | | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ |
3505 | | FLAG_APME_IN_WUC, | 3505 | | FLAG_APME_IN_WUC, |
3506 | .flags2 = FLAG2_HAS_PHY_STATS, | ||
3506 | .pba = 26, | 3507 | .pba = 26, |
3507 | .max_hw_frame_size = 4096, | 3508 | .max_hw_frame_size = 4096, |
3508 | .get_variants = e1000_get_variants_ich8lan, | 3509 | .get_variants = e1000_get_variants_ich8lan, |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 57a7e41da69e..b4c431d84516 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -3672,6 +3672,110 @@ static void e1000_update_phy_info(unsigned long data) | |||
3672 | } | 3672 | } |
3673 | 3673 | ||
3674 | /** | 3674 | /** |
3675 | * e1000e_update_phy_stats - Update the PHY statistics counters | ||
3676 | * @adapter: board private structure | ||
3677 | **/ | ||
3678 | static void e1000e_update_phy_stats(struct e1000_adapter *adapter) | ||
3679 | { | ||
3680 | struct e1000_hw *hw = &adapter->hw; | ||
3681 | s32 ret_val; | ||
3682 | u16 phy_data; | ||
3683 | |||
3684 | ret_val = hw->phy.ops.acquire(hw); | ||
3685 | if (ret_val) | ||
3686 | return; | ||
3687 | |||
3688 | hw->phy.addr = 1; | ||
3689 | |||
3690 | #define HV_PHY_STATS_PAGE 778 | ||
3691 | /* | ||
3692 | * A page set is expensive so check if already on desired page. | ||
3693 | * If not, set to the page with the PHY status registers. | ||
3694 | */ | ||
3695 | ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, | ||
3696 | &phy_data); | ||
3697 | if (ret_val) | ||
3698 | goto release; | ||
3699 | if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) { | ||
3700 | ret_val = e1000e_write_phy_reg_mdic(hw, | ||
3701 | IGP01E1000_PHY_PAGE_SELECT, | ||
3702 | (HV_PHY_STATS_PAGE << | ||
3703 | IGP_PAGE_SHIFT)); | ||
3704 | if (ret_val) | ||
3705 | goto release; | ||
3706 | } | ||
3707 | |||
3708 | /* Read/clear the upper 16-bit registers and read/accumulate lower */ | ||
3709 | |||
3710 | /* Single Collision Count */ | ||
3711 | e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS, | ||
3712 | &phy_data); | ||
3713 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3714 | HV_SCC_LOWER & MAX_PHY_REG_ADDRESS, | ||
3715 | &phy_data); | ||
3716 | if (!ret_val) | ||
3717 | adapter->stats.scc += phy_data; | ||
3718 | |||
3719 | /* Excessive Collision Count */ | ||
3720 | e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS, | ||
3721 | &phy_data); | ||
3722 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3723 | HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS, | ||
3724 | &phy_data); | ||
3725 | if (!ret_val) | ||
3726 | adapter->stats.ecol += phy_data; | ||
3727 | |||
3728 | /* Multiple Collision Count */ | ||
3729 | e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS, | ||
3730 | &phy_data); | ||
3731 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3732 | HV_MCC_LOWER & MAX_PHY_REG_ADDRESS, | ||
3733 | &phy_data); | ||
3734 | if (!ret_val) | ||
3735 | adapter->stats.mcc += phy_data; | ||
3736 | |||
3737 | /* Late Collision Count */ | ||
3738 | e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS, | ||
3739 | &phy_data); | ||
3740 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3741 | HV_LATECOL_LOWER & | ||
3742 | MAX_PHY_REG_ADDRESS, | ||
3743 | &phy_data); | ||
3744 | if (!ret_val) | ||
3745 | adapter->stats.latecol += phy_data; | ||
3746 | |||
3747 | /* Collision Count - also used for adaptive IFS */ | ||
3748 | e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS, | ||
3749 | &phy_data); | ||
3750 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3751 | HV_COLC_LOWER & MAX_PHY_REG_ADDRESS, | ||
3752 | &phy_data); | ||
3753 | if (!ret_val) | ||
3754 | hw->mac.collision_delta = phy_data; | ||
3755 | |||
3756 | /* Defer Count */ | ||
3757 | e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS, | ||
3758 | &phy_data); | ||
3759 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3760 | HV_DC_LOWER & MAX_PHY_REG_ADDRESS, | ||
3761 | &phy_data); | ||
3762 | if (!ret_val) | ||
3763 | adapter->stats.dc += phy_data; | ||
3764 | |||
3765 | /* Transmit with no CRS */ | ||
3766 | e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS, | ||
3767 | &phy_data); | ||
3768 | ret_val = e1000e_read_phy_reg_mdic(hw, | ||
3769 | HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS, | ||
3770 | &phy_data); | ||
3771 | if (!ret_val) | ||
3772 | adapter->stats.tncrs += phy_data; | ||
3773 | |||
3774 | release: | ||
3775 | hw->phy.ops.release(hw); | ||
3776 | } | ||
3777 | |||
3778 | /** | ||
3675 | * e1000e_update_stats - Update the board statistics counters | 3779 | * e1000e_update_stats - Update the board statistics counters |
3676 | * @adapter: board private structure | 3780 | * @adapter: board private structure |
3677 | **/ | 3781 | **/ |
@@ -3680,7 +3784,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3680 | struct net_device *netdev = adapter->netdev; | 3784 | struct net_device *netdev = adapter->netdev; |
3681 | struct e1000_hw *hw = &adapter->hw; | 3785 | struct e1000_hw *hw = &adapter->hw; |
3682 | struct pci_dev *pdev = adapter->pdev; | 3786 | struct pci_dev *pdev = adapter->pdev; |
3683 | u16 phy_data; | ||
3684 | 3787 | ||
3685 | /* | 3788 | /* |
3686 | * Prevent stats update while adapter is being reset, or if the pci | 3789 | * Prevent stats update while adapter is being reset, or if the pci |
@@ -3700,34 +3803,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3700 | adapter->stats.roc += er32(ROC); | 3803 | adapter->stats.roc += er32(ROC); |
3701 | 3804 | ||
3702 | adapter->stats.mpc += er32(MPC); | 3805 | adapter->stats.mpc += er32(MPC); |
3703 | if ((hw->phy.type == e1000_phy_82578) || | 3806 | |
3704 | (hw->phy.type == e1000_phy_82577)) { | 3807 | /* Half-duplex statistics */ |
3705 | e1e_rphy(hw, HV_SCC_UPPER, &phy_data); | 3808 | if (adapter->link_duplex == HALF_DUPLEX) { |
3706 | if (!e1e_rphy(hw, HV_SCC_LOWER, &phy_data)) | 3809 | if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { |
3707 | adapter->stats.scc += phy_data; | 3810 | e1000e_update_phy_stats(adapter); |
3708 | 3811 | } else { | |
3709 | e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); | 3812 | adapter->stats.scc += er32(SCC); |
3710 | if (!e1e_rphy(hw, HV_ECOL_LOWER, &phy_data)) | 3813 | adapter->stats.ecol += er32(ECOL); |
3711 | adapter->stats.ecol += phy_data; | 3814 | adapter->stats.mcc += er32(MCC); |
3712 | 3815 | adapter->stats.latecol += er32(LATECOL); | |
3713 | e1e_rphy(hw, HV_MCC_UPPER, &phy_data); | 3816 | adapter->stats.dc += er32(DC); |
3714 | if (!e1e_rphy(hw, HV_MCC_LOWER, &phy_data)) | 3817 | |
3715 | adapter->stats.mcc += phy_data; | 3818 | hw->mac.collision_delta = er32(COLC); |
3716 | 3819 | ||
3717 | e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); | 3820 | if ((hw->mac.type != e1000_82574) && |
3718 | if (!e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data)) | 3821 | (hw->mac.type != e1000_82583)) |
3719 | adapter->stats.latecol += phy_data; | 3822 | adapter->stats.tncrs += er32(TNCRS); |
3720 | 3823 | } | |
3721 | e1e_rphy(hw, HV_DC_UPPER, &phy_data); | 3824 | adapter->stats.colc += hw->mac.collision_delta; |
3722 | if (!e1e_rphy(hw, HV_DC_LOWER, &phy_data)) | ||
3723 | adapter->stats.dc += phy_data; | ||
3724 | } else { | ||
3725 | adapter->stats.scc += er32(SCC); | ||
3726 | adapter->stats.ecol += er32(ECOL); | ||
3727 | adapter->stats.mcc += er32(MCC); | ||
3728 | adapter->stats.latecol += er32(LATECOL); | ||
3729 | adapter->stats.dc += er32(DC); | ||
3730 | } | 3825 | } |
3826 | |||
3731 | adapter->stats.xonrxc += er32(XONRXC); | 3827 | adapter->stats.xonrxc += er32(XONRXC); |
3732 | adapter->stats.xontxc += er32(XONTXC); | 3828 | adapter->stats.xontxc += er32(XONTXC); |
3733 | adapter->stats.xoffrxc += er32(XOFFRXC); | 3829 | adapter->stats.xoffrxc += er32(XOFFRXC); |
@@ -3745,28 +3841,9 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3745 | 3841 | ||
3746 | hw->mac.tx_packet_delta = er32(TPT); | 3842 | hw->mac.tx_packet_delta = er32(TPT); |
3747 | adapter->stats.tpt += hw->mac.tx_packet_delta; | 3843 | adapter->stats.tpt += hw->mac.tx_packet_delta; |
3748 | if ((hw->phy.type == e1000_phy_82578) || | ||
3749 | (hw->phy.type == e1000_phy_82577)) { | ||
3750 | e1e_rphy(hw, HV_COLC_UPPER, &phy_data); | ||
3751 | if (!e1e_rphy(hw, HV_COLC_LOWER, &phy_data)) | ||
3752 | hw->mac.collision_delta = phy_data; | ||
3753 | } else { | ||
3754 | hw->mac.collision_delta = er32(COLC); | ||
3755 | } | ||
3756 | adapter->stats.colc += hw->mac.collision_delta; | ||
3757 | 3844 | ||
3758 | adapter->stats.algnerrc += er32(ALGNERRC); | 3845 | adapter->stats.algnerrc += er32(ALGNERRC); |
3759 | adapter->stats.rxerrc += er32(RXERRC); | 3846 | adapter->stats.rxerrc += er32(RXERRC); |
3760 | if ((hw->phy.type == e1000_phy_82578) || | ||
3761 | (hw->phy.type == e1000_phy_82577)) { | ||
3762 | e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); | ||
3763 | if (!e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data)) | ||
3764 | adapter->stats.tncrs += phy_data; | ||
3765 | } else { | ||
3766 | if ((hw->mac.type != e1000_82574) && | ||
3767 | (hw->mac.type != e1000_82583)) | ||
3768 | adapter->stats.tncrs += er32(TNCRS); | ||
3769 | } | ||
3770 | adapter->stats.cexterr += er32(CEXTERR); | 3847 | adapter->stats.cexterr += er32(CEXTERR); |
3771 | adapter->stats.tsctc += er32(TSCTC); | 3848 | adapter->stats.tsctc += er32(TSCTC); |
3772 | adapter->stats.tsctfc += er32(TSCTFC); | 3849 | adapter->stats.tsctfc += er32(TSCTFC); |