Fix for the tdls mutiple peer instability issues
Send the correct staIdx as assigned during tdls add sta from
lim -> wdi -> firmware when tdls change sta is called to update
the capabilities.
Add a wait for tdls del sta to complete.
Don't deregister tdls station from TL if it's not registered.
Introduce a new state i.e. eTDLS_LINK_TEARING and change the
link state to tearing while sending teardown indication to
supplicant.
CRs-Fixed: 468574
Change-Id: I59d0d08a6362077f331f87240e8e1d7240e5b430
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 8a7c095..bda2ace 100755
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -2005,6 +2005,7 @@
}
case eCSR_ROAM_RESULT_DELETE_TDLS_PEER:
{
+ hddTdlsPeer_t *curr_peer;
for ( staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
{
if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pRoamInfo->sessionId) &&
@@ -2013,10 +2014,13 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
("HDD: del STA IDX = %x"), pRoamInfo->staId) ;
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac);
+ if (NULL != curr_peer && TDLS_IS_CONNECTED(curr_peer))
+ {
+ hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId );
+ wlan_hdd_tdls_decrement_peer_count(pAdapter);
+ }
wlan_hdd_tdls_reset_peer(pAdapter, pRoamInfo->peerMac);
- hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId );
- wlan_hdd_tdls_decrement_peer_count(pAdapter);
-
(WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = NULL;
pHddCtx->tdlsConnInfo[staIdx].staId = 0 ;
@@ -2028,20 +2032,19 @@
break ;
}
}
+ complete(&pAdapter->tdls_del_station_comp);
}
break ;
case eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND:
{
+ hddTdlsPeer_t *curr_peer;
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Sending teardown to supplicant with reason code %u",
__func__, pRoamInfo->reasonCode);
#ifdef CONFIG_TDLS_IMPLICIT
- cfg80211_tdls_oper_request(pAdapter->dev,
- pRoamInfo->peerMac,
- NL80211_TDLS_TEARDOWN,
- pRoamInfo->reasonCode,
- GFP_KERNEL);
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac);
+ wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, pRoamInfo->reasonCode);
#endif
status = eHAL_STATUS_SUCCESS ;
break ;
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index ab4c9d0..a6a8494 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2808,6 +2808,15 @@
__func__, MAC_ADDR_ARRAY(mac));
return -EPERM;
}
+ /* when self is not on-ongoing, we don't want to allow change_station */
+ if ((1 == update) && !wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: " MAC_ADDRESS_STR
+ " TDLS is not connecting. change station declined.",
+ __func__, MAC_ADDR_ARRAY(mac));
+ return -EPERM;
+ }
/* when others are on-going, we want to change link_status to idle */
if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
@@ -2834,7 +2843,7 @@
{
hddTdlsPeer_t *pTdlsPeer;
pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
- if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
+ if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR " already connected. Request declined.",
@@ -2842,8 +2851,34 @@
return -EPERM;
}
}
+ if (0 == update)
+ wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
- wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
+ if (NULL != StaParams)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: TDLS Peer Parameters.", __func__);
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "ht_capa->extended_capabilities: %0x",
+ StaParams->HTCap.extendedHtCapInfo);
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "params->capability: %0x",StaParams->capability);
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "params->ext_capab_len: %0x",StaParams->extn_capability);
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
+ StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
+ StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
+ {
+ int i = 0;
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:");
+ for (i = 0; i < sizeof(StaParams->supported_rates); i++)
+ VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "[%d]: %x ", i, StaParams->supported_rates[i]);
+ }
+ }
INIT_COMPLETION(pAdapter->tdls_add_station_comp);
@@ -2894,7 +2929,6 @@
v_MACADDR_t STAMacAddress;
#ifdef FEATURE_WLAN_TDLS
tCsrStaParams StaParams = {0};
- u32 set;
tANI_U8 isBufSta = 0;
#endif
ENTER();
@@ -2908,48 +2942,6 @@
vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
-#ifdef FEATURE_WLAN_TDLS
- StaParams.capability = params->capability;
- StaParams.uapsd_queues = params->uapsd_queues;
- StaParams.max_sp = params->max_sp;
-
- if (0 != params->ext_capab_len)
- vos_mem_copy(StaParams.extn_capability, params->ext_capab,
- sizeof(StaParams.extn_capability));
-
- if (NULL != params->ht_capa)
- vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
-
- StaParams.supported_rates_len = params->supported_rates_len;
-
- /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
- * The supported_rates array , for all the structures propogating till Add Sta
- * to the firmware has to be modified , if the supplicant (ieee80211) is
- * modified to send more rates.
- */
-
- /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
- */
- if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
- StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
-
- if (0 != StaParams.supported_rates_len) {
- int i = 0;
- vos_mem_copy(StaParams.supported_rates, params->supported_rates,
- StaParams.supported_rates_len);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "Supported Rates with Length %d", StaParams.supported_rates_len);
- for (i=0; i < StaParams.supported_rates_len; i++)
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "[%d]: %0x", i, StaParams.supported_rates[i]);
- }
-
- if (NULL != params->vht_capa)
- vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
-
- set = params->sta_flags_set;
-#endif
-
if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
|| (pAdapter->device_mode == WLAN_HDD_P2P_GO))
{
@@ -2965,57 +2957,58 @@
}
#ifdef FEATURE_WLAN_TDLS
else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
- if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ StaParams.capability = params->capability;
+ StaParams.uapsd_queues = params->uapsd_queues;
+ StaParams.max_sp = params->max_sp;
+
+ if (0 != params->ext_capab_len)
+ vos_mem_copy(StaParams.extn_capability, params->ext_capab,
+ sizeof(StaParams.extn_capability));
+
+ if (NULL != params->ht_capa)
+ vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
+
+ StaParams.supported_rates_len = params->supported_rates_len;
+
+ /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
+ * The supported_rates array , for all the structures propogating till Add Sta
+ * to the firmware has to be modified , if the supplicant (ieee80211) is
+ * modified to send more rates.
+ */
+
+ /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
+ */
+ if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
+ StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
+
+ if (0 != StaParams.supported_rates_len) {
+ int i = 0;
+ vos_mem_copy(StaParams.supported_rates, params->supported_rates,
+ StaParams.supported_rates_len);
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "Supported Rates with Length %d", StaParams.supported_rates_len);
+ for (i=0; i < StaParams.supported_rates_len; i++)
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "[%d]: %0x", i, StaParams.supported_rates[i]);
+ }
+
+ if (NULL != params->vht_capa)
+ vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
+
if (0 != params->ext_capab_len ) {
/*Define A Macro : TODO Sunil*/
if ((1<<4) & StaParams.extn_capability[3]) {
isBufSta = 1;
}
}
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "%s: TDLS Peer Parameters.", __func__);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "uapsd_queues: %0x\n", params->uapsd_queues);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "max_sp: %0x\n", params->max_sp);
- if (params->ht_capa) {
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->ampdu_params_info: %0x\n",
- params->ht_capa->ampdu_params_info);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->extended_capabilities: %0x\n",
- params->ht_capa->extended_ht_cap_info);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->tx_BF_cap_info: %0x\n",
- params->ht_capa->tx_BF_cap_info);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->antenna_selection_info: %0x\n",
- params->ht_capa->antenna_selection_info);
- }
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "params->capability: %0x\n",params->capability);
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "params->ext_capab_len: %0x\n",params->ext_capab_len);
- if (0 != params->ext_capab_len )
- {
- int i =0;
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "Extended capabilities:");
- for (i=0; i < params->ext_capab_len; i++)
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "[%d]: %0x", i, params->ext_capab[i]);
- }
//status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
// params->max_sp, isBufSta);
- if (VOS_STATUS_SUCCESS != status) {
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
- return -EINVAL;
- }
- VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
- "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
+ //if (VOS_STATUS_SUCCESS != status) {
+ // VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ // "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
+ // return -EINVAL;
+ //}
status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
if (VOS_STATUS_SUCCESS != status) {
@@ -6936,7 +6929,7 @@
if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
(SIR_MAC_TDLS_DIS_RSP == action_code))
{
- wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
+ wlan_hdd_tdls_set_cap (pAdapter, peer, eTDLS_CAP_SUPPORTED);
}
/* other than teardown frame, other mgmt frames are not sent if disabled */
@@ -7001,7 +6994,7 @@
{
hddTdlsPeer_t *pTdlsPeer;
pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
- if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
+ if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
@@ -7155,7 +7148,7 @@
return -EINVAL;
}
- if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
+ if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status)
{
wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
/* start TDLS client registration with TL */
@@ -7175,8 +7168,23 @@
if(NULL != curr_peer)
{
+ long status;
+
+ INIT_COMPLETION(pAdapter->tdls_del_station_comp);
+
sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, peer );
+
+ status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
+ msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
+ if (status <= 0)
+ {
+ wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Del station failed status %ld",
+ __func__, status);
+ return -EPERM;
+ }
wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
}
else
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index ef5a03f..d001fa6 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -1716,6 +1716,7 @@
init_completion(&pAdapter->tx_action_cnf_event);
#ifdef FEATURE_WLAN_TDLS
init_completion(&pAdapter->tdls_add_station_comp);
+ init_completion(&pAdapter->tdls_del_station_comp);
init_completion(&pAdapter->tdls_mgmt_comp);
#endif
init_completion(&pHddCtx->mc_sus_event_var);
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 1b6d093..dfea415 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -303,10 +303,9 @@
"Tear down - low RSSI: " MAC_ADDRESS_STR "!",
MAC_ADDR_ARRAY(curr_peer->peerMac));
#ifdef CONFIG_TDLS_IMPLICIT
- cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev,
- curr_peer->peerMac,
- NL80211_TDLS_TEARDOWN, FALSE,
- GFP_KERNEL);
+ wlan_hdd_tdls_indicate_teardown(pHddTdlsCtx->pAdapter,
+ curr_peer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
#endif
goto next_peer;
}
@@ -347,7 +346,7 @@
// }
}
} else if (eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) {
- if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
+ if (!TDLS_IS_CONNECTED(curr_peer)) {
if (curr_peer->tx_pkt >=
pHddTdlsCtx->threshold_config.tx_packet_n) {
@@ -393,11 +392,9 @@
return;
}
- cfg80211_tdls_oper_request(curr_peer->pHddTdlsCtx->pAdapter->dev,
- curr_peer->peerMac,
- NL80211_TDLS_TEARDOWN,
- eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
- GFP_KERNEL);
+ wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter,
+ curr_peer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
mutex_unlock(&tdls_lock);
#endif
}
@@ -688,7 +685,7 @@
if (mutex_lock_interruptible(&tdls_lock))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "%s: unabile to lock list", __func__);
+ "%s: unable to lock list", __func__);
vos_mem_free(peer);
return NULL;
}
@@ -1216,7 +1213,7 @@
MAC_ADDR_ARRAY(curr_peer->peerMac),
curr_peer->staId,
(curr_peer->tdls_support == eTDLS_CAP_SUPPORTED) ? "Y":"N",
- (curr_peer->link_status == eTDLS_LINK_CONNECTED) ? "Y":"N",
+ TDLS_IS_CONNECTED(curr_peer) ? "Y":"N",
curr_peer->rssi);
buf += len;
buflen -= len;
@@ -1736,6 +1733,7 @@
if (connectedTdlsPeers)
{
tANI_U8 staIdx;
+ hddTdlsPeer_t *curr_peer;
for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
{
@@ -1745,11 +1743,8 @@
("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ;
#ifdef CONFIG_TDLS_IMPLICIT
- cfg80211_tdls_oper_request(pAdapter->dev,
- pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes,
- NL80211_TDLS_TEARDOWN,
- eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
- GFP_KERNEL);
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter,pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes);
+ wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
#endif
}
}
@@ -1823,3 +1818,20 @@
vos_timer_start(timer, expirationTime);
}
}
+void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter,
+ hddTdlsPeer_t *curr_peer,
+ tANI_U16 reason)
+{
+ if (NULL == pAdapter || NULL == curr_peer)
+ return;
+
+ if (eTDLS_LINK_CONNECTED != curr_peer->link_status)
+ return;
+
+ wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING);
+ cfg80211_tdls_oper_request(pAdapter->dev,
+ curr_peer->peerMac,
+ NL80211_TDLS_TEARDOWN,
+ reason,
+ GFP_KERNEL);
+}