Skip to contentSkip to conversation

FAILED: patch "[PATCH] wifi: rtw89: pci: add .shutdown callback to stop rfkill" failed to apply to 6.18-stable tree

PATCH New [email protected] 2 participants 2 messages Sep 4 – Sep 10

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 667c12782aaf8dd3cb2213e528fe63a73cb63345
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090432-juvenile-roundworm-d5e3@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 667c12782aaf8dd3cb2213e528fe63a73cb63345 Mon Sep 17 00:00:00 2001
From: "Yuhang.chen" <[email protected]>
Date: Wed, 29 Jul 2026 09:41:42 +0800
Subject: [PATCH] wifi: rtw89: pci: add .shutdown callback to stop rfkill
polling on reboot

Since the hardware rfkill polling was introduced, arm64 platforms can panic with an asynchronous SError during warm reboot:

SError Interrupt on CPU8, code 0x00000000be000011 -- SError

  Workqueue: events_power_efficient rfkill_poll [rfkill]
    rtw89_pci_ops_read8+0x94/0x160 [rtw89_pci]
    rtw89_core_rfkill_poll+0x50/0x1e0 [rtw89_core]
    rtw89_ops_rfkill_poll+0x40/0x68 [rtw89_core]
    ieee80211_rfkill_poll+0x3c/0x70 [mac80211]
    cfg80211_rfkill_poll+0x40/0x2a0 [cfg80211]
    rfkill_poll+0x30/0x88 [rfkill]
  Kernel panic - not syncing: Asynchronous SError Interrupt

On the reboot path the kernel only runs device_shutdown(), which calls each driver's .shutdown callback; .remove is not invoked. The rtw89 PCI driver had no .shutdown callback, so nothing stopped the rfkill polling work while the platform was tearing the PCIe link down. Once the link is gone, the next MMIO read from the poll handler targets a non-responding device and is reported as a fatal asynchronous SError on arm64.

Add rtw89_pci_shutdown(), wired to all rtw89 PCI device drivers, which sets a new RTW89_FLAG_SHUTDOWN flag (mirroring the USB RTW89_FLAG_UNPLUGGED pattern). When the flag is set, rtw89_ops_rfkill_poll() returns early, so no MMIO read is issued to the chip after shutdown begins and the SError no longer occurs.

This does not call the full .remove path from .shutdown, to keep the shutdown handler minimal and avoid running the non-idempotent teardown twice.

drivers/net/wireless/realtek/rtw89/core.h +1 -0
index 09c19a6b9058..889a94d7f534 100644
@@ -6453,6 +6453,7 @@ enum rtw89_flags {
 	RTW89_FLAG_CHANGING_INTERFACE,
 	RTW89_FLAG_HW_RFKILL_STATE,
 	RTW89_FLAG_UNPLUGGED,
+	RTW89_FLAG_SHUTDOWN,
 
 	NUM_OF_RTW89_FLAGS,
 };
drivers/net/wireless/realtek/rtw89/mac80211.c +2 -1
index e381aacda667..c1be69a3c192 100644
@@ -2004,7 +2004,8 @@ static void rtw89_ops_rfkill_poll(struct ieee80211_hw *hw)
 	lockdep_assert_wiphy(hw->wiphy);
 
 	/* wl_disable GPIO get floating when entering LPS */
-	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
+	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags) ||
+	    test_bit(RTW89_FLAG_SHUTDOWN, rtwdev->flags))
 		return;
 
 	rtw89_core_rfkill_poll(rtwdev, false);
drivers/net/wireless/realtek/rtw89/pci.c +13 -0
index c5b82fc46d06..8c3f4eb52cc5 100644
@@ -4878,6 +4878,19 @@ void rtw89_pci_remove(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL(rtw89_pci_remove);
 
+void rtw89_pci_shutdown(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct rtw89_dev *rtwdev;
+
+	if (!hw)
+		return;
+
+	rtwdev = hw->priv;
+	set_bit(RTW89_FLAG_SHUTDOWN, rtwdev->flags);
+}
+EXPORT_SYMBOL(rtw89_pci_shutdown);
+
 MODULE_AUTHOR("Realtek Corporation");
 MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
drivers/net/wireless/realtek/rtw89/pci.h +1 -0
index 0e1557cedd20..cba52584ea68 100644
@@ -1752,6 +1752,7 @@ struct pci_device_id;
 
 int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
 void rtw89_pci_remove(struct pci_dev *pdev);
+void rtw89_pci_shutdown(struct pci_dev *pdev);
 void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume);
 void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev);
 int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en);
drivers/net/wireless/realtek/rtw89/rtw8851be.c +1 -0
index 459d2e778b83..81c62296c32d 100644
@@ -94,6 +94,7 @@ static struct pci_driver rtw89_8851be_driver = {
 	.id_table	= rtw89_8851be_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852ae.c +1 -0
index 142a45a2e718..3defb0748648 100644
@@ -96,6 +96,7 @@ static struct pci_driver rtw89_8852ae_driver = {
 	.id_table	= rtw89_8852ae_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852be.c +1 -0
index 1c622a99c070..9b48e70c2b56 100644
@@ -98,6 +98,7 @@ static struct pci_driver rtw89_8852be_driver = {
 	.id_table	= rtw89_8852be_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852bte.c +1 -0
index 73c7ebd33ab4..850ae9cbac18 100644
@@ -100,6 +100,7 @@ static struct pci_driver rtw89_8852bte_driver = {
 	.id_table	= rtw89_8852bte_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852ce.c +1 -0
index bb5d5745aa62..daff152f66bc 100644
@@ -123,6 +123,7 @@ static struct pci_driver rtw89_8852ce_driver = {
 	.id_table	= rtw89_8852ce_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8922ae.c +1 -0
index 8f3a1cd463d9..e82c866dfa36 100644
@@ -113,6 +113,7 @@ static struct pci_driver rtw89_8922ae_driver = {
 	.id_table	= rtw89_8922ae_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops_be,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8922de.c +1 -0
index 09400a0efcfd..a71e41f28544 100644
@@ -113,6 +113,7 @@ static struct pci_driver rtw89_8922de_driver = {
 	.id_table	= rtw89_8922de_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops_be,
 	.err_handler    = &rtw89_pci_err_handler,
 };
maintainer
#1 lore raw

PATCH 1/1 wifi: rtw89: pci: add .shutdown callback to stop rfkill polling on reboot

From: "Yuhang.chen" <[email protected]>

[ Upstream commit 667c12782aaf8dd3cb2213e528fe63a73cb63345 ]

Since the hardware rfkill polling was introduced, arm64 platforms can panic with an asynchronous SError during warm reboot:

SError Interrupt on CPU8, code 0x00000000be000011 -- SError

  Workqueue: events_power_efficient rfkill_poll [rfkill]
    rtw89_pci_ops_read8+0x94/0x160 [rtw89_pci]
    rtw89_core_rfkill_poll+0x50/0x1e0 [rtw89_core]
    rtw89_ops_rfkill_poll+0x40/0x68 [rtw89_core]
    ieee80211_rfkill_poll+0x3c/0x70 [mac80211]
    cfg80211_rfkill_poll+0x40/0x2a0 [cfg80211]
    rfkill_poll+0x30/0x88 [rfkill]
  Kernel panic - not syncing: Asynchronous SError Interrupt

On the reboot path the kernel only runs device_shutdown(), which calls each driver's .shutdown callback; .remove is not invoked. The rtw89 PCI driver had no .shutdown callback, so nothing stopped the rfkill polling work while the platform was tearing the PCIe link down. Once the link is gone, the next MMIO read from the poll handler targets a non-responding device and is reported as a fatal asynchronous SError on arm64.

Add rtw89_pci_shutdown(), wired to all rtw89 PCI device drivers, which sets a new RTW89_FLAG_SHUTDOWN flag (mirroring the USB RTW89_FLAG_UNPLUGGED pattern). When the flag is set, rtw89_ops_rfkill_poll() returns early, so no MMIO read is issued to the chip after shutdown begins and the SError no longer occurs.

This does not call the full .remove path from .shutdown, to keep the shutdown handler minimal and avoid running the non-idempotent teardown twice.

Fixes 0b38e6277aed ("wifi: rtw89: add support for hardware rfkill")
[ Omitted the .shutdown registration in rtw8922de.c because the driver is absent from the target tree. ]
---
 drivers/net/wireless/realtek/rtw89/core.h       |  1 +
 drivers/net/wireless/realtek/rtw89/mac80211.c   |  3 ++-
 drivers/net/wireless/realtek/rtw89/pci.c        | 13 +++++++++++++
 drivers/net/wireless/realtek/rtw89/pci.h        |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8851be.c  |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852ae.c  |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852be.c  |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852bte.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852ce.c  |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922ae.c  |  1 +
 10 files changed, 23 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/core.h +1 -0
index e146fd082f21a..7e35168e8d606 100644
@@ -5042,6 +5042,7 @@ enum rtw89_flags {
 	RTW89_FLAG_CHANGING_INTERFACE,
 	RTW89_FLAG_HW_RFKILL_STATE,
 	RTW89_FLAG_UNPLUGGED,
+	RTW89_FLAG_SHUTDOWN,
 
 	NUM_OF_RTW89_FLAGS,
 };
drivers/net/wireless/realtek/rtw89/mac80211.c +2 -1
index 474be7a5e49c7..968d0346a87f4 100644
@@ -1879,7 +1879,8 @@ static void rtw89_ops_rfkill_poll(struct ieee80211_hw *hw)
 	lockdep_assert_wiphy(hw->wiphy);
 
 	/* wl_disable GPIO get floating when entering LPS */
-	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
+	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags) ||
+	    test_bit(RTW89_FLAG_SHUTDOWN, rtwdev->flags))
 		return;
 
 	rtw89_core_rfkill_poll(rtwdev, false);
drivers/net/wireless/realtek/rtw89/pci.c +13 -0
index 17a199ee1d4a4..6c1f66e65497f 100644
@@ -4829,6 +4829,19 @@ void rtw89_pci_remove(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL(rtw89_pci_remove);
 
+void rtw89_pci_shutdown(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct rtw89_dev *rtwdev;
+
+	if (!hw)
+		return;
+
+	rtwdev = hw->priv;
+	set_bit(RTW89_FLAG_SHUTDOWN, rtwdev->flags);
+}
+EXPORT_SYMBOL(rtw89_pci_shutdown);
+
 MODULE_AUTHOR("Realtek Corporation");
 MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver");
 MODULE_LICENSE("Dual BSD/GPL");
drivers/net/wireless/realtek/rtw89/pci.h +1 -0
index cb05c83dfd567..09fca0e46cd1b 100644
@@ -1737,6 +1737,7 @@ struct pci_device_id;
 
 int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
 void rtw89_pci_remove(struct pci_dev *pdev);
+void rtw89_pci_shutdown(struct pci_dev *pdev);
 void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume);
 void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev);
 int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en);
drivers/net/wireless/realtek/rtw89/rtw8851be.c +1 -0
index ce59ac9f56ba8..79ea3ccb79572 100644
@@ -92,6 +92,7 @@ static struct pci_driver rtw89_8851be_driver = {
 	.id_table	= rtw89_8851be_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852ae.c +1 -0
index 9e05e831569d2..4f1624740dd2b 100644
@@ -94,6 +94,7 @@ static struct pci_driver rtw89_8852ae_driver = {
 	.id_table	= rtw89_8852ae_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852be.c +1 -0
index 12db0d0be5479..72bbaf22893fc 100644
@@ -96,6 +96,7 @@ static struct pci_driver rtw89_8852be_driver = {
 	.id_table	= rtw89_8852be_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852bte.c +1 -0
index 8c995aa953251..b10587fa5f324 100644
@@ -98,6 +98,7 @@ static struct pci_driver rtw89_8852bte_driver = {
 	.id_table	= rtw89_8852bte_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8852ce.c +1 -0
index 150fed189414d..281f46455de42 100644
@@ -121,6 +121,7 @@ static struct pci_driver rtw89_8852ce_driver = {
 	.id_table	= rtw89_8852ce_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops,
 	.err_handler    = &rtw89_pci_err_handler,
 };
drivers/net/wireless/realtek/rtw89/rtw8922ae.c +1 -0
index 90c62b757c57b..1ad7d44d03522 100644
@@ -109,6 +109,7 @@ static struct pci_driver rtw89_8922ae_driver = {
 	.id_table	= rtw89_8922ae_id_table,
 	.probe		= rtw89_pci_probe,
 	.remove		= rtw89_pci_remove,
+	.shutdown	= rtw89_pci_shutdown,
 	.driver.pm	= &rtw89_pm_ops_be,
 	.err_handler    = &rtw89_pci_err_handler,
 };
Signature · 1 line
2.53.0