summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgaolez <gaolez@codeaurora.org>2017-02-20 20:25:07 +0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-13 00:03:45 -0700
commit71cb0da488414e597d74a058ff09c95d20ab2a24 (patch)
tree9321f839fa047f07abf18a8f7cedef08fb4294cb
parent08290584a807fad4e78c6acff954b78cd3d88932 (diff)
qcacld-2.0: Manual switch to 5/10M mode in disconnect state
User can set channel width of STA or SAP device to 5/10 MHz while device in disconnect state. Change-Id: Ic2618c13c9be0e60f45d0a17feb787f8e4b962e3 CRs-Fixed: 2010071
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg80211.h1
-rw-r--r--CORE/HDD/inc/wlan_hdd_hostapd.h4
-rw-r--r--CORE/HDD/src/wlan_hdd_assoc.c7
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c243
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c53
-rw-r--r--CORE/MAC/inc/aniGlobal.h1
-rw-r--r--CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c2
-rw-r--r--CORE/MAC/src/pe/lim/limSendMessages.c6
-rw-r--r--CORE/MAC/src/pe/lim/limUtils.c12
-rw-r--r--CORE/SAP/inc/sapApi.h12
-rw-r--r--CORE/SAP/src/sapModule.c54
-rw-r--r--CORE/SME/inc/sme_Api.h3
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c27
13 files changed, 379 insertions, 46 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index c16be3359719..b4ddc2e8768b 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -1748,6 +1748,7 @@ enum qca_wlan_vendor_config {
QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND = 34,
QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC = 35,
QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT = 36,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH = 39,
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_LAST,
diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h
index 07452cb67db1..2a08dc9b0319 100644
--- a/CORE/HDD/inc/wlan_hdd_hostapd.h
+++ b/CORE/HDD/inc/wlan_hdd_hostapd.h
@@ -228,7 +228,7 @@ bool hdd_hostapd_sub20_channelwidth_can_switch(
hdd_adapter_t *adapter, uint32_t *sub20_channel_width);
bool hdd_hostapd_sub20_channelwidth_can_restore(
hdd_adapter_t *adapter);
-bool hdd_hostapd_sub20_channelwidth_can_set(
+bool hdd_sub20_channelwidth_can_set(
hdd_adapter_t *adapter, uint32_t sub20_channel_width);
int hdd_softap_set_channel_sub20_chanwidth_change(
struct net_device *dev, uint32_t chan_width);
@@ -245,7 +245,7 @@ static inline bool hdd_hostapd_sub20_channelwidth_can_restore(
return false;
}
-static inline bool hdd_hostapd_sub20_channelwidth_can_set(
+static inline bool hdd_sub20_channelwidth_can_set(
hdd_adapter_t *adapter, uint32_t sub20_channel_width)
{
return false;
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 60bf3065daed..7c632ec814ef 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1217,13 +1217,6 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *
hdd_decide_dynamic_chain_mask(pHddCtx,
HDD_ANTENNA_MODE_INVALID);
- if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) {
- sme_update_sub20_channel_width(
- WLAN_HDD_GET_HAL_CTX(pAdapter),
- pAdapter->sessionId,
- SUB20_MODE_NONE);
- }
-
//Unblock anyone waiting for disconnect to complete
complete(&pAdapter->disconnect_comp_var);
return( status );
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 6c04bcfdab62..238442d87878 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9176,9 +9176,11 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
}
if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
- if (WLANSAP_get_sub20_channel_width(
- WLAN_HDD_GET_SAP_CTX_PTR(adapter))
- == SUB20_MODE_NONE) {
+ uint32_t sap_sub20_channelwidth;
+ WLANSAP_get_sub20_channelwidth(WLAN_HDD_GET_SAP_CTX_PTR(
+ adapter),
+ &sap_sub20_channelwidth);
+ if (sap_sub20_channelwidth == SUB20_MODE_NONE) {
hddLog(LOGE, FL("Bss started, relaunch ACS"));
status = wlan_hdd_cfg80211_relaunch_acs(adapter);
} else {
@@ -9582,6 +9584,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX
.type = NLA_UNSPEC},
[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT] = {
.type = NLA_U32},
+ [QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH] = {.type = NLA_U32},
};
/**
@@ -9690,6 +9693,82 @@ static int hdd_set_qpower_config(hdd_context_t *hddctx, hdd_adapter_t *adapter,
}
/**
+ * hdd_sta_set_sub20_channelwidth() -
+ * This api function does a sub20 channel width change
+ * for STA while STA in disconnect state
+ * @adapter: HDD adapter
+ * @chan_width: New channel width change to
+ *
+ * Return: The VOS_STATUS code associated with performing
+ * the operation
+ */
+static VOS_STATUS
+hdd_sta_set_sub20_channelwidth(hdd_adapter_t *adapter, uint32_t chan_width)
+{
+ tHalHandle hal_ptr;
+
+ hddLog(LOGE, FL("chanwidth: %d"), chan_width);
+
+ if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
+ hddLog(LOGE, FL("hdd adapter cookie is invalid"));
+ return -EINVAL;
+ }
+
+ if (WLAN_HDD_INFRA_STATION != adapter->device_mode) {
+ hddLog(LOGE, FL("Only Sta Mode supported!"));
+ return -ENOTSUPP;
+ }
+
+ hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter);
+ if (hal_ptr == NULL) {
+ hddLog(LOGE, FL("hdd hal is null"));
+ return -EINVAL;
+ }
+
+ sme_set_sta_chanlist_with_sub20(hal_ptr, chan_width);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_get_sub20_channelwidth() -
+ * This api function get sub20 channel width
+ * @adapter: HDD adapter
+ * @sub20_channelwidth: restore sub20 channel width
+ *
+ * Return: The VOS_STATUS code associated with performing
+ * the operation
+ */
+static VOS_STATUS
+hdd_get_sub20_channelwidth(hdd_adapter_t *adapter, uint32_t *sub20_channelwidth)
+{
+ tHalHandle hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter);
+ tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal_ptr);
+ v_CONTEXT_t vos_ctx_ptr = WLAN_HDD_GET_SAP_CTX_PTR(adapter);
+ uint32_t sap_sub20_channelwidth;
+
+ if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
+ hddLog(LOGE, FL("hdd adapter cookie is invalid"));
+ return -EINVAL;
+ }
+
+ if (WLAN_HDD_INFRA_STATION == adapter->device_mode) {
+ *sub20_channelwidth = mac_ptr->sta_sub20_current_channelwidth ?
+ mac_ptr->sta_sub20_current_channelwidth :
+ mac_ptr->sub20_channelwidth;
+ } else if (WLAN_HDD_SOFTAP == adapter->device_mode) {
+ WLANSAP_get_sub20_channelwidth(vos_ctx_ptr,
+ &sap_sub20_channelwidth);
+ *sub20_channelwidth = sap_sub20_channelwidth;
+ } else {
+ hddLog(LOGE, FL("error dev mode!"));
+ return -EINVAL;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
+/**
* __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
* vendor command
*
@@ -10156,6 +10235,38 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
}
}
+ if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH]) {
+ bool manual_set_sub20;
+ uint32_t sub20_chan_width;
+
+ sub20_chan_width = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH]);
+ hddLog(LOGE, FL("SUB20 %d"), sub20_chan_width);
+
+ switch (sub20_chan_width) {
+ case NL80211_CHAN_WIDTH_5:
+ sub20_chan_width = SUB20_MODE_5MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ sub20_chan_width = SUB20_MODE_10MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ sub20_chan_width = SUB20_MODE_NONE;
+ break;
+ default:
+ hddLog(LOGE, FL("invalid param %d"), sub20_chan_width);
+ return -EINVAL;
+ }
+ manual_set_sub20 =
+ hdd_sub20_channelwidth_can_set(pAdapter,
+ sub20_chan_width);
+ if (!manual_set_sub20) {
+ hddLog(LOGE, FL("STA can't set sub20 chanwidth"));
+ return -EINVAL;
+ }
+ hdd_sta_set_sub20_channelwidth(pAdapter, sub20_chan_width);
+ }
+
return ret_val;
}
@@ -10187,6 +10298,124 @@ static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
return ret;
}
+/**
+ * __wlan_hdd_cfg80211_wifi_configuration_get() -
+ * Get the wifi configuration info
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Return: Return the Success or Failure code.
+ */
+static int
+__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
+ uint32_t sub20_chan_width = 0;
+ int status;
+ struct sk_buff *reply_skb;
+ uint32_t skb_len = 0, count = 0;
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ ENTER();
+
+ if (VOS_FTM_MODE == hdd_get_conparam()) {
+ hddLog(LOGE, FL("Command not allowed in FTM mode"));
+ return -EINVAL;
+ }
+
+ status = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != status)
+ return -EINVAL;
+
+ if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
+ data_len, wlan_hdd_wifi_config_policy)) {
+ hddLog(LOGE, FL("WIFI_CFG_GET NL CMD parsing failed"));
+ return -EINVAL;
+ }
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH]) {
+ hdd_get_sub20_channelwidth(adapter, &sub20_chan_width);
+
+ switch (sub20_chan_width) {
+ case SUB20_MODE_5MHZ:
+ sub20_chan_width = NL80211_CHAN_WIDTH_5;
+ break;
+ case SUB20_MODE_10MHZ:
+ sub20_chan_width = NL80211_CHAN_WIDTH_10;
+ break;
+ case SUB20_MODE_NONE:
+ sub20_chan_width = NL80211_CHAN_WIDTH_20_NOHT;
+ break;
+ default:
+ hddLog(LOGE, FL("invalid val %d"), sub20_chan_width);
+ return -EINVAL;
+ }
+ hddLog(LOGE, FL("SUB20 chanwidth %d"), sub20_chan_width);
+
+ skb_len += sizeof(sub20_chan_width);
+ count++;
+ }
+
+ if (count == 0) {
+ hddLog(LOGE, FL("unknown attribute in get_wifi_cfg request"));
+ return -EINVAL;
+ }
+
+ skb_len += NLMSG_HDRLEN;
+ reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
+
+ if (!reply_skb)
+ goto error_skb_fail;
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH]) {
+ if (nla_put_u32(reply_skb,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH,
+ sub20_chan_width))
+ goto error_nla_fail;
+ }
+
+ return cfg80211_vendor_cmd_reply(reply_skb);
+
+error_skb_fail:
+ hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
+ return -ENOMEM;
+
+error_nla_fail:
+ hddLog(LOGE, FL("nla put fail"));
+ kfree_skb(reply_skb);
+ return -EINVAL;
+}
+
+/**
+ * wlan_hdd_cfg80211_wifi_configuration_get() - Get the wifi configuration info
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Return: Return the Success or Failure code.
+ */
+static int
+wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
+ data, data_len);
+ vos_ssr_unprotect(__func__);
+
+ return ret;
+}
+
#ifdef FEATURE_WLAN_TDLS
/* TDLS capabilities params */
@@ -13902,6 +14131,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
},
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_wifi_configuration_get
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_NETDEV,
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index e2971c4f564b..76cf2fc634f7 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -476,26 +476,34 @@ bool hdd_hostapd_sub20_channelwidth_can_restore(
}
/**
- * hdd_hostapd_sub20_channelwidth_can_set() - check
+ * hdd_sub20_channelwidth_can_set() - check
* channel width manual switch to 5/10M condition
* @adapter: pointer to HDD context
* @sub20_channel_width: new channel width
*
* Return: true or false
*/
-bool hdd_hostapd_sub20_channelwidth_can_set(
+bool hdd_sub20_channelwidth_can_set(
hdd_adapter_t *adapter, uint32_t sub20_channel_width)
{
int i;
- int sta_count = 0;
+ uint32_t sta_count = 0;
uint8_t sap_s20_config;
- uint8_t sta_s20_caps = SUB20_MODE_NONE;
- tHalHandle hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter);
+ uint8_t sta_s20_caps = SUB20_MODE_10MHZ|SUB20_MODE_5MHZ;
+ tHalHandle hal_ptr;
tSmeConfigParams *sme_config;
hdd_station_info_t *sta;
- hdd_ap_ctx_t *ap = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+ hdd_ap_ctx_t *ap;
bool channel_support_sub20 = true;
enum phy_ch_width phy_sub20_channel_width = CH_WIDTH_INVALID;
+ hdd_station_ctx_t *hddstactx;
+
+ if (adapter == NULL) {
+ hddLog(LOGE, FL("adapter NULL"));
+ return false;
+ }
+ hal_ptr = WLAN_HDD_GET_HAL_CTX(adapter);
+ ap = WLAN_HDD_GET_AP_CTX_PTR(adapter);
sme_config = vos_mem_malloc(sizeof(*sme_config));
if (!sme_config) {
@@ -521,11 +529,27 @@ bool hdd_hostapd_sub20_channelwidth_can_set(
phy_sub20_channel_width = CH_WIDTH_10MHZ;
break;
case SUB20_MODE_NONE:
- return true;
+ if (WLAN_HDD_SOFTAP == adapter->device_mode)
+ return true;
+ break;
default:
return false;
}
+ if (WLAN_HDD_INFRA_STATION == adapter->device_mode) {
+ hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (hddstactx == NULL) {
+ hddLog(LOGE, FL("hdd hddstactx is null"));
+ return false;
+ }
+ if (hdd_connIsConnected(hddstactx)) {
+ hddLog(LOGE, FL("sta in Connected state!"));
+ return false;
+ }
+ hddLog(LOGE, FL("sta can set sub20"));
+ return true;
+ }
+
channel_support_sub20 =
vos_is_channel_support_sub20(ap->operatingChannel,
phy_sub20_channel_width,
@@ -542,21 +566,18 @@ bool hdd_hostapd_sub20_channelwidth_can_set(
sta = &adapter->aStaInfo[i];
if (sta->isUsed && (ap->uBCStaId != i)) {
sta_count++;
- sta_s20_caps |=
+ sta_s20_caps &=
sta->sub20_dynamic_channelwidth;
}
}
spin_unlock_bh(&adapter->staInfo_lock);
- if (sta_count != 1) {
+ if (sta_count >= 1 && !(sta_s20_caps & sub20_channel_width)) {
hddLog(VOS_TRACE_LEVEL_ERROR,
"%d STAs connected with sub20 Channelwidth %d",
sta_count, sta_s20_caps);
return false;
}
- if (!(sta_s20_caps & sub20_channel_width))
- return false;
-
return true;
}
@@ -2659,10 +2680,6 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa
hdd_wlan_green_ap_del_sta(pHddCtx);
- if (hdd_hostapd_sub20_channelwidth_can_restore(pHostapdAdapter)) {
- WLANSAP_set_sub20_channelwidth_with_csa(
- WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), 0);
- }
break;
case eSAP_WPS_PBC_PROBE_REQ_EVENT:
{
@@ -3179,8 +3196,8 @@ int hdd_softap_set_channel_sub20_chanwidth_change(struct net_device *dev,
}
sub20_operate_permission =
- hdd_hostapd_sub20_channelwidth_can_set(hostapd_adapter,
- sub20_chan_width);
+ hdd_sub20_channelwidth_can_set(hostapd_adapter,
+ sub20_chan_width);
if (!sub20_operate_permission) {
hddLog(LOGE, FL("can't set sub20_chan_width in curr chan"));
return -EINVAL;
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index e838794259ec..d548e414fc0e 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -1291,6 +1291,7 @@ typedef struct sAniSirGlobal
uint8_t sub20_config_info;
uint8_t sub20_channelwidth;
uint8_t sub20_dynamic_channelwidth;
+ uint8_t sta_sub20_current_channelwidth;
bool max_power_cmd_pending;
} tAniSirGlobal;
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index f75506bf82f9..24e299f161da 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -733,6 +733,8 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
/* Update sub 20MHz channel width */
psessionEntry->sub20_channelwidth = pSmeStartBssReq->sub20_channelwidth;
+ psessionEntry->lim_sub20_channel_switch_bandwidth =
+ pSmeStartBssReq->sub20_channelwidth;
vos_mem_copy((void*)&psessionEntry->rateSet,
(void*)&pSmeStartBssReq->operationalRateSet,
diff --git a/CORE/MAC/src/pe/lim/limSendMessages.c b/CORE/MAC/src/pe/lim/limSendMessages.c
index 49b176edcd64..daaf7a4a653f 100644
--- a/CORE/MAC/src/pe/lim/limSendMessages.c
+++ b/CORE/MAC/src/pe/lim/limSendMessages.c
@@ -235,6 +235,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac,
tSirRetStatus retCode = eSIR_SUCCESS;
tSirMsgQ msgQ;
tpPESession pSessionEntry;
+ uint32_t old_channelwidth;
if((pSessionEntry = peFindSessionBySessionId(pMac, peSessionId)) == NULL)
{
limLog( pMac, LOGP,
@@ -273,11 +274,16 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac,
pChnlParams->reduced_beacon_interval =
pMac->sap.SapDfsInfo.reduced_beacon_interval;
+ old_channelwidth = pChnlParams->channelwidth;
if (pSessionEntry->sub20_channelwidth == SUB20_MODE_5MHZ)
pChnlParams->channelwidth = CH_WIDTH_5MHZ;
else if (pSessionEntry->sub20_channelwidth == SUB20_MODE_10MHZ)
pChnlParams->channelwidth = CH_WIDTH_10MHZ;
+ if (old_channelwidth != pChnlParams->channelwidth)
+ sme_set_sta_chanlist_with_sub20(pMac,
+ pSessionEntry->sub20_channelwidth);
+
limLog(pMac, LOG1, FL("Set sub20 channel width %d"),
pSessionEntry->sub20_channelwidth);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 14373d90dd35..ded733ca06d8 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -2813,6 +2813,12 @@ void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession
pMac->lim.gpchangeChannelCallback = limSwitchChannelCback;
pMac->lim.gpchangeChannelData = NULL;
+ pMac->sub20_channelwidth =
+ psessionEntry->lim_sub20_channel_switch_bandwidth;
+
+ pMac->sta_sub20_current_channelwidth =
+ psessionEntry->lim_sub20_channel_switch_bandwidth;
+
psessionEntry->sub20_channelwidth =
psessionEntry->lim_sub20_channel_switch_bandwidth;
@@ -2876,6 +2882,12 @@ void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionE
pMac->lim.gpchangeChannelCallback = limSwitchChannelCback;
pMac->lim.gpchangeChannelData = NULL;
+ pMac->sub20_channelwidth =
+ psessionEntry->lim_sub20_channel_switch_bandwidth;
+
+ pMac->sta_sub20_current_channelwidth =
+ psessionEntry->lim_sub20_channel_switch_bandwidth;
+
psessionEntry->sub20_channelwidth =
psessionEntry->lim_sub20_channel_switch_bandwidth;
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index 4e77b8ff9513..126be8057f78 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -2492,8 +2492,9 @@ VOS_STATUS wlansap_set_invalid_session(v_PVOID_t pctx);
VOS_STATUS
WLANSAP_set_sub20_channelwidth_with_csa(
void *vos_ctx_ptr, uint32_t chan_width);
-uint8_t
-WLANSAP_get_sub20_channel_width(void *vos_ctx_ptr);
+VOS_STATUS
+WLANSAP_get_sub20_channelwidth(void *vos_ctx_ptr, uint32_t *chan_width);
+
#else
static inline VOS_STATUS
WLANSAP_set_sub20_channelwidth_with_csa(
@@ -2502,10 +2503,11 @@ WLANSAP_set_sub20_channelwidth_with_csa(
return VOS_STATUS_SUCCESS;
}
-static inline uint8_t
-WLANSAP_get_sub20_channel_width(void *vos_ctx_ptr)
+static inline VOS_STATUS
+WLANSAP_get_sub20_channelwidth(void *vos_ctx_ptr, uint32_t *chan_width)
{
- return SUB20_MODE_NONE;
+ *chan_width = 0;
+ return VOS_STATUS_SUCCESS;
}
#endif
#ifdef __cplusplus
diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c
index 7381385fc19b..a340e113e6b8 100644
--- a/CORE/SAP/src/sapModule.c
+++ b/CORE/SAP/src/sapModule.c
@@ -833,9 +833,8 @@ WLANSAP_StartBss
pmac->sap.SapDfsInfo.reduced_beacon_interval =
pConfig->reduced_beacon_interval;
pmac->sap.SapDfsInfo.sub20_switch_mode = pConfig->sub20_switch_mode;
- if (pConfig->sub20_switch_mode == SUB20_STATIC)
- pmac->sap.SapDfsInfo.new_sub20_channelwidth =
- pmac->sub20_channelwidth;
+ pmac->sap.SapDfsInfo.new_sub20_channelwidth =
+ pmac->sub20_channelwidth;
// Copy MAC filtering settings to sap context
pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl;
@@ -854,6 +853,7 @@ WLANSAP_StartBss
/* Store the HDD callback in SAP context */
pSapCtx->pfnSapEventCallback = pSapEventCallback;
+ pSapCtx->sub20_channelwidth = pmac->sub20_channelwidth;
/* Handle event*/
vosStatus = sapFsm(pSapCtx, &sapEvent);
@@ -1827,6 +1827,7 @@ WLANSAP_set_sub20_channelwidth_with_csa(void *vos_ctx_ptr, uint32_t chan_width)
sap_context_ptr->ch_width_orig;
mac_ptr->sap.SapDfsInfo.new_sub20_channelwidth =
chan_width;
+ mac_ptr->sub20_channelwidth = chan_width;
mac_ptr->sap.SapDfsInfo.csaIERequired =
VOS_TRUE;
@@ -1869,8 +1870,9 @@ WLANSAP_set_sub20_channelwidth_with_csa(void *vos_ctx_ptr, uint32_t chan_width)
} else {
VOS_TRACE(VOS_MODULE_ID_SAP,
VOS_TRACE_LEVEL_ERROR,
- "%s: ChannelWidth = %d is not valid",
- __func__, chan_width);
+ "%s: curr ChWidth = %d, %d is invalid",
+ __func__, sap_context_ptr->sub20_channelwidth,
+ chan_width);
return VOS_STATUS_E_FAULT;
}
@@ -1882,13 +1884,45 @@ WLANSAP_set_sub20_channelwidth_with_csa(void *vos_ctx_ptr, uint32_t chan_width)
return VOS_STATUS_SUCCESS;
}
-uint8_t
-WLANSAP_get_sub20_channel_width(void *vos_ctx_ptr)
+/**
+ * WLANSAP_get_sub20_channelwidth() -
+ * This api function get sub20 channel width
+ * @vos_ctx_ptr: Pointer to vos global context structure
+ * @chan_width: restore sub20 channel width
+ *
+ * Return: The VOS_STATUS code associated with performing
+ * the operation
+ */
+VOS_STATUS
+WLANSAP_get_sub20_channelwidth(void *vos_ctx_ptr, uint32_t *chan_width)
{
- ptSapContext sap_context_ptr =
- VOS_GET_SAP_CB(vos_ctx_ptr);
+ ptSapContext sap_context_ptr = NULL;
+ void *hal_ptr = NULL;
+ tpAniSirGlobal mac_ptr = NULL;
+
+ sap_context_ptr = VOS_GET_SAP_CB(vos_ctx_ptr);
+ if (NULL == sap_context_ptr) {
+ VOS_TRACE(VOS_MODULE_ID_SAP,
+ VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid SAP pointer from pvosGCtx", __func__);
+
+ return VOS_STATUS_E_FAULT;
+ }
- return sap_context_ptr->sub20_channelwidth;
+ hal_ptr = VOS_GET_HAL_CB(sap_context_ptr->pvosGCtx);
+ if (NULL == hal_ptr) {
+ VOS_TRACE(VOS_MODULE_ID_SAP,
+ VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid HAL pointer from pvosGCtx", __func__);
+ return VOS_STATUS_E_FAULT;
+ }
+ mac_ptr = PMAC_STRUCT(hal_ptr);
+
+ *chan_width = sap_context_ptr->sub20_channelwidth ?
+ sap_context_ptr->sub20_channelwidth :
+ mac_ptr->sub20_channelwidth;
+
+ return VOS_STATUS_SUCCESS;
}
#endif
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 1bbf5c782252..686243ca9472 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4580,7 +4580,8 @@ void sme_add_set_thermal_level_callback(tHalHandle hHal,
eHalStatus sme_handle_set_fcc_channel(tHalHandle hHal,
bool fcc_constraint,
uint32_t scan_pending);
-
+eHalStatus sme_set_sta_chanlist_with_sub20(tHalHandle hal_ptr,
+ uint8_t chan_width);
eHalStatus sme_set_rssi_monitoring(tHalHandle hal,
struct rssi_monitor_req *input);
eHalStatus sme_set_rssi_threshold_breached_cb(tHalHandle hal,
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 17b5a3c7bc77..4dd595d91f97 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -18144,6 +18144,33 @@ eHalStatus sme_handle_set_fcc_channel(tHalHandle hal, bool fcc_constraint,
return status;
}
+
+/**
+ * sme_set_sta_chanlist_with_sub20()- update channel list with 5/10M
+ * info
+ * @hal_ptr: Hal context pointor
+ * @chan_width: 5/10M channel width info
+ *
+ * Return: eHalStatus
+ */
+eHalStatus
+sme_set_sta_chanlist_with_sub20(tHalHandle hal_ptr, uint8_t chan_width)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal_ptr);
+
+ status = sme_AcquireGlobalLock(&mac_ptr->sme);
+
+ if (eHAL_STATUS_SUCCESS == status) {
+ mac_ptr->sub20_channelwidth = chan_width;
+ mac_ptr->sta_sub20_current_channelwidth = chan_width;
+ status = csrUpdateChannelList(mac_ptr);
+ }
+ sme_ReleaseGlobalLock(&mac_ptr->sme);
+
+ return status;
+}
+
/**
* sme_enable_phy_error_logs() - Enable DFS phy error logs
* @hal: global hal handle