e1000e: fix test for PHY being accessible on 82577/8/9 and I217
Occasionally, the PHY can be initially inaccessible when the first read of a PHY register, e.g. PHY_ID1, happens (signified by the returned value 0xFFFF) but subsequent accesses of the PHY work as expected. Add a retry counter similar to how it is done in the generic e1000_get_phy_id(). Also, when the PHY is completely inaccessible (i.e. when subsequent reads of the PHY_IDx registers returns all F's) and the MDIO access mode must be set to slow before attempting to read the PHY ID again, the functions that do these latter two actions expect the SW/FW/HW semaphore is not already set so the semaphore must be released before and re-acquired after calling them otherwise there is an unnecessarily inordinate amount of delay during device initialization. Reported-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
d0efa8f23a
commit
a52359b56c
|
@ -325,24 +325,46 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
|
||||||
**/
|
**/
|
||||||
static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
|
static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
|
||||||
{
|
{
|
||||||
u16 phy_reg;
|
u16 phy_reg = 0;
|
||||||
u32 phy_id;
|
u32 phy_id = 0;
|
||||||
|
s32 ret_val;
|
||||||
|
u16 retry_count;
|
||||||
|
|
||||||
e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
|
for (retry_count = 0; retry_count < 2; retry_count++) {
|
||||||
phy_id = (u32)(phy_reg << 16);
|
ret_val = e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
|
||||||
e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
|
if (ret_val || (phy_reg == 0xFFFF))
|
||||||
phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
|
continue;
|
||||||
|
phy_id = (u32)(phy_reg << 16);
|
||||||
|
|
||||||
|
ret_val = e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
|
||||||
|
if (ret_val || (phy_reg == 0xFFFF)) {
|
||||||
|
phy_id = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (hw->phy.id) {
|
if (hw->phy.id) {
|
||||||
if (hw->phy.id == phy_id)
|
if (hw->phy.id == phy_id)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else if (phy_id) {
|
||||||
if ((phy_id != 0) && (phy_id != PHY_REVISION_MASK))
|
hw->phy.id = phy_id;
|
||||||
hw->phy.id = phy_id;
|
hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
/*
|
||||||
|
* In case the PHY needs to be in mdio slow mode,
|
||||||
|
* set slow mode and try to get the PHY id again.
|
||||||
|
*/
|
||||||
|
hw->phy.ops.release(hw);
|
||||||
|
ret_val = e1000_set_mdio_slow_mode_hv(hw);
|
||||||
|
if (!ret_val)
|
||||||
|
ret_val = e1000e_get_phy_id(hw);
|
||||||
|
hw->phy.ops.acquire(hw);
|
||||||
|
|
||||||
|
return !ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue