qcacld-3.0: Send Deauth and delete all TDLS stations
This change addresses sending Deauth to TDLS peers,
delete TDLS stations and clear hdd structures if
concurrency is detected.
Change-Id: Ia9f6724a9db20c6d9ebfc2fa735569305f35f084
CRs-Fixed: 2022489
diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h
index 82377a7..18e793f 100644
--- a/core/hdd/inc/wlan_hdd_assoc.h
+++ b/core/hdd/inc/wlan_hdd_assoc.h
@@ -289,6 +289,8 @@
uint8_t ucastSig, uint8_t qos);
#endif
+QDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter, uint8_t staId);
+
/**
* hdd_perform_roam_set_key_complete() - perform set key complete
* @pAdapter: pointer to adapter
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index 85f5009..25ea28d 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -3565,8 +3565,7 @@
*
* Return: QDF_STATUS enumeration
*/
-static QDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter,
- uint8_t staId)
+QDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter, uint8_t staId)
{
QDF_STATUS qdf_status;
qdf_status = cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
@@ -3826,9 +3825,11 @@
} else
mutex_unlock(&pHddCtx->tdls_lock);
+ mutex_lock(&pHddCtx->tdls_lock);
wlan_hdd_tdls_reset_peer(pAdapter,
pRoamInfo->
peerMac.bytes);
+ mutex_unlock(&pHddCtx->tdls_lock);
pHddCtx->tdlsConnInfo[staIdx].staId = 0;
pHddCtx->tdlsConnInfo[staIdx].
@@ -3878,11 +3879,13 @@
[staIdx].
peerMac.
bytes));
+ mutex_lock(&pHddCtx->tdls_lock);
wlan_hdd_tdls_reset_peer(pAdapter,
pHddCtx->
tdlsConnInfo
[staIdx].
peerMac.bytes);
+ mutex_unlock(&pHddCtx->tdls_lock);
hdd_roam_deregister_tdlssta(pAdapter,
pHddCtx->
tdlsConnInfo
@@ -4148,7 +4151,7 @@
}
#else
-static inline QDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter,
+inline QDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter,
uint8_t staId)
{
return QDF_STATUS_SUCCESS;
diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c
index 1e92181..2e58dad 100644
--- a/core/hdd/src/wlan_hdd_tdls.c
+++ b/core/hdd/src/wlan_hdd_tdls.c
@@ -43,6 +43,8 @@
#include <net/ieee80211_radiotap.h>
#include "wlan_hdd_tdls.h"
#include "wlan_hdd_cfg80211.h"
+#include "wlan_hdd_assoc.h"
+#include "sme_api.h"
#include "cds_sched.h"
#include "wma_types.h"
#include "cds_concurrency.h"
@@ -234,8 +236,10 @@
connected_tdls_peers = wlan_hdd_tdls_connected_peers(adapter);
- if (!connected_tdls_peers)
- return ;
+ if (!connected_tdls_peers) {
+ hdd_notice("No TDLS connected peers to delete");
+ return;
+ }
/* TDLS is not supported in case of concurrency.
* Disable TDLS Offchannel in FW to avoid more
@@ -254,6 +258,9 @@
TDLS_SEC_OFFCHAN_OFFSET_40PLUS);
hdd_set_tdls_offchannelmode(adapter, DISABLE_CHANSWITCH);
+ /* Send Msg to PE for deleting all the TDLS peers */
+ sme_delete_all_tdls_peers(hddctx->hHal, adapter->sessionId);
+
for (staidx = 0; staidx < hddctx->max_num_tdls_sta;
staidx++) {
if (!hddctx->tdlsConnInfo[staidx].staId)
@@ -262,20 +269,35 @@
mutex_lock(&hddctx->tdls_lock);
curr_peer = wlan_hdd_tdls_find_all_peer(hddctx,
hddctx->tdlsConnInfo[staidx].peerMac.bytes);
-
if (!curr_peer)
continue;
hdd_notice("indicate TDLS teardown (staId %d)",
curr_peer->staId);
+ /* Indicate teardown to supplicant */
wlan_hdd_tdls_indicate_teardown(
curr_peer->pHddTdlsCtx->pAdapter,
curr_peer,
eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+
+ /*
+ * Del Sta happened already as part of sme_delete_all_tdls_peers
+ * Hence clear hdd data structure.
+ */
+ wlan_hdd_tdls_reset_peer(adapter, curr_peer->peerMac);
hdd_send_wlan_tdls_teardown_event(eTDLS_TEARDOWN_CONCURRENCY,
curr_peer->peerMac);
mutex_unlock(&hddctx->tdls_lock);
+
+ hdd_roam_deregister_tdlssta(adapter,
+ hddctx->tdlsConnInfo[staidx].staId);
+ wlan_hdd_tdls_decrement_peer_count(adapter);
+ hddctx->tdlsConnInfo[staidx].staId = 0;
+ hddctx->tdlsConnInfo[staidx].sessionId = 255;
+
+ qdf_mem_zero(&hddctx->tdlsConnInfo[staidx].peerMac,
+ sizeof(struct qdf_mac_addr));
}
}
@@ -1918,7 +1940,6 @@
tdlsCtx_t *hdd_tdls_ctx;
tdlsInfo_t *tdls_param;
QDF_STATUS qdf_ret_status = QDF_STATUS_E_FAILURE;
- uint16_t staIdx;
/* If TDLS support is disabled then no need to update target */
if (false == hdd_ctx->config->fEnableTDLSSupport) {
@@ -1986,29 +2007,6 @@
hdd_warn("Concurrency not allowed in TDLS! set state cnt %d",
hdd_ctx->set_state_info.set_state_cnt);
wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_ctx);
- if (hdd_ctx->connected_peer_count >= 1) {
- /* clean up the tdls peers if any */
- for (staIdx = 0; staIdx < hdd_ctx->max_num_tdls_sta;
- staIdx++) {
- if ((hdd_ctx->tdlsConnInfo[staIdx].sessionId ==
- adapter->sessionId)
- && (hdd_ctx->tdlsConnInfo[staIdx].staId)) {
- uint8_t *mac;
- mac = hdd_ctx->tdlsConnInfo[staIdx].
- peerMac.bytes;
- hdd_notice("call sme_delete_tdls_peer_"
- "sta staId %d sessionId %d "
- MAC_ADDRESS_STR,
- hdd_ctx->tdlsConnInfo
- [staIdx].staId,
- adapter->sessionId,
- MAC_ADDR_ARRAY(mac));
- sme_delete_tdls_peer_sta(
- WLAN_HDD_GET_HAL_CTX(adapter),
- adapter->sessionId, mac);
- }
- }
- }
tdls_prohibited = true;
hdd_ctx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED;
tdls_param->vdev_id = hdd_ctx->set_state_info.vdev_id;
@@ -2364,12 +2362,11 @@
goto ret_status;
}
- mutex_lock(&pHddCtx->tdls_lock);
curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
if (curr_peer == NULL) {
hdd_err("curr_peer is NULL");
status = -EINVAL;
- goto rel_lock;
+ goto ret_status;
}
/*
@@ -2392,8 +2389,6 @@
eTDLS_LINK_IDLE,
eTDLS_LINK_UNSPECIFIED);
curr_peer->staId = 0;
-rel_lock:
- mutex_unlock(&pHddCtx->tdls_lock);
ret_status:
return status;
}
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index af33223..88dca21 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -6900,4 +6900,15 @@
#endif
+/**
+ * struct sir_del_all_tdls_peers - delete all tdls peers
+ * @msg_type: type of message
+ * @msg_len: length of message
+ * @bssid: bssid of peer device
+ */
+struct sir_del_all_tdls_peers {
+ uint16_t msg_type;
+ uint16_t msg_len;
+ struct qdf_mac_addr bssid;
+};
#endif /* __SIR_API_H */
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index 969327c..6bed944 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -263,6 +263,7 @@
eWNI_SME_DEFAULT_SCAN_IE,
eWNI_SME_ROAM_SCAN_OFFLOAD_REQ,
eWNI_SME_LOST_LINK_INFO_IND,
+ eWNI_SME_DEL_ALL_TDLS_PEERS,
eWNI_SME_MSG_TYPES_END
};
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index bc9e321..e467268 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -1964,6 +1964,11 @@
qdf_mem_free((void *)msg->bodyptr);
msg->bodyptr = NULL;
break;
+ case eWNI_SME_DEL_ALL_TDLS_PEERS:
+ lim_process_sme_del_all_tdls_peers(mac_ctx, msg->bodyptr);
+ qdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
default:
qdf_mem_free((void *)msg->bodyptr);
msg->bodyptr = NULL;
diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c
index a382137..1a5d46f 100644
--- a/core/mac/src/pe/lim/lim_process_tdls.c
+++ b/core/mac/src/pe/lim/lim_process_tdls.c
@@ -3368,6 +3368,67 @@
}
/**
+ * lim_check_aid_and_delete_peer() - Funtion to check aid and delete peer
+ * @p_mac: pointer to mac context
+ * @session_entry: pointer to PE session
+ *
+ * This function verifies aid and delete's peer with that aid from hash table
+ *
+ * Return: None
+ */
+static void lim_check_aid_and_delete_peer(tpAniSirGlobal p_mac,
+ tpPESession session_entry)
+{
+ tpDphHashNode stads = NULL;
+ int i, aid;
+ size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap);
+ struct qdf_mac_addr mac_addr;
+
+ /*
+ * Check all the set bit in peerAIDBitmap and delete the peer
+ * (with that aid) entry from the hash table and add the aid
+ * in free pool
+ */
+ lim_log(p_mac, LOG1, FL("Delete all the TDLS peer connected"));
+ for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) {
+ for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) {
+ if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid))
+ continue;
+ stads = dph_get_hash_entry(p_mac,
+ (aid + i * (sizeof(uint32_t) << 3)),
+ &session_entry->dph.dphHashTable);
+
+ if (NULL == stads)
+ goto skip;
+
+ lim_log(p_mac, LOG1,
+ FL("Deleting "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(stads->staAddr));
+
+ lim_send_deauth_mgmt_frame(p_mac,
+ eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
+ stads->staAddr, session_entry, false);
+
+ /* Delete TDLS peer */
+ qdf_mem_copy(mac_addr.bytes, stads->staAddr,
+ QDF_MAC_ADDR_SIZE);
+
+ lim_tdls_del_sta(p_mac, mac_addr,
+ session_entry, false);
+
+ dph_delete_hash_entry(p_mac,
+ stads->staAddr, stads->assocId,
+ &session_entry->dph.dphHashTable);
+skip:
+ lim_release_peer_idx(p_mac,
+ (aid + i * (sizeof(uint32_t) << 3)),
+ session_entry);
+ CLEAR_BIT(session_entry->peerAIDBitmap[i], aid);
+ }
+ }
+}
+
+/**
* lim_delete_tdls_peers() - delete tdls peers
*
* @mac_ctx - global MAC context
@@ -3380,56 +3441,12 @@
tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx,
tpPESession session_entry)
{
- tpDphHashNode stads = NULL;
- int i, aid;
- size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap);
- struct qdf_mac_addr mac_addr;
-
if (NULL == session_entry) {
lim_log(mac_ctx, LOGE, FL("NULL session_entry"));
return eSIR_FAILURE;
}
- /*
- * Check all the set bit in peerAIDBitmap and delete the peer
- * (with that aid) entry from the hash table and add the aid
- * in free pool
- */
- lim_log(mac_ctx, LOGE, FL("Delete all the TDLS peer connected."));
- for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) {
- for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) {
- if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid))
- continue;
- stads = dph_get_hash_entry(mac_ctx,
- (aid + i * (sizeof(uint32_t) << 3)),
- &session_entry->dph.dphHashTable);
-
- if (NULL != stads) {
- lim_log(mac_ctx, LOGE,
- FL("Deleting "MAC_ADDRESS_STR),
- MAC_ADDR_ARRAY(stads->staAddr));
-
- lim_send_deauth_mgmt_frame(mac_ctx,
- eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
- stads->staAddr, session_entry, false);
-
- /* Delete TDLS peer */
- qdf_mem_copy(mac_addr.bytes, stads->staAddr,
- QDF_MAC_ADDR_SIZE);
-
- lim_tdls_del_sta(mac_ctx, mac_addr,
- session_entry, false);
-
- dph_delete_hash_entry(mac_ctx,
- stads->staAddr, stads->assocId,
- &session_entry->dph.dphHashTable);
- }
- lim_release_peer_idx(mac_ctx,
- (aid + i * (sizeof(uint32_t) << 3)),
- session_entry);
- CLEAR_BIT(session_entry->peerAIDBitmap[i], aid);
- }
- }
+ lim_check_aid_and_delete_peer(mac_ctx, session_entry);
if (lim_is_roam_synch_in_progress(session_entry))
return eSIR_SUCCESS;
lim_send_sme_tdls_delete_all_peer_ind(mac_ctx, session_entry);
@@ -3438,6 +3455,40 @@
}
/**
+ * lim_process_sme_del_all_tdls_peers(): process delete tdls peers
+ * @p_mac: pointer to mac context
+ * @msg_buf: message buffer
+ *
+ * This function processes request to delete tdls peers
+ *
+ * Return: Success: eSIR_SUCCESS Failure: Error value
+ */
+tSirRetStatus lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac,
+ uint32_t *msg_buf)
+{
+ struct sir_del_all_tdls_peers *msg;
+ tpPESession session_entry;
+ uint8_t session_id;
+
+ msg = (struct sir_del_all_tdls_peers *)msg_buf;
+ if (msg == NULL) {
+ lim_log(p_mac, LOGE, FL("NULL msg"));
+ return eSIR_FAILURE;
+ }
+
+ session_entry = pe_find_session_by_bssid(p_mac,
+ msg->bssid.bytes, &session_id);
+ if (NULL == session_entry) {
+ lim_log(p_mac, LOGE, FL("NULL psessionEntry"));
+ return eSIR_FAILURE;
+ }
+
+ lim_check_aid_and_delete_peer(p_mac, session_entry);
+
+ return eSIR_SUCCESS;
+}
+
+/**
* lim_process_tdls_del_sta_rsp() - Handle WDA_DELETE_STA_RSP for TDLS
* @mac_ctx: Global MAC context
* @lim_msg: LIM message
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 7fd7082..e7fc7d4 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -910,7 +910,8 @@
void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, QDF_STATUS status, uint32_t *data);
void lim_send_sme_disassoc_deauth_ntf(tpAniSirGlobal mac_ctx,
QDF_STATUS status, uint32_t *ctx);
-
+tSirRetStatus lim_process_sme_del_all_tdls_peers(tpAniSirGlobal p_mac,
+ uint32_t *msg_buf);
/* / Bit value data structure */
typedef enum sHalBitVal /* For Bit operations */
{
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 6ecb2c2..d56aa31 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1435,4 +1435,6 @@
const tSirMacAddr bssid,
uint8_t **frame_buf, uint32_t *frame_len);
+QDF_STATUS sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id);
+
#endif /* #if !defined( __SME_API_H ) */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index cea3414..6840a77 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -16458,3 +16458,43 @@
return QDF_STATUS_SUCCESS;
}
+/**
+ * sme_delete_all_tdls_peers(): send request to delete tdls peers
+ * @hal: handler for HAL
+ * @session_id: session id
+ *
+ * This function sends request to lim to delete tdls peers
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id)
+{
+ struct sir_del_all_tdls_peers *msg;
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ tpAniSirGlobal p_mac = PMAC_STRUCT(hal);
+ tCsrRoamSession *session = CSR_GET_SESSION(p_mac, session_id);
+
+ msg = qdf_mem_malloc(sizeof(*msg));
+ if (NULL == msg) {
+ sms_log(p_mac, LOGE, FL("memory alloc failed"));
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ qdf_mem_zero(msg, sizeof(*msg));
+
+ msg->msg_type = eWNI_SME_DEL_ALL_TDLS_PEERS;
+ msg->msg_len = (uint16_t) sizeof(*msg);
+
+ qdf_mem_copy(msg->bssid.bytes, session->connectedProfile.bssid.bytes,
+ sizeof(struct qdf_mac_addr));
+
+ status = umac_send_mb_message_to_mac(msg);
+
+ if (status != QDF_STATUS_SUCCESS) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ FL("cds_send_mb_message_to_mac Failed"));
+ status = QDF_STATUS_E_FAILURE;
+ }
+
+ return status;
+}