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