git: 37bfb1c96596 - stable/13 - igc: Use hardware routine for PHY reset

From: Peter Grehan <grehan_at_FreeBSD.org>
Date: Fri, 12 Nov 2021 22:43:21 UTC
The branch stable/13 has been updated by grehan:

URL: https://cgit.FreeBSD.org/src/commit/?id=37bfb1c96596f0801e33a497f7f15d07a02e1a09

commit 37bfb1c96596f0801e33a497f7f15d07a02e1a09
Author:     Peter Grehan <grehan@FreeBSD.org>
AuthorDate: 2021-11-01 13:35:43 +0000
Commit:     Peter Grehan <grehan@FreeBSD.org>
CommitDate: 2021-11-12 20:45:41 +0000

    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)
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    
    (cherry picked from commit 561cd74b1704ab76a3286733fb43da53b6892ea4)
---
 sys/dev/igc/igc_api.c  | 15 ---------------
 sys/dev/igc/igc_api.h  |  1 -
 sys/dev/igc/igc_hw.h   |  1 -
 sys/dev/igc/igc_i225.c | 11 +++--------
 sys/dev/igc/igc_phy.c  | 37 ++-----------------------------------
 sys/dev/igc/igc_phy.h  |  1 -
 6 files changed, 5 insertions(+), 61 deletions(-)

diff --git a/sys/dev/igc/igc_api.c b/sys/dev/igc/igc_api.c
index cad116c2395d..6aafc9898df8 100644
--- a/sys/dev/igc/igc_api.c
+++ b/sys/dev/igc/igc_api.c
@@ -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
diff --git a/sys/dev/igc/igc_api.h b/sys/dev/igc/igc_api.h
index a0fc9ff21166..f9064b540c7c 100644
--- a/sys/dev/igc/igc_api.h
+++ b/sys/dev/igc/igc_api.h
@@ -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);
diff --git a/sys/dev/igc/igc_hw.h b/sys/dev/igc/igc_hw.h
index a07d2894f97a..a8323a8578a9 100644
--- a/sys/dev/igc/igc_hw.h
+++ b/sys/dev/igc/igc_hw.h
@@ -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);
diff --git a/sys/dev/igc/igc_i225.c b/sys/dev/igc/igc_i225.c
index 75c4b5125a97..4c50daa16b79 100644
--- a/sys/dev/igc/igc_i225.c
+++ b/sys/dev/igc/igc_i225.c
@@ -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) {
diff --git a/sys/dev/igc/igc_phy.c b/sys/dev/igc/igc_phy.c
index a1d71ab15829..a6823ddf7bac 100644
--- a/sys/dev/igc/igc_phy.c
+++ b/sys/dev/igc/igc_phy.c
@@ -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
diff --git a/sys/dev/igc/igc_phy.h b/sys/dev/igc/igc_phy.h
index 61cc46cdc583..36fa0677c3e6 100644
--- a/sys/dev/igc/igc_phy.h
+++ b/sys/dev/igc/igc_phy.h
@@ -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);