diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index 82377a74d495..18e793ffb496 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -289,6 +289,8 @@ QDF_STATUS hdd_roam_register_tdlssta(hdd_adapter_t *pAdapter, 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 85f5009f2421..25ea28d40e62 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3565,8 +3565,7 @@ QDF_STATUS hdd_roam_register_tdlssta(hdd_adapter_t *pAdapter, * * 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 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, } 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 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, [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 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, } #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 1e92181d308b..2e58dad8b8e7 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -43,6 +43,8 @@ #include #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 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) 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 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) 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 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) 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 @@ void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, 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 @@ void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, 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 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac) 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 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac) 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 af33223adaaf..88dca219bf26 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -6900,4 +6900,15 @@ struct wow_enable_params { #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 969327c3900f..6bed9444edc0 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 @@ enum eWniMsgTypes { 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 bc9e32132c47..e467268bdf78 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 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx, 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 a382137b4933..1a5d46f3ac1f 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -3367,6 +3367,67 @@ lim_tdls_link_establish_error: return eSIR_SUCCESS; } +/** + * 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 * @@ -3380,56 +3441,12 @@ lim_tdls_link_establish_error: 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); @@ -3437,6 +3454,40 @@ tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, return eSIR_SUCCESS; } +/** + * 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 diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 7fd7082bf9f8..e7fc7d407a55 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -910,7 +910,8 @@ int lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg); 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 6ecb2c227ec3..d56aa31fdd2a 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1435,4 +1435,6 @@ QDF_STATUS sme_get_beacon_frm(tHalHandle hal, tCsrRoamProfile *profile, 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 cea3414297b7..6840a776d640 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -16458,3 +16458,43 @@ free_scan_flter: 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; +}