aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2010-06-16 09:26:41 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-19 01:12:15 -0400
commit8c7bbb925337705dd1459070ac620aeec6a29666 (patch)
tree688e5310b27bc0a276a578eeacf8b9b272bc0504 /drivers/net/e1000e
parent3f0c16e84438d657d29446f85fe375794a93f159 (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.h1
-rw-r--r--drivers/net/e1000e/ich8lan.c1
-rw-r--r--drivers/net/e1000e/netdev.c171
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 **/
3678static 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
3774release:
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);