linux/drivers/net/wireless
Kang Yang 27fda36eed wifi: ath10k: avoid NULL pointer error during sdio remove
commit 95c38953cb upstream.

When running 'rmmod ath10k', ath10k_sdio_remove() will free sdio
workqueue by destroy_workqueue(). But if CONFIG_INIT_ON_FREE_DEFAULT_ON
is set to yes, kernel panic will happen:
Call trace:
 destroy_workqueue+0x1c/0x258
 ath10k_sdio_remove+0x84/0x94
 sdio_bus_remove+0x50/0x16c
 device_release_driver_internal+0x188/0x25c
 device_driver_detach+0x20/0x2c

This is because during 'rmmod ath10k', ath10k_sdio_remove() will call
ath10k_core_destroy() before destroy_workqueue(). wiphy_dev_release()
will finally be called in ath10k_core_destroy(). This function will free
struct cfg80211_registered_device *rdev and all its members, including
wiphy, dev and the pointer of sdio workqueue. Then the pointer of sdio
workqueue will be set to NULL due to CONFIG_INIT_ON_FREE_DEFAULT_ON.

After device release, destroy_workqueue() will use NULL pointer then the
kernel panic happen.

Call trace:
ath10k_sdio_remove
  ->ath10k_core_unregister
    ……
    ->ath10k_core_stop
      ->ath10k_hif_stop
        ->ath10k_sdio_irq_disable
    ->ath10k_hif_power_down
      ->del_timer_sync(&ar_sdio->sleep_timer)
  ->ath10k_core_destroy
    ->ath10k_mac_destroy
      ->ieee80211_free_hw
        ->wiphy_free
    ……
          ->wiphy_dev_release
  ->destroy_workqueue

Need to call destroy_workqueue() before ath10k_core_destroy(), free
the work queue buffer first and then free pointer of work queue by
ath10k_core_destroy(). This order matches the error path order in
ath10k_sdio_probe().

No work will be queued on sdio workqueue between it is destroyed and
ath10k_core_destroy() is called. Based on the call_stack above, the
reason is:
Only ath10k_sdio_sleep_timer_handler(), ath10k_sdio_hif_tx_sg() and
ath10k_sdio_irq_disable() will queue work on sdio workqueue.
Sleep timer will be deleted before ath10k_core_destroy() in
ath10k_hif_power_down().
ath10k_sdio_irq_disable() only be called in ath10k_hif_stop().
ath10k_core_unregister() will call ath10k_hif_power_down() to stop hif
bus, so ath10k_sdio_hif_tx_sg() won't be called anymore.

Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00189

Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
Tested-by: David Ruth <druth@chromium.org>
Reviewed-by: David Ruth <druth@chromium.org>
Link: https://patch.msgid.link/20241008022246.1010-1-quic_kangyang@quicinc.com
Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Alva Lan <alvalan9@foxmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2025-05-02 07:44:19 +02:00
..
admtek module: remove never implemented MODULE_SUPPORTED_DEVICE 2021-03-17 13:16:18 -07:00
ath wifi: ath10k: avoid NULL pointer error during sdio remove 2025-05-02 07:44:19 +02:00
atmel wifi: at76c50x: fix use after free access in at76_disconnect 2025-05-02 07:44:08 +02:00
broadcom wifi: brcmfmac: fix NULL pointer dereference in brcmf_txfinalize() 2025-03-13 12:50:27 +01:00
cisco wifi: airo: avoid uninitialized warning in airo_get_rate() 2023-07-23 13:47:44 +02:00
intel wifi: iwlwifi: fw: allocate chained SG tables for dump 2025-04-10 14:32:03 +02:00
intersil wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq() 2024-12-14 19:50:52 +01:00
marvell wifi: mwifiex: Fix memcpy() field-spanning write warning in mwifiex_config_scan() 2024-12-14 19:50:55 +01:00
mediatek wifi: mt76: Add check for devm_kstrdup() 2025-05-02 07:44:02 +02:00
microchip wifi: wilc1000: fix potential RCU dereference issue in wilc_parse_join_bss_param 2024-10-17 15:10:46 +02:00
quantenna wireless: Remove redundant 'flush_workqueue()' calls 2024-03-26 18:21:19 -04:00
ralink wifi: rt2x00: use explicitly signed or unsigned types 2024-07-27 10:46:17 +02:00
realtek wifi: rtlwifi: rtl8821ae: Fix media status report 2025-03-13 12:50:26 +01:00
rsi wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown 2023-07-23 13:46:52 +02:00
st wifi: cw1200: Avoid processing an invalid TIM IE 2024-09-04 13:23:20 +02:00
ti wifi: wl1251: fix memory leak in wl1251_tx_work 2025-05-02 07:44:08 +02:00
zydas zd1211rw: Prefer pr_err over printk error msg 2021-06-15 16:37:01 +03:00
Kconfig wireless: remove CONFIG_WIRELESS_WDS 2020-11-10 09:39:08 +01:00
mac80211_hwsim.c wifi: mac80211_hwsim: fix clang-specific fortify warning 2023-11-28 16:56:15 +00:00
mac80211_hwsim.h mac80211_hwsim: notify wmediumd of used MAC addresses 2020-04-24 11:45:47 +02:00
Makefile wilc1000: move wilc driver out of staging 2020-06-26 08:46:46 +03:00
ray_cs.c wifi: ray_cs: Fix an error handling path in ray_probe() 2023-07-23 13:46:51 +02:00
ray_cs.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
rayctl.h ray_cs: Replace zero-length array with flexible-array member 2020-03-23 19:18:27 +02:00
rndis_wlan.c wireless: Remove redundant 'flush_workqueue()' calls 2024-03-26 18:21:19 -04:00
virt_wifi.c wifi: virt_wifi: don't use strlen() in const context 2024-08-19 05:44:58 +02:00
wl3501.h wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join 2021-04-22 17:38:41 +03:00
wl3501_cs.c wifi: wl3501_cs: Fix an error handling path in wl3501_probe() 2023-07-23 13:46:51 +02:00