@@ -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
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+