prima: Protect tdls peer list with a mutex
Protect tdls peer list with a mutex.
Change-Id: I46e1c8a0ba20770981ed682162d4ed755555e596
CRs-Fixed: 916191
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index a52d667..4046126 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -3041,7 +3041,9 @@
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, TRUE);
+ mutex_lock(&pHddCtx->tdls_lock);
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter,
+ pRoamInfo->peerMac, FALSE);
if (NULL != curr_peer)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -3050,10 +3052,17 @@
if (TDLS_IS_CONNECTED(curr_peer) ||
(eTDLS_LINK_CONNECTING == curr_peer->link_status))
{
+ mutex_unlock(&pHddCtx->tdls_lock);
hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId );
}
+ else
+ mutex_unlock(&pHddCtx->tdls_lock);
+
wlan_hdd_tdls_decrement_peer_count(pAdapter);
}
+ else
+ mutex_unlock(&pHddCtx->tdls_lock);
+
wlan_hdd_tdls_reset_peer(pAdapter, pRoamInfo->peerMac);
pHddCtx->tdlsConnInfo[staIdx].staId = 0 ;
@@ -3076,8 +3085,11 @@
__func__, pRoamInfo->reasonCode);
#ifdef CONFIG_TDLS_IMPLICIT
- curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac, TRUE);
+ mutex_lock(&pHddCtx->tdls_lock);
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter, pRoamInfo->peerMac,
+ FALSE);
wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, pRoamInfo->reasonCode);
+ mutex_unlock(&pHddCtx->tdls_lock);
#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 b74cb3c..ce623e5 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -10274,7 +10274,6 @@
mutex_unlock(&pHddCtx->tdls_lock);
return -EINVAL;
}
- mutex_unlock(&pHddCtx->tdls_lock);
/* in add station, we accept existing valid staId if there is */
if ((0 == update) &&
@@ -10285,6 +10284,7 @@
"%s: " MAC_ADDRESS_STR
" link_status %d. staId %d. add station ignored.",
__func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
+ mutex_unlock(&pHddCtx->tdls_lock);
return 0;
}
/* in change station, we accept only when staId is valid */
@@ -10292,13 +10292,16 @@
((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
(!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
{
+ tANI_U16 staId = pTdlsPeer->staId;
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR
" link status %d. staId %d. change station %s.",
- __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
- (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
- return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
+ __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, staId,
+ (TDLS_STA_INDEX_VALID(staId)) ? "ignored" : "declined");
+ mutex_unlock(&pHddCtx->tdls_lock);
+ return (TDLS_STA_INDEX_VALID(staId)) ? 0 : -EPERM;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
/* when others are on-going, we want to change link_status to idle */
if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
@@ -10327,14 +10330,17 @@
else
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
+ mutex_lock(&pHddCtx->tdls_lock);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE);
if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
+ mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR " already connected. Request declined.",
__func__, MAC_ADDR_ARRAY(mac));
return -EPERM;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
}
if (0 == update)
wlan_hdd_tdls_set_link_status(pAdapter,
@@ -16816,14 +16822,17 @@
else
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+ mutex_lock(&pHddCtx->tdls_lock);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
+ mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
__func__, MAC_ADDR_ARRAY(peer), action_code);
return -EPERM;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
}
}
@@ -16838,7 +16847,9 @@
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+
+ mutex_lock(&pHddCtx->tdls_lock);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
responder = pTdlsPeer->is_responder;
@@ -16848,8 +16859,10 @@
"%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %zu",
__func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
dialog_token, status_code, len);
+ mutex_unlock(&pHddCtx->tdls_lock);
return -EPERM;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
}
/* For explicit trigger of DIS_REQ come out of BMPS for
@@ -17088,7 +17101,6 @@
mutex_unlock(&pHddCtx->tdls_lock);
return -EINVAL;
}
- mutex_unlock(&pHddCtx->tdls_lock);
/* check FW TDLS Off Channel capability */
if ((TRUE == sme_IsFeatureSupportedByFW(TDLS_OFF_CHANNEL)) &&
@@ -17136,6 +17148,8 @@
if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
+ mutex_unlock(&pHddCtx->tdls_lock);
+
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" %s TDLS Add Force Peer Failed",
__func__);
@@ -17144,12 +17158,15 @@
/*EXT TDLS*/
if ( 0 != wlan_hdd_set_callback(pTdlsPeer, callback) ) {
+ mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" %s TDLS set callback Failed",
__func__);
return -EINVAL;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
+
return(0);
}
@@ -17184,10 +17201,11 @@
return -ENOTSUPP;
}
-
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+ mutex_lock(&pHddCtx->tdls_lock);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
if ( NULL == pTdlsPeer ) {
+ mutex_unlock(&pHddCtx->tdls_lock);
hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
" peer not existing",
__func__, MAC_ADDR_ARRAY(peer));
@@ -17206,6 +17224,7 @@
}
if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) ) {
+ mutex_unlock(&pHddCtx->tdls_lock);
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set force peer"));
return -EINVAL;
}
@@ -17213,14 +17232,16 @@
/*EXT TDLS*/
if ( 0 != wlan_hdd_set_callback(pTdlsPeer, NULL )) {
-
+ mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" %s TDLS set callback Failed",
__func__);
return -EINVAL;
}
- return(0);
+ mutex_unlock(&pHddCtx->tdls_lock);
+
+ return(0);
}
static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
@@ -17284,6 +17305,7 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
" %s : NL80211_TDLS_ENABLE_LINK for " MAC_ADDRESS_STR,
__func__, MAC_ADDR_ARRAY(peer));
+
pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
memset(&staDesc, 0, sizeof(staDesc));
if ( NULL == pTdlsPeer ) {
@@ -17325,6 +17347,7 @@
"TDLS channel switch", __func__);
connPeer->isOffChannelEstablished = FALSE;
+
ret = sme_SendTdlsChanSwitchReq(
WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId,
@@ -17384,6 +17407,7 @@
return -EINVAL;
}
}
+
wlan_hdd_tdls_set_peer_link_status(pTdlsPeer,
eTDLS_LINK_CONNECTED,
eTDLS_LINK_SUCCESS);
@@ -17527,7 +17551,6 @@
}
}
}
-
}
break;
case NL80211_TDLS_DISABLE_LINK:
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index eea0994..ca63678 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -86,6 +86,7 @@
u8 staIdx;
hddTdlsPeer_t *curr_peer = NULL;
hdd_adapter_t *adapter = NULL;
+ bool tdls_unlock = FALSE;
if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) {
hddLog(LOG1, FL("TDLS mode is disabled OR not enabled in FW"));
@@ -109,18 +110,29 @@
* Disable TDLS Offchannel to avoid more than two concurrent channels.
*/
if (connected_tdls_peers == 1) {
+ tSirMacAddr peer_mac;
+ int32_t channel;
+
+ mutex_lock(&hddctx->tdls_lock);
curr_peer = wlan_hdd_tdls_get_connected_peer(adapter);
if (curr_peer && (curr_peer->isOffChannelConfigured == TRUE)) {
hddLog(LOG1, FL("%s: Concurrency detected, Disable "
"TDLS channel switch"), __func__);
curr_peer->isOffChannelEstablished = FALSE;
+ channel = curr_peer->peerParams.channel;
+ vos_mem_copy(peer_mac, curr_peer->peerMac, sizeof(tSirMacAddr));
+ mutex_unlock(&hddctx->tdls_lock);
+
sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(adapter),
adapter->sessionId,
- curr_peer->peerMac,
- curr_peer->peerParams.channel,
+ peer_mac,
+ channel,
TDLS_OFF_CHANNEL_BW_OFFSET,
TDLS_CHANNEL_SWITCH_DISABLE);
+ tdls_unlock = TRUE;
}
+ if (tdls_unlock == FALSE)
+ mutex_unlock(&hddctx->tdls_lock);
}
/* Send Msg to PE for sending deauth and deleting all the TDLS peers */
@@ -1890,22 +1902,21 @@
#endif
tANI_BOOLEAN forcePeer)
{
+ /* NOTE:
+ * Hold mutex tdls_lock before calling this function
+ */
hddTdlsPeer_t *curr_peer;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
if ((NULL == pHddCtx)) return -1;
- mutex_lock(&pHddCtx->tdls_lock);
-
curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE);
if (curr_peer == NULL)
goto error;
curr_peer->isForcedPeer = forcePeer;
- mutex_unlock(&pHddCtx->tdls_lock);
return 0;
error:
- mutex_unlock(&pHddCtx->tdls_lock);
return -1;
}
@@ -2141,6 +2152,9 @@
hddTdlsPeer_t *wlan_hdd_tdls_get_connected_peer(hdd_adapter_t *pAdapter)
{
+ /* NOTE:
+ * Hold mutext tdls_lock before calling this function
+ */
int i;
struct list_head *head;
struct list_head *pos;
@@ -2154,10 +2168,8 @@
return NULL;
}
- mutex_lock(&pHddCtx->tdls_lock);
pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
if (NULL == pHddTdlsCtx) {
- mutex_unlock(&pHddCtx->tdls_lock);
return NULL;
}
for (i = 0; i < 256; i++) {
@@ -2167,7 +2179,6 @@
curr_peer= list_entry (pos, hddTdlsPeer_t, node);
if (curr_peer && (curr_peer->link_status == eTDLS_LINK_CONNECTED))
{
- mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: " MAC_ADDRESS_STR " eTDLS_LINK_CONNECTED",
__func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
@@ -2175,7 +2186,6 @@
}
}
}
- mutex_unlock(&pHddCtx->tdls_lock);
EXIT();
return NULL;
@@ -3125,6 +3135,9 @@
int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer,
cfg80211_exttdls_callback callback)
{
+ /* NOTE:
+ * Hold mutex tdls_lock before calling this function
+ */
hdd_context_t *pHddCtx;
hdd_adapter_t *pAdapter;
@@ -3135,14 +3148,9 @@
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
if ((NULL == pHddCtx)) return -1;
- mutex_lock(&pHddCtx->tdls_lock);
-
curr_peer->state_change_notification = callback;
- mutex_unlock(&pHddCtx->tdls_lock);
return 0;
-
-
}
void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer,
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index b9e9e8e..6dac951 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -10063,12 +10063,15 @@
eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
{
/* Send TDLS Channel Switch Request to connected peer */
+ mutex_lock(&pHddCtx->tdls_lock);
connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
if (NULL == connPeer) {
+ mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: No TDLS Connected Peer", __func__);
return -1;
}
+ mutex_unlock(&pHddCtx->tdls_lock);
}
else
{