qcacld-3.0: Acquire mutex before accessing tdls context
peer_list is a parameter for tdls_ctx, so every access
to peer_list should be protected with mutex lock.
This change refactors the code for wlan_hdd_tdls_add_station()
and wlan_hdd_tdls_set_link_status().
Change-Id: Ibb323d6dccfb91fddf8bde849054cfc331081ff8
CRs-Fixed: 1115781
diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c
index edaa21e..f1e9ff4 100644
--- a/core/hdd/src/wlan_hdd_tdls.c
+++ b/core/hdd/src/wlan_hdd_tdls.c
@@ -1158,14 +1158,13 @@
if (wlan_hdd_validate_context(pHddCtx))
return;
- curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true);
+ curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, false);
if (curr_peer == NULL) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
FL("curr_peer is NULL"));
return;
}
- mutex_lock(&pHddCtx->tdls_lock);
curr_peer->link_status = linkStatus;
/* If TDLS link status is already passed the discovery state
@@ -1174,7 +1173,7 @@
if (linkStatus >= eTDLS_LINK_DISCOVERED) {
curr_peer->discovery_attempt = 0;
}
- mutex_unlock(&pHddCtx->tdls_lock);
+
if (curr_peer->isForcedPeer && curr_peer->state_change_notification) {
uint32_t opclass;
uint32_t channel;
@@ -3856,6 +3855,7 @@
hdd_context_t *pHddCtx = wiphy_priv(wiphy);
QDF_STATUS status;
hddTdlsPeer_t *pTdlsPeer;
+ tTDLSLinkStatus link_status;
uint16_t numCurrTdlsPeers;
unsigned long rc;
int ret;
@@ -3874,14 +3874,18 @@
return -ENOTSUPP;
}
- pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
+ mutex_lock(&pHddCtx->tdls_lock);
+ pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac, false);
if (NULL == pTdlsPeer) {
+ mutex_unlock(&pHddCtx->tdls_lock);
hdd_err(MAC_ADDRESS_STR " update %d not exist. return invalid",
MAC_ADDR_ARRAY(mac), update);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rel_lock;
}
+ link_status = pTdlsPeer->link_status;
/* in add station, we accept existing valid staId if there is */
if ((0 == update) &&
((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
@@ -3889,7 +3893,8 @@
hdd_notice(MAC_ADDRESS_STR " link_status %d. staId %d. add station ignored.",
MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status,
pTdlsPeer->staId);
- return 0;
+ ret = 0;
+ goto rel_lock;
}
/* in change station, we accept only when staId is valid */
if ((1 == update) &&
@@ -3900,13 +3905,16 @@
pTdlsPeer->staId,
(TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" :
"declined");
- return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
+ ret = (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
+ goto rel_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)) {
+ if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, true, false)) {
+ mutex_unlock(&pHddCtx->tdls_lock);
hdd_notice(MAC_ADDRESS_STR " TDLS setup is ongoing. Request declined.",
MAC_ADDR_ARRAY(mac));
+ ret = -EPERM;
goto error;
}
@@ -3922,16 +3930,25 @@
" Num of peers (%d), Max allowed (%d).",
__func__, MAC_ADDR_ARRAY(mac), numCurrTdlsPeers,
pHddCtx->max_num_tdls_sta);
+ mutex_unlock(&pHddCtx->tdls_lock);
+ ret = -EPERM;
goto error;
} else {
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, true);
- if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "%s: " MAC_ADDRESS_STR
- " already connected. Request declined.",
- __func__, MAC_ADDR_ARRAY(mac));
- return -EPERM;
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, false);
+ if (pTdlsPeer) {
+ link_status = pTdlsPeer->link_status;
+ if (TDLS_IS_CONNECTED(pTdlsPeer)) {
+ mutex_unlock(&pHddCtx->tdls_lock);
+ QDF_TRACE(QDF_MODULE_ID_HDD,
+ QDF_TRACE_LEVEL_ERROR,
+ "%s: " MAC_ADDRESS_STR
+ " already connected. "
+ "Request declined.",
+ __func__, MAC_ADDR_ARRAY(mac));
+ ret = -EPERM;
+ goto ret_status;
+ }
}
}
if (0 == update)
@@ -3968,8 +3985,10 @@
StaParams->supported_rates[rate_idx]);
} /* end debug code */
else if ((1 == update) && (NULL == StaParams)) {
+ mutex_unlock(&pHddCtx->tdls_lock);
hdd_err("update is true, but staParams is NULL. Error!");
- return -EPERM;
+ ret = -EPERM;
+ goto ret_status;
}
INIT_COMPLETION(pAdapter->tdls_add_station_comp);
@@ -3978,11 +3997,12 @@
if ((NULL != StaParams) && (StaParams->htcap_present)) {
hddTdlsPeer_t *tdls_peer;
- tdls_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true);
+ tdls_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, false);
if (NULL != tdls_peer)
tdls_peer->spatial_streams =
StaParams->HTCap.suppMcsSet[1];
}
+ mutex_unlock(&pHddCtx->tdls_lock);
if (!update) {
status = sme_add_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX(pAdapter),
@@ -3999,24 +4019,29 @@
if (!rc) {
hdd_err("timeout waiting for tdls add station indication %ld peer link status %u",
- rc, pTdlsPeer->link_status);
+ rc, link_status);
+ ret = -EPERM;
goto error;
}
if (QDF_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s: Add Station is unsuccessful", __func__);
+ ret = -EPERM;
goto error;
}
- return 0;
+ goto ret_status;
error:
wlan_hdd_tdls_set_link_status(pAdapter,
mac,
eTDLS_LINK_IDLE, eTDLS_LINK_UNSPECIFIED);
- return -EPERM;
-
+ goto ret_status;
+rel_lock:
+ mutex_unlock(&pHddCtx->tdls_lock);
+ret_status:
+ return ret;
}
#if TDLS_MGMT_VERSION2