Skip to contentSkip to conversation

Put the NIC in runtime suspended during s2ram

PATCH In review Chen Yu 2 participants 5 messages Dec 1, 2020 – Dec 2, 2020

Subsystems (3)
lore
Share & tools
lore

Chen Yu

author
#0 lore raw

v3 cover Put the NIC in runtime suspended during s2ram

The NIC is put in runtime suspend status when there is no cable connected. As a result, it is safe to keep non-wakeup NIC in runtime suspended during s2ram because the system does not rely on the NIC plug event nor WoL to wake up the system. Besides that, unlike the s2idle, s2ram does not need to manipulate S0ix settings during suspend.

Chen Yu (2):
e1000e: Leverage direct_complete to speed up s2ram
e1000e: Remove the runtime suspend restriction on CNP+

 drivers/net/ethernet/intel/e1000e/netdev.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
Signature · 1 line
2.17.1
author
#1 lore raw

PATCH v3 1/2 e1000e: Leverage direct_complete to speed up s2ram

The NIC is put in runtime suspend status when there is no cable connected. As a result, it is safe to keep non-wakeup NIC in runtime suspended during s2ram because the system does not rely on the NIC plug event nor WoL to wake up the system. Besides that, unlike the s2idle, s2ram does not need to manipulate S0ix settings during suspend.

This patch introduces the .prepare() for e1000e so that if the NIC is runtime suspended the subsequent suspend/resume hooks will be skipped so as to speed up the s2ram. The pm core will check whether the NIC is a wake up device so there's no need to check it again in .prepare(). DPM_FLAG_SMART_PREPARE flag should be set during probe to ask the pci subsystem to honor the driver's prepare() result. Besides, the NIC remains runtime suspended after resumed from s2ram as there is no need to resume it.

Tested on i7-2600K with 82579V NIC
Before the patch:
e1000e 0000:00:19.0: pci_pm_suspend+0x0/0x160 returned 0 after 225146 usecs e1000e 0000:00:19.0: pci_pm_resume+0x0/0x90 returned 0 after 140588 usecs

After the patch:
echo disabled > //sys/devices/pci0000\:00/0000\:00\:19.0/power/wakeup becomes 0 usecs because the hooks will be skipped.

---
v2: Added test data and some commit log revise(Paul Menzel)
Only skip the suspend/resume if the NIC is not a wake up device specified by the user(Kai-Heng Feng)
v3: Leverage direct complete mechanism to skip all hooks(Kai-Heng Feng)

---
 drivers/net/ethernet/intel/e1000e/netdev.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000e/netdev.c +9 -1
index b30f00891c03..b210bba3f20a 100644
@@ -25,6 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/aer.h>
 #include <linux/prefetch.h>
+#include <linux/suspend.h>
 
 #include "e1000.h"
 
@@ -6957,6 +6958,12 @@ static int __e1000_resume(struct pci_dev *pdev)
 	return 0;
 }
 
+static int e1000e_pm_prepare(struct device *dev)
+{
+	return pm_runtime_suspended(dev) &&
+		pm_suspend_via_firmware();
+}
+
 static __maybe_unused int e1000e_pm_suspend(struct device *dev)
 {
 	struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
@@ -7665,7 +7672,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	e1000_print_device_info(adapter);
 
-	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
 
 	if (pci_dev_run_wake(pdev) && hw->mac.type < e1000_pch_cnp)
 		pm_runtime_put_noidle(&pdev->dev);
@@ -7890,6 +7897,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
 static const struct dev_pm_ops e1000_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
+	.prepare	= e1000e_pm_prepare,
 	.suspend	= e1000e_pm_suspend,
 	.resume		= e1000e_pm_resume,
 	.freeze		= e1000e_pm_freeze,
Signature · 1 line
2.17.1
#2 lore raw

Re: [PATCH 1/2][v3] e1000e: Leverage direct_complete to speed up s2ram

Hi Yu,

Quoted 21 lines · Chen Yu

The NIC is put in runtime suspend status when there is no cable connected. As a result, it is safe to keep non-wakeup NIC in runtime suspended during s2ram because the system does not rely on the NIC plug event nor WoL to wake up the system. Besides that, unlike the s2idle, s2ram does not need to manipulate S0ix settings during suspend.

This patch introduces the .prepare() for e1000e so that if the NIC is runtime suspended the subsequent suspend/resume hooks will be skipped so as to speed up the s2ram. The pm core will check whether the NIC is a wake up device so there's no need to check it again in .prepare(). DPM_FLAG_SMART_PREPARE flag should be set during probe to ask the pci subsystem to honor the driver's prepare() result. Besides, the NIC remains runtime suspended after resumed from s2ram as there is no need to resume it.

Tested on i7-2600K with 82579V NIC
Before the patch:
e1000e 0000:00:19.0: pci_pm_suspend+0x0/0x160 returned 0 after 225146 usecs e1000e 0000:00:19.0: pci_pm_resume+0x0/0x90 returned 0 after 140588 usecs

Quoted 6 lines

After the patch:
echo disabled > //sys/devices/pci0000\:00/0000\:00\:19.0/power/wakeup becomes 0 usecs because the hooks will be skipped.

Well, I was intended to send it, but anyway :)

Quoted 35 lines

---
v2: Added test data and some commit log revise(Paul Menzel)
Only skip the suspend/resume if the NIC is not a wake up device specified by the user(Kai-Heng Feng)
v3: Leverage direct complete mechanism to skip all hooks(Kai-Heng Feng)
---
drivers/net/ethernet/intel/e1000e/netdev.c | 10 +++++++++-

1 file changed, 9 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000e/netdev.c +7 -0
index b30f00891c03..b210bba3f20a 100644
@@ -25,6 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/aer.h>
 #include <linux/prefetch.h>
+#include <linux/suspend.h>
 
 #include "e1000.h"
 
@@ -6957,6 +6958,12 @@ static int __e1000_resume(struct pci_dev *pdev)
 	return 0;
 }
 
+static int e1000e_pm_prepare(struct device *dev)
+{
+	return pm_runtime_suspended(dev) &&
+		pm_suspend_via_firmware();
+}
+
 static __maybe_unused int e1000e_pm_suspend(struct device *dev)
 {
 	struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));

drivers/net/ethernet/intel/e1000e/netdev.c static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · line 7675

Quoted 5 lines
drivers/net/ethernet/intel/e1000e/netdev.c +1 -1
@@ -7665,7 +7672,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	e1000_print_device_info(adapter);
 
-	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);

This isn't required for pci_pm_prepare() to use driver's .prepare callback.

drivers/net/ethernet/intel/e1000e/netdev.c MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); · line 7900

Quoted 8 lines
drivers/net/ethernet/intel/e1000e/netdev.c +1 -0
 	if (pci_dev_run_wake(pdev) && hw->mac.type < e1000_pch_cnp)
 		pm_runtime_put_noidle(&pdev->dev);
@@ -7890,6 +7897,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
 static const struct dev_pm_ops e1000_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
+	.prepare	= e1000e_pm_prepare,

How do we make sure a link change happened in S3 can be detect after resume, without a .complete callback which ask device to runtime resume?

Kai-Heng

Quoted 6 lines
drivers/net/ethernet/intel/e1000e/netdev.c +0 -0
 	.suspend	= e1000e_pm_suspend,
 	.resume		= e1000e_pm_resume,
 	.freeze		= e1000e_pm_freeze,
Signature · 1 line
2.17.1
author
#3 lore raw

Re: [PATCH 1/2][v3] e1000e: Leverage direct_complete to speed up s2ram

Hi Kai-Heng,

Quoted 7 lines · Kai-Heng Feng
Quoted 7 lines

---
v2: Added test data and some commit log revise(Paul Menzel)
Only skip the suspend/resume if the NIC is not a wake up device specified by the user(Kai-Heng Feng)
v3: Leverage direct complete mechanism to skip all hooks(Kai-Heng Feng)
---

Quoted 5 lines

drivers/net/ethernet/intel/e1000e/netdev.c static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · line 7675

Quoted 2 lines
drivers/net/ethernet/intel/e1000e/netdev.c +1 -1
-	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);

This isn't required for pci_pm_prepare() to use driver's .prepare callback.

pci_pm_prepare() is likely to return 1 even if driver's prepare() return 0, when DPM_FLAG_SMART_PREPARE is not set, which might cause prblems:
if (!error && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE))

	return 0;
Quoted 11 lines

drivers/net/ethernet/intel/e1000e/netdev.c MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); · line 7900

Quoted 8 lines
	if (pci_dev_run_wake(pdev) && hw->mac.type < e1000_pch_cnp)
		pm_runtime_put_noidle(&pdev->dev);
drivers/net/ethernet/intel/e1000e/netdev.c +1 -0
@@ -7890,6 +7897,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
 static const struct dev_pm_ops e1000_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
+	.prepare	= e1000e_pm_prepare,

How do we make sure a link change happened in S3 can be detect after resume, without a .complete callback which ask device to runtime resume?

The pm core's device_complete() has already done that pm_runtime_put() in the end.

Just talked to Rafael and he might also give some feedbacks later.

thanks,
Chenyu

Quoted 3 lines

Kai-Heng

author
#4 lore raw

PATCH v3 2/2 e1000e: Remove the runtime suspend restriction on CNP+

In reply to Chen Yu

Although there is platform issue of runtime suspend support on CNP, it would be more flexible to let the user decide whether to disable runtime or not because:
1. This can be done in userspace via
echo on > /sys/devices/pci0000\:00/0000\:00\:1f.d/power/control
2. More and more NICs would support runtime suspend, disabling the runtime suspend on them by default would impact the validation.

Only disable runtime suspend on CNP in case of any user space regression.

---
 drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000e/netdev.c +1 -1
index b210bba3f20a..d06435267dc8 100644
@@ -7674,7 +7674,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
 
-	if (pci_dev_run_wake(pdev) && hw->mac.type < e1000_pch_cnp)
+	if (pci_dev_run_wake(pdev) && hw->mac.type != e1000_pch_cnp)
 		pm_runtime_put_noidle(&pdev->dev);
 
 	return 0;
Signature · 1 line
2.17.1