ACK/Cmnt: [E/OEM-OSP1-B] [PATCH] e1000e: Add support for S0ix
Stefan Bader
stefan.bader at canonical.com
Thu Jan 16 13:55:42 UTC 2020
On 10.01.20 06:44, Kai-Heng Feng wrote:
> From: Sasha Neftin <sasha.neftin at intel.com>
>
> BugLink: https://bugs.launchpad.net/bugs/1859126
>
> Implement flow for S0ix support. Modern SoCs support S0ix low power
> states during idle periods, which are sub-states of ACPI S0 that increase
> power saving while supporting an instant-on experience for providing
> lower latency that ACPI S0. The S0ix states shut off parts of the SoC
> when they are not in use, while still maintaning optimal performance.
> This patch add support for S0ix started from an Ice Lake platform.
>
> Suggested-by: "Rafael J. Wysocki" <rafael.j.wysocki at intel.com>
> Signed-off-by: Vitaly Lifshits <vitaly.lifshits at intel.com>
> Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj at linux.intel.com>
> Signed-off-by: Sasha Neftin <sasha.neftin at intel.com>
> Tested-by: Aaron Brown <aaron.f.brown at intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
> (backported from commit f15bb6dde738cc8fa00c24fb89b5456ea3342879)
> Signed-off-by: Kai-Heng Feng <kai.heng.feng at canonical.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---
The additional code is rather extensive but hopefully limited to only the subset
of NICs which support this. Also please try to have the bug report tasks in a
sensible state. "Incomplete" does not sound like its ready.
-Stefan
> drivers/net/ethernet/intel/e1000e/netdev.c | 182 +++++++++++++++++++++
> drivers/net/ethernet/intel/e1000e/regs.h | 4 +
> 2 files changed, 186 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
> index 17aef6c95b2f..4259162b293e 100644
> --- a/drivers/net/ethernet/intel/e1000e/netdev.c
> +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
> @@ -6295,6 +6295,174 @@ static void e1000e_flush_lpic(struct pci_dev *pdev)
> pm_runtime_put_sync(netdev->dev.parent);
> }
>
> +/* S0ix implementation */
> +static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
> +{
> + struct e1000_hw *hw = &adapter->hw;
> + u32 mac_data;
> + u16 phy_data;
> +
> + /* Disable the periodic inband message,
> + * don't request PCIe clock in K1 page770_17[10:9] = 10b
> + */
> + e1e_rphy(hw, HV_PM_CTRL, &phy_data);
> + phy_data &= ~HV_PM_CTRL_K1_CLK_REQ;
> + phy_data |= BIT(10);
> + e1e_wphy(hw, HV_PM_CTRL, phy_data);
> +
> + /* Make sure we don't exit K1 every time a new packet arrives
> + * 772_29[5] = 1 CS_Mode_Stay_In_K1
> + */
> + e1e_rphy(hw, I217_CGFREG, &phy_data);
> + phy_data |= BIT(5);
> + e1e_wphy(hw, I217_CGFREG, phy_data);
> +
> + /* Change the MAC/PHY interface to SMBus
> + * Force the SMBus in PHY page769_23[0] = 1
> + * Force the SMBus in MAC CTRL_EXT[11] = 1
> + */
> + e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
> + phy_data |= CV_SMB_CTRL_FORCE_SMBUS;
> + e1e_wphy(hw, CV_SMB_CTRL, phy_data);
> + mac_data = er32(CTRL_EXT);
> + mac_data |= E1000_CTRL_EXT_FORCE_SMBUS;
> + ew32(CTRL_EXT, mac_data);
> +
> + /* DFT control: PHY bit: page769_20[0] = 1
> + * Gate PPW via EXTCNF_CTRL - set 0x0F00[7] = 1
> + */
> + e1e_rphy(hw, I82579_DFT_CTRL, &phy_data);
> + phy_data |= BIT(0);
> + e1e_wphy(hw, I82579_DFT_CTRL, phy_data);
> +
> + mac_data = er32(EXTCNF_CTRL);
> + mac_data |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
> + ew32(EXTCNF_CTRL, mac_data);
> +
> + /* Check MAC Tx/Rx packet buffer pointers.
> + * Reset MAC Tx/Rx packet buffer pointers to suppress any
> + * pending traffic indication that would prevent power gating.
> + */
> + mac_data = er32(TDFH);
> + if (mac_data)
> + ew32(TDFH, 0);
> + mac_data = er32(TDFT);
> + if (mac_data)
> + ew32(TDFT, 0);
> + mac_data = er32(TDFHS);
> + if (mac_data)
> + ew32(TDFHS, 0);
> + mac_data = er32(TDFTS);
> + if (mac_data)
> + ew32(TDFTS, 0);
> + mac_data = er32(TDFPC);
> + if (mac_data)
> + ew32(TDFPC, 0);
> + mac_data = er32(RDFH);
> + if (mac_data)
> + ew32(RDFH, 0);
> + mac_data = er32(RDFT);
> + if (mac_data)
> + ew32(RDFT, 0);
> + mac_data = er32(RDFHS);
> + if (mac_data)
> + ew32(RDFHS, 0);
> + mac_data = er32(RDFTS);
> + if (mac_data)
> + ew32(RDFTS, 0);
> + mac_data = er32(RDFPC);
> + if (mac_data)
> + ew32(RDFPC, 0);
> +
> + /* Enable the Dynamic Power Gating in the MAC */
> + mac_data = er32(FEXTNVM7);
> + mac_data |= BIT(22);
> + ew32(FEXTNVM7, mac_data);
> +
> + /* Disable the time synchronization clock */
> + mac_data = er32(FEXTNVM7);
> + mac_data |= BIT(31);
> + mac_data &= ~BIT(0);
> + ew32(FEXTNVM7, mac_data);
> +
> + /* Dynamic Power Gating Enable */
> + mac_data = er32(CTRL_EXT);
> + mac_data |= BIT(3);
> + ew32(CTRL_EXT, mac_data);
> +
> + /* Enable the Dynamic Clock Gating in the DMA and MAC */
> + mac_data = er32(CTRL_EXT);
> + mac_data |= E1000_CTRL_EXT_DMA_DYN_CLK_EN;
> + ew32(CTRL_EXT, mac_data);
> +
> + /* No MAC DPG gating SLP_S0 in modern standby
> + * Switch the logic of the lanphypc to use PMC counter
> + */
> + mac_data = er32(FEXTNVM5);
> + mac_data |= BIT(7);
> + ew32(FEXTNVM5, mac_data);
> +}
> +
> +static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
> +{
> + struct e1000_hw *hw = &adapter->hw;
> + u32 mac_data;
> + u16 phy_data;
> +
> + /* Disable the Dynamic Power Gating in the MAC */
> + mac_data = er32(FEXTNVM7);
> + mac_data &= 0xFFBFFFFF;
> + ew32(FEXTNVM7, mac_data);
> +
> + /* Enable the time synchronization clock */
> + mac_data = er32(FEXTNVM7);
> + mac_data |= BIT(0);
> + ew32(FEXTNVM7, mac_data);
> +
> + /* Disable Dynamic Power Gating */
> + mac_data = er32(CTRL_EXT);
> + mac_data &= 0xFFFFFFF7;
> + ew32(CTRL_EXT, mac_data);
> +
> + /* Disable the Dynamic Clock Gating in the DMA and MAC */
> + mac_data = er32(CTRL_EXT);
> + mac_data &= 0xFFF7FFFF;
> + ew32(CTRL_EXT, mac_data);
> +
> + /* Revert the lanphypc logic to use the internal Gbe counter
> + * and not the PMC counter
> + */
> + mac_data = er32(FEXTNVM5);
> + mac_data &= 0xFFFFFF7F;
> + ew32(FEXTNVM5, mac_data);
> +
> + /* Enable the periodic inband message,
> + * Request PCIe clock in K1 page770_17[10:9] =01b
> + */
> + e1e_rphy(hw, HV_PM_CTRL, &phy_data);
> + phy_data &= 0xFBFF;
> + phy_data |= HV_PM_CTRL_K1_CLK_REQ;
> + e1e_wphy(hw, HV_PM_CTRL, phy_data);
> +
> + /* Return back configuration
> + * 772_29[5] = 0 CS_Mode_Stay_In_K1
> + */
> + e1e_rphy(hw, I217_CGFREG, &phy_data);
> + phy_data &= 0xFFDF;
> + e1e_wphy(hw, I217_CGFREG, phy_data);
> +
> + /* Change the MAC/PHY interface to Kumeran
> + * Unforce the SMBus in PHY page769_23[0] = 0
> + * Unforce the SMBus in MAC CTRL_EXT[11] = 0
> + */
> + e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
> + phy_data &= ~CV_SMB_CTRL_FORCE_SMBUS;
> + e1e_wphy(hw, CV_SMB_CTRL, phy_data);
> + mac_data = er32(CTRL_EXT);
> + mac_data &= ~E1000_CTRL_EXT_FORCE_SMBUS;
> + ew32(CTRL_EXT, mac_data);
> +}
> +
> static int e1000e_pm_freeze(struct device *dev)
> {
> struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
> @@ -6650,7 +6818,10 @@ static int e1000e_pm_thaw(struct device *dev)
>
> static 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;
> int rc;
>
> e1000e_flush_lpic(pdev);
> @@ -6661,14 +6832,25 @@ static int e1000e_pm_suspend(struct device *dev)
> if (rc)
> e1000e_pm_thaw(dev);
>
> + /* Introduce S0ix implementation */
> + if (hw->mac.type >= e1000_pch_cnp)
> + e1000e_s0ix_entry_flow(adapter);
> +
> return rc;
> }
>
> static 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;
> int rc;
>
> + /* Introduce S0ix implementation */
> + if (hw->mac.type >= e1000_pch_cnp)
> + e1000e_s0ix_exit_flow(adapter);
> +
> rc = __e1000_resume(pdev);
> if (rc)
> return rc;
> diff --git a/drivers/net/ethernet/intel/e1000e/regs.h b/drivers/net/ethernet/intel/e1000e/regs.h
> index 47f5ca793970..df59fd1d660c 100644
> --- a/drivers/net/ethernet/intel/e1000e/regs.h
> +++ b/drivers/net/ethernet/intel/e1000e/regs.h
> @@ -18,6 +18,7 @@
> #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
> #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */
> #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
> +#define E1000_FEXTNVM5 0x00014 /* Future Extended NVM 5 - RW */
> #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
> #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
> #define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */
> @@ -234,4 +235,7 @@
> #define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
> #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
>
> +/* PHY registers */
> +#define I82579_DFT_CTRL PHY_REG(769, 20)
> +
> #endif
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20200116/554f1029/attachment.sig>
More information about the kernel-team
mailing list