Commit 1866aa0d authored by Sasha Neftin's avatar Sasha Neftin Committed by Tony Nguyen

e1000e: Fix possible HW unit hang after an s0ix exit

Disable the OEM bit/Gig Disable/restart AN impact and disable the PHY
LAN connected device (LCD) reset during power management flows. This
fixes possible HW unit hangs on the s0ix exit on some corporate ADL
platforms.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=214821
Fixes: 3e55d231 ("e1000e: Add handshake with the CSME to support S0ix")
Suggested-by: default avatarDima Ruinskiy <dima.ruinskiy@intel.com>
Suggested-by: default avatarNir Efrati <nir.efrati@intel.com>
Signed-off-by: default avatarSasha Neftin <sasha.neftin@intel.com>
Tested-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent c4208653
...@@ -630,6 +630,7 @@ struct e1000_phy_info { ...@@ -630,6 +630,7 @@ struct e1000_phy_info {
bool disable_polarity_correction; bool disable_polarity_correction;
bool is_mdix; bool is_mdix;
bool polarity_correction; bool polarity_correction;
bool reset_disable;
bool speed_downgraded; bool speed_downgraded;
bool autoneg_wait_to_complete; bool autoneg_wait_to_complete;
}; };
......
...@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) ...@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
bool blocked = false; bool blocked = false;
int i = 0; int i = 0;
/* Check the PHY (LCD) reset flag */
if (hw->phy.reset_disable)
return true;
while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) && while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) &&
(i++ < 30)) (i++ < 30))
usleep_range(10000, 11000); usleep_range(10000, 11000);
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 #define I217_CGFREG_ENABLE_MTA_RESET 0x0002
#define I217_MEMPWR PHY_REG(772, 26) #define I217_MEMPWR PHY_REG(772, 26)
#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 #define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010
#define I217_MEMPWR_MOEM 0x1000
/* Receive Address Initial CRC Calculation */ /* Receive Address Initial CRC Calculation */
#define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) #define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4))
......
...@@ -6987,8 +6987,21 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev) ...@@ -6987,8 +6987,21 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct e1000_hw *hw = &adapter->hw;
u16 phy_data;
int rc; int rc;
if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID &&
hw->mac.type >= e1000_pch_adp) {
/* Mask OEM Bits / Gig Disable / Restart AN (772_26[12] = 1) */
e1e_rphy(hw, I217_MEMPWR, &phy_data);
phy_data |= I217_MEMPWR_MOEM;
e1e_wphy(hw, I217_MEMPWR, phy_data);
/* Disable LCD reset */
hw->phy.reset_disable = true;
}
e1000e_flush_lpic(pdev); e1000e_flush_lpic(pdev);
e1000e_pm_freeze(dev); e1000e_pm_freeze(dev);
...@@ -7010,6 +7023,8 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev) ...@@ -7010,6 +7023,8 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct e1000_hw *hw = &adapter->hw;
u16 phy_data;
int rc; int rc;
/* Introduce S0ix implementation */ /* Introduce S0ix implementation */
...@@ -7020,6 +7035,17 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev) ...@@ -7020,6 +7035,17 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
if (rc) if (rc)
return rc; return rc;
if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID &&
hw->mac.type >= e1000_pch_adp) {
/* Unmask OEM Bits / Gig Disable / Restart AN 772_26[12] = 0 */
e1e_rphy(hw, I217_MEMPWR, &phy_data);
phy_data &= ~I217_MEMPWR_MOEM;
e1e_wphy(hw, I217_MEMPWR, phy_data);
/* Enable LCD reset */
hw->phy.reset_disable = false;
}
return e1000e_pm_thaw(dev); return e1000e_pm_thaw(dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment