qcacld-3.0: Enhance SAP beacon template updation during DFS CSA
The hosts sends the beacon template to firmware through the
command WMI_BCN_TMPL_CMDID. The firmware sends a TX complete
indication via the WMI_OFFLOAD_BCN_TX_STATUS_EVENT and upon
receiving this host decrements the CSA count.
The hosts waits until the csa count becomes zero and then sends
vdev restart to firmware. There are some issues with this
implementation when 10 beacons with CSA are taking more time
than 1 sec. This is because in STA+SAP case sometime the
WMI_OFFLOAD_BCN_TX_STATUS_EVENT is received after in 200-300ms.
If the host doesn't receive the channel change event, it gets
struck in the channel change.
To avoid this scenario, send the beacon template to the firmware
for every beacon interval without waiting for the beacon TX
complete indication from FW except for the first beacon template
updation. Introduced a new timer (ap_ecsa_timer) to update the
firmware with the beacon template.
Change-Id: I377768b87c96fd5064aa04d1ed5434a475e656ef
CRs-Fixed: 2294661
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 19b6bd0..dd49f4a 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
@@ -5607,18 +5607,7 @@
dfs_csa_ie_req->ch_params.center_freq_seg0;
skip_vht:
/* Send CSA IE request from here */
- if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
- QDF_STATUS_SUCCESS) {
- pe_err("Unable to set CSA IE in beacon");
- return;
- }
-
- /*
- * First beacon update request is sent here, the remaining updates are
- * done when the FW responds back after sending the first beacon after
- * the template update
- */
- lim_send_beacon_ind(mac_ctx, session_entry);
+ lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
if (dfs_csa_ie_req->ch_params.ch_width == CH_WIDTH_80MHZ)
ch_offset = BW80;
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 d90522a..50c44f4 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
@@ -2298,32 +2298,6 @@
return;
}
-/*--------------------------------------------------------------------------
- \brief lim_send_dfs_chan_sw_ie_update()
- This timer handler updates the channel switch IE in beacon template
-
- \param pMac - pointer to global adapter context
- \return - channel to scan from valid session else zero.
- \sa
- --------------------------------------------------------------------------*/
-static void
-lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal pMac, tpPESession psessionEntry)
-{
-
- /* Update the beacon template and send to FW */
- if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != QDF_STATUS_SUCCESS) {
- pe_err("Unable to set CSA IE in beacon");
- return;
- }
-
- /* Send update beacon template message */
- lim_send_beacon_ind(pMac, psessionEntry);
- pe_debug("Updated CSA IE, IE COUNT: %d",
- psessionEntry->gLimChannelSwitch.switchCount);
-
- return;
-}
-
/** -----------------------------------------------------------------
\brief lim_send_sme_ap_channel_switch_resp() - sends
eWNI_SME_CHANNEL_CHANGE_RSP
@@ -2479,116 +2453,60 @@
}
#endif
-/** -----------------------------------------------------------------
- \brief lim_process_beacon_tx_success_ind() - This function is used
- explicitly to handle successful beacon transmission indication
- from the FW. This is a generic event generated by the FW afer the
- first beacon is sent out after the beacon template update by the
- host
- \param pMac - global mac structure
- \param psessionEntry - session info
- \return none
- \sa
- ----------------------------------------------------------------- */
void
-lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t msgType, void *event)
+lim_process_beacon_tx_success_ind(tpAniSirGlobal mac_ctx, uint16_t msgType,
+ void *event)
{
- /* Currently, this event is used only for DFS channel switch announcement
- * IE update in the template. If required to be used for other IE updates
- * add appropriate code by introducing a state variable
- */
- tpPESession psessionEntry;
- struct scheduler_msg mmhMsg = {0};
- tSirSmeCSAIeTxCompleteRsp *pChanSwTxResponse;
- struct sir_beacon_tx_complete_rsp *beacon_tx_comp_rsp_ptr;
- uint8_t length = sizeof(tSirSmeCSAIeTxCompleteRsp);
- tpSirFirstBeaconTxCompleteInd pBcnTxInd =
+ tpPESession session;
+ struct scheduler_msg msg = {0};
+ struct sir_beacon_tx_complete_rsp *bcn_tx_comp_rsp;
+ tpSirFirstBeaconTxCompleteInd bcn_ind =
(tSirFirstBeaconTxCompleteInd *) event;
- uint8_t ch, ch_width;
+ QDF_STATUS status;
- psessionEntry = pe_find_session_by_bss_idx(pMac, pBcnTxInd->bssIdx);
- if (psessionEntry == NULL) {
- pe_err("Session Does not exist for given sessionID");
+ session = pe_find_session_by_bss_idx(mac_ctx, bcn_ind->bssIdx);
+ if (!session) {
+ pe_err("Session Does not exist for given session id");
return;
}
- pe_debug("role: %d swIe: %d opIe: %d",
- GET_LIM_SYSTEM_ROLE(psessionEntry),
- psessionEntry->dfsIncludeChanSwIe,
- psessionEntry->gLimOperatingMode.present);
+ pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d",
+ GET_LIM_SYSTEM_ROLE(session),
+ session->dfsIncludeChanSwIe,
+ session->gLimOperatingMode.present,
+ session->gLimChannelSwitch.switchCount);
- if (LIM_IS_AP_ROLE(psessionEntry) &&
- true == psessionEntry->dfsIncludeChanSwIe) {
+ if (!LIM_IS_AP_ROLE(session))
+ return;
- if (psessionEntry->gLimChannelSwitch.switchCount) {
- /* Decrement the beacon switch count */
- psessionEntry->gLimChannelSwitch.switchCount--;
- pe_debug("current beacon count %d",
- psessionEntry->gLimChannelSwitch.switchCount);
- }
+ if (session->dfsIncludeChanSwIe &&
+ (session->gLimChannelSwitch.switchCount ==
+ mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt))
+ lim_process_ap_ecsa_timeout(session);
- /* Send only 5 beacons with CSA IE Set in when a radar is detected */
- if (psessionEntry->gLimChannelSwitch.switchCount > 0) {
- /*
- * Send the next beacon with updated CSA IE count
- */
- lim_send_dfs_chan_sw_ie_update(pMac, psessionEntry);
- ch = psessionEntry->gLimChannelSwitch.primaryChannel;
- ch_width = psessionEntry->gLimChannelSwitch.ch_width;
- if (pMac->sap.SapDfsInfo.dfs_beacon_tx_enhanced)
- /* Send Action frame after updating beacon */
- lim_send_chan_switch_action_frame(pMac,
- ch, ch_width, psessionEntry);
-
- } else {
- /* Done with CSA IE update, send response back to SME */
- psessionEntry->gLimChannelSwitch.switchCount = 0;
- if (pMac->sap.SapDfsInfo.disable_dfs_ch_switch == false)
- psessionEntry->gLimChannelSwitch.switchMode = 0;
- psessionEntry->dfsIncludeChanSwIe = false;
- psessionEntry->dfsIncludeChanWrapperIe = false;
-
- pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *)
- qdf_mem_malloc(length);
-
- if (NULL == pChanSwTxResponse) {
- pe_err("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp");
- return;
- }
-
- pChanSwTxResponse->sessionId =
- psessionEntry->smeSessionId;
- pChanSwTxResponse->chanSwIeTxStatus =
- QDF_STATUS_SUCCESS;
-
- mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND;
- mmhMsg.bodyptr = pChanSwTxResponse;
- mmhMsg.bodyval = 0;
- lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
- }
- }
-
- if (LIM_IS_AP_ROLE(psessionEntry) &&
- psessionEntry->gLimOperatingMode.present) {
+ if (session->gLimOperatingMode.present) {
/* Done with nss update, send response back to SME */
- psessionEntry->gLimOperatingMode.present = 0;
- beacon_tx_comp_rsp_ptr = (struct sir_beacon_tx_complete_rsp *)
- qdf_mem_malloc(sizeof(*beacon_tx_comp_rsp_ptr));
- if (NULL == beacon_tx_comp_rsp_ptr) {
- pe_err("AllocateMemory failed for beacon_tx_comp_rsp_ptr");
+ session->gLimOperatingMode.present = 0;
+ bcn_tx_comp_rsp = (struct sir_beacon_tx_complete_rsp *)
+ qdf_mem_malloc(sizeof(*bcn_tx_comp_rsp));
+ if (NULL == bcn_tx_comp_rsp) {
+ pe_err("AllocateMemory failed for bcn_tx_comp_rsp");
return;
}
- beacon_tx_comp_rsp_ptr->session_id =
- psessionEntry->smeSessionId;
- beacon_tx_comp_rsp_ptr->tx_status = QDF_STATUS_SUCCESS;
- mmhMsg.type = eWNI_SME_NSS_UPDATE_RSP;
- mmhMsg.bodyptr = beacon_tx_comp_rsp_ptr;
- mmhMsg.bodyval = 0;
- lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ bcn_tx_comp_rsp->session_id = session->smeSessionId;
+ bcn_tx_comp_rsp->tx_status = QDF_STATUS_SUCCESS;
+ msg.type = eWNI_SME_NSS_UPDATE_RSP;
+ msg.bodyptr = bcn_tx_comp_rsp;
+ msg.bodyval = 0;
+ status = scheduler_post_msg(QDF_MODULE_ID_SME, &msg);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ sme_err("Failed to post eWNI_SME_NSS_UPDATE_RSP");
+ qdf_mem_free(bcn_tx_comp_rsp);
+ }
}
- lim_handle_bss_color_change_ie(pMac, psessionEntry);
+ lim_handle_bss_color_change_ie(mac_ctx, session);
return;
}
diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h
index 0529083..6ff6e2e 100644
--- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h
+++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h
@@ -112,6 +112,14 @@
void lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tpSwitchChannelParams pChnlParams);
+/*
+ * lim_process_beacon_tx_success_ind() - handle successful beacon transmission
+ * indication from the FW This is a generic event generated by the FW afer the
+ * first beacon is sent out after the beacon template update by the host.
+ *
+ * @mac_ctx: Global mac_ctx
+ * @msg_type: msg_type
+ */
void
lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t msgType,
void *event);
diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c
index ef5b12e..a2420a9 100644
--- a/core/mac/src/pe/lim/lim_session.c
+++ b/core/mac/src/pe/lim/lim_session.c
@@ -161,6 +161,14 @@
return;
}
+ /*
+ * If dfsIncludeChanSwIe is set restrat timer as we are going to change
+ * channel and no point in checking protection mode for this channel.
+ */
+ if (pe_session_entry->dfsIncludeChanSwIe) {
+ pe_err("CSA going on restart timer");
+ goto restart_timer;
+ }
current_protection_state |=
pe_session_entry->gLimOverlap11gParams.protectionEnabled |
pe_session_entry->gLimOverlap11aParams.protectionEnabled << 1 |
@@ -254,6 +262,7 @@
}
pe_session_entry->old_protection_state = current_protection_state;
+restart_timer:
if (qdf_mc_timer_start(&pe_session_entry->
protection_fields_reset_timer,
SCH_PROTECTION_RESET_TIME)
@@ -709,6 +718,13 @@
pe_err("cannot create protection fields reset timer");
else
session_ptr->is_obss_reset_timer_initialized = true;
+
+ status = qdf_mc_timer_init(&session_ptr->ap_ecsa_timer,
+ QDF_TIMER_TYPE_WAKE_APPS,
+ lim_process_ap_ecsa_timeout,
+ (void *)&pMac->lim.gpSession[i]);
+ if (status != QDF_STATUS_SUCCESS)
+ pe_err("cannot create ap_ecsa_timer");
}
pe_init_fils_info(session_ptr);
pe_init_pmf_comeback_timer(pMac, session_ptr, *sessionId);
@@ -880,6 +896,8 @@
if (LIM_IS_AP_ROLE(session)) {
qdf_mc_timer_stop(&session->protection_fields_reset_timer);
qdf_mc_timer_destroy(&session->protection_fields_reset_timer);
+ qdf_mc_timer_stop(&session->ap_ecsa_timer);
+ qdf_mc_timer_destroy(&session->ap_ecsa_timer);
lim_del_pmf_sa_query_timer(mac_ctx, session);
}
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
index 0afe87d..1e8a97d 100644
--- a/core/mac/src/pe/lim/lim_utils.c
+++ b/core/mac/src/pe/lim/lim_utils.c
@@ -8321,3 +8321,103 @@
return;
}
+void
+lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal mac_ctx, tpPESession session)
+{
+ /* Update the beacon template and send to FW */
+ if (sch_set_fixed_beacon_fields(mac_ctx, session) !=
+ QDF_STATUS_SUCCESS) {
+ pe_err("Unable to set CSA IE in beacon");
+ return;
+ }
+
+ /* Send update beacon template message */
+ lim_send_beacon_ind(mac_ctx, session);
+ pe_debug("Updated CSA IE, IE COUNT: %d",
+ session->gLimChannelSwitch.switchCount);
+}
+
+void lim_process_ap_ecsa_timeout(void *data)
+{
+ tpPESession session = (tpPESession)data;
+ tpAniSirGlobal mac_ctx;
+ uint8_t bcn_int, ch, ch_width;
+ QDF_STATUS status;
+
+ if (!session) {
+ pe_err("Session is NULL");
+ return;
+ }
+
+ mac_ctx = (tpAniSirGlobal)session->mac_ctx;
+
+ if (!session->dfsIncludeChanSwIe) {
+ pe_debug("session->dfsIncludeChanSwIe not set");
+ return;
+ }
+
+ if (session->gLimChannelSwitch.switchCount) {
+ /* Decrement the beacon switch count */
+ session->gLimChannelSwitch.switchCount--;
+ pe_debug("current beacon count %d",
+ session->gLimChannelSwitch.switchCount);
+ }
+
+ /*
+ * Send only g_sap_chanswitch_beacon_cnt beacons with CSA IE Set in
+ * when a radar is detected
+ */
+ if (session->gLimChannelSwitch.switchCount > 0) {
+ /* Send the next beacon with updated CSA IE count */
+ lim_send_dfs_chan_sw_ie_update(mac_ctx, session);
+
+ ch = session->gLimChannelSwitch.primaryChannel;
+ ch_width = session->gLimChannelSwitch.ch_width;
+ if (mac_ctx->sap.SapDfsInfo.dfs_beacon_tx_enhanced)
+ /* Send Action frame after updating beacon */
+ lim_send_chan_switch_action_frame(mac_ctx, ch, ch_width,
+ session);
+
+ /* Restart the timer */
+ if (session->beaconParams.beaconInterval)
+ bcn_int = session->beaconParams.beaconInterval;
+ else
+ bcn_int = WNI_CFG_BEACON_INTERVAL_STADEF;
+
+ status = qdf_mc_timer_start(&session->ap_ecsa_timer,
+ bcn_int);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ pe_err("cannot start ap_ecsa_timer");
+ 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) {
+ pe_err("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp");
+ 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_msg(QDF_MODULE_ID_SME, &msg);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ sme_err("Failed to post eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND");
+ qdf_mem_free(chan_switch_tx_rsp);
+ }
+ }
+}
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
index a639408..310d23d 100644
--- a/core/mac/src/pe/lim/lim_utils.h
+++ b/core/mac/src/pe/lim/lim_utils.h
@@ -1341,6 +1341,26 @@
enum rateid lim_get_min_session_txrate(tpPESession session);
/**
+ * lim_send_dfs_chan_sw_ie_update() - updates the channel switch IE in beacon
+ * template
+ *
+ * @mac_ctx - pointer to global mac context
+ * @session - A pointer to pesession
+ * Return None
+ */
+void lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal mac_ctx,
+ tpPESession session);
+
+/**
+ * lim_process_ap_ecsa_timeout() -process ECSA timeout which decrement csa count
+ * in beacon and update beacon template in firmware
+ *
+ * @data - A pointer to pesession
+ * Return None
+ */
+void lim_process_ap_ecsa_timeout(void *session);
+
+/**
* lim_send_chan_switch_action_frame()- Send an action frame
* containing CSA IE or ECSA IE depending on the connected
* sta capability.