prima: HDD changes to support the TDLS off channel feature.
HDD changes to support the TDLS off channel feature.
This change inlcudes
1) Changes to enable/disable TDLS offchannel
based on number of TDLS peers connected.
2) Passing correct channel for TDLS peer.
Change-Id: I37b91bf2c60bc97abb131fa909d0ce3093defaf6
cRs-Fixed: 791759
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 0759f36..e400902 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -63,6 +63,14 @@
#define TDLS_IS_CONNECTED(peer) \
((eTDLS_LINK_CONNECTED == (peer)->link_status) || \
(eTDLS_LINK_TEARING == (peer)->link_status))
+
+/* TDLS Off Channel Bandwidth Offset */
+#define TDLS_OFF_CHANNEL_BW_OFFSET 0
+
+/* TDLS Channel Switch Request */
+#define TDLS_CHANNEL_SWITCH_ENABLE 1
+#define TDLS_CHANNEL_SWITCH_DISABLE 2
+
typedef struct
{
tANI_U32 tdls;
@@ -209,6 +217,8 @@
/*EXT TDLS*/
tTDLSLinkReason reason;
cfg80211_exttdls_callback state_change_notification;
+ tANI_BOOLEAN isOffChannelConfigured;
+ tdls_req_params_t peerParams;
} hddTdlsPeer_t;
typedef struct {
@@ -330,6 +340,7 @@
int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, u8 *peer);
int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
u8 *peer,
+ tdls_req_params_t *tdls_peer_params,
cfg80211_exttdls_callback callback);
/*EXT TDLS*/
int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter,
@@ -345,5 +356,5 @@
tANI_U8 *ptr);
// tdlsoffchan
-hddTdlsPeer_t *wlan_hdd_tdls_get_first_connected_peer(hdd_adapter_t *pAdapter);
+hddTdlsPeer_t *wlan_hdd_tdls_get_connected_peer(hdd_adapter_t *pAdapter);
#endif // __HDD_TDSL_H
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 642b18e..5a121ba 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -4387,6 +4387,7 @@
return (wlan_hdd_tdls_extctrl_config_peer(pAdapter,
peer,
+ &pReqMsg,
wlan_hdd_cfg80211_exttdls_callback));
}
@@ -14312,10 +14313,11 @@
int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
u8 *peer,
+ tdls_req_params_t *tdls_peer_params,
cfg80211_exttdls_callback callback)
{
- hddTdlsPeer_t *pTdlsPeer;
+ hddTdlsPeer_t *pTdlsPeer = NULL;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
" %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
@@ -14341,6 +14343,38 @@
return -EINVAL;
}
+ if (NULL != tdls_peer_params)
+ {
+ pTdlsPeer->peerParams.channel = tdls_peer_params->channel;
+ pTdlsPeer->peerParams.global_operating_class =
+ tdls_peer_params->global_operating_class;
+ pTdlsPeer->peerParams.max_latency_ms = tdls_peer_params->max_latency_ms;
+ pTdlsPeer->peerParams.min_bandwidth_kbps =
+ tdls_peer_params->min_bandwidth_kbps;
+ /* check configured channel is valid and non dfs */
+ if (sme_IsTdlsOffChannelValid(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ tdls_peer_params->channel))
+ {
+ pTdlsPeer->isOffChannelConfigured = TRUE;
+ }
+ else
+ {
+ pTdlsPeer->isOffChannelConfigured = FALSE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Configured Tdls Off Channel is not valid", __func__);
+
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: tdls_off_channel %d isOffChannelConfigured %d",
+ __func__, pTdlsPeer->peerParams.channel,
+ pTdlsPeer->isOffChannelConfigured);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid TDLS Peer Params", __func__);
+ }
+
if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -14391,6 +14425,13 @@
else {
wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+ /* if channel switch is configured, reset
+ the channel for this peer */
+ if (TRUE == pTdlsPeer->isOffChannelConfigured)
+ {
+ pTdlsPeer->peerParams.channel = 0;
+ pTdlsPeer->isOffChannelConfigured = FALSE;
+ }
}
if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) )
@@ -14452,6 +14493,8 @@
long ret;
tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
WLAN_STADescType staDesc;
+ tANI_U16 numCurrTdlsPeers = 0;
+ hddTdlsPeer_t *connPeer = NULL;
pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
memset(&staDesc, 0, sizeof(staDesc));
@@ -14475,6 +14518,36 @@
return -EINVAL;
}
+ /* TDLS Off Channel, Disable tdls channel switch,
+ when there are more than one tdls link */
+ numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
+ if (numCurrTdlsPeers == 1)
+ {
+ /* get connected peer and send disable tdls off chan */
+ connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
+ if (connPeer && (connPeer->isOffChannelConfigured == TRUE))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: More then one peer connected, Disable "
+ "TDLS channel switch", __func__);
+
+ sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ connPeer->peerMac,
+ connPeer->peerParams.channel,
+ TDLS_OFF_CHANNEL_BW_OFFSET,
+ TDLS_CHANNEL_SWITCH_DISABLE);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: No TDLS Connected Peer or "
+ "isOffChannelConfigured %d",
+ __func__,
+ (connPeer ? connPeer->isOffChannelConfigured : -1));
+ }
+ }
+
if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
{
if (IS_ADVANCE_TDLS_ENABLE) {
@@ -14530,6 +14603,36 @@
&staId, NULL);
}
wlan_hdd_tdls_increment_peer_count(pAdapter);
+
+ /* TDLS Off Channel, Enable tdls channel switch,
+ when their is only one tdls link and it supports */
+ numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
+ if ((numCurrTdlsPeers == 1) &&
+ (TRUE == pTdlsPeer->isOffChannelSupported) &&
+ (TRUE == pTdlsPeer->isOffChannelConfigured))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Send TDLS channel switch request for channel %d",
+ __func__, pTdlsPeer->peerParams.channel);
+ ret = sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ pTdlsPeer->peerMac,
+ pTdlsPeer->peerParams.channel,
+ TDLS_OFF_CHANNEL_BW_OFFSET,
+ TDLS_CHANNEL_SWITCH_ENABLE);
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: TDLS channel switch request not sent"
+ " numCurrTdlsPeers %d "
+ "isOffChannelSupported %d "
+ "isOffChannelConfigured %d",
+ __func__, numCurrTdlsPeers,
+ pTdlsPeer->isOffChannelSupported,
+ pTdlsPeer->isOffChannelConfigured);
+ }
+
}
wlan_hdd_tdls_check_bmps(pAdapter);
@@ -14557,6 +14660,9 @@
break;
case NL80211_TDLS_DISABLE_LINK:
{
+ tANI_U16 numCurrTdlsPeers = 0;
+ hddTdlsPeer_t *connPeer = NULL;
+
pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
if ( NULL == pTdlsPeer ) {
@@ -14598,6 +14704,39 @@
__func__, status);
return -EPERM;
}
+
+ /* TDLS Off Channel, Enable tdls channel switch,
+ when their is only one tdls link and it supports */
+ numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
+ if (numCurrTdlsPeers == 1)
+ {
+ connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
+ if ((connPeer) &&
+ (connPeer->isOffChannelSupported == TRUE) &&
+ (connPeer->isOffChannelConfigured == TRUE))
+ {
+ sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId,
+ connPeer->peerMac,
+ connPeer->peerParams.channel,
+ TDLS_OFF_CHANNEL_BW_OFFSET,
+ TDLS_CHANNEL_SWITCH_ENABLE);
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: TDLS channel switch "
+ "isOffChannelSupported %d "
+ "isOffChannelConfigured %d",
+ __func__,
+ (connPeer ? connPeer->isOffChannelSupported : -1),
+ (connPeer ? connPeer->isOffChannelConfigured : -1));
+ }
+ else
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: TDLS channel switch request not sent "
+ "numCurrTdlsPeers %d ",
+ __func__, numCurrTdlsPeers);
+ }
}
else
{
@@ -14622,6 +14761,7 @@
{
status = wlan_hdd_tdls_extctrl_config_peer(pAdapter,
peer,
+ NULL,
NULL);
if (0 != status)
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 0d6e8a3..3cb9492 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -1852,7 +1852,7 @@
return pHddCtx->connected_peer_count;
}
-hddTdlsPeer_t *wlan_hdd_tdls_get_first_connected_peer(hdd_adapter_t *pAdapter)
+hddTdlsPeer_t *wlan_hdd_tdls_get_connected_peer(hdd_adapter_t *pAdapter)
{
int i;
struct list_head *head;
@@ -2626,7 +2626,7 @@
(connectedTdlsPeers == 1) )
{
/* get connected peer information */
- connected_peer = wlan_hdd_tdls_get_first_connected_peer(pAdapter);
+ connected_peer = wlan_hdd_tdls_get_connected_peer(pAdapter);
if (NULL == connected_peer) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: Invalid connected_peer, Continue Scanning", __func__);
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 9e208d1..480c7c6 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -8650,7 +8650,7 @@
{
if (offchanoffset == 0)
{
- tdlsOffChBwOffset = 0;
+ tdlsOffChBwOffset = 1;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
@@ -8660,7 +8660,7 @@
if ( offchanoffset == 40 )
{
- tdlsOffChBwOffset = 1;
+ tdlsOffChBwOffset = 2;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
@@ -8707,7 +8707,7 @@
eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
{
/* Send TDLS Channel Switch Request to connected peer */
- connPeer = wlan_hdd_tdls_get_first_connected_peer(pAdapter);
+ connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
if (NULL == connPeer) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: No TDLS Connected Peer", __func__);