diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 57a5f3094d..c407c3fcd2 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2881,18 +2881,85 @@ static void __lim_counter_measures(tpAniSirGlobal pMac, tpPESession psessionEntr mac, psessionEntry, false); }; +/** + * lim_send_stop_bss_failure_resp() -send failure delete bss resp to sme + * @mac_ctx: mac ctx + * @session: session pointer + * + * Return None + */ +static void lim_send_stop_bss_failure_resp(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + session->limSmeState = session->limPrevSmeState; + + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session->peSessionId, + session->limSmeState)); + + lim_send_sme_rsp(mac_ctx, eWNI_SME_STOP_BSS_RSP, + eSIR_SME_STOP_BSS_FAILURE, session->smeSessionId, + session->transactionId); +} + +void lim_delete_all_peers(tpPESession session) +{ + uint8_t i = 0; + tpAniSirGlobal mac_ctx = session->mac_ctx; + tpDphHashNode sta_ds = NULL; + QDF_STATUS status; + + for (i = 1; i < session->dph.dphHashTable.size; i++) { + sta_ds = dph_get_hash_entry(mac_ctx, i, + &session->dph.dphHashTable); + if (!sta_ds) + continue; + status = lim_del_sta(mac_ctx, sta_ds, false, session); + if (QDF_STATUS_SUCCESS == status) { + lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, + sta_ds->assocId, session); + lim_release_peer_idx(mac_ctx, sta_ds->assocId, session); + } else { + pe_err("lim_del_sta failed with Status: %d", status); + QDF_ASSERT(0); + } + } +} + +void lim_send_vdev_stop(tpPESession session) +{ + tpAniSirGlobal mac_ctx = session->mac_ctx; + QDF_STATUS status; + + status = lim_del_bss(mac_ctx, NULL, session->bssIdx, session); + + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("delBss failed for bss %d", session->bssIdx); + lim_send_stop_bss_failure_resp(mac_ctx, session); + } +} + +/** + * lim_delete_peers_and_send_vdev_stop() -delete peers and send vdev stop + * @session: session pointer + * + * Return None + */ +static void lim_delete_peers_and_send_vdev_stop(tpPESession session) +{ + lim_delete_all_peers(session); + /* send a delBss to HAL and wait for a response */ + lim_send_vdev_stop(session); +} + static void __lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) { tSirSmeStopBssReq stopBssReq; - QDF_STATUS status; tLimSmeStates prevState; tpPESession psessionEntry; uint8_t smesessionId; uint8_t sessionId; uint16_t smetransactionId; - uint8_t i = 0; - tpDphHashNode pStaDs = NULL; qdf_mem_copy(&stopBssReq, pMsgBuf, sizeof(tSirSmeStopBssReq)); smesessionId = stopBssReq.sessionId; @@ -2947,6 +3014,7 @@ __lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) stopBssReq.reasonCode); prevState = psessionEntry->limSmeState; + psessionEntry->limPrevSmeState = prevState; psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; MTRACE(mac_trace @@ -2991,36 +3059,9 @@ __lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) */ pMac->lim.gLimIbssCoalescingHappened = false; } - for (i = 1; i < psessionEntry->dph.dphHashTable.size; i++) { - pStaDs = - dph_get_hash_entry(pMac, i, &psessionEntry->dph.dphHashTable); - if (NULL == pStaDs) - continue; - status = lim_del_sta(pMac, pStaDs, false, psessionEntry); - if (QDF_STATUS_SUCCESS == status) { - lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, - pStaDs->assocId, psessionEntry); - lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry); - } else { - pe_err("lim_del_sta failed with Status: %d", status); - QDF_ASSERT(0); - } - } - /* send a delBss to HAL and wait for a response */ - status = lim_del_bss(pMac, NULL, psessionEntry->bssIdx, psessionEntry); - if (status != QDF_STATUS_SUCCESS) { - pe_err("delBss failed for bss %d", psessionEntry->bssIdx); - psessionEntry->limSmeState = prevState; + lim_delete_peers_and_send_vdev_stop(psessionEntry); - MTRACE(mac_trace - (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, - psessionEntry->limSmeState)); - - lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, - eSIR_SME_STOP_BSS_FAILURE, smesessionId, - smetransactionId); - } } /** diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index fd3f3d7848..63eeb8f527 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1360,6 +1360,23 @@ void lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal mac_ctx, */ void lim_process_ap_ecsa_timeout(void *session); +/** + * lim_delete_all_peers() -delete all connected peers + * @session: session pointer + * + * Return None + */ +void lim_delete_all_peers(tpPESession session); + +/** + * lim_send_vdev_stop() -send delete bss/stop vdev req + * @session: session pointer + * + * Return None + */ +void lim_send_vdev_stop(tpPESession session); + + /** * lim_send_chan_switch_action_frame()- Send an action frame * containing CSA IE or ECSA IE depending on the connected diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index c2661049a2..e9df305d69 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -540,6 +540,33 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev, uint32_t peer_type, uint8_t vdev_id, bool roam_synch_in_progress); +/** + * wma_send_del_bss_response() - send delete bss resp + * @wma: wma handle + * @req: target request + * + * Return: none + */ +void wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req); +/** + * __wma_vdev_stop_resp_handler() - vdev stop response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: QDF_STATUS_SUCCESS for success or QDF_ERROR code + */ +QDF_STATUS +__wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event); + +/** + * wma_vdev_stop_resp_handler() - vdev stop response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, u32 len); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index fae07469f1..46c26b4362 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1953,22 +1953,12 @@ wma_check_and_find_mcc_ap(tp_wma_handle wma, uint8_t vdev_id) {} #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ -/** - * wma_send_del_bss_response() - send del bss resp to upper layer - * @wma: wma handle. - * @vdev_id: vdev ID of device for which MCC has to be checked - * - * This function sends del bss resp to upper layer - * - * Return: none - */ -static void -wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req, - uint8_t vdev_id) +void wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req) { struct wma_txrx_node *iface; struct beacon_info *bcn; tpDeleteBssParams params; + uint8_t vdev_id; void *soc = cds_get_context(QDF_MODULE_ID_SOC); if (!req) { @@ -1976,6 +1966,7 @@ wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req, return; } + vdev_id = req->vdev_id; iface = &wma->interfaces[vdev_id]; if (!iface->handle) { WMA_LOGE("%s vdev id %d is already deleted", @@ -1987,12 +1978,6 @@ wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req, } params = (tpDeleteBssParams)req->user_data; - if (wma_send_vdev_down_to_fw(wma, vdev_id) != QDF_STATUS_SUCCESS) { - WMA_LOGE("Failed to send vdev down cmd: vdev %d", vdev_id); - } else { - wma_vdev_set_mlme_state(wma, vdev_id, WLAN_VDEV_S_STOP); - wma_check_and_find_mcc_ap(wma, vdev_id); - } cdp_fc_vdev_flush(soc, iface->handle); WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for VDEV_STOP rsp", @@ -2040,41 +2025,51 @@ wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req, } /** - * wma_vdev_stop_resp_handler() - vdev stop response handler - * @handle: wma handle - * @cmd_param_info: event buffer - * @len: buffer length + * wma_send_del_bss_response() - send del bss resp to upper layer + * @wma: wma handle. + * @vdev_id: vdev ID of device for which MCC has to be checked * - * Return: 0 for success or error code + * This function sends del bss resp to upper layer + * + * Return: none */ -int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, - u32 len) +static void +wma_send_vdev_down_bss(tp_wma_handle wma, struct wma_target_req *req) { - tp_wma_handle wma = (tp_wma_handle) handle; - WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf; - wmi_vdev_stopped_event_fixed_param *resp_event; + uint8_t vdev_id; + + if (!req) { + WMA_LOGE("%s req is NULL", __func__); + return; + } + + vdev_id = req->vdev_id; + + if (wma_send_vdev_down_to_fw(wma, vdev_id) != QDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to send vdev down cmd: vdev %d", vdev_id); + } else { + wma_vdev_set_mlme_state(wma, vdev_id, WLAN_VDEV_S_STOP); + wma_check_and_find_mcc_ap(wma, vdev_id); + } + + wma_send_del_bss_response(wma, req); +} + +QDF_STATUS +__wma_vdev_stop_resp_handler(wmi_vdev_stopped_event_fixed_param *resp_event) +{ + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); struct wma_target_req *req_msg, *del_req; struct cdp_pdev *pdev; void *peer = NULL; uint8_t peer_id; struct wma_txrx_node *iface; - int32_t status = 0; + int status = 0; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - WMA_LOGD("%s: Enter", __func__); - - param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; - if (!param_buf) { - WMA_LOGE("Invalid event buffer"); - return -EINVAL; - } - - resp_event = param_buf->fixed_param; - - if (resp_event->vdev_id >= wma->max_bssid) { - WMA_LOGE("%s: Invalid vdev_id %d from FW", - __func__, resp_event->vdev_id); - return -EINVAL; + if (!wma) { + WMA_LOGE("%s: wma is null", __func__); + return QDF_STATUS_E_INVAL; } iface = &wma->interfaces[resp_event->vdev_id]; @@ -2099,7 +2094,7 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, if (!req_msg) { WMA_LOGE("%s: Failed to lookup vdev request for vdev id %d", __func__, resp_event->vdev_id); - return -EINVAL; + return QDF_STATUS_E_INVAL; } pdev = cds_get_context(QDF_MODULE_ID_TXRX); @@ -2144,7 +2139,7 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, wmi_service_sync_delete_cmds)) goto free_req_msg; - wma_send_del_bss_response(wma, req_msg, resp_event->vdev_id); + wma_send_vdev_down_bss(wma, req_msg); } else if (req_msg->msg_type == WMA_SET_LINK_STATE) { tpLinkStateParams params = (tpLinkStateParams) req_msg->user_data; @@ -2190,7 +2185,42 @@ free_req_msg: PEER_DEBUG_ID_WMA_VDEV_STOP_RESP); qdf_mc_timer_destroy(&req_msg->event_timeout); qdf_mem_free(req_msg); - return status; + + if (status) + return QDF_STATUS_E_INVAL; + else + return QDF_STATUS_SUCCESS; +} + +int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, + u32 len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf; + wmi_vdev_stopped_event_fixed_param *resp_event; + int32_t status = 0; + + WMA_LOGD("%s: Enter", __func__); + + param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + + resp_event = param_buf->fixed_param; + + if (resp_event->vdev_id >= wma->max_bssid) { + WMA_LOGE("%s: Invalid vdev_id %d from FW", + __func__, resp_event->vdev_id); + return -EINVAL; + } + + status = __wma_vdev_stop_resp_handler(resp_event); + if (QDF_IS_STATUS_ERROR(status)) + return -EINVAL; + + return 0; } /** @@ -3106,7 +3136,7 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, } wma_send_msg(wma, WMA_SET_LINK_STATE_RSP, (void *)params, 0); } else if (req_msg->type == WMA_DELETE_PEER_RSP) { - wma_send_del_bss_response(wma, req_msg, req_msg->vdev_id); + wma_send_vdev_down_bss(wma, req_msg); } qdf_mem_free(req_msg); return status;