wlan: Add support to send ECSA IE in beacons in SAP/GO
Adds support for ECSA and CSA IE in beacons in SAP/GO.
Channel change will be initiated by IOCTL.
Change-Id: I8d4b9161015c03ed58648ca203be7d29e6c0975e
CRs-Fixed: 2143138
diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h
index 764384e..aaccdd9 100644
--- a/CORE/HDD/inc/qc_sap_ioctl.h
+++ b/CORE/HDD/inc/qc_sap_ioctl.h
@@ -195,7 +195,8 @@
QCSAP_PARAM_GET_FRAME_LOGS = 12,
QCSAP_PARAM_SET_PROXIMITY = 13,
QCSAP_PARAM_SET_WOWL = 14,
- QCSAP_PARAM_CAP_TSF = 15
+ QCSAP_PARAM_CAP_TSF = 15,
+ QCSAP_PARAM_SET_CHANNEL_CHANGE = 16,
};
int iw_softap_get_channel_list(struct net_device *dev,
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index c6a2412..235e0a6 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -2148,6 +2148,18 @@
(uint32_t *)&set_value, 1);
break;
}
+ case QCSAP_PARAM_SET_CHANNEL_CHANGE:
+ if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) ||
+ (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) {
+ hddLog(LOG1, FL("ET Channel Change to new channel= %d"),
+ set_value);
+ ret = wlansap_set_channel_change(pVosContext, set_value);
+ } else {
+ hddLog(LOGE, FL("Channel %d Change Failed, Device in not in SAP/GO mode"),
+ set_value);
+ ret = -EINVAL;
+ }
+ break;
default:
hddLog(LOGE, FL("Invalid setparam command %d value %d"),
sub_cmd, set_value);
@@ -4776,6 +4788,8 @@
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setProximity" },
{ QCSAP_PARAM_CAP_TSF,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "cap_tsf" },
+ {QCSAP_PARAM_SET_CHANNEL_CHANGE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setChanChange"},
{ QCSAP_PARAM_SET_WOWL,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wowl" },
{ QCSAP_IOCTL_GETPARAM,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 2bb9f04..6693298 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -155,6 +155,9 @@
#define WLAN_DISA_MAX_PAYLOAD_SIZE 1600
+#define CHANNEL_SWITCH_BEACON_COUNT 5
+#define SAP_CHANNEL_SWITCH_MODE 1
+
enum eSirHostMsgTypes
{
SIR_HAL_APP_SETUP_NTF = SIR_HAL_HOST_MSG_START,
@@ -6331,4 +6334,21 @@
typedef struct {
tANI_U8 session_id;
}tDelBaParams,*ptDelBaParams;
+
+/**
+ * struct sir_ecsa_ie_req - structure to send req to include ECSA IE in beacon
+ * @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
+ */
+struct sir_ecsa_ie_req {
+ uint16_t type;
+ uint16_t len;
+ uint8_t new_chan;
+ uint8_t cb_mode;
+ uint8_t bssid[VOS_MAC_ADDR_SIZE];
+};
+
#endif /* __SIR_API_H */
diff --git a/CORE/MAC/inc/sirMacProtDef.h b/CORE/MAC/inc/sirMacProtDef.h
index 52c172a..13b795c 100644
--- a/CORE/MAC/inc/sirMacProtDef.h
+++ b/CORE/MAC/inc/sirMacProtDef.h
@@ -392,6 +392,10 @@
#define SIR_MAC_RSN_EID_MIN 4
#define SIR_MAC_RSN_EID_MAX 254
+#define SIR_MAC_EXT_CHNL_SWITCH_ANN_EID 60
+#define SIR_MAC_WIDER_BW_CHANNEL_SWITCH_ANN 194
+
+
//using reserved EID for Qos Action IE for now,
//need to check 11e spec for the actual EID
#define SIR_MAC_QOS_ACTION_EID 49
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 6445286..855c7ee 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -396,6 +396,7 @@
#endif
eWNI_SME_DEL_BA_SES_REQ,
+ eWNI_SME_SET_CHAN_SW_IE_REQ,
eWNI_SME_MSG_TYPES_END
};
diff --git a/CORE/MAC/src/include/parserApi.h b/CORE/MAC/src/include/parserApi.h
index d891dc6..33f1fcd 100644
--- a/CORE/MAC/src/include/parserApi.h
+++ b/CORE/MAC/src/include/parserApi.h
@@ -574,6 +574,19 @@
struct sDphHashNode *pSta,
tpPESession psessionEntry);
+/**
+ * populate_dot11f_ext_chann_switch_ann() - Function to populate ECS
+ * @mac_ptr: Pointer to PMAC structure
+ * @dot_11_ptr: ECS element
+ * @session_entry: PE session entry
+ *
+ * This function is used to populate the extended channel switch element
+ *
+ * Return: None
+ */
+void populate_dot11f_ext_chann_switch_ann(tpAniSirGlobal mac_ctx,
+ tDot11fIEext_chan_switch_ann *dot_11_ptr, tpPESession session_entry);
+
/// Populate a tDot11fIEChanSwitchAnn
void
PopulateDot11fChanSwitchAnn(tpAniSirGlobal pMac,
@@ -582,7 +595,7 @@
/// Populate a tDot11fIEChanSwitchAnn
void
-PopulateDot11fExtChanSwitchAnn(tpAniSirGlobal pMac,
+PopulateDot11fsecChanOffset(tpAniSirGlobal pMac,
tDot11fIEsec_chan_offset *pDot11f,
tpPESession psessionEntry);
diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h
index 21b75bf..5a2a6e0 100644
--- a/CORE/MAC/src/pe/include/limSession.h
+++ b/CORE/MAC/src/pe/include/limSession.h
@@ -320,6 +320,8 @@
/* *********************11H related*****************************/
//tANI_U32 gLim11hEnable;
tLimSpecMgmtInfo gLimSpecMgmt;
+ bool include_ecsa_ie;
+ bool include_wide_ch_bw_ie;
// CB Primary/Secondary Channel Switch Info
tLimChannelSwitchInfo gLimChannelSwitch;
/* *********************End 11H related*****************************/
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index ddb9f5f..e037756 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1721,6 +1721,7 @@
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
case eWNI_SME_MAC_SPOOF_ADDR_IND:
case eWNI_SME_REGISTER_MGMT_FRAME_CB:
+ case eWNI_SME_SET_CHAN_SW_IE_REQ:
// These messages are from HDD
limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd
break;
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 346585c..e9d5187 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -5627,6 +5627,84 @@
else
limLog(pMac, LOGE, FL("sme_req->callback is null"));
}
+/**
+ * lim_process_sme_set_csa_ie_request() - process sme dfs csa ie req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ * Return: None
+ */
+static void lim_process_sme_set_csa_ie_request(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ struct sir_ecsa_ie_req *csa_ie_req = (struct sir_ecsa_ie_req *)msg_buf;
+ uint8_t session_id;
+ tpPESession session_entry = NULL;
+ tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch;
+
+ if (!csa_ie_req) {
+ limLog(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ session_entry = peFindSessionByBssid(mac_ctx,
+ csa_ie_req->bssid, &session_id);
+ if (!session_entry) {
+ limLog(mac_ctx, LOGE,
+ FL("Session not found for given BSSID" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(csa_ie_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;
+ }
+
+ /* target channel */
+ session_entry->gLimChannelSwitch.primaryChannel = csa_ie_req->new_chan;
+
+ /* Channel switch announcement needs to be included in beacon */
+ session_entry->include_ecsa_ie = true;
+ session_entry->gLimChannelSwitch.switchCount =
+ CHANNEL_SWITCH_BEACON_COUNT;
+ session_entry->gLimChannelSwitch.secondarySubBand =
+ csa_ie_req->cb_mode;
+ session_entry->gLimChannelSwitch.switchMode = SAP_CHANNEL_SWITCH_MODE;
+
+ /* Now encode the Wider Ch BW element depending on the ch width */
+ if (session_entry->vhtCapability &&
+ (csa_ie_req->cb_mode >=
+ PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED)) {
+ wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch;
+ session_entry->include_wide_ch_bw_ie = true;
+ wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ /* Fetch the center channel based on the channel width */
+ wider_bw_ch_switch->newCenterChanFreq0 =
+ limGetCenterChannel(mac_ctx, csa_ie_req->new_chan,
+ csa_ie_req->cb_mode,
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ);
+ }
+ /* Send ECSA/CSA IE request from here */
+ if (schSetFixedBeaconFields(mac_ctx, session_entry) != eSIR_SUCCESS) {
+ limLog(mac_ctx, LOGE, FL("Unable to set CSA IE in beacon"));
+ return;
+ }
+
+ 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);
+}
/**
* limProcessSmeReqMessages()
@@ -5988,6 +6066,8 @@
case eWNI_SME_REGISTER_MGMT_FRAME_CB:
lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf);
break;
+ case eWNI_SME_SET_CHAN_SW_IE_REQ:
+ lim_process_sme_set_csa_ie_request(pMac, pMsgBuf);
default:
vos_mem_free((v_VOID_t*)pMsg->bodyptr);
pMsg->bodyptr = NULL;
diff --git a/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
index 692e8dc..920da90 100644
--- a/CORE/MAC/src/pe/lim/limSendManagementFrames.c
+++ b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
@@ -798,6 +798,18 @@
}
#endif
+ if (LIM_IS_AP_ROLE(psessionEntry) && psessionEntry->include_ecsa_ie) {
+ populate_dot11f_ext_chann_switch_ann(pMac, &pFrm->ext_chan_switch_ann,
+ psessionEntry);
+ if (psessionEntry->lim11hEnable) {
+ PopulateDot11fChanSwitchAnn(pMac,
+ &pFrm->ChanSwitchAnn, psessionEntry);
+ if (psessionEntry->include_wide_ch_bw_ie)
+ PopulateDot11fWiderBWChanSwitchAnn(pMac,
+ &pFrm->WiderBWChanSwitchAnn, psessionEntry);
+ }
+ }
+
if ( psessionEntry->pLimStartBssReq )
{
diff --git a/CORE/MAC/src/pe/sch/schBeaconGen.c b/CORE/MAC/src/pe/sch/schBeaconGen.c
index 15438a7..19553ad 100644
--- a/CORE/MAC/src/pe/sch/schBeaconGen.c
+++ b/CORE/MAC/src/pe/sch/schBeaconGen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -377,6 +377,18 @@
}
#endif
+ if (LIM_IS_AP_ROLE(psessionEntry) && psessionEntry->include_ecsa_ie) {
+ populate_dot11f_ext_chann_switch_ann(pMac, &pBcn2->ext_chan_switch_ann,
+ psessionEntry);
+ if (psessionEntry->lim11hEnable) {
+ PopulateDot11fChanSwitchAnn(pMac,
+ &pBcn2->ChanSwitchAnn, psessionEntry);
+ if (psessionEntry->include_wide_ch_bw_ie)
+ PopulateDot11fWiderBWChanSwitchAnn(pMac,
+ &pBcn2->WiderBWChanSwitchAnn, psessionEntry);
+ }
+ }
+
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&pBcn2->ExtSuppRates, psessionEntry );
@@ -463,7 +475,6 @@
}
}
-
nStatus = dot11fPackBeacon2( pMac, pBcn2,
pMac->sch.schObject.gSchBeaconFrameEnd,
SCH_MAX_BEACON_SIZE, &nBytes );
@@ -591,13 +602,28 @@
sizeof(beacon2->PowerConstraints));
}
+
+ if (beacon2->ext_chan_switch_ann.present) {
+ SetProbeRspIeBitmap(DefProbeRspIeBitmap,
+ SIR_MAC_EXT_CHNL_SWITCH_ANN_EID);
+ vos_mem_copy((void *)&prb_rsp->ext_chan_switch_ann,
+ (void *)&beacon2->ext_chan_switch_ann,
+ sizeof(beacon2->ext_chan_switch_ann));
+ }
/* Channel Switch Annoouncement SIR_MAC_CHNL_SWITCH_ANN_EID */
if(beacon2->ChanSwitchAnn.present)
{
SetProbeRspIeBitmap(DefProbeRspIeBitmap,SIR_MAC_CHNL_SWITCH_ANN_EID);
vos_mem_copy((void *)&prb_rsp->ChanSwitchAnn, (void *)&beacon2->ChanSwitchAnn,
sizeof(beacon2->ChanSwitchAnn));
-
+ if (beacon2->WiderBWChanSwitchAnn.present)
+ {
+ SetProbeRspIeBitmap(DefProbeRspIeBitmap,
+ SIR_MAC_WIDER_BW_CHANNEL_SWITCH_ANN);
+ vos_mem_copy((void *)&prb_rsp->WiderBWChanSwitchAnn,
+ (void *)&beacon2->WiderBWChanSwitchAnn,
+ sizeof(beacon2->WiderBWChanSwitchAnn));
+ }
}
/* ERP information */
if(beacon2->ERPInfo.present)
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index 390e10b..3da71fa 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -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.
*
@@ -1617,6 +1617,17 @@
v_U16_t reason_code,
v_U8_t subtype,
struct tagCsrDelStaParams *pDelStaParams);
+/**
+ * wlansap_set_channel_change() -
+ * This function to support SAP channel change with CSA/ECSA IE
+ * set in the beacons.
+ *
+ * @vos_ctx: vos context.
+ * @new_channel: target channel number.
+ *
+ * Return: 0 for success, non zero for failure
+ */
+int wlansap_set_channel_change(v_PVOID_t vos_ctx, uint32_t new_channel);
#ifdef __cplusplus
}
diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c
index 9e48d8c..42f4f47 100644
--- a/CORE/SAP/src/sapFsm.c
+++ b/CORE/SAP/src/sapFsm.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.
*
@@ -1172,6 +1172,17 @@
sapContext->sapsMachine = eSAP_DISCONNECTING;
vosStatus = sapGotoDisconnecting(sapContext);
}
+ else if (msg == eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START ) {
+ tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
+ if (!hHal) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ "In %s, NULL hHal in state %s, msg %d",
+ __func__, "eSAP_STARTING", msg);
+ }
+ vosStatus = sme_roam_csa_ie_request(hHal, sapContext->bssid,
+ sapContext->ecsa_info.new_channel,
+ sapContext->csrRoamProfile.phyMode);
+ }
else
{
VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, invalid event msg %d",
diff --git a/CORE/SAP/src/sapFsm_ext.h b/CORE/SAP/src/sapFsm_ext.h
index bc5ee88..ebaa824 100644
--- a/CORE/SAP/src/sapFsm_ext.h
+++ b/CORE/SAP/src/sapFsm_ext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -50,6 +50,7 @@
eSAP_MAC_START_FAILS,
eSAP_HDD_STOP_INFRA_BSS,
eSAP_WRITE_REMOTE_AMP_ASSOC,
+ eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START,
eSAP_NO_MSG
}eSapMsg_t;
diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h
index dd94138..ed7cd1e 100644
--- a/CORE/SAP/src/sapInternal.h
+++ b/CORE/SAP/src/sapInternal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, 2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2015, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -189,6 +189,16 @@
} hdd_station_info_t;
+/**
+ * struct ecsa_info - structure to store ecsa info
+ * @new_channel: new channel to which switch is requested
+ * @channel_switch_in_progress: check if channel switch is in progress
+ */
+struct ecsa_info {
+ uint8_t new_channel;
+ bool channel_switch_in_progress;
+};
+
typedef struct sSapContext {
vos_lock_t SapGlobalLock;
@@ -275,6 +285,7 @@
v_U8_t ObssScanInterval;
v_U8_t ObssTransitionDelayFactor;
#endif
+ struct ecsa_info ecsa_info;
} *ptSapContext;
diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c
index 3b1749c..de981ca 100644
--- a/CORE/SAP/src/sapModule.c
+++ b/CORE/SAP/src/sapModule.c
@@ -2459,3 +2459,89 @@
pDelStaParams->reason_code, pDelStaParams->subtype,
MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
}
+
+/**
+ * wlansap_validate_phy_mode() -
+ * validate if the phymode allow the channel to set.
+ *
+ * @phy_mode: current phymode
+ * @channel: target channel number.
+ *
+ * Return: true if channel is allowed else false
+ */
+static bool wlansap_validate_phy_mode(uint32_t phy_mode, uint32_t channel)
+{
+ switch (phy_mode) {
+ case eSAP_DOT11_MODE_11a:
+ if (channel <= SIR_11B_CHANNEL_END)
+ return false;
+ case eSAP_DOT11_MODE_11b:
+ case eSAP_DOT11_MODE_11g:
+ case eSAP_DOT11_MODE_11g_ONLY:
+ case eSAP_DOT11_MODE_11b_ONLY:
+ if (channel > SIR_11B_CHANNEL_END)
+ return false;
+ default:
+ return true;
+ }
+
+ return true;
+}
+
+int wlansap_set_channel_change(v_PVOID_t vos_ctx, uint32_t new_channel)
+{
+ ptSapContext sap_ctx;
+ tWLAN_SAPEvent sap_event = {0};
+ v_PVOID_t hal;
+ tpAniSirGlobal mac_ctx;
+
+ sap_ctx = VOS_GET_SAP_CB(vos_ctx);
+
+ if (!sap_ctx) {
+ hddLog(LOGE, FL("sap_ctx is NULL"));
+ return -EINVAL;
+ }
+
+ hal = VOS_GET_HAL_CB(sap_ctx->pvosGCtx);
+ if (!hal) {
+ hddLog(LOGE, FL("hal is NULL"));
+ return -EINVAL;
+ }
+ mac_ctx = PMAC_STRUCT(hal);
+ if (sap_ctx->channel == new_channel) {
+ hddLog(LOGE, FL("channel %d already set"), new_channel);
+ return -EALREADY;
+ }
+ if (sap_ctx->ecsa_info.channel_switch_in_progress) {
+ hddLog(LOGE, FL("channel switch already in progress ignore"));
+ return -EALREADY;
+ }
+ if (NV_CHANNEL_ENABLE != vos_nv_getChannelEnabledState(new_channel)) {
+ hddLog(LOGE, FL("Invalid channel Ignore channel switch "));
+ return -EINVAL;
+ }
+
+ if (eSAP_STARTED != sap_ctx->sapsMachine) {
+ hddLog(LOGE, FL("SAP is not in eSAP_STARTED state "));
+ return -EINVAL;
+ }
+ if (!wlansap_validate_phy_mode(sap_ctx->csrRoamProfile.phyMode,
+ new_channel)) {
+ hddLog(LOGE, FL("Channel %d not valid for phyMode %d"), new_channel,
+ sap_ctx->csrRoamProfile.phyMode);
+ return -EINVAL;
+ }
+
+ sap_ctx->ecsa_info.new_channel = new_channel;
+ sap_ctx->ecsa_info.channel_switch_in_progress = true;
+ /*
+ * Post the eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START
+ * to SAP state machine to process the channel
+ * request with CSA IE set in the beacons.
+ */
+ sap_event.event = eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START;
+ sapFsm(sap_ctx, &sap_event);
+
+ return 0;
+}
+
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
index 902e0a0..7e5ec7f 100644
--- a/CORE/SME/inc/smeInside.h
+++ b/CORE/SME/inc/smeInside.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -362,5 +362,20 @@
void activeListCmdTimeoutHandle(void *userData);
void csrGetStaticUapsdMask(tpAniSirGlobal pMac, tANI_U8 *staticUapsdMask);
+/**
+ * csr_roam_send_chan_sw_ie_request() - Request to transmit CSA IE
+ * @mac_ctx: Global MAC context
+ * @bssid: BSSID
+ * @new_chan: Channel on which to send the IE
+ * @cb_mode: cb mode
+ *
+ * This function sends request to transmit channel switch announcement
+ * IE to lower layers
+ *
+ * Return: success or failure
+ **/
+VOS_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx,
+ tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode);
+
#endif //#if !defined( __SMEINSIDE_H )
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 5d4a807..431f568 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4009,4 +4009,16 @@
pgetArpStatsParams pGetStatsParam);
eHalStatus sme_del_sta_ba_session_req(tHalHandle hHal,
tDelBaParams sta_del_params);
+/**
+ * sme_roam_csa_ie_request() - request CSA IE transmission from PE
+ * @hal: handle returned by mac_open
+ * @bssid: SAP bssid
+ * @new_chan: target channel information
+ * @phy_mode: SAP phymode
+ *
+ * Return: VOS_STATUS
+ */
+VOS_STATUS sme_roam_csa_ie_request(tHalHandle hal, tCsrBssid bssid,
+ uint8_t new_chan, uint32_t phy_mode);
+
#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 0418201..e897126 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -19648,3 +19648,29 @@
*staticUapsdMask = pSession->pCurRoamProfile->uapsd_mask;
}
+VOS_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx,
+ tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ struct sir_ecsa_ie_req *msg;
+
+ 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_SET_CHAN_SW_IE_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);
+
+ 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/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index a6bd8b3..76d943b 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -15090,3 +15090,24 @@
}
return(status);
}
+
+VOS_STATUS sme_roam_csa_ie_request(tHalHandle hal, tCsrBssid bssid,
+ uint8_t new_chan, uint32_t phy_mode)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ 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, phy_mode, new_chan);
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
+ }
+ status = csr_roam_send_chan_sw_ie_request(mac_ctx, bssid,
+ new_chan, cb_mode);
+ 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 ba7c97a..70c2f7a 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -582,6 +582,7 @@
CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
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);
default:
return( (tANI_U8*)"UNKNOWN" );
break;
diff --git a/CORE/SYS/legacy/src/utils/src/parserApi.c b/CORE/SYS/legacy/src/utils/src/parserApi.c
index e5e1f75..b761a40 100644
--- a/CORE/SYS/legacy/src/utils/src/parserApi.c
+++ b/CORE/SYS/legacy/src/utils/src/parserApi.c
@@ -295,6 +295,32 @@
} // End PopulateDot11fCapabilities2.
+void populate_dot11f_ext_chann_switch_ann(tpAniSirGlobal mac_ctx,
+ tDot11fIEext_chan_switch_ann *dot_11_ptr, tpPESession session_entry)
+{
+ offset_t ch_offset;
+
+ if (session_entry->gLimChannelSwitch.secondarySubBand >=
+ PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED)
+ ch_offset = BW80;
+ else
+ ch_offset = session_entry->gLimChannelSwitch.secondarySubBand;
+
+ dot_11_ptr->switch_mode = session_entry->gLimChannelSwitch.switchMode;
+ dot_11_ptr->new_reg_class = limGetOPClassFromChannel(
+ mac_ctx->scan.countryCodeCurrent,
+ session_entry->gLimChannelSwitch.primaryChannel, ch_offset);
+ dot_11_ptr->new_channel = session_entry->gLimChannelSwitch.primaryChannel;
+ dot_11_ptr->switch_count = session_entry->gLimChannelSwitch.switchCount;
+ dot_11_ptr->present = 1;
+
+ limLog(mac_ctx, LOG1, FL("country:%s cb mode:%d width:%d reg:%d off:%d"),
+ mac_ctx->scan.countryCodeCurrent,
+ session_entry->gLimChannelSwitch.primaryChannel,
+ session_entry->gLimChannelSwitch.secondarySubBand,
+ dot_11_ptr->new_reg_class, ch_offset);
+}
+
void
PopulateDot11fChanSwitchAnn(tpAniSirGlobal pMac,
tDot11fIEChanSwitchAnn *pDot11f,
@@ -308,7 +334,7 @@
} // End PopulateDot11fChanSwitchAnn.
void
-PopulateDot11fExtChanSwitchAnn(tpAniSirGlobal pMac,
+PopulateDot11fsecChanOffset(tpAniSirGlobal pMac,
tDot11fIEsec_chan_offset *pDot11f,
tpPESession psessionEntry)
{
@@ -329,6 +355,9 @@
pDot11f->newChanWidth = psessionEntry->gLimWiderBWChannelSwitch.newChanWidth;
pDot11f->newCenterChanFreq0 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0;
pDot11f->newCenterChanFreq1 = psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1;
+ limLog(pMac, LOG1, FL("wrapper: width:%d f0:%d f1:%d"),
+ pDot11f->newChanWidth, pDot11f->newCenterChanFreq0,
+ pDot11f->newCenterChanFreq1);
}
#endif