diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index 884c287e4c11..3ce7101ed9d6 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -1548,6 +1548,31 @@ QDF_STATUS mlme_vdev_self_peer_delete(struct scheduler_msg *self_peer_del_msg) return status; } +/** + * ap_mlme_vdev_csa_complete() - callback to initiate csa complete + * + * @vdev_mlme: vdev mlme object + * + * This function is called for csa complete indication + * + * Return: QDF_STATUS + */ +static QDF_STATUS ap_mlme_vdev_csa_complete(struct vdev_mlme_obj *vdev_mlme) + +{ + uint8_t vdev_id; + + vdev_id = wlan_vdev_get_id(vdev_mlme->vdev); + mlme_legacy_debug("vdev id = %d ", vdev_id); + + if (lim_is_csa_tx_pending(vdev_id)) + lim_send_csa_tx_complete(vdev_id); + else + mlme_legacy_debug("CSAIE_TX_COMPLETE_IND already sent"); + + return QDF_STATUS_SUCCESS; +} + /** * struct sta_mlme_ops - VDEV MLME operation callbacks strucutre for sta * @mlme_vdev_start_send: callback to initiate actions of VDEV @@ -1645,6 +1670,7 @@ static struct vdev_mlme_ops ap_mlme_ops = { .mlme_vdev_ext_start_rsp = vdevmgr_vdev_start_rsp_handle, .mlme_vdev_ext_peer_delete_all_rsp = vdevmgr_vdev_peer_delete_all_rsp_handle, + .mlme_vdev_csa_complete = ap_mlme_vdev_csa_complete, }; static struct vdev_mlme_ops mon_mlme_ops = { diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 6c9ad5e845ce..6d7ca4679076 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2146,6 +2146,7 @@ lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType, void *event) { struct pe_session *session; + bool csa_tx_offload; tpSirFirstBeaconTxCompleteInd bcn_ind = (tSirFirstBeaconTxCompleteInd *) event; @@ -2163,10 +2164,12 @@ lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType, if (!LIM_IS_AP_ROLE(session)) return; - + csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, + WLAN_SOC_CEXT_CSA_TX_OFFLOAD); if (session->dfsIncludeChanSwIe && (session->gLimChannelSwitch.switchCount == - mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt)) + mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) && + !csa_tx_offload) lim_process_ap_ecsa_timeout(session); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index a73d40fb43f7..2045edfb9eb1 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7929,12 +7929,92 @@ lim_send_dfs_chan_sw_ie_update(struct mac_context *mac_ctx, struct pe_session *s session->gLimChannelSwitch.switchCount); } +bool lim_is_csa_tx_pending(uint8_t vdev_id) +{ + struct pe_session *session; + struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + bool csa_tx_offload; + + if (!mac_ctx) { + mlme_err("Invalid mac context"); + return false; + } + + session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); + if (!session) { + pe_err("Session does not exist for given vdev_id %d", vdev_id); + return false; + } + + csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, + WLAN_SOC_CEXT_CSA_TX_OFFLOAD); + if (session->dfsIncludeChanSwIe && + (session->gLimChannelSwitch.switchCount == + mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) && + csa_tx_offload) + return true; + + return false; +} + +void lim_send_csa_tx_complete(uint8_t vdev_id) +{ + QDF_STATUS status; + tSirSmeCSAIeTxCompleteRsp *chan_switch_tx_rsp; + struct pe_session *session; + struct scheduler_msg msg = {0}; + bool csa_tx_offload; + uint8_t length = sizeof(*chan_switch_tx_rsp); + struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + + if (!mac_ctx) { + mlme_err("Invalid mac context"); + return; + } + + session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); + if (!session) { + pe_err("Session does not exist for given vdev_id %d", vdev_id); + return; + } + + /* Stop the timer if already running in case of csa*/ + csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, + WLAN_SOC_CEXT_CSA_TX_OFFLOAD); + if (csa_tx_offload) + qdf_mc_timer_stop(&session->ap_ecsa_timer); + + /* Done with CSA IE update, send response back to SME */ + session->gLimChannelSwitch.switchCount = 0; + if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) + session->gLimChannelSwitch.switchMode = 0; + + session->dfsIncludeChanSwIe = false; + session->dfsIncludeChanWrapperIe = false; + + chan_switch_tx_rsp = qdf_mem_malloc(length); + if (!chan_switch_tx_rsp) + return; + + chan_switch_tx_rsp->sessionId = session->smeSessionId; + chan_switch_tx_rsp->chanSwIeTxStatus = QDF_STATUS_SUCCESS; + + msg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; + msg.bodyptr = chan_switch_tx_rsp; + + status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME, + QDF_MODULE_ID_SME, &msg); + if (QDF_IS_STATUS_ERROR(status)) + qdf_mem_free(chan_switch_tx_rsp); +} + void lim_process_ap_ecsa_timeout(void *data) { struct pe_session *session = (struct pe_session *)data; struct mac_context *mac_ctx; uint8_t bcn_int, ch_width; uint32_t ch_freq; + bool csa_tx_offload; QDF_STATUS status; if (!session || !session->valid) { @@ -7949,6 +8029,15 @@ void lim_process_ap_ecsa_timeout(void *data) return; } + if (lim_is_csa_tx_pending(session->vdev_id)) + return lim_send_csa_tx_complete(session->vdev_id); + + csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, + WLAN_SOC_CEXT_CSA_TX_OFFLOAD); + + if (csa_tx_offload) + return; + /* Stop the timer if already running */ qdf_mc_timer_stop(&session->ap_ecsa_timer); @@ -7992,32 +8081,7 @@ void lim_process_ap_ecsa_timeout(void *data) lim_process_ap_ecsa_timeout(session); } } else { - tSirSmeCSAIeTxCompleteRsp *chan_switch_tx_rsp; - struct scheduler_msg msg = {0}; - uint8_t length = sizeof(*chan_switch_tx_rsp); - - /* Done with CSA IE update, send response back to SME */ - session->gLimChannelSwitch.switchCount = 0; - if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) - session->gLimChannelSwitch.switchMode = 0; - session->dfsIncludeChanSwIe = false; - session->dfsIncludeChanWrapperIe = false; - - chan_switch_tx_rsp = qdf_mem_malloc(length); - if (!chan_switch_tx_rsp) - return; - - chan_switch_tx_rsp->sessionId = session->smeSessionId; - chan_switch_tx_rsp->chanSwIeTxStatus = QDF_STATUS_SUCCESS; - - msg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; - msg.bodyptr = chan_switch_tx_rsp; - - status = scheduler_post_message(QDF_MODULE_ID_PE, - QDF_MODULE_ID_SME, - QDF_MODULE_ID_SME, &msg); - if (QDF_IS_STATUS_ERROR(status)) - qdf_mem_free(chan_switch_tx_rsp); + lim_send_csa_tx_complete(session->vdev_id); } } diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 24fa999ea436..07f05025a529 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1667,6 +1667,23 @@ void lim_send_dfs_chan_sw_ie_update(struct mac_context *mac_ctx, */ void lim_process_ap_ecsa_timeout(void *session); +/** + * lim_send_csa_tx_complete() - send csa tx complete event when beacon + * count decremented to zero + * + * @vdev_id - vdev_id + * Return None + */ +void lim_send_csa_tx_complete(uint8_t vdev_id); + +/** + * lim_is_csa_tx_pending() - check id csa tx ind not sent + * + * @vdev_id - vdev_id + * Return - true if csa tx ind is not sent else false + */ +bool lim_is_csa_tx_pending(uint8_t vdev_id); + /** * lim_send_stop_bss_failure_resp() -send failure delete bss resp to sme * @mac_ctx: mac ctx