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>
This commit is contained in:
parent
3f0c16e844
commit
8c7bbb9253
|
@ -421,6 +421,7 @@ struct e1000_info {
|
|||
#define FLAG2_HAS_PHY_WAKEUP (1 << 1)
|
||||
#define FLAG2_IS_DISCARDING (1 << 2)
|
||||
#define FLAG2_DISABLE_ASPM_L1 (1 << 3)
|
||||
#define FLAG2_HAS_PHY_STATS (1 << 4)
|
||||
|
||||
#define E1000_RX_DESC_PS(R, i) \
|
||||
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
|
||||
|
|
|
@ -3503,6 +3503,7 @@ struct e1000_info e1000_pch_info = {
|
|||
| FLAG_HAS_JUMBO_FRAMES
|
||||
| FLAG_DISABLE_FC_PAUSE_TIME /* errata */
|
||||
| FLAG_APME_IN_WUC,
|
||||
.flags2 = FLAG2_HAS_PHY_STATS,
|
||||
.pba = 26,
|
||||
.max_hw_frame_size = 4096,
|
||||
.get_variants = e1000_get_variants_ich8lan,
|
||||
|
|
|
@ -3671,6 +3671,110 @@ static void e1000_update_phy_info(unsigned long data)
|
|||
schedule_work(&adapter->update_phy_task);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_update_phy_stats - Update the PHY statistics counters
|
||||
* @adapter: board private structure
|
||||
**/
|
||||
static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
s32 ret_val;
|
||||
u16 phy_data;
|
||||
|
||||
ret_val = hw->phy.ops.acquire(hw);
|
||||
if (ret_val)
|
||||
return;
|
||||
|
||||
hw->phy.addr = 1;
|
||||
|
||||
#define HV_PHY_STATS_PAGE 778
|
||||
/*
|
||||
* A page set is expensive so check if already on desired page.
|
||||
* If not, set to the page with the PHY status registers.
|
||||
*/
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
|
||||
&phy_data);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) {
|
||||
ret_val = e1000e_write_phy_reg_mdic(hw,
|
||||
IGP01E1000_PHY_PAGE_SELECT,
|
||||
(HV_PHY_STATS_PAGE <<
|
||||
IGP_PAGE_SHIFT));
|
||||
if (ret_val)
|
||||
goto release;
|
||||
}
|
||||
|
||||
/* Read/clear the upper 16-bit registers and read/accumulate lower */
|
||||
|
||||
/* Single Collision Count */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.scc += phy_data;
|
||||
|
||||
/* Excessive Collision Count */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.ecol += phy_data;
|
||||
|
||||
/* Multiple Collision Count */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.mcc += phy_data;
|
||||
|
||||
/* Late Collision Count */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_LATECOL_LOWER &
|
||||
MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.latecol += phy_data;
|
||||
|
||||
/* Collision Count - also used for adaptive IFS */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
hw->mac.collision_delta = phy_data;
|
||||
|
||||
/* Defer Count */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.dc += phy_data;
|
||||
|
||||
/* Transmit with no CRS */
|
||||
e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
ret_val = e1000e_read_phy_reg_mdic(hw,
|
||||
HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
|
||||
&phy_data);
|
||||
if (!ret_val)
|
||||
adapter->stats.tncrs += phy_data;
|
||||
|
||||
release:
|
||||
hw->phy.ops.release(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_update_stats - Update the board statistics counters
|
||||
* @adapter: board private structure
|
||||
|
@ -3680,7 +3784,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
u16 phy_data;
|
||||
|
||||
/*
|
||||
* Prevent stats update while adapter is being reset, or if the pci
|
||||
|
@ -3700,34 +3803,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
adapter->stats.roc += er32(ROC);
|
||||
|
||||
adapter->stats.mpc += er32(MPC);
|
||||
if ((hw->phy.type == e1000_phy_82578) ||
|
||||
(hw->phy.type == e1000_phy_82577)) {
|
||||
e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_SCC_LOWER, &phy_data))
|
||||
adapter->stats.scc += phy_data;
|
||||
|
||||
e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_ECOL_LOWER, &phy_data))
|
||||
adapter->stats.ecol += phy_data;
|
||||
/* Half-duplex statistics */
|
||||
if (adapter->link_duplex == HALF_DUPLEX) {
|
||||
if (adapter->flags2 & FLAG2_HAS_PHY_STATS) {
|
||||
e1000e_update_phy_stats(adapter);
|
||||
} else {
|
||||
adapter->stats.scc += er32(SCC);
|
||||
adapter->stats.ecol += er32(ECOL);
|
||||
adapter->stats.mcc += er32(MCC);
|
||||
adapter->stats.latecol += er32(LATECOL);
|
||||
adapter->stats.dc += er32(DC);
|
||||
|
||||
e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_MCC_LOWER, &phy_data))
|
||||
adapter->stats.mcc += phy_data;
|
||||
hw->mac.collision_delta = er32(COLC);
|
||||
|
||||
e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data))
|
||||
adapter->stats.latecol += phy_data;
|
||||
|
||||
e1e_rphy(hw, HV_DC_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_DC_LOWER, &phy_data))
|
||||
adapter->stats.dc += phy_data;
|
||||
} else {
|
||||
adapter->stats.scc += er32(SCC);
|
||||
adapter->stats.ecol += er32(ECOL);
|
||||
adapter->stats.mcc += er32(MCC);
|
||||
adapter->stats.latecol += er32(LATECOL);
|
||||
adapter->stats.dc += er32(DC);
|
||||
if ((hw->mac.type != e1000_82574) &&
|
||||
(hw->mac.type != e1000_82583))
|
||||
adapter->stats.tncrs += er32(TNCRS);
|
||||
}
|
||||
adapter->stats.colc += hw->mac.collision_delta;
|
||||
}
|
||||
|
||||
adapter->stats.xonrxc += er32(XONRXC);
|
||||
adapter->stats.xontxc += er32(XONTXC);
|
||||
adapter->stats.xoffrxc += er32(XOFFRXC);
|
||||
|
@ -3745,28 +3841,9 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
|
||||
hw->mac.tx_packet_delta = er32(TPT);
|
||||
adapter->stats.tpt += hw->mac.tx_packet_delta;
|
||||
if ((hw->phy.type == e1000_phy_82578) ||
|
||||
(hw->phy.type == e1000_phy_82577)) {
|
||||
e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_COLC_LOWER, &phy_data))
|
||||
hw->mac.collision_delta = phy_data;
|
||||
} else {
|
||||
hw->mac.collision_delta = er32(COLC);
|
||||
}
|
||||
adapter->stats.colc += hw->mac.collision_delta;
|
||||
|
||||
adapter->stats.algnerrc += er32(ALGNERRC);
|
||||
adapter->stats.rxerrc += er32(RXERRC);
|
||||
if ((hw->phy.type == e1000_phy_82578) ||
|
||||
(hw->phy.type == e1000_phy_82577)) {
|
||||
e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
|
||||
if (!e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data))
|
||||
adapter->stats.tncrs += phy_data;
|
||||
} else {
|
||||
if ((hw->mac.type != e1000_82574) &&
|
||||
(hw->mac.type != e1000_82583))
|
||||
adapter->stats.tncrs += er32(TNCRS);
|
||||
}
|
||||
adapter->stats.cexterr += er32(CEXTERR);
|
||||
adapter->stats.tsctc += er32(TSCTC);
|
||||
adapter->stats.tsctfc += er32(TSCTFC);
|
||||
|
|
Loading…
Reference in a new issue