]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
e1000e: Fix possible HW unit hang after an s0ix exit
authorSasha Neftin <sasha.neftin@intel.com>
Tue, 25 Jan 2022 17:31:23 +0000 (19:31 +0200)
committerPaolo Pisati <paolo.pisati@canonical.com>
Wed, 9 Mar 2022 14:17:57 +0000 (15:17 +0100)
BugLink: https://bugs.launchpad.net/bugs/1964361
[ Upstream commit 1866aa0d0d6492bc2f8d22d0df49abaccf50cddd ]

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: 3e55d231716e ("e1000e: Add handshake with the CSME to support S0ix")
Suggested-by: Dima Ruinskiy <dima.ruinskiy@intel.com>
Suggested-by: Nir Efrati <nir.efrati@intel.com>
Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/e1000e/netdev.c

index bcf680e838113ddfd9d73a712fb94eac772ea343..13382df2f2eff4577128430ff55882a7434280d7 100644 (file)
@@ -630,6 +630,7 @@ struct e1000_phy_info {
        bool disable_polarity_correction;
        bool is_mdix;
        bool polarity_correction;
+       bool reset_disable;
        bool speed_downgraded;
        bool autoneg_wait_to_complete;
 };
index a3e42d06c63e707c09f801da1244c663b7cd0c47..d60e2016d03c6116062ca882b2d5142db26cebca 100644 (file)
@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
        bool blocked = false;
        int i = 0;
 
+       /* Check the PHY (LCD) reset flag */
+       if (hw->phy.reset_disable)
+               return true;
+
        while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) &&
               (i++ < 30))
                usleep_range(10000, 11000);
index 2504b11c3169fa6886403b163bb8705729ffda56..638a3ddd7ada8b3d9bae93e4c0c9e99527ef4cac 100644 (file)
 #define I217_CGFREG_ENABLE_MTA_RESET   0x0002
 #define I217_MEMPWR                    PHY_REG(772, 26)
 #define I217_MEMPWR_DISABLE_SMB_RELEASE        0x0010
+#define I217_MEMPWR_MOEM               0x1000
 
 /* Receive Address Initial CRC Calculation */
 #define E1000_PCH_RAICC(_n)    (0x05F50 + ((_n) * 4))
index af2029bb43e358f7338af01d314fe8100ad31a01..ce48e630fe55022ff730ffa57688b98765022858 100644 (file)
@@ -6992,8 +6992,21 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct pci_dev *pdev = to_pci_dev(dev);
+       struct e1000_hw *hw = &adapter->hw;
+       u16 phy_data;
        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_pm_freeze(dev);
@@ -7015,6 +7028,8 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct pci_dev *pdev = to_pci_dev(dev);
+       struct e1000_hw *hw = &adapter->hw;
+       u16 phy_data;
        int rc;
 
        /* Introduce S0ix implementation */
@@ -7025,6 +7040,17 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev)
        if (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);
 }