Commit 74f88c16 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2020-12-23

Commit e086ba2f ("e1000e: disable s0ix entry and exit flows for ME
systems") disabled S0ix flows for systems that have various incarnations of
the i219-LM ethernet controller.  This was done because of some regressions
caused by an earlier commit 632fbd5e ("e1000e: fix S0ix flows for
cable connected case") with i219-LM controller.

Per discussion with Intel architecture team this direction should be
changed and allow S0ix flows to be used by default.  This patch series
includes directional changes for their conclusions in
https://lkml.org/lkml/2020/12/13/15.

* '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue:
  e1000e: Export S0ix flags to ethtool
  Revert "e1000e: disable s0ix entry and exit flows for ME systems"
  e1000e: bump up timeout to wait when ME un-configures ULP mode
  e1000e: Only run S0ix flows if shutdown succeeded
====================

Link: https://lore.kernel.org/r/20201223233625.92519-1-anthony.l.nguyen@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e7579d5d 3c98cbf2
...@@ -436,6 +436,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca); ...@@ -436,6 +436,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca);
#define FLAG2_DFLT_CRC_STRIPPING BIT(12) #define FLAG2_DFLT_CRC_STRIPPING BIT(12)
#define FLAG2_CHECK_RX_HWTSTAMP BIT(13) #define FLAG2_CHECK_RX_HWTSTAMP BIT(13)
#define FLAG2_CHECK_SYSTIM_OVERFLOW BIT(14) #define FLAG2_CHECK_SYSTIM_OVERFLOW BIT(14)
#define FLAG2_ENABLE_S0IX_FLOWS BIT(15)
#define E1000_RX_DESC_PS(R, i) \ #define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
......
...@@ -23,6 +23,13 @@ struct e1000_stats { ...@@ -23,6 +23,13 @@ struct e1000_stats {
int stat_offset; int stat_offset;
}; };
static const char e1000e_priv_flags_strings[][ETH_GSTRING_LEN] = {
#define E1000E_PRIV_FLAGS_S0IX_ENABLED BIT(0)
"s0ix-enabled",
};
#define E1000E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(e1000e_priv_flags_strings)
#define E1000_STAT(str, m) { \ #define E1000_STAT(str, m) { \
.stat_string = str, \ .stat_string = str, \
.type = E1000_STATS, \ .type = E1000_STATS, \
...@@ -1776,6 +1783,8 @@ static int e1000e_get_sset_count(struct net_device __always_unused *netdev, ...@@ -1776,6 +1783,8 @@ static int e1000e_get_sset_count(struct net_device __always_unused *netdev,
return E1000_TEST_LEN; return E1000_TEST_LEN;
case ETH_SS_STATS: case ETH_SS_STATS:
return E1000_STATS_LEN; return E1000_STATS_LEN;
case ETH_SS_PRIV_FLAGS:
return E1000E_PRIV_FLAGS_STR_LEN;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -2097,6 +2106,10 @@ static void e1000_get_strings(struct net_device __always_unused *netdev, ...@@ -2097,6 +2106,10 @@ static void e1000_get_strings(struct net_device __always_unused *netdev,
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
break; break;
case ETH_SS_PRIV_FLAGS:
memcpy(data, e1000e_priv_flags_strings,
E1000E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
break;
} }
} }
...@@ -2305,6 +2318,37 @@ static int e1000e_get_ts_info(struct net_device *netdev, ...@@ -2305,6 +2318,37 @@ static int e1000e_get_ts_info(struct net_device *netdev,
return 0; return 0;
} }
static u32 e1000e_get_priv_flags(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
u32 priv_flags = 0;
if (adapter->flags2 & FLAG2_ENABLE_S0IX_FLOWS)
priv_flags |= E1000E_PRIV_FLAGS_S0IX_ENABLED;
return priv_flags;
}
static int e1000e_set_priv_flags(struct net_device *netdev, u32 priv_flags)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
unsigned int flags2 = adapter->flags2;
flags2 &= ~FLAG2_ENABLE_S0IX_FLOWS;
if (priv_flags & E1000E_PRIV_FLAGS_S0IX_ENABLED) {
struct e1000_hw *hw = &adapter->hw;
if (hw->mac.type < e1000_pch_cnp)
return -EINVAL;
flags2 |= FLAG2_ENABLE_S0IX_FLOWS;
}
if (flags2 != adapter->flags2)
adapter->flags2 = flags2;
return 0;
}
static const struct ethtool_ops e1000_ethtool_ops = { static const struct ethtool_ops e1000_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS, .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS,
.get_drvinfo = e1000_get_drvinfo, .get_drvinfo = e1000_get_drvinfo,
...@@ -2336,6 +2380,8 @@ static const struct ethtool_ops e1000_ethtool_ops = { ...@@ -2336,6 +2380,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.set_eee = e1000e_set_eee, .set_eee = e1000e_set_eee,
.get_link_ksettings = e1000_get_link_ksettings, .get_link_ksettings = e1000_get_link_ksettings,
.set_link_ksettings = e1000_set_link_ksettings, .set_link_ksettings = e1000_set_link_ksettings,
.get_priv_flags = e1000e_get_priv_flags,
.set_priv_flags = e1000e_set_priv_flags,
}; };
void e1000e_set_ethtool_ops(struct net_device *netdev) void e1000e_set_ethtool_ops(struct net_device *netdev)
......
...@@ -1240,6 +1240,9 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) ...@@ -1240,6 +1240,9 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
return 0; return 0;
if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) {
struct e1000_adapter *adapter = hw->adapter;
bool firmware_bug = false;
if (force) { if (force) {
/* Request ME un-configure ULP mode in the PHY */ /* Request ME un-configure ULP mode in the PHY */
mac_reg = er32(H2ME); mac_reg = er32(H2ME);
...@@ -1248,15 +1251,23 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) ...@@ -1248,15 +1251,23 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
ew32(H2ME, mac_reg); ew32(H2ME, mac_reg);
} }
/* Poll up to 300msec for ME to clear ULP_CFG_DONE. */ /* Poll up to 2.5 seconds for ME to clear ULP_CFG_DONE.
* If this takes more than 1 second, show a warning indicating a
* firmware bug
*/
while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) { while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) {
if (i++ == 30) { if (i++ == 250) {
ret_val = -E1000_ERR_PHY; ret_val = -E1000_ERR_PHY;
goto out; goto out;
} }
if (i > 100 && !firmware_bug)
firmware_bug = true;
usleep_range(10000, 11000); usleep_range(10000, 11000);
} }
if (firmware_bug)
e_warn("ULP_CONFIG_DONE took %dmsec. This is a firmware bug\n", i * 10);
else
e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10); e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10);
if (force) { if (force) {
......
...@@ -103,45 +103,6 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { ...@@ -103,45 +103,6 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
{0, NULL} {0, NULL}
}; };
struct e1000e_me_supported {
u16 device_id; /* supported device ID */
};
static const struct e1000e_me_supported me_supported[] = {
{E1000_DEV_ID_PCH_LPT_I217_LM},
{E1000_DEV_ID_PCH_LPTLP_I218_LM},
{E1000_DEV_ID_PCH_I218_LM2},
{E1000_DEV_ID_PCH_I218_LM3},
{E1000_DEV_ID_PCH_SPT_I219_LM},
{E1000_DEV_ID_PCH_SPT_I219_LM2},
{E1000_DEV_ID_PCH_LBG_I219_LM3},
{E1000_DEV_ID_PCH_SPT_I219_LM4},
{E1000_DEV_ID_PCH_SPT_I219_LM5},
{E1000_DEV_ID_PCH_CNP_I219_LM6},
{E1000_DEV_ID_PCH_CNP_I219_LM7},
{E1000_DEV_ID_PCH_ICP_I219_LM8},
{E1000_DEV_ID_PCH_ICP_I219_LM9},
{E1000_DEV_ID_PCH_CMP_I219_LM10},
{E1000_DEV_ID_PCH_CMP_I219_LM11},
{E1000_DEV_ID_PCH_CMP_I219_LM12},
{E1000_DEV_ID_PCH_TGP_I219_LM13},
{E1000_DEV_ID_PCH_TGP_I219_LM14},
{E1000_DEV_ID_PCH_TGP_I219_LM15},
{0}
};
static bool e1000e_check_me(u16 device_id)
{
struct e1000e_me_supported *id;
for (id = (struct e1000e_me_supported *)me_supported;
id->device_id; id++)
if (device_id == id->device_id)
return true;
return false;
}
/** /**
* __ew32_prepare - prepare to write to MAC CSR register on certain parts * __ew32_prepare - prepare to write to MAC CSR register on certain parts
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -6962,7 +6923,6 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev) ...@@ -6962,7 +6923,6 @@ 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;
int rc; int rc;
e1000e_flush_lpic(pdev); e1000e_flush_lpic(pdev);
...@@ -6970,13 +6930,13 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev) ...@@ -6970,13 +6930,13 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
e1000e_pm_freeze(dev); e1000e_pm_freeze(dev);
rc = __e1000_shutdown(pdev, false); rc = __e1000_shutdown(pdev, false);
if (rc) if (rc) {
e1000e_pm_thaw(dev); e1000e_pm_thaw(dev);
} else {
/* Introduce S0ix implementation */ /* Introduce S0ix implementation */
if (hw->mac.type >= e1000_pch_cnp && if (adapter->flags2 & FLAG2_ENABLE_S0IX_FLOWS)
!e1000e_check_me(hw->adapter->pdev->device))
e1000e_s0ix_entry_flow(adapter); e1000e_s0ix_entry_flow(adapter);
}
return rc; return rc;
} }
...@@ -6986,12 +6946,10 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev) ...@@ -6986,12 +6946,10 @@ 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;
int rc; int rc;
/* Introduce S0ix implementation */ /* Introduce S0ix implementation */
if (hw->mac.type >= e1000_pch_cnp && if (adapter->flags2 & FLAG2_ENABLE_S0IX_FLOWS)
!e1000e_check_me(hw->adapter->pdev->device))
e1000e_s0ix_exit_flow(adapter); e1000e_s0ix_exit_flow(adapter);
rc = __e1000_resume(pdev); rc = __e1000_resume(pdev);
...@@ -7655,6 +7613,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -7655,6 +7613,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!(adapter->flags & FLAG_HAS_AMT)) if (!(adapter->flags & FLAG_HAS_AMT))
e1000e_get_hw_control(adapter); e1000e_get_hw_control(adapter);
if (hw->mac.type >= e1000_pch_cnp)
adapter->flags2 |= FLAG2_ENABLE_S0IX_FLOWS;
strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); strlcpy(netdev->name, "eth%d", sizeof(netdev->name));
err = register_netdev(netdev); err = register_netdev(netdev);
if (err) if (err)
......
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