igc: Use hardware routine for PHY reset

Summary:
The previously used software reset routine wasn't sufficient
to reset the PHY if the	bootloader hadn't left the device in
an initialized state. This was seen with the onboard igc port
on an 11th-gen Intel NUC.

The software reset isn't used in the Linux driver so all related
code has been removed.

Tested on: Netgate 6100 onboard ports, a discrete PCIe I225-LM card,
and an 11th-gen Intel NUC.

Reported by:	woodsb02
Tested by:	woodsb02 (NUC)
MFC after:	3 days
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Reviewed by:	kbowling
Differential Revision: https://reviews.freebsd.org/D32772
This commit is contained in:
Peter Grehan 2021-11-01 23:35:43 +10:00
parent 6e0755b37b
commit 561cd74b17
6 changed files with 5 additions and 61 deletions

View File

@ -535,21 +535,6 @@ s32 igc_phy_hw_reset(struct igc_hw *hw)
return IGC_SUCCESS;
}
/**
* igc_phy_commit - Soft PHY reset
* @hw: pointer to the HW structure
*
* Performs a soft PHY reset on those that apply. This is a function pointer
* entry point called by drivers.
**/
s32 igc_phy_commit(struct igc_hw *hw)
{
if (hw->phy.ops.commit)
return hw->phy.ops.commit(hw);
return IGC_SUCCESS;
}
/**
* igc_set_d0_lplu_state - Sets low power link up state for D0
* @hw: pointer to the HW structure

View File

@ -42,7 +42,6 @@ s32 igc_get_phy_info(struct igc_hw *hw);
void igc_release_phy(struct igc_hw *hw);
s32 igc_acquire_phy(struct igc_hw *hw);
s32 igc_phy_hw_reset(struct igc_hw *hw);
s32 igc_phy_commit(struct igc_hw *hw);
void igc_power_up_phy(struct igc_hw *hw);
void igc_power_down_phy(struct igc_hw *hw);
s32 igc_read_mac_addr(struct igc_hw *hw);

View File

@ -382,7 +382,6 @@ struct igc_phy_operations {
s32 (*init_params)(struct igc_hw *);
s32 (*acquire)(struct igc_hw *);
s32 (*check_reset_block)(struct igc_hw *);
s32 (*commit)(struct igc_hw *);
s32 (*force_speed_duplex)(struct igc_hw *);
s32 (*get_info)(struct igc_hw *);
s32 (*set_page)(struct igc_hw *, u16);

View File

@ -136,7 +136,6 @@ static s32 igc_init_phy_params_i225(struct igc_hw *hw)
{
struct igc_phy_info *phy = &hw->phy;
s32 ret_val = IGC_SUCCESS;
u32 ctrl_ext;
DEBUGFUNC("igc_init_phy_params_i225");
@ -155,10 +154,10 @@ static s32 igc_init_phy_params_i225(struct igc_hw *hw)
phy->ops.acquire = igc_acquire_phy_base;
phy->ops.check_reset_block = igc_check_reset_block_generic;
phy->ops.commit = igc_phy_sw_reset_generic;
phy->ops.release = igc_release_phy_base;
ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
phy->ops.reset = igc_phy_hw_reset_generic;
phy->ops.read_reg = igc_read_phy_reg_gpy;
phy->ops.write_reg = igc_write_phy_reg_gpy;
/* Make sure the PHY is in a good state. Several people have reported
* firmware leaving the PHY's page select register set to something
@ -169,10 +168,6 @@ static s32 igc_init_phy_params_i225(struct igc_hw *hw)
if (ret_val)
goto out;
IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
phy->ops.read_reg = igc_read_phy_reg_gpy;
phy->ops.write_reg = igc_write_phy_reg_gpy;
ret_val = igc_get_phy_id(hw);
/* Verify phy id and set remaining function pointers */
switch (phy->id) {

View File

@ -26,7 +26,6 @@ void igc_init_phy_ops_generic(struct igc_hw *hw)
phy->ops.init_params = igc_null_ops_generic;
phy->ops.acquire = igc_null_ops_generic;
phy->ops.check_reset_block = igc_null_ops_generic;
phy->ops.commit = igc_null_ops_generic;
phy->ops.force_speed_duplex = igc_null_ops_generic;
phy->ops.get_info = igc_null_ops_generic;
phy->ops.set_page = igc_null_set_page;
@ -147,7 +146,7 @@ s32 igc_get_phy_id(struct igc_hw *hw)
return ret_val;
phy->id = (u32)(phy_id << 16);
usec_delay(20);
usec_delay(200);
ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
if (ret_val)
return ret_val;
@ -155,7 +154,6 @@ s32 igc_get_phy_id(struct igc_hw *hw)
phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
return IGC_SUCCESS;
}
@ -314,7 +312,7 @@ static s32 igc_phy_setup_autoneg(struct igc_hw *hw)
if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
hw->phy.id == I225_I_PHY_ID) {
/* Read the MULTI GBT AN Control Register - reg 7.32 */
/* Read the MULTI GBT AN Control Register - reg 7.32 */
ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
MMD_DEVADDR_SHIFT) |
ANEG_MULTIGBT_AN_CTRL,
@ -847,37 +845,6 @@ s32 igc_phy_has_link_generic(struct igc_hw *hw, u32 iterations,
return ret_val;
}
/**
* igc_phy_sw_reset_generic - PHY software reset
* @hw: pointer to the HW structure
*
* Does a software reset of the PHY by reading the PHY control register and
* setting/write the control register reset bit to the PHY.
**/
s32 igc_phy_sw_reset_generic(struct igc_hw *hw)
{
s32 ret_val;
u16 phy_ctrl;
DEBUGFUNC("igc_phy_sw_reset_generic");
if (!hw->phy.ops.read_reg)
return IGC_SUCCESS;
ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
if (ret_val)
return ret_val;
phy_ctrl |= MII_CR_RESET;
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
if (ret_val)
return ret_val;
usec_delay(1);
return ret_val;
}
/**
* igc_phy_hw_reset_generic - PHY hardware reset
* @hw: pointer to the HW structure

View File

@ -18,7 +18,6 @@ s32 igc_null_set_page(struct igc_hw *hw, u16 data);
s32 igc_check_downshift_generic(struct igc_hw *hw);
s32 igc_check_reset_block_generic(struct igc_hw *hw);
s32 igc_get_phy_id(struct igc_hw *hw);
s32 igc_phy_sw_reset_generic(struct igc_hw *hw);
void igc_phy_force_speed_duplex_setup(struct igc_hw *hw, u16 *phy_ctrl);
s32 igc_phy_hw_reset_generic(struct igc_hw *hw);
s32 igc_phy_reset_dsp_generic(struct igc_hw *hw);