From: Maharaja Kennadyrajan Date: Mon, 13 Apr 2026 15:38:39 +0000 (+0530) Subject: wifi: ath12k: reorder group start/stop for safe thermal sysfs cleanup X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ab4dc09b7819ddea698fe5a0cc711a64186f12d;p=thirdparty%2Fkernel%2Flinux.git wifi: ath12k: reorder group start/stop for safe thermal sysfs cleanup A later change adds thermal cooling device sysfs under the wiphy device kobject. With the current teardown order, MAC/wiphy are unregistered before per-device cleanup, so any subsequent thermal sysfs removal would run after the wiphy kobject is gone. That ordering is asymmetric with setup and would risk kernfs issues during removal. This change also adjusts the position of ath12k_mac_mlo_teardown(). Previously it ran before per-device cleanup/MAC unregister. MLO teardown issues WMI to teardown multi-link state and is part of the MAC teardown sequence. Placing it alongside MAC unregister (after per-device cleanup) preserves setup/teardown symmetry and avoids racing with remaining netdev/wiphy state. Reorder hw_group_stop() so per-device cleanup (including thermal/hwmon sysfs removal) runs while the wiphy still exists. After per-device cleanup completes, unregister the MAC (dropping wiphys), run ath12k_mac_mlo_teardown(), and finally destroy the MAC. This mirrors the setup sequence and keeps sysfs cleanup safe when introduced in a later patch. To keep start/stop symmetry, add ath12k_core_device_setup() to encapsulate the per-device bring-up steps (pdev create, IRQ enable, rfkill config) that were previously open-coded in hw_group_start(). Use this helper in hw_group_start() to match the existing per-device cleanup helper used by hw_group_stop(). Note that set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags) is now executed outside the ab->core_lock critical section. The core_lock has not provided protection for the REGISTERED flag, readers do not rely on core_lock for this bit, and the flag is only toggled in the serialized group start/stop path using atomic bitops. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 Signed-off-by: Maharaja Kennadyrajan Reviewed-by: Rameshkumar Sundaram Reviewed-by: Baochen Qiang Link: https://patch.msgid.link/20260413153840.1969931-5-maharaja.kennadyrajan@oss.qualcomm.com Signed-off-by: Jeff Johnson --- diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index e8137144fd1f5..1a9866061f829 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1006,6 +1006,27 @@ static void ath12k_core_device_cleanup(struct ath12k_base *ab) mutex_unlock(&ab->core_lock); } +static int ath12k_core_device_setup(struct ath12k_base *ab) +{ + int ret; + + guard(mutex)(&ab->core_lock); + + ret = ath12k_core_pdev_create(ab); + if (ret) { + ath12k_err(ab, "failed to create pdev core %d\n", ret); + return ret; + } + + ath12k_hif_irq_enable(ab); + + ret = ath12k_core_rfkill_config(ab); + if (ret && ret != -EOPNOTSUPP) + return ret; + + return 0; +} + static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) { struct ath12k_base *ab; @@ -1015,10 +1036,6 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) clear_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags); - ath12k_mac_unregister(ag); - - ath12k_mac_mlo_teardown(ag); - for (i = ag->num_devices - 1; i >= 0; i--) { ab = ag->ab[i]; if (!ab) @@ -1029,6 +1046,12 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) ath12k_core_device_cleanup(ab); } + /* Unregister MAC (drops wiphys) only after per-device cleanup */ + ath12k_mac_unregister(ag); + + /* Teardown MLO state after MAC unregister for symmetry */ + ath12k_mac_mlo_teardown(ag); + ath12k_mac_destroy(ag); } @@ -1165,26 +1188,11 @@ core_pdev_create: if (!ab) continue; - mutex_lock(&ab->core_lock); - set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); - ret = ath12k_core_pdev_create(ab); - if (ret) { - ath12k_err(ab, "failed to create pdev core %d\n", ret); - mutex_unlock(&ab->core_lock); - goto err; - } - - ath12k_hif_irq_enable(ab); - - ret = ath12k_core_rfkill_config(ab); - if (ret && ret != -EOPNOTSUPP) { - mutex_unlock(&ab->core_lock); + ret = ath12k_core_device_setup(ab); + if (ret) goto err; - } - - mutex_unlock(&ab->core_lock); } return 0;