From 3a3ead7c317c4912945cb787e2defb92006cce28 Mon Sep 17 00:00:00 2001 From: Surya Prakash Sivaraj Date: Wed, 28 Jan 2026 23:24:10 -0800 Subject: [PATCH] qcacld-3.0: Prevent ping loss due to runtime suspend Scenario: 1) FW sends roam start to the host, and host disables the netif queues. Therefore, the ping from the stack does not reach the driver. 3) The driver goes into runtime suspend, and the firmware aborts roaming due to pmf assoc retry. 4) After assoc comeback timeout, the firmware successfully roams. However, both roam abort and roam sync are not wakeable events. 5) Therefore, the host stays in runtime suspend until the timeout as part of the serialization command queued during roam start. 6) Netif queues are enabled back after roam start timeout and ping resumes. This results in a data loss for a longer time, eventhough the firmware has aborted the roaming. Currently, the host driver prevents runtime suspend only from roam sync event until roam sync completion. To fix this issue, prevent the runtime suspend from the roam start until roam sync completion/roam abort/roam ho-failure. Change-Id: I9d63dd6af09d17e90d7d2d6a63a8aaa59297a047 CRs-Fixed: 4413987 --- core/wma/inc/wma.h | 2 ++ core/wma/src/wma_main.c | 1 + core/wma/src/wma_scan_roam.c | 3 +++ core/wma/src/wma_utils.c | 8 ++++++++ 4 files changed, 14 insertions(+) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 787f5d3c3e6f..99b2164e618a 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -911,6 +911,7 @@ struct wma_wlm_stats_data { * @wma_fw_time_sync_timer: timer used for firmware time sync * @fw_therm_throt_support: FW Supports thermal throttling? * @roam_sync_runtime_lock: roam sync runtime lock + * @is_roam_lock_acquired: Is roam_sync_runtime_lock acquired * * This structure is the global wma context. It contains global wma * module parameters and handles of other modules. @@ -1046,6 +1047,7 @@ typedef struct { bool fw_therm_throt_support; bool enable_tx_compl_tsf64; qdf_runtime_lock_t roam_sync_runtime_lock; + bool is_roam_lock_acquired; } t_wma_handle, *tp_wma_handle; /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 6165e7fc31e2..7021b8720fc3 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3429,6 +3429,7 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, qdf_runtime_lock_init(&wma_handle->wmi_cmd_rsp_runtime_lock); qdf_runtime_lock_init(&wma_handle->sap_prevent_runtime_pm_lock); qdf_runtime_lock_init(&wma_handle->roam_sync_runtime_lock); + wma_handle->is_roam_lock_acquired = false; /* Register peer assoc conf event handler */ wmi_unified_register_event_handler(wma_handle->wmi_handle, diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 994e08c449d7..276f64af9cf8 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -4558,10 +4558,12 @@ static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle, if (notif == WMI_ROAM_NOTIF_ROAM_START) { wma_handle->interfaces[vdev_id].roaming_in_progress = true; op_code = SIR_ROAMING_START; + wma_prevent_pm_during_roam_sync(wma_handle); } else if (notif == WMI_ROAM_NOTIF_ROAM_ABORT) { wma_handle->interfaces[vdev_id].roaming_in_progress = false; op_code = SIR_ROAMING_ABORT; lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id); + wma_allow_pm_after_roam_sync(wma_handle); } else { wma_debug("Invalid notif %d", notif); return; @@ -4737,6 +4739,7 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, = false; lim_sae_auth_cleanup_retry(wma_handle->mac_context, wmi_event->vdev_id); + wma_allow_pm_after_roam_sync(wma_handle); break; #endif case WMI_ROAM_REASON_INVALID: diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 28c927fbcd41..87c194ee45f0 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -3827,7 +3827,11 @@ void wma_prevent_pm_during_roam_sync(t_wma_handle *wma) if (!wma) return; + if (wma->is_roam_lock_acquired) + return; + qdf_runtime_pm_prevent_suspend(&wma->roam_sync_runtime_lock); + wma->is_roam_lock_acquired = true; } void wma_allow_pm_after_roam_sync(t_wma_handle *wma) @@ -3835,7 +3839,11 @@ void wma_allow_pm_after_roam_sync(t_wma_handle *wma) if (!wma) return; + if (!wma->is_roam_lock_acquired) + return; + qdf_runtime_pm_allow_suspend(&wma->roam_sync_runtime_lock); + wma->is_roam_lock_acquired = false; } QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)