public inbox for development@lists.ipfire.org
 help / color / mirror / Atom feed
* [PATCH] linux: Fix igb runtime PM issues
@ 2026-11-13 10:57 Antonio Quartulli
  0 siblings, 0 replies; only message in thread
From: Antonio Quartulli @ 2026-11-13 10:57 UTC (permalink / raw)
  To: development; +Cc: Antonio Quartulli

igb re-opens the interface without RTNL when resuming from runtime
suspend (e.g. after a link loss), which triggers "RTNL: assertion
failed" warnings. It also runtime suspends devices that can't wake up
again, whose ports then stay down when the link comes back. Backport the
three upstream-bound fixes.

Fixes: #13562
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
---
Notes:
- The three kernel patches are being submitted upstream (intel-wired-lan);
  the first one alone fixes the warning on 6.6/6.12. The kernel is
  shipped by the next Core Update anyway.
- All reproduced and tested in a VM with an emulated igb NIC (details and
  a reproducer in #13562). Runtime PM is only active with
  power/control=auto (e.g. set by powertop --auto-tune); IPFire's default
  is off.

 lfs/linux                                     |   7 +
 ...fix-rtnl-assertion-on-runtime-resume.patch |  88 ++++++++++++
 ...apis-under-rtnl-after-runtime-resume.patch | 133 ++++++++++++++++++
 ...low-runtime-pm-if-device-can-wake-up.patch |  66 +++++++++
 4 files changed, 294 insertions(+)
 create mode 100644 src/patches/linux/linux-6.18-igb-fix-rtnl-assertion-on-runtime-resume.patch
 create mode 100644 src/patches/linux/linux-6.18-igb-link-queue-napis-under-rtnl-after-runtime-resume.patch
 create mode 100644 src/patches/linux/linux-6.18-igb-only-allow-runtime-pm-if-device-can-wake-up.patch

diff --git a/lfs/linux b/lfs/linux
index 7312bebac..1443d72fb 100644
--- a/lfs/linux
+++ b/lfs/linux
@@ -122,6 +122,13 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
 	# Fix igb and e1000e crash
 	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-4.14.1-igb-e1000e_fix_lock_at_update_stats.patch
 
+	# Fix RTNL assertion in igb when resuming from runtime suspend (#13562)
+	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-6.18-igb-fix-rtnl-assertion-on-runtime-resume.patch
+	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-6.18-igb-link-queue-napis-under-rtnl-after-runtime-resume.patch
+
+	# Don't runtime suspend igb devices that can't wake up again (#13562)
+	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-6.18-igb-only-allow-runtime-pm-if-device-can-wake-up.patch
+
 	# Fix uevent PHYSDEVDRIVER
 	cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-2.6.32.27_mcs7830-fix-driver-name.patch
 
diff --git a/src/patches/linux/linux-6.18-igb-fix-rtnl-assertion-on-runtime-resume.patch b/src/patches/linux/linux-6.18-igb-fix-rtnl-assertion-on-runtime-resume.patch
new file mode 100644
index 000000000..b23d3d63c
--- /dev/null
+++ b/src/patches/linux/linux-6.18-igb-fix-rtnl-assertion-on-runtime-resume.patch
@@ -0,0 +1,88 @@
+From a500722ce84ee6e30a9b79c92c1bb6b8915bcb77 Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <antonio@mandelbit.com>
+Date: Thu, 12 Nov 2026 17:11:21 +0100
+To: intel-wired-lan@lists.osuosl.org
+Cc: Tony Nguyen <anthony.l.nguyen@intel.com>,
+    Przemek Kitszel <przemyslaw.kitszel@intel.com>,
+    Andrew Lunn <andrew+netdev@lunn.ch>,
+    "David S. Miller" <davem@davemloft.net>,
+    Eric Dumazet <edumazet@kernel.org>,
+    Jakub Kicinski <kuba@kernel.org>,
+    Paolo Abeni <pabeni@redhat.com>,
+    Heiner Kallweit <hkallweit1@gmail.com>,
+    netdev@vger.kernel.org,
+    linux-kernel@vger.kernel.org
+Subject: [PATCH net 1/3] igb: fix RTNL assertion when resuming from runtime
+ suspend
+
+Since commit ac8c58f5b535 ("igb: fix deadlock caused by taking RTNL in
+RPM resume path") __igb_resume() doesn't take RTNL for runtime resume,
+but __igb_open() still calls netif_set_real_num_{tx,rx}_queues(), which
+require it. An asynchronous runtime resume (e.g. after the link comes
+back) then triggers "RTNL: assertion failed".
+
+The queue counts only change on paths that re-open the device under
+RTNL (ethtool -L, SR-IOV reconfiguration): set them in igb_open() only,
+as igc does since commit 6f31d6b643a3 ("igc: Refactor runtime power
+management flow").
+
+Fixes: ac8c58f5b535 ("igb: fix deadlock caused by taking RTNL in RPM resume path")
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.ipfire.org/show_bug.cgi?id=13562
+Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
+---
+ drivers/net/ethernet/intel/igb/igb_main.c | 24 +++++++++++------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 78f0786..bd1185d 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -4178,17 +4178,6 @@ static int __igb_open(struct net_device *netdev, bool resuming)
+ 	if (err)
+ 		goto err_req_irq;
+ 
+-	/* Notify the stack of the actual queue counts. */
+-	err = netif_set_real_num_tx_queues(adapter->netdev,
+-					   adapter->num_tx_queues);
+-	if (err)
+-		goto err_set_queues;
+-
+-	err = netif_set_real_num_rx_queues(adapter->netdev,
+-					   adapter->num_rx_queues);
+-	if (err)
+-		goto err_set_queues;
+-
+ 	/* From here on the code is the same as igb_up() */
+ 	clear_bit(__IGB_DOWN, &adapter->state);
+ 
+@@ -4223,8 +4212,6 @@ static int __igb_open(struct net_device *netdev, bool resuming)
+ 
+ 	return 0;
+ 
+-err_set_queues:
+-	igb_free_irq(adapter);
+ err_req_irq:
+ 	igb_release_hw_control(adapter);
+ 	igb_power_down_link(adapter);
+@@ -4241,6 +4228,17 @@ err_setup_tx:
+ 
+ int igb_open(struct net_device *netdev)
+ {
++	struct igb_adapter *adapter = netdev_priv(netdev);
++	int err;
++
++	/* Notify the stack of the actual queue counts. */
++	err = netif_set_real_num_queues(netdev, adapter->num_tx_queues,
++					adapter->num_rx_queues);
++	if (err) {
++		netdev_err(netdev, "error setting real queue count\n");
++		return err;
++	}
++
+ 	return __igb_open(netdev, false);
+ }
+ 
+-- 
+2.56.0
+
diff --git a/src/patches/linux/linux-6.18-igb-link-queue-napis-under-rtnl-after-runtime-resume.patch b/src/patches/linux/linux-6.18-igb-link-queue-napis-under-rtnl-after-runtime-resume.patch
new file mode 100644
index 000000000..552c92361
--- /dev/null
+++ b/src/patches/linux/linux-6.18-igb-link-queue-napis-under-rtnl-after-runtime-resume.patch
@@ -0,0 +1,133 @@
+From cc5272e3cf609b42948d35bf9d8afdf8691fe81e Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <antonio@mandelbit.com>
+Date: Thu, 12 Nov 2026 17:22:46 +0100
+To: intel-wired-lan@lists.osuosl.org
+Cc: Tony Nguyen <anthony.l.nguyen@intel.com>,
+    Przemek Kitszel <przemyslaw.kitszel@intel.com>,
+    Andrew Lunn <andrew+netdev@lunn.ch>,
+    "David S. Miller" <davem@davemloft.net>,
+    Eric Dumazet <edumazet@kernel.org>,
+    Jakub Kicinski <kuba@kernel.org>,
+    Paolo Abeni <pabeni@redhat.com>,
+    Kurt Kanzenbach <kurt@linutronix.de>,
+    Joe Damato <joe@dama.to>,
+    netdev@vger.kernel.org,
+    linux-kernel@vger.kernel.org
+Subject: [PATCH net 2/3] igb: link queues to NAPIs under RTNL after runtime resume
+
+__igb_open() links queues to NAPIs with netif_queue_set_napi(), which
+requires RTNL, but RTNL isn't held when resuming from runtime suspend:
+this triggers "RTNL: assertion failed".
+
+Don't link them in __igb_open() when resuming: do it right away on
+system resume (RTNL held) and from a work item taking RTNL on runtime
+resume. The links can't be kept across a suspend, because
+__igb_shutdown() frees the q_vectors. These are only freed under RTNL
+with __IGB_DOWN set, so the work item checks __IGB_DOWN under RTNL.
+
+Fixes: b75a1dea500f ("igb: Link queues to NAPI instances")
+Cc: stable@vger.kernel.org # 6.16+
+Closes: https://bugzilla.ipfire.org/show_bug.cgi?id=13562
+Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
+---
+Note: igc may have the same issue: __igc_open() also links queues to NAPIs
+(igc_set_queue_napi()) on the RTNL-less runtime resume path. We didn't
+have igc hardware to test a fix with, so no igc patch is sent for now.
+
+ drivers/net/ethernet/intel/igb/igb.h      |  1 +
+ drivers/net/ethernet/intel/igb/igb_main.c | 38 +++++++++++++++++++++--
+ 2 files changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
+index 0fff1df..ea2d739 100644
+--- a/drivers/net/ethernet/intel/igb/igb.h
++++ b/drivers/net/ethernet/intel/igb/igb.h
+@@ -585,6 +585,7 @@ struct igb_adapter {
+ 
+ 	struct work_struct reset_task;
+ 	struct work_struct watchdog_task;
++	struct work_struct queue_napi_task;
+ 	bool fc_autoneg;
+ 	u8  tx_timeout_factor;
+ 	struct timer_list blink_timer;
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index bd1185d..4d97399 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -2115,6 +2115,30 @@ void igb_set_queue_napi(struct igb_adapter *adapter, int vector,
+ 				     NETDEV_QUEUE_TYPE_TX, napi);
+ }
+ 
++static void igb_link_queue_napis(struct igb_adapter *adapter)
++{
++	int i;
++
++	for (i = 0; i < adapter->num_q_vectors; i++)
++		igb_set_queue_napi(adapter, i, &adapter->q_vector[i]->napi);
++}
++
++/* Linking queues to NAPIs requires RTNL, which isn't held when resuming
++ * from runtime suspend: do it from here instead. The q_vectors are only
++ * freed under RTNL with __IGB_DOWN set, so checking it under RTNL is safe.
++ */
++static void igb_queue_napi_task(struct work_struct *work)
++{
++	struct igb_adapter *adapter = container_of(work, struct igb_adapter,
++						   queue_napi_task);
++
++	rtnl_lock();
++	if (!test_bit(__IGB_DOWN, &adapter->state) &&
++	    netif_running(adapter->netdev))
++		igb_link_queue_napis(adapter);
++	rtnl_unlock();
++}
++
+ /**
+  *  igb_up - Open the interface and prepare it to handle traffic
+  *  @adapter: board private structure
+@@ -3426,6 +3450,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	INIT_WORK(&adapter->reset_task, igb_reset_task);
+ 	INIT_WORK(&adapter->watchdog_task, igb_watchdog_task);
++	INIT_WORK(&adapter->queue_napi_task, igb_queue_napi_task);
+ 
+ 	/* Initialize link properties that are user-changeable */
+ 	adapter->fc_autoneg = true;
+@@ -3890,6 +3915,7 @@ static void igb_remove(struct pci_dev *pdev)
+ 
+ 	cancel_work_sync(&adapter->reset_task);
+ 	cancel_work_sync(&adapter->watchdog_task);
++	cancel_work_sync(&adapter->queue_napi_task);
+ 
+ #ifdef CONFIG_IGB_DCA
+ 	if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
+@@ -4184,7 +4210,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
+ 	for (i = 0; i < adapter->num_q_vectors; i++) {
+ 		napi = &adapter->q_vector[i]->napi;
+ 		napi_enable(napi);
+-		igb_set_queue_napi(adapter, i, napi);
++		if (!resuming)
++			igb_set_queue_napi(adapter, i, napi);
+ 	}
+ 
+ 	/* Clear any pending interrupts. */
+@@ -9631,8 +9658,15 @@ static int __igb_resume(struct device *dev, bool rpm)
+ 
+ 	if (!rpm)
+ 		rtnl_lock();
+-	if (!err && netif_running(netdev))
++	if (!err && netif_running(netdev)) {
+ 		err = __igb_open(netdev, true);
++		if (!err) {
++			if (rpm)
++				schedule_work(&adapter->queue_napi_task);
++			else
++				igb_link_queue_napis(adapter);
++		}
++	}
+ 
+ 	if (!err)
+ 		netif_device_attach(netdev);
+-- 
+2.56.0
+
diff --git a/src/patches/linux/linux-6.18-igb-only-allow-runtime-pm-if-device-can-wake-up.patch b/src/patches/linux/linux-6.18-igb-only-allow-runtime-pm-if-device-can-wake-up.patch
new file mode 100644
index 000000000..4c6de2859
--- /dev/null
+++ b/src/patches/linux/linux-6.18-igb-only-allow-runtime-pm-if-device-can-wake-up.patch
@@ -0,0 +1,66 @@
+From 730d4d0bcdff9c76ba07b95c6877c8dcf8d36bb3 Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <antonio@mandelbit.com>
+Date: Thu, 12 Nov 2026 22:12:06 +0100
+To: intel-wired-lan@lists.osuosl.org
+Cc: Tony Nguyen <anthony.l.nguyen@intel.com>,
+    Przemek Kitszel <przemyslaw.kitszel@intel.com>,
+    Andrew Lunn <andrew+netdev@lunn.ch>,
+    "David S. Miller" <davem@davemloft.net>,
+    Eric Dumazet <edumazet@kernel.org>,
+    Jakub Kicinski <kuba@kernel.org>,
+    Paolo Abeni <pabeni@redhat.com>,
+    "Yan, Zheng" <zheng.z.yan@intel.com>,
+    netdev@vger.kernel.org,
+    linux-kernel@vger.kernel.org
+Subject: [PATCH net 3/3] igb: only allow runtime PM if the device can wake up
+
+igb lets the device be runtime suspended even if it can't signal a
+wake-up from D3. Such a device doesn't notice the link coming back, so
+the port stays down until it is resumed from user space.
+
+Allow runtime PM only if pci_dev_run_wake() is true, as e1000e and
+r8169 do. Devices that can't wake up no longer runtime suspend, even
+with power/control set to auto.
+
+Fixes: 749ab2cd1270 ("igb: add basic runtime PM support")
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.ipfire.org/show_bug.cgi?id=13562
+Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
+---
+Note: igc may have the same issue: igc_probe() also allows runtime PM
+regardless of pci_dev_run_wake(). We didn't have igc hardware to test a
+fix with, so no igc patch is sent for now.
+
+ drivers/net/ethernet/intel/igb/igb_main.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 4d97399..59f59da 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -3677,7 +3677,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+ 
+-	pm_runtime_put_noidle(&pdev->dev);
++	/* A device that can't wake up wouldn't notice the link coming back
++	 * while runtime suspended
++	 */
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_put_noidle(&pdev->dev);
+ 	return 0;
+ 
+ err_register:
+@@ -3900,7 +3904,8 @@ static void igb_remove(struct pci_dev *pdev)
+ 	struct igb_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+-	pm_runtime_get_noresume(&pdev->dev);
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_get_noresume(&pdev->dev);
+ #ifdef CONFIG_IGB_HWMON
+ 	igb_sysfs_exit(adapter);
+ #endif
+-- 
+2.56.0
+
-- 
2.56.0



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-13 10:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 10:57 [PATCH] linux: Fix igb runtime PM issues Antonio Quartulli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox