diff mbox series

Reduce e1000e boot time by tighteningsleep ranges

Message ID 8ef1b846-caf6-45de-33aa-a46406548167@molgen.mpg.de
State Changes Requested
Delegated to: Jeff Kirsher
Headers show
Series Reduce e1000e boot time by tighteningsleep ranges | expand

Commit Message

Paul Menzel May 17, 2019, 2:55 p.m. UTC
From 6ce17ba6e04802462425ee9d38084523fc1a7ab6 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Mon, 25 Jul 2016 06:44:34 -0500

The e1000e driver is a great user of the usleep_range() API,
and has nice ranges that in principle help power management.

However the ranges that are used only during system startup are
very long (and can add easily 100 msec to the boot time) while
the power savings of such long ranges is irrelevant due to the
one-off, boot only, nature of these functions.

This patch shrinks some of the longest ranges to be shorter
(while still using a power friendly 1 msec range); this saves
100msec+ of boot time on my BDW NUCs

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de>
---

This upstreams a patch carried by the Clear Linux project [1].

[1]: 
https://github.com/clearlinux-pkgs/linux/blob/master/0111-reduce-e1000e-boot-time-by-tightening-sleep-ranges.patch

  .../net/ethernet/intel/e1000e/80003es2lan.c   |  2 +-
  drivers/net/ethernet/intel/e1000e/82571.c     |  2 +-
  drivers/net/ethernet/intel/e1000e/ethtool.c   | 14 ++++++-------
  drivers/net/ethernet/intel/e1000e/ich8lan.c   | 20 +++++++++----------
  drivers/net/ethernet/intel/e1000e/mac.c       |  2 +-
  drivers/net/ethernet/intel/e1000e/netdev.c    | 14 ++++++-------
  drivers/net/ethernet/intel/e1000e/nvm.c       |  2 +-
  7 files changed, 28 insertions(+), 28 deletions(-)

Comments

Paul Menzel May 18, 2019, 4:56 p.m. UTC | #1
Dear Linux folks,


On 17.05.19 16:55, Paul Menzel wrote:
>  From 6ce17ba6e04802462425ee9d38084523fc1a7ab6 Mon Sep 17 00:00:00 2001
> From: Arjan van de Ven <arjan@linux.intel.com>
> Date: Mon, 25 Jul 2016 06:44:34 -0500
> 
> The e1000e driver is a great user of the usleep_range() API,
> and has nice ranges that in principle help power management.
> 
> However the ranges that are used only during system startup are
> very long (and can add easily 100 msec to the boot time) while
> the power savings of such long ranges is irrelevant due to the
> one-off, boot only, nature of these functions.
> 
> This patch shrinks some of the longest ranges to be shorter
> (while still using a power friendly 1 msec range); this saves
> 100msec+ of boot time on my BDW NUCs

On the Dell Latitude E7250 with Linux 5.0.1 from Debian experimental 
(without this patch), the module e1000e takes quite long too initialize.

> [   68.449925] calling  e1000_init_module+0x0/0x1000 [e1000e] @ 315
> [   68.449926] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
> [   68.449926] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
> [   68.449949] e1000e 0000:00:19.0: enabling device (0000 -> 0002)
> [   68.451074] e1000e 0000:00:19.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode
> [   68.767735] e1000e 0000:00:19.0 0000:00:19.0 (uninitialized): registered PHC clock
> [   68.864427] e1000e 0000:00:19.0 eth0: (PCI Express:2.5GT/s:Width x1) 34:e6:d7:6a:72:f4
> [   68.864429] e1000e 0000:00:19.0 eth0: Intel(R) PRO/1000 Network Connection
> [   68.864454] e1000e 0000:00:19.0 eth0: MAC: 11, PHY: 12, PBA No: FFFFFF-0FF
> [   68.864498] initcall e1000_init_module+0x0/0x1000 [e1000e] returned 0 after 40406 usecs
> [   68.868506] e1000e 0000:00:19.0 eno1: renamed from eth0
> [   73.932930] e1000e: eno1 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: Rx/Tx

I have no idea, why the `initcall_debug` time of 40.4 ms deviates from 
the Linux message time stamps (414 ms).


Kind regards,

Paul
Sasha Neftin May 20, 2019, 5:31 a.m. UTC | #2
On 5/17/2019 17:58, Paul Menzel wrote:
> Dear Jeff,
> 
> 
> Mozilla Thunderbird probably mangled the patch, so please find it attached.
> 
> 
> Kind regards,
> 
> Paul
> 
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
> 
The e1000e driver supports a pretty long list of 1G devices. We are 
afraid that initialization flow could be a break for some devices. 
Although this works on BDW,  we cannot confirm this for all other devices.
Arjan van de Ven May 20, 2019, 5:42 a.m. UTC | #3
On 5/19/2019 10:31 PM, Neftin, Sasha wrote:
> The e1000e driver supports a pretty long list of 1G devices. We are afraid that initialization flow could be a break for some devices. Although this works on BDW,  we 
> cannot confirm this for all other devices.

Hi

this is not a valid argument against this patch. The patch does not reduce the specified minimum delays, it only reduces the maximum delays.
If the minimum delays are not actually correct your drivers is already buggy since the kernel already does not guarantee that you get more than the minimum,
depending on what else is going on you are getting something arbitrary between minimum and maxium.

this patch  moves the maximum closer to the minimum reducing variability
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c 
b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index 257bd59bc9c6..94bce9823336 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -680,7 +680,7 @@  static s32 e1000_reset_hw_80003es2lan(struct 
e1000_hw *hw)
  	ew32(TCTL, E1000_TCTL_PSP);
  	e1e_flush();

-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	ctrl = er32(CTRL);

diff --git a/drivers/net/ethernet/intel/e1000e/82571.c 
b/drivers/net/ethernet/intel/e1000e/82571.c
index b9309302c29e..2c1bab377b2a 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -959,7 +959,7 @@  static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
  	ew32(TCTL, tctl);
  	e1e_flush();

-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	/* Must acquire the MDIO ownership before MAC reset.
  	 * Ownership defaults to firmware after a reset.
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c 
b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 02ebf208f48b..08342698386d 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -1014,7 +1014,7 @@  static int e1000_intr_test(struct e1000_adapter 
*adapter, u64 *data)
  	/* Disable all the interrupts */
  	ew32(IMC, 0xFFFFFFFF);
  	e1e_flush();
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	/* Test each interrupt */
  	for (i = 0; i < 10; i++) {
@@ -1046,7 +1046,7 @@  static int e1000_intr_test(struct e1000_adapter 
*adapter, u64 *data)
  			ew32(IMC, mask);
  			ew32(ICS, mask);
  			e1e_flush();
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);

  			if (adapter->test_icr & mask) {
  				*data = 3;
@@ -1064,7 +1064,7 @@  static int e1000_intr_test(struct e1000_adapter 
*adapter, u64 *data)
  		ew32(IMS, mask);
  		ew32(ICS, mask);
  		e1e_flush();
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);

  		if (!(adapter->test_icr & mask)) {
  			*data = 4;
@@ -1082,7 +1082,7 @@  static int e1000_intr_test(struct e1000_adapter 
*adapter, u64 *data)
  			ew32(IMC, ~mask & 0x00007FFF);
  			ew32(ICS, ~mask & 0x00007FFF);
  			e1e_flush();
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);

  			if (adapter->test_icr) {
  				*data = 5;
@@ -1094,7 +1094,7 @@  static int e1000_intr_test(struct e1000_adapter 
*adapter, u64 *data)
  	/* Disable all the interrupts */
  	ew32(IMC, 0xFFFFFFFF);
  	e1e_flush();
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	/* Unhook test interrupt handler */
  	free_irq(irq, netdev);
@@ -1470,7 +1470,7 @@  static int e1000_set_82571_fiber_loopback(struct 
e1000_adapter *adapter)
  	 */
  	ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK);
  	e1e_flush();
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	return 0;
  }
@@ -1584,7 +1584,7 @@  static void e1000_loopback_cleanup(struct 
e1000_adapter *adapter)
  		    hw->phy.media_type == e1000_media_type_internal_serdes) {
  			ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
  			e1e_flush();
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);
  			break;
  		}
  		/* Fall Through */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c 
b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index cdae0efde8e6..395b05701480 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -271,7 +271,7 @@  static void e1000_toggle_lanphypc_pch_lpt(struct 
e1000_hw *hw)
  		u16 count = 20;

  		do {
-			usleep_range(5000, 10000);
+			usleep_range(5000, 6000);
  		} while (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LPCD) && count--);

  		msleep(30);
@@ -405,7 +405,7 @@  static s32 e1000_init_phy_workarounds_pchlan(struct 
e1000_hw *hw)
  	/* Ungate automatic PHY configuration on non-managed 82579 */
  	if ((hw->mac.type == e1000_pch2lan) &&
  	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  		e1000_gate_hw_phy_config_ich8lan(hw, false);
  	}

@@ -531,7 +531,7 @@  static s32 e1000_init_phy_params_ich8lan(struct 
e1000_hw *hw)
  	phy->id = 0;
  	while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) &&
  	       (i++ < 100)) {
-		usleep_range(1000, 2000);
+		usleep_range(1000, 1100);
  		ret_val = e1000e_get_phy_id(hw);
  		if (ret_val)
  			return ret_val;
@@ -1244,7 +1244,7 @@  static s32 e1000_disable_ulp_lpt_lp(struct 
e1000_hw *hw, bool force)
  				goto out;
  			}

-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);
  		}
  		e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10);

@@ -1999,7 +1999,7 @@  static s32 e1000_check_reset_block_ich8lan(struct 
e1000_hw *hw)

  	while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) &&
  	       (i++ < 30))
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  	return blocked ? E1000_BLK_PHY_RESET : 0;
  }

@@ -2818,7 +2818,7 @@  static s32 e1000_post_phy_reset_ich8lan(struct 
e1000_hw *hw)
  		return 0;

  	/* Allow time for h/w to get to quiescent state after reset */
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	/* Perform any necessary post-reset workarounds */
  	switch (hw->mac.type) {
@@ -2854,7 +2854,7 @@  static s32 e1000_post_phy_reset_ich8lan(struct 
e1000_hw *hw)
  	if (hw->mac.type == e1000_pch2lan) {
  		/* Ungate automatic PHY configuration on non-managed 82579 */
  		if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);
  			e1000_gate_hw_phy_config_ich8lan(hw, false);
  		}

@@ -3875,7 +3875,7 @@  static s32 e1000_update_nvm_checksum_spt(struct 
e1000_hw *hw)
  	 */
  	if (!ret_val) {
  		nvm->ops.reload(hw);
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  	}

  out:
@@ -4026,7 +4026,7 @@  static s32 
e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
  	 */
  	if (!ret_val) {
  		nvm->ops.reload(hw);
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  	}

  out:
@@ -4650,7 +4650,7 @@  static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
  	ew32(TCTL, E1000_TCTL_PSP);
  	e1e_flush();

-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	/* Workaround for ICH8 bit corruption issue in FIFO memory */
  	if (hw->mac.type == e1000_ich8lan) {
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c 
b/drivers/net/ethernet/intel/e1000e/mac.c
index 4abd55d646c5..e531976f8a67 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -797,7 +797,7 @@  static s32 
e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
  	 * milliseconds even if the other end is doing it in SW).
  	 */
  	for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  		status = er32(STATUS);
  		if (status & E1000_STATUS_LU)
  			break;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c 
b/drivers/net/ethernet/intel/e1000e/netdev.c
index 189f231075c2..ce4aaa9f2163 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3208,7 +3208,7 @@  static void e1000_configure_rx(struct 
e1000_adapter *adapter)
  	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
  		ew32(RCTL, rctl & ~E1000_RCTL_EN);
  	e1e_flush();
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	if (adapter->flags2 & FLAG2_DMA_BURST) {
  		/* set the writeback threshold (only takes effect if the RDTR
@@ -4273,7 +4273,7 @@  void e1000e_down(struct e1000_adapter *adapter, 
bool reset)

  	/* flush both disables and wait for them to finish */
  	e1e_flush();
-	usleep_range(10000, 20000);
+	usleep_range(10000, 11000);

  	e1000_irq_disable(adapter);

@@ -4311,7 +4311,7 @@  void e1000e_reinit_locked(struct e1000_adapter 
*adapter)
  {
  	might_sleep();
  	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
+		usleep_range(1000, 1100);
  	e1000e_down(adapter, true);
  	e1000e_up(adapter);
  	clear_bit(__E1000_RESETTING, &adapter->state);
@@ -4708,7 +4708,7 @@  int e1000e_close(struct net_device *netdev)
  	int count = E1000_CHECK_RESET_COUNT;

  	while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);

  	WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));

@@ -6026,7 +6026,7 @@  static int e1000_change_mtu(struct net_device 
*netdev, int new_mtu)
  	}

  	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
+		usleep_range(1000, 1100);
  	/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */
  	adapter->max_frame_size = max_frame;
  	e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -6306,7 +6306,7 @@  static int e1000e_pm_freeze(struct device *dev)
  		int count = E1000_CHECK_RESET_COUNT;

  		while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);

  		WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));

@@ -6721,7 +6721,7 @@  static int e1000e_pm_runtime_suspend(struct device 
*dev)
  		int count = E1000_CHECK_RESET_COUNT;

  		while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
-			usleep_range(10000, 20000);
+			usleep_range(10000, 11000);

  		WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));

diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c 
b/drivers/net/ethernet/intel/e1000e/nvm.c
index 937f9af22d26..e609f4df86f4 100644
--- a/drivers/net/ethernet/intel/e1000e/nvm.c
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -392,7 +392,7 @@  s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 
offset, u16 words, u16 *data)
  				break;
  			}
  		}
-		usleep_range(10000, 20000);
+		usleep_range(10000, 11000);
  		nvm->ops.release(hw);
  	}