wlan: Switch to new channel once ECSA is indicated in beacon
Once ECSA is indicated in beacon Swith to new channel and update the
beacon on new channel.
Change-Id: I8f9b1dd5d6b3fe7a9b41d3dc8cfa6016d28b18e6
CRs-Fixed: 2143138
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 5257cfb..2768d24 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -243,6 +243,7 @@
* for a period of time on a particular DFS channel
*/
TX_TIMER gLimActiveToPassiveChannelTimer;
+ TX_TIMER g_lim_ap_ecsa_timer;
//********************TIMER SECTION ENDS**************************************************
// ALL THE FIELDS BELOW THIS CAN BE ZEROED OUT in limInitialize
//****************************************************************************************
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 6693298..3a59b44 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -6351,4 +6351,47 @@
uint8_t bssid[VOS_MAC_ADDR_SIZE];
};
+/**
+ * struct sir_ecsa_ie_complete_ind - structure to send indication that ECSA IE
+ * TX completion in beacon
+ * @session_id: session on which ECSA IE was sent
+ */
+struct sir_ecsa_ie_complete_ind {
+ uint8_t session_id;
+};
+
+/**
+ * struct sir_channel_chanege_req - structure to send channel change req to LIM
+ * @type: type of msg
+ * @len: length of msg
+ * @new_chan: new channel to which switch is requested
+ * @cb_mode:cbmode of the new channel
+ * @bssid: bssid of the AP
+ * @dot11mode: new dot11 mode
+ * @operational_rateset: new rate set
+ * @extended_rateset: new extended rate set
+ */
+struct sir_channel_chanege_req {
+ uint16_t type;
+ uint16_t len;
+ uint8_t new_chan;
+ uint8_t cb_mode;
+ uint8_t bssid[VOS_MAC_ADDR_SIZE];
+ uint32_t dot11mode;
+ tSirMacRateSet operational_rateset;
+ tSirMacRateSet extended_rateset;
+};
+
+/**
+ * struct sir_channel_chanege_rsp - structure for channel change resp from LIM
+ * @sme_session_id: sme session on which channel was changed
+ * @new_channel: new channel to which channel is changed
+ * @status:status of channel change
+ */
+struct sir_channel_chanege_rsp {
+ uint8_t sme_session_id;
+ uint8_t new_channel;
+ VOS_STATUS status;
+};
+
#endif /* __SIR_API_H */
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 855c7ee..a5579eb 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -397,6 +397,9 @@
eWNI_SME_DEL_BA_SES_REQ,
eWNI_SME_SET_CHAN_SW_IE_REQ,
+ eWNI_SME_ECSA_IE_BEACON_COMP_IND,
+ eWNI_SME_ECSA_CHAN_CHANGE_REQ,
+ eWNI_SME_ECSA_CHAN_CHANGE_RSP,
eWNI_SME_MSG_TYPES_END
};
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index dca671d..98f5107 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -913,6 +913,7 @@
#define SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE (SIR_LIM_TIMEOUT_MSG_START + 0x2C)
#define SIR_LIM_AUTH_RETRY_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2D)
+#define SIR_LIM_SAP_ECSA_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2E)
#define SIR_LIM_MSG_TYPES_END (SIR_LIM_MSG_TYPES_BEGIN+0xFF)
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index e037756..a09aead 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1722,6 +1722,7 @@
case eWNI_SME_MAC_SPOOF_ADDR_IND:
case eWNI_SME_REGISTER_MGMT_FRAME_CB:
case eWNI_SME_SET_CHAN_SW_IE_REQ:
+ case eWNI_SME_ECSA_CHAN_CHANGE_REQ:
// These messages are from HDD
limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd
break;
@@ -2009,6 +2010,7 @@
case SIR_LIM_DEAUTH_ACK_TIMEOUT:
case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
case SIR_LIM_AUTH_RETRY_TIMEOUT:
+ case SIR_LIM_SAP_ECSA_TIMEOUT:
#ifdef WLAN_FEATURE_LFR_MBB
case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT:
case SIR_LIM_REASSOC_MBB_RSP_TIMEOUT:
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
index 195f844..63952b6 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
@@ -176,6 +176,7 @@
break;
case SIR_LIM_DISASSOC_ACK_TIMEOUT: limProcessDisassocAckTimeout(pMac); break;
case SIR_LIM_DEAUTH_ACK_TIMEOUT: limProcessDeauthAckTimeout(pMac); break;
+ case SIR_LIM_SAP_ECSA_TIMEOUT: lim_process_ap_ecsa_timeout(pMac);break;
case LIM_MLM_ADDBA_REQ: limProcessMlmAddBAReq( pMac, Msg->bodyptr ); break;
case LIM_MLM_ADDBA_RSP: limProcessMlmAddBARsp( pMac, Msg->bodyptr ); break;
case LIM_MLM_DELBA_REQ: limProcessMlmDelBAReq( pMac, Msg->bodyptr ); break;
@@ -3517,6 +3518,94 @@
limSendDeauthCnf(pMac);
}
+void lim_process_ap_ecsa_timeout(tpAniSirGlobal mac_ctx)
+{
+ tSirMsgQ msg = {0};
+ struct sir_ecsa_ie_complete_ind *ecsa_ie_cmp_ind;
+ tpPESession session;
+
+ session = peFindSessionBySessionId(mac_ctx,
+ mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer.sessionId);
+
+ if(!session)
+ {
+ limLog(mac_ctx, LOGE, FL("session does not exist for given sessionId %d"),
+ mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer.sessionId);
+ return;
+ }
+ limLog(mac_ctx, LOG1, FL("session id %d switch count %d"),
+ mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer.sessionId,
+ session->gLimChannelSwitch.switchCount);
+ /*
+ * For each beacon interval decrement switch count to use proper value
+ * in probe resp sent by host. Once it becomes 0 send tx complete
+ * indication to SME.
+ */
+ if (session->gLimChannelSwitch.switchCount > 0) {
+ session->gLimChannelSwitch.switchCount--;
+ mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer.sessionId =
+ session->peSessionId;
+ limDeactivateAndChangeTimer(mac_ctx, eLIM_AP_ECSA_TIMER);
+
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer) !=
+ TX_SUCCESS)
+ {
+ limLog(mac_ctx, LOGE, FL("Couldn't activate g_lim_ap_ecsa_timer"));
+ lim_process_ap_ecsa_timeout(mac_ctx);
+ }
+ return;
+ }
+
+ session->include_ecsa_ie = false;
+ session->include_wide_ch_bw_ie = false;
+
+ ecsa_ie_cmp_ind = vos_mem_malloc(sizeof(*ecsa_ie_cmp_ind));
+ if(!ecsa_ie_cmp_ind)
+ {
+ limLog(mac_ctx, LOGE, FL("failed to allocate ecsa_ie_cmp_ind"));
+ return;
+ }
+ ecsa_ie_cmp_ind->session_id = session->smeSessionId;
+
+ msg.type = eWNI_SME_ECSA_IE_BEACON_COMP_IND;
+ msg.bodyptr = ecsa_ie_cmp_ind;
+ limSysProcessMmhMsgApi(mac_ctx, &msg, ePROT);
+ return;
+}
+
+void lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal mac_ctx,
+ tpPESession session, tpSwitchChannelParams chan_params)
+{
+ tSirMsgQ msg = {0};
+ struct sir_channel_chanege_rsp *params;
+
+ params = vos_mem_malloc(sizeof(*params));
+ if (!params) {
+ limLog(mac_ctx, LOGE, FL("AllocateMemory failed for pSmeSwithChnlParams"));
+ return;
+ }
+
+ params->sme_session_id = session->smeSessionId;
+ params->new_channel = chan_params->channelNumber;
+ params->status = chan_params->status;
+
+ msg.type = eWNI_SME_ECSA_CHAN_CHANGE_RSP;
+ msg.bodyptr = params;
+ msg.bodyval = 0;
+ limSysProcessMmhMsgApi(mac_ctx, &msg, ePROT);
+
+ if (chan_params->channelNumber == session->currentOperChannel) {
+ limApplyConfiguration(mac_ctx, session);
+ limSendBeaconInd(mac_ctx, session);
+ } else {
+ limLog(mac_ctx, LOGE, FL("channel switch resp chan %d and session channel doesnt match %d"),
+ chan_params->channelNumber, session->currentOperChannel);
+ }
+
+ return;
+}
+
+
/**
* limProcessMlmDeauthReq()
*
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
index 52c0799..85932f8 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
@@ -4181,6 +4181,10 @@
pMac->lim.gpchangeChannelCallback(pMac, status, pMac->lim.gpchangeChannelData, psessionEntry);
}
break;
+ case LIM_SWITCH_CHANNEL_SAP_ECSA:
+ lim_send_sme_ap_channel_switch_resp(pMac,
+ psessionEntry, pChnlParams);
+ break;
default:
break;
}
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index e9d5187..ea216a3 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -5697,13 +5697,109 @@
}
limSendBeaconInd(mac_ctx, session_entry);
- session_entry->include_ecsa_ie = false;
- session_entry->include_wide_ch_bw_ie = false;
limLog(mac_ctx, LOG1, FL("IE count:%d chan:%d secondarySubBand:%d"),
session_entry->gLimChannelSwitch.switchCount,
session_entry->gLimChannelSwitch.primaryChannel,
session_entry->gLimChannelSwitch.secondarySubBand);
+
+ mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer.sessionId =
+ session_entry->peSessionId;
+ limDeactivateAndChangeTimer(mac_ctx, eLIM_AP_ECSA_TIMER);
+
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.g_lim_ap_ecsa_timer) !=
+ TX_SUCCESS)
+ {
+ limLog(mac_ctx, LOGE, FL("Couldn't activate g_lim_ap_ecsa_timer"));
+ lim_process_ap_ecsa_timeout(mac_ctx);
+ }
+}
+
+/**
+ * lim_process_sme_channel_change_request() - process sme ch change req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_CHANNEL_CHANGE_REQ message
+ *
+ * Return: None
+ */
+static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ struct sir_channel_chanege_req *ch_change_req;
+ tpPESession session_entry;
+ uint8_t session_id; /* PE session_id */
+ int8_t max_tx_pwr;
+ uint32_t val = 0;
+
+ if (!msg_buf) {
+ limLog(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+ ch_change_req = (struct sir_channel_chanege_req *)msg_buf;
+
+ max_tx_pwr = cfgGetRegulatoryMaxTransmitPower(mac_ctx,
+ ch_change_req->new_chan);
+
+ if ((max_tx_pwr == WDA_MAX_TXPOWER_INVALID)) {
+ limLog(mac_ctx, LOGE, FL("Invalid Request/max_tx_pwr"));
+ return;
+ }
+
+ session_entry = peFindSessionByBssid(mac_ctx,
+ ch_change_req->bssid, &session_id);
+ if (!session_entry) {
+ limLog(mac_ctx, LOGE,
+ FL("Session not found for given BSSID" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(ch_change_req->bssid));
+ return;
+ }
+
+ if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
+ limLog(mac_ctx, LOGE, FL("Invalid SystemRole %d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ return;
+ }
+ if (session_entry->currentOperChannel ==
+ ch_change_req->new_chan) {
+ limLog(mac_ctx, LOGE, FL("target CH is same as current CH %d"),
+ session_entry->currentOperChannel);
+ return;
+ }
+
+ session_entry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_SAP_ECSA;
+
+ limLog(mac_ctx, LOGE, FL("switch old chnl %d to new chnl %d, cb_mode %d"),
+ session_entry->currentOperChannel,
+ ch_change_req->new_chan,
+ ch_change_req->cb_mode);
+
+ /* Store the New Channel Params in session_entry */
+ session_entry->htSecondaryChannelOffset =
+ limGetHTCBState(ch_change_req->cb_mode);
+ session_entry->htSupportedChannelWidthSet = (ch_change_req->cb_mode ? 1 : 0);
+ session_entry->htRecommendedTxWidthSet =
+ session_entry->htSupportedChannelWidthSet;
+ session_entry->currentOperChannel = ch_change_req->new_chan;
+ session_entry->limRFBand = limGetRFBand(session_entry->currentOperChannel);
+ /* Initialize 11h Enable Flag */
+ if (SIR_BAND_5_GHZ == session_entry->limRFBand) {
+ if (wlan_cfgGetInt(mac_ctx, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS)
+ limLog(mac_ctx, LOGE, FL("Fail to get WNI_CFG_11H_ENABLED"));
+ }
+
+ session_entry->lim11hEnable = val;
+ session_entry->dot11mode = ch_change_req->dot11mode;
+ vos_mem_copy(&session_entry->rateSet, &ch_change_req->operational_rateset,
+ sizeof(session_entry->rateSet));
+ vos_mem_copy(&session_entry->extRateSet, &ch_change_req->extended_rateset,
+ sizeof(session_entry->extRateSet));
+ limSetChannel(mac_ctx, ch_change_req->new_chan,
+ session_entry->htSecondaryChannelOffset,
+ max_tx_pwr, session_entry->peSessionId);
}
/**
@@ -6068,6 +6164,10 @@
break;
case eWNI_SME_SET_CHAN_SW_IE_REQ:
lim_process_sme_set_csa_ie_request(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_ECSA_CHAN_CHANGE_REQ:
+ lim_process_sme_channel_change_request(pMac, pMsgBuf);
+ break;
default:
vos_mem_free((v_VOID_t*)pMsg->bodyptr);
pMsg->bodyptr = NULL;
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index 1e47421..5a5163a 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -734,6 +734,17 @@
limLog(pMac, LOG1,
FL("gLimActiveToPassiveChannelTimer not created %d"), cfgValue);
}
+ cfgValue = WNI_CFG_BEACON_INTERVAL_STADEF;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.g_lim_ap_ecsa_timer,
+ "AP ECSA TIMER", limTimerHandler,
+ SIR_LIM_SAP_ECSA_TIMEOUT,
+ cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGW,FL("could not create timer for passive channel to active channel"));
+ goto err_timer;
+ }
return TX_SUCCESS;
@@ -772,6 +783,7 @@
tx_timer_delete(&pMac->lim.limTimers.gLimMinChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
+ tx_timer_delete(&pMac->lim.limTimers.g_lim_ap_ecsa_timer);
if(NULL != pMac->lim.gLimPreAuthTimerTable.pTable)
{
@@ -1896,8 +1908,35 @@
return;
}
break;
+ case eLIM_AP_ECSA_TIMER:
+ if (tx_timer_deactivate(
+ &pMac->lim.limTimers.g_lim_ap_ecsa_timer) != TX_SUCCESS)
+ {
+ /*
+ * Could not deactivate SingleShot NOA Insert
+ * timer. Log error.
+ */
+ limLog(pMac, LOGE, FL("Unable to deactivate AP ecsa timer"));
+ return;
+ }
+ if ((psessionEntry = peFindSessionBySessionId(pMac,
+ pMac->lim.limTimers.g_lim_ap_ecsa_timer.sessionId)) == NULL)
+ {
+ limLog(pMac, LOGE,
+ FL("session does not exist for given SessionId : %d, for AP ecsa timer"),
+ pMac->lim.limTimers.g_lim_ap_ecsa_timer.sessionId);
+ break;
+ }
+ val = psessionEntry->beaconParams.beaconInterval;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change(&pMac->lim.limTimers.g_lim_ap_ecsa_timer,
+ val, 0) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGE, FL("Unable to change g_lim_ap_ecsa_timer timer"));
+ }
- default:
+ break;
+ default:
// Invalid timerId. Log error
break;
}
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index eba64ac..2b10fdc 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -78,6 +78,7 @@
eLIM_INSERT_SINGLESHOT_NOA_TIMER,
eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE,
eLIM_AUTH_RETRY_TIMER,
+ eLIM_AP_ECSA_TIMER,
#ifdef WLAN_FEATURE_LFR_MBB
eLIM_PREAUTH_MBB_RSP_TIMER,
eLIM_REASSOC_MBB_RSP_TIMER
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index 6325d69..1062dae 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -167,6 +167,7 @@
LIM_SWITCH_CHANNEL_JOIN,
LIM_SWITCH_CHANNEL_OPERATION, // Generic change channel
LIM_SWITCH_CHANNEL_CSA,
+ LIM_SWITCH_CHANNEL_SAP_ECSA,
};
typedef struct sLimAuthRspTimeout
@@ -1060,6 +1061,26 @@
void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac);
void limProcessDisassocAckTimeout(tpAniSirGlobal pMac);
void limProcessDeauthAckTimeout(tpAniSirGlobal pMac);
+/**
+ * lim_process_ap_ecsa_timeout() -process ECSA timeout which indicate ECSA IE TX
+ * complete in beacon
+ * @mac_ctx - A pointer to Global MAC structure
+ *
+ * Return None
+ */
+void lim_process_ap_ecsa_timeout(tpAniSirGlobal mac_ctx);
+/**
+ * lim_send_sme_ap_channel_switch_resp() -process channel switch resp for ecsa
+ * channel switch req
+ * @mac_ctx - A pointer to Global MAC structure
+ * @session: session on which channel switch was done
+ * @chan_param: channel switch resp params
+ *
+ * Return None
+ */
+void lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal mac_ctx,
+ tpPESession session, tpSwitchChannelParams chan_param);
+
eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac);
eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 97f3daf..560e7f7 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -1138,6 +1138,9 @@
tx_timer_deactivate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
+ tx_timer_deactivate(&pMac->lim.limTimers.g_lim_ap_ecsa_timer);
+ tx_timer_delete(&pMac->lim.limTimers.g_lim_ap_ecsa_timer);
+
pMac->lim.gLimTimersCreated = 0;
}
diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c
index a0234c6..34cc975 100644
--- a/CORE/SAP/src/sapApiLinkCntl.c
+++ b/CORE/SAP/src/sapApiLinkCntl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1135,6 +1135,94 @@
return sapstatus;
}// WLANSAP_ScanCallback
+/**
+ * sap_roam_process_ecsa_bcn_tx_ind() - handles the case for
+ * eCSR_ROAM_ECSA_BCN_TX_IND in wlansap_roam_callback()
+ * @hal: hal global context
+ * @sap_ctx: sap context
+ *
+ * Return: VOS_STATUS
+ */
+static VOS_STATUS sap_roam_process_ecsa_bcn_tx_ind(tHalHandle hHal,
+ ptSapContext sap_ctx)
+{
+ tWLAN_SAPEvent sap_event;
+ VOS_STATUS qdf_status;
+
+ if (eSAP_STARTED != sap_ctx->sapsMachine) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_WARN,
+ FL("eCSR_ROAM_ECSA_BCN_TX_IND received in (%d) state"),
+ sap_ctx->sapsMachine);
+ return VOS_STATUS_E_INVAL;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("sapdfs: from state eSAP_STARTED => eSAP_DISCONNECTING"));
+ /* SAP to be moved to DISCONNECTING state */
+ sap_ctx->sapsMachine = eSAP_DISCONNECTING;
+
+ /* Send channel switch request */
+ sap_event.event = eWNI_ECSA_TX_COMPLETED;
+ sap_event.params = 0;
+ sap_event.u1 = 0;
+ sap_event.u2 = 0;
+ /* Handle event */
+ qdf_status = sapFsm(sap_ctx, &sap_event);
+ if (!VOS_IS_STATUS_SUCCESS(qdf_status)) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ FL("post chnl chng req failed, sap[%pK]"), sap_ctx);
+ return VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * sap_roam_process_ch_change_resp() - handles the case for
+ * eCSR_ROAM_ECSA_CHAN_CHANGE_RSP in function wlansap_roam_callback()
+ * @sap_ctx: sap context
+ * @csr_roam_info: raom info struct
+ *
+ * Return: VOS_STATUS
+ */
+static VOS_STATUS sap_roam_process_ch_change_resp(ptSapContext sap_ctx,
+ tCsrRoamInfo *csr_roam_info)
+{
+ tWLAN_SAPEvent sap_event;
+ VOS_STATUS status;
+
+ if (!VOS_IS_STATUS_SUCCESS(csr_roam_info->ap_chan_change_rsp->status)) {
+ sap_event.event = eWNI_ECSA_CHANNEL_CHANGE_RSP;
+ sap_event.params = 0;
+ sap_event.u1 = eCSR_ROAM_INFRA_IND;
+ sap_event.u2 = eCSR_ROAM_RESULT_FAILURE;
+
+ status = sapFsm(sap_ctx, &sap_event);
+ return status;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("sapdfs: changing target channel to [%d]"),
+ sap_ctx->ecsa_info.new_channel);
+ sap_ctx->channel = sap_ctx->ecsa_info.new_channel;
+
+ if (eSAP_DISCONNECTING != sap_ctx->sapsMachine)
+ return VOS_STATUS_E_FAILURE;
+
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING on sapctx[%pK]"),
+ sap_ctx);
+ sap_ctx->sapsMachine = eSAP_STARTING;
+ sap_ctx->ecsa_info.channel_switch_in_progress = false;
+ sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
+ sap_event.params = csr_roam_info;
+ sap_event.u1 = eCSR_ROAM_INFRA_IND;
+ sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
+
+ /* Handle the event */
+ status = sapFsm(sap_ctx, &sap_event);
+ return status;
+}
+
/*==========================================================================
FUNCTION WLANSAP_RoamCallback()
@@ -1335,7 +1423,31 @@
sapCheckHT2040CoexAction(sapContext, pCsrRoamInfo->pSmeHT2040CoexInfoInd);
break;
#endif
+ case eCSR_ROAM_ECSA_BCN_TX_IND:
+ {
+ tHalHandle hal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("CSR roamStatus = %s (%d)"),
+ get_eRoamCmdStatus_str(roamStatus), roamStatus);
+ if (!hal)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ "In %s invalid hHal", __func__);
+ halStatus = eHAL_STATUS_FAILED_ALLOC;
+ break;
+ }
+ vosStatus = sap_roam_process_ecsa_bcn_tx_ind(hal, sapContext);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ halStatus = eHAL_STATUS_FAILURE;
+ break;
+ }
+ case eCSR_ROAM_ECSA_CHAN_CHANGE_RSP:
+ vosStatus = sap_roam_process_ch_change_resp(sapContext,
+ pCsrRoamInfo);
+ if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+ halStatus = eHAL_STATUS_FAILURE;
+ break;
default:
VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
FL("CSR roamStatus not handled roamStatus = %s (%d)"),
diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c
index 42f4f47..be18ea4 100644
--- a/CORE/SAP/src/sapFsm.c
+++ b/CORE/SAP/src/sapFsm.c
@@ -977,6 +977,41 @@
} /* sapSignalApAppStartBssEvent */
+/**
+ * wlansap_channel_change_request() -Initiate the channel change req to new
+ * channel
+ * @sapContext - sap context on which channel change is required
+ *
+ * Return VOS_STATUS
+ */
+static VOS_STATUS wlansap_channel_change_request(ptSapContext sapContext)
+{
+ tHalHandle hal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
+ VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+
+ if (!hal) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ "In %s, Hall is NULL", __func__);
+ return VOS_STATUS_E_INVAL;
+ }
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_MED,
+ FL("sapdfs: Send channel change on sapctx[%pK]"),
+ sapContext);
+ sapContext->channel = sapContext->ecsa_info.new_channel;
+ if (sapContext->csrRoamProfile.ChannelInfo.numOfChannels == 0 ||
+ sapContext->csrRoamProfile.ChannelInfo.ChannelList == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ FL("Invalid channel list"));
+ return VOS_STATUS_E_FAULT;
+ }
+ sapContext->csrRoamProfile.ChannelInfo.ChannelList[0] = sapContext->channel;
+ vos_status = sme_roam_channel_change_req(hal, sapContext->bssid,
+ sapContext->ecsa_info.new_channel,
+ &sapContext->csrRoamProfile);
+ return vos_status;
+}
+
+
/*==========================================================================
FUNCTION sapFsm
@@ -1248,14 +1283,23 @@
(v_PVOID_t) eSAP_STATUS_SUCCESS);
}
}
- }
- if (msg == eSAP_CHANNEL_SELECTION_FAILED)
+ } else if (msg == eSAP_CHANNEL_SELECTION_FAILED)
{
/* Set SAP device role */
sapContext->sapsMachine = eSAP_CH_SELECT;
/* Perform sme_ScanRequest */
vosStatus = sapGotoChannelSel(sapContext, sapEvent);
+ } else if (msg == eWNI_ECSA_TX_COMPLETED)
+ {
+ vosStatus = wlansap_channel_change_request(sapContext);
+ } else if (msg == eWNI_ECSA_CHANNEL_CHANGE_RSP)
+ {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+ FL("in state %s, event msg %d result %d"),
+ "eSAP_DISCONNECTING ", msg, sapEvent->u2);
+ if (sapEvent->u2 == eCSR_ROAM_RESULT_FAILURE)
+ vosStatus = sapGotoDisconnecting(sapContext);
}
else
{
diff --git a/CORE/SAP/src/sapFsm_ext.h b/CORE/SAP/src/sapFsm_ext.h
index ebaa824..9123c39 100644
--- a/CORE/SAP/src/sapFsm_ext.h
+++ b/CORE/SAP/src/sapFsm_ext.h
@@ -51,6 +51,8 @@
eSAP_HDD_STOP_INFRA_BSS,
eSAP_WRITE_REMOTE_AMP_ASSOC,
eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START,
+ eWNI_ECSA_TX_COMPLETED,
+ eWNI_ECSA_CHANNEL_CHANGE_RSP,
eSAP_NO_MSG
}eSapMsg_t;
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index 715c7e6..5ac3d94 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -520,6 +520,8 @@
eCSR_ROAM_UPDATE_MAX_RATE_IND,
eCSR_ROAM_LOST_LINK_PARAMS_IND,
eCSR_ROAM_UPDATE_SCAN_RESULT,
+ eCSR_ROAM_ECSA_BCN_TX_IND,
+ eCSR_ROAM_ECSA_CHAN_CHANGE_RSP,
}eRoamCmdStatus;
@@ -1342,6 +1344,7 @@
tDot11fIEVHTOperation vht_operation;
tDot11fIEHTInfo ht_operation;
bool reassoc;
+ struct sir_channel_chanege_rsp *ap_chan_change_rsp;
}tCsrRoamInfo;
typedef struct tagCsrFreqScanInfo
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
index 7e5ec7f..fbbd5d0 100644
--- a/CORE/SME/inc/smeInside.h
+++ b/CORE/SME/inc/smeInside.h
@@ -377,5 +377,17 @@
VOS_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx,
tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode);
+/**
+ * csr_roam_channel_change_req() - Post channel change request to LIM
+ * @mac_ctx: Global MAC context
+ * @bssid: BSSID
+ * @new_chan: Channel on which to send the IE
+ * @cb_mode: cb mode
+ * @profile: ap profile
+ *
+ * Return: VOS_STATUS
+ **/
+VOS_STATUS csr_roam_channel_change_req(tpAniSirGlobal mac_ctx,
+ tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode ,tCsrRoamProfile *profile);
#endif //#if !defined( __SMEINSIDE_H )
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 431f568..a853885 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4021,4 +4021,19 @@
VOS_STATUS sme_roam_csa_ie_request(tHalHandle hal, tCsrBssid bssid,
uint8_t new_chan, uint32_t phy_mode);
+/**
+ * sme_roam_channel_change_req() - Channel change to new target channel
+ * @hal: handle returned by mac_open
+ * @bssid: SAP bssid
+ * @new_chan: target channel information
+ * @profile: roam profile
+ *
+ * API to Indicate Channel change to new target channel
+ *
+ * Return: VOS_STATUS
+ */
+VOS_STATUS sme_roam_channel_change_req(tHalHandle hal, tCsrBssid bssid,
+ uint8_t new_chan, tCsrRoamProfile *profile);
+
+
#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index e897126..b06ffb4 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -2837,7 +2837,10 @@
* failure, decrement bRefAssocStartCnt.
*/
pSession->bRefAssocStartCnt--;
- }
+ } else if (u1 == eCSR_ROAM_ECSA_CHAN_CHANGE_RSP && u2 ==
+ eCSR_ROAM_RESULT_NONE)
+ pSession->connectedProfile.operationChannel =
+ pRoamInfo->ap_chan_change_rsp->new_channel;
if(NULL != pSession->callback)
{
@@ -19670,7 +19673,49 @@
status = palSendMBMessage(mac_ctx->hHdd, msg);
if (!VOS_IS_STATUS_SUCCESS(status))
smsLog(mac_ctx, LOGE,
- FL(" channel switch req fauiled status %d "), status);
+ FL(" channel switch IE req failed status %d "), status);
return status;
}
+VOS_STATUS csr_roam_channel_change_req(tpAniSirGlobal mac_ctx,
+ tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode, tCsrRoamProfile *profile)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ struct sir_channel_chanege_req *msg;
+ tCsrRoamStartBssParams param;
+
+ vos_mem_zero(¶m, sizeof(tCsrRoamStartBssParams));
+
+ csrRoamGetBssStartParms(mac_ctx, profile, ¶m);
+
+ msg = vos_mem_malloc(sizeof(*msg));
+ if (!msg) {
+ smsLog(mac_ctx, LOGE, FL(" Memory alloc failed "));
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ msg->type = eWNI_SME_ECSA_CHAN_CHANGE_REQ;
+ msg->len = sizeof(*msg);
+
+ msg->new_chan = new_chan;
+ msg->cb_mode = cb_mode;
+ vos_mem_copy(msg->bssid, bssid, VOS_MAC_ADDR_SIZE);
+ msg->dot11mode = csrTranslateToWNICfgDot11Mode(mac_ctx,
+ mac_ctx->roam.configParam.uCfgDot11Mode);
+ if (IS_24G_CH(msg->new_chan) &&
+ (false == mac_ctx->roam.configParam.enableVhtFor24GHz) &&
+ (WNI_CFG_DOT11_MODE_11AC == msg->dot11mode ||
+ WNI_CFG_DOT11_MODE_11AC_ONLY == msg->dot11mode))
+ msg->dot11mode = WNI_CFG_DOT11_MODE_11N;
+
+ vos_mem_copy(&msg->operational_rateset,
+ ¶m.operationalRateSet, sizeof(msg->operational_rateset));
+ vos_mem_copy(&msg->extended_rateset,
+ ¶m.extendedRateSet, sizeof(msg->extended_rateset));
+
+ status = palSendMBMessage(mac_ctx->hHdd, msg);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ smsLog(mac_ctx, LOGE,
+ FL(" channel switch req fauiled status %d "), status);
+ return status;
+}
diff --git a/CORE/SME/src/csr/csrUtil.c b/CORE/SME/src/csr/csrUtil.c
index 52687fe..4f4d524 100644
--- a/CORE/SME/src/csr/csrUtil.c
+++ b/CORE/SME/src/csr/csrUtil.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1304,6 +1304,8 @@
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
CASE_RETURN_STR(eCSR_ROAM_UPDATE_MAX_RATE_IND);
CASE_RETURN_STR(eCSR_ROAM_LOST_LINK_PARAMS_IND);
+ CASE_RETURN_STR(eCSR_ROAM_ECSA_BCN_TX_IND);
+ CASE_RETURN_STR(eCSR_ROAM_ECSA_CHAN_CHANGE_RSP);
default:
return "unknown";
}
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 76d943b..6d523a3 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -2384,6 +2384,72 @@
return status;
}
+/**
+ * sme_ecsa_msg_processor() - Handle ECSA indication and resp from LIM
+ * @mac_ctx: A pointer to Global MAC structure
+ * @msg_type: Indication/resp type
+ * @msg_buf: Indication/resp buffer
+ *
+ * Return VOS_STATUS
+ */
+static VOS_STATUS sme_ecsa_msg_processor(tpAniSirGlobal mac_ctx,
+ uint16_t msg_type, void *msg_buf)
+{
+ tCsrRoamInfo roam_info = { 0 };
+ struct sir_ecsa_ie_complete_ind *ecsa_ie_cmp_ind;
+ struct sir_channel_chanege_rsp *chan_params;
+ uint32_t session_id = 0;
+ eRoamCmdStatus roamStatus;
+ eCsrRoamResult roamResult;
+
+ switch (msg_type) {
+ case eWNI_SME_ECSA_IE_BEACON_COMP_IND:
+ ecsa_ie_cmp_ind =
+ (struct sir_ecsa_ie_complete_ind *) msg_buf;
+ if (!ecsa_ie_cmp_ind) {
+ smsLog(mac_ctx, LOGE, FL("pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ session_id = ecsa_ie_cmp_ind->session_id;
+ roamStatus = eCSR_ROAM_ECSA_BCN_TX_IND;
+ roamResult = eCSR_ROAM_RESULT_NONE;
+ smsLog(mac_ctx, LOG1, FL("sapdfs: Received eWNI_SME_ECSA_IE_BEACON_COMP_IND for session id [%d]"),
+ session_id);
+ break;
+ case eWNI_SME_ECSA_CHAN_CHANGE_RSP:
+ chan_params = (struct sir_channel_chanege_rsp *)msg_buf;
+ roam_info.ap_chan_change_rsp =
+ vos_mem_malloc(sizeof(struct sir_channel_chanege_rsp));
+ if (!roam_info.ap_chan_change_rsp) {
+ smsLog(mac_ctx, LOGE, FL("failed to allocate ap_chan_change_rsp"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ session_id = chan_params->sme_session_id;
+ roam_info.ap_chan_change_rsp->sme_session_id = session_id;
+ roam_info.ap_chan_change_rsp->new_channel = chan_params->new_channel;
+ if (chan_params->status == VOS_STATUS_SUCCESS) {
+ roam_info.ap_chan_change_rsp->status = VOS_STATUS_SUCCESS;
+ roamResult = eCSR_ROAM_RESULT_NONE;
+ } else {
+ roam_info.ap_chan_change_rsp->status = VOS_STATUS_E_FAILURE;
+ roamResult = eCSR_ROAM_RESULT_FAILURE;
+ }
+ roamStatus = eCSR_ROAM_ECSA_CHAN_CHANGE_RSP;
+ break;
+ default:
+ smsLog(mac_ctx, LOGE, FL("Invalid ECSA message: 0x%x"), msg_type);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ /* Indicate Radar Event to SAP */
+ csrRoamCallCallback(mac_ctx, session_id, &roam_info, 0,
+ roamStatus, roamResult);
+ if (roam_info.ap_chan_change_rsp)
+ vos_mem_free(roam_info.ap_chan_change_rsp);
+
+ return VOS_STATUS_SUCCESS;
+}
+
/*--------------------------------------------------------------------------
\brief sme_ProcessMsg() - The main message processor for SME.
@@ -2873,6 +2939,21 @@
" nothing to process");
}
break;
+ case eWNI_SME_ECSA_IE_BEACON_COMP_IND:
+ case eWNI_SME_ECSA_CHAN_CHANGE_RSP:
+ MTRACE(vos_trace(VOS_MODULE_ID_SME,
+ TRACE_CODE_SME_RX_WDA_MSG, NO_SESSION, pMsg->type));
+ if (pMsg->bodyptr)
+ {
+ sme_ecsa_msg_processor(pMac, pMsg->type, pMsg->bodyptr);
+ vos_mem_free(pMsg->bodyptr);
+ }
+ else
+ {
+ smsLog(pMac, LOGE,
+ FL("Empty message for (eWNI_SME_ECSA_IE_BEACON_COMP_IND)"));
+ }
+ break;
default:
@@ -15111,3 +15192,24 @@
return status;
}
+
+VOS_STATUS sme_roam_channel_change_req(tHalHandle hal, tCsrBssid bssid,
+ uint8_t new_chan, tCsrRoamProfile *profile)
+{
+ VOS_STATUS status;
+ tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+ uint8_t cb_mode = 0;
+
+ status = sme_AcquireGlobalLock(&mac_ctx->sme);
+ if (VOS_IS_STATUS_SUCCESS(status)) {
+ if (CSR_IS_CHANNEL_5GHZ(new_chan)) {
+ sme_SelectCBMode(hal, profile->phyMode, new_chan);
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
+ }
+ status = csr_roam_channel_change_req(mac_ctx, bssid, new_chan, cb_mode,
+ profile);
+ sme_ReleaseGlobalLock(&mac_ctx->sme);
+ }
+ return status;
+}
+
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 70c2f7a..5c72c14 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -583,6 +583,9 @@
CASE_RETURN_STRING(eWNI_SME_CAP_TSF_REQ);
CASE_RETURN_STRING(eWNI_SME_GET_TSF_REQ);
CASE_RETURN_STRING(eWNI_SME_SET_CHAN_SW_IE_REQ);
+ CASE_RETURN_STRING(eWNI_SME_ECSA_IE_BEACON_COMP_IND);
+ CASE_RETURN_STRING(eWNI_SME_ECSA_CHAN_CHANGE_REQ);
+ CASE_RETURN_STRING(eWNI_SME_ECSA_CHAN_CHANGE_RSP);
default:
return( (tANI_U8*)"UNKNOWN" );
break;
@@ -998,6 +1001,7 @@
#endif
CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT);
+ CASE_RETURN_STRING(SIR_LIM_SAP_ECSA_TIMEOUT);
CASE_RETURN_STRING(SIR_LIM_MSG_TYPES_END);
CASE_RETURN_STRING(LIM_MLM_SCAN_REQ);