diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index eb27884e3e9c..cc8e3bce1e8e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -129,6 +129,7 @@ #else #define WLAN_WAIT_TIME_DISCONNECT 5000 #endif +#define WLAN_WAIT_TIME_STOP_ROAM 4000 #define WLAN_WAIT_TIME_STATS 800 #define WLAN_WAIT_TIME_POWER 800 #define WLAN_WAIT_TIME_COUNTRY 1000 @@ -973,6 +974,8 @@ struct hdd_adapter_s { /** completion variable for disconnect callback */ struct completion disconnect_comp_var; + struct completion roaming_comp_var; + /** Completion of change country code */ struct completion change_country_code; @@ -1139,18 +1142,11 @@ struct hdd_adapter_s { bool fast_roaming_allowed; /* - * defer disconnect is used as a flag by roaming to check - * if any disconnect has been deferred because of roaming - * and handle it. It stores the source of the disconnect. - * Based on the source, it will appropriately handle the - * disconnect. + * Indicate if HO fails during disconnect so that + * disconnect is not initiated by HDD as its already + * initiated by CSR */ - uint8_t defer_disconnect; - /* - * cfg80211 issues a reason for disconnect. Store this reason if the - * disconnect is being deferred. - */ - uint8_t cfg80211_disconnect_reason; + bool roam_ho_fail; struct lfr_firmware_status lfr_fw_status; /* * Store the restrict_offchannel count @@ -1159,13 +1155,6 @@ struct hdd_adapter_s { u8 restrict_offchannel_cnt; }; -/* - * Below two definitions are useful to distinguish the - * source of the disconnect when a disconnect is deferred - */ -#define DEFER_DISCONNECT_TRY_DISCONNECT 1 -#define DEFER_DISCONNECT_CFG80211_DISCONNECT 2 - #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) #define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap) #define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.station.WextState) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 62cbcc708a81..b8d5814d9816 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2034,11 +2034,6 @@ static void hdd_send_re_assoc_event(struct net_device *dev, qdf_mem_zero(&roam_profile, sizeof(roam_profile)); - if (pAdapter->defer_disconnect) { - hdd_debug("Do not send roam event as discon will be processed"); - goto done; - } - if (!rspRsnIe) { hdd_err("Unable to allocate RSN IE"); goto done; @@ -2758,31 +2753,30 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter, QDF_TRACE_LEVEL_DEBUG, pFTAssocReq, assocReqlen); - if (!pAdapter->defer_disconnect) { - roam_bss = hdd_cfg80211_get_bss( - pAdapter->wdev.wiphy, - chan, - pRoamInfo->bssid.bytes, - pRoamInfo->u. - pConnectedProfile->SSID.ssId, - pRoamInfo->u. - pConnectedProfile->SSID.length); - cfg80211_roamed_bss(dev, - roam_bss, - pFTAssocReq, - assocReqlen, - pFTAssocRsp, - assocRsplen, - GFP_KERNEL); - wlan_hdd_send_roam_auth_event( - pAdapter, - pRoamInfo->bssid.bytes, - pFTAssocReq, - assocReqlen, - pFTAssocRsp, - assocRsplen, - pRoamInfo); - } + roam_bss = + hdd_cfg80211_get_bss( + pAdapter->wdev.wiphy, + chan, + pRoamInfo->bssid.bytes, + pRoamInfo->u. + pConnectedProfile->SSID.ssId, + pRoamInfo->u. + pConnectedProfile->SSID.length); + cfg80211_roamed_bss(dev, + roam_bss, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + GFP_KERNEL); + wlan_hdd_send_roam_auth_event( + pAdapter, + pRoamInfo->bssid.bytes, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + pRoamInfo); } if (sme_get_ftptk_state (WLAN_HDD_GET_HAL_CTX(pAdapter), @@ -4923,8 +4917,11 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, hdd_debug("After Roam Synch Comp: NAPI Serialize OFF"); hdd_napi_serialize(0); hdd_set_roaming_in_progress(false); - if (pAdapter->defer_disconnect) - hdd_process_defer_disconnect(pAdapter); + if (roamResult == eCSR_ROAM_RESULT_FAILURE) + pAdapter->roam_ho_fail = true; + else + pAdapter->roam_ho_fail = false; + complete(&pAdapter->roaming_comp_var); break; case eCSR_ROAM_SHOULD_ROAM: /* notify apps that we can't pass traffic anymore */ @@ -4953,7 +4950,8 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, hdd_napi_serialize(0); hdd_set_connection_in_progress(false); hdd_set_roaming_in_progress(false); - pAdapter->defer_disconnect = 0; + pAdapter->roam_ho_fail = false; + complete(&pAdapter->roaming_comp_var); /* Call to clear any MC Addr List filter applied after * successful connection. @@ -5190,11 +5188,8 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, WLAN_CONTROL_PATH); hdd_set_connection_in_progress(false); hdd_set_roaming_in_progress(false); - /* - * If disconnect operation is in deferred state, do it now. - */ - if (pAdapter->defer_disconnect) - hdd_process_defer_disconnect(pAdapter); + pAdapter->roam_ho_fail = false; + complete(&pAdapter->roaming_comp_var); break; default: diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 1dd0e6d3d182..64fe97116684 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4597,19 +4597,6 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid, !roam_info_ptr->roamSynchInProgress) return 0; - /* - * The user space has issued a disconnect when roaming is in - * progress. The disconnect should be honored gracefully. - * If the roaming is complete and the roam event is sent - * back to the user space, it will get confused as it is - * expecting a disconnect event. So, do not send the event - * and handle the disconnect later. - */ - if (adapter->defer_disconnect) { - hdd_debug("LFR3:Do not send roam auth event"); - return 0; - } - skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy, &(adapter->wdev), ETH_ALEN + req_rsn_len + rsp_rsn_len + @@ -14707,27 +14694,28 @@ int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter) hal = WLAN_HDD_GET_HAL_CTX(pAdapter); if (pAdapter->device_mode == QDF_STA_MODE) { hdd_debug("Stop firmware roaming"); - sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued); - } - /* - * If firmware has already started roaming process, driver - * needs to defer the processing of this disconnect request. - * - */ - if (hdd_is_roaming_in_progress(pAdapter)) { - /* - * Defer the disconnect action until firmware roaming - * result is received. If STA is in connected state after - * that, send the disconnect command to CSR, otherwise - * CSR would have already sent disconnect event to upper - * layer. - */ + sme_stop_roaming(hal, pAdapter->sessionId, eCsrForcedDisassoc); - hdd_warn("Roaming in progress, deferred"); - pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT; - pAdapter->cfg80211_disconnect_reason = - eCSR_DISCONNECT_REASON_UNSPECIFIED; - return 0; + /* + * If firmware has already started roaming process, driver + * needs to wait for processing of this disconnect request. + * + */ + INIT_COMPLETION(pAdapter->roaming_comp_var); + if (hdd_is_roaming_in_progress(pAdapter)) { + rc = wait_for_completion_timeout( + &pAdapter->roaming_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM)); + if (!rc) { + hdd_err("roaming comp var timed out session Id: %d", + pAdapter->sessionId); + } + if (pAdapter->roam_ho_fail) { + INIT_COMPLETION(pAdapter->disconnect_comp_var); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Disconnecting); + } + } } if ((QDF_IBSS_MODE == pAdapter->device_mode) || @@ -15047,25 +15035,32 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) if (pAdapter->device_mode == QDF_STA_MODE) { hdd_debug("Stop firmware roaming"); status = sme_stop_roaming(hal, pAdapter->sessionId, - eCsrHddIssued); - } - /* - * If firmware has already started roaming process, driver - * needs to defer the processing of this disconnect request. - */ - if (hdd_is_roaming_in_progress(pAdapter)) { + eCsrForcedDisassoc); /* - * Defer the disconnect action until firmware roaming - * result is received. If STA is in connected state after - * that, send the disconnect command to CSR, otherwise - * CSR would have already sent disconnect event to upper - * layer. + * If firmware has already started roaming process, driver + * needs to wait for processing of this disconnect request. + * */ - hdd_warn("Roaming in progress, disconnect command deferred"); - pAdapter->defer_disconnect = - DEFER_DISCONNECT_CFG80211_DISCONNECT; - pAdapter->cfg80211_disconnect_reason = reason; - return 0; + INIT_COMPLETION(pAdapter->roaming_comp_var); + if (hdd_is_roaming_in_progress(pAdapter)) { + rc = wait_for_completion_timeout( + &pAdapter->roaming_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM)); + if (!rc) { + hdd_err("roaming comp var timed out session Id: %d", + pAdapter->sessionId); + } + if (pAdapter->roam_ho_fail) { + INIT_COMPLETION(pAdapter->disconnect_comp_var); + hdd_notice("Disabling queues"); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Disconnecting); + goto wait_for_disconnect; + } + } } prev_conn_state = pHddStaCtx->conn_info.connState; @@ -15101,6 +15096,7 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) result = -EINVAL; goto disconnected; } +wait_for_disconnect: rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, msecs_to_jiffies (WLAN_WAIT_TIME_DISCONNECT)); @@ -17472,36 +17468,6 @@ void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter) return; } -/** - * hdd_process_defer_disconnect() - Handle the deferred disconnect - * @adapter: HDD Adapter - * - * If roaming is in progress and there is a request to - * disconnect the session, then it is deferred. Once - * roaming is complete/aborted, then this routine is - * used to resume the disconnect that was deferred - * - * Return: None - */ -void hdd_process_defer_disconnect(hdd_adapter_t *adapter) -{ - switch (adapter->defer_disconnect) { - case DEFER_DISCONNECT_CFG80211_DISCONNECT: - adapter->defer_disconnect = 0; - wlan_hdd_disconnect(adapter, - adapter->cfg80211_disconnect_reason); - break; - case DEFER_DISCONNECT_TRY_DISCONNECT: - wlan_hdd_try_disconnect(adapter); - adapter->defer_disconnect = 0; - break; - default: - hdd_debug("Invalid source to defer:%d. Hence not handling it", - adapter->defer_disconnect); - break; - } -} - #define CNT_DIFF(cur, prev) \ ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1))) #define MAX_COUNT 0xffffffff diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index bd23ecb21780..fa172ec39584 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2843,6 +2843,7 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, init_completion(&adapter->session_open_comp_var); init_completion(&adapter->session_close_comp_var); init_completion(&adapter->disconnect_comp_var); + init_completion(&adapter->roaming_comp_var); init_completion(&adapter->linkup_event_var); init_completion(&adapter->cancel_rem_on_chan_var); init_completion(&adapter->rem_on_chan_ready_event); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index cc27419d29d4..c2259d5b0685 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1460,6 +1460,7 @@ QDF_STATUS hdd_wlan_re_init(void) pHddCtx->last_scan_reject_timestamp = 0; hdd_set_roaming_in_progress(false); + complete(&pAdapter->roaming_comp_var); pHddCtx->btCoexModeSet = false; /* Allow the phone to go to sleep */ diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 74cbfc1e5107..cf9b2576c631 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -325,6 +325,7 @@ void csr_roam_reset_roam_params(tpAniSirGlobal mac_ptr); #define REASON_ROAM_SCAN_STA_ROAM_POLICY_CHANGED 35 #define REASON_ROAM_SYNCH_FAILED 36 #define REASON_ROAM_PSK_PMK_CHANGED 37 +#define REASON_ROAM_STOP_ALL 38 #define REASON_SUPPLICANT_DISABLED_ROAMING 39 #define REASON_CTX_INIT 40 diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 3139dfa10c56..e6fd4c643119 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -8039,7 +8039,10 @@ QDF_STATUS sme_stop_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason) } req->Command = ROAM_SCAN_OFFLOAD_STOP; - req->reason = REASON_ROAM_SYNCH_FAILED; + if (reason == eCsrForcedDisassoc) + req->reason = REASON_ROAM_STOP_ALL; + else + req->reason = REASON_ROAM_SYNCH_FAILED; req->sessionId = sessionId; if (csr_neighbor_middle_of_roaming(mac_ctx, sessionId)) req->middle_of_roaming = 1; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 95c9f5e0376f..4681e3158f11 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -19412,7 +19412,7 @@ void csr_process_ho_fail_ind(tpAniSirGlobal mac_ctx, void *pMsgBuf) csr_roam_roaming_offload_timer_action(mac_ctx, 0, sessionId, ROAMING_OFFLOAD_TIMER_STOP); csr_roam_call_callback(mac_ctx, sessionId, NULL, 0, - eCSR_ROAM_NAPI_OFF, eSIR_SME_SUCCESS); + eCSR_ROAM_NAPI_OFF, eCSR_ROAM_RESULT_FAILURE); csr_roam_synch_clean_up(mac_ctx, sessionId); csr_roaming_report_diag_event(mac_ctx, NULL, eCSR_REASON_ROAM_HO_FAIL); diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index cf8f24a45d41..9016a23ee3d0 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1850,13 +1850,18 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, case ROAM_SCAN_OFFLOAD_STOP: wma_handle->suitable_ap_hb_failure = false; if (wma_handle->roam_offload_enabled) { + uint32_t mode; wma_roam_scan_fill_scan_params(wma_handle, pMac, NULL, &scan_params); + + if (roam_req->reason == REASON_ROAM_STOP_ALL) + mode = WMI_ROAM_SCAN_MODE_NONE; + else + mode = WMI_ROAM_SCAN_MODE_NONE | + WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; qdf_status = wma_roam_scan_offload_mode(wma_handle, - &scan_params, NULL, - WMI_ROAM_SCAN_MODE_NONE | - WMI_ROAM_SCAN_MODE_ROAMOFFLOAD, + &scan_params, NULL, mode, roam_req->sessionId); } /*