diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 95b516645210..b42f2fa81528 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1298,6 +1298,8 @@ struct hdd_context_s { bool enable_tdls_connection_tracker; uint8_t tdls_external_peer_count; bool tdls_nss_switch_in_progress; + bool tdls_nss_teardown_complete; + enum tdls_nss_transition_type tdls_nss_transition_mode; int32_t tdls_teardown_peers_cnt; struct tdls_set_state_info set_state_info; #endif diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 4273d722ea36..0985d1af6e05 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -144,6 +144,18 @@ enum tdls_spatial_streams { TDLS_NSS_2x2_MODE = 0xff, }; +/** + * enum tdls_nss_transition_type - TDLS NSS transition states + * @TDLS_NSS_TRANSITION_UNKNOWN: default state + * @TDLS_NSS_TRANSITION_2x2_to_1x1: transition from 2x2 to 1x1 stream + * @TDLS_NSS_TRANSITION_1x1_to_2x2: transition from 1x1 to 2x2 stream + */ +enum tdls_nss_transition_type { + TDLS_NSS_TRANSITION_UNKNOWN = 0, + TDLS_NSS_TRANSITION_2x2_to_1x1, + TDLS_NSS_TRANSITION_1x1_to_2x2, +}; + /** * enum tTDLSCapType - tdls capability type * diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 5ca71152c474..f5240d10fcda 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -6691,6 +6691,17 @@ static int drv_cmd_set_antenna_mode(hdd_adapter_t *adapter, hdd_ctx->current_antenna_mode); ret = 0; exit: +#ifdef FEATURE_WLAN_TDLS + /* Reset tdls NSS flags */ + if (hdd_ctx->tdls_nss_switch_in_progress && + hdd_ctx->tdls_nss_teardown_complete) { + hdd_ctx->tdls_nss_switch_in_progress = false; + hdd_ctx->tdls_nss_teardown_complete = false; + } + hdd_info("tdls_nss_switch_in_progress: %d tdls_nss_teardown_complete: %d", + hdd_ctx->tdls_nss_switch_in_progress, + hdd_ctx->tdls_nss_teardown_complete); +#endif hdd_info("Set antenna status: %d current mode: %d", ret, hdd_ctx->current_antenna_mode); return ret; diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 6ba82a47259b..915cbafb6e9a 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -654,6 +654,8 @@ void hdd_tdls_context_init(hdd_context_t *hdd_ctx) hdd_ctx->tdls_external_peer_count = 0; hdd_ctx->set_state_info.set_state_cnt = 0; hdd_ctx->set_state_info.vdev_id = 0; + hdd_ctx->tdls_nss_teardown_complete = false; + hdd_ctx->tdls_nss_transition_mode = TDLS_NSS_TRANSITION_UNKNOWN; /* This flag will set be true, only when device operates in * standalone STA mode @@ -4082,8 +4084,24 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, mutex_lock(&pHddCtx->tdls_lock); if (pHddCtx->tdls_teardown_peers_cnt != 0) pHddCtx->tdls_teardown_peers_cnt--; - if (pHddCtx->tdls_teardown_peers_cnt == 0) - pHddCtx->tdls_nss_switch_in_progress = false; + if (pHddCtx->tdls_teardown_peers_cnt == 0) { + if (pHddCtx->tdls_nss_transition_mode == + TDLS_NSS_TRANSITION_1x1_to_2x2) { + /* TDLS NSS switch is fully completed, so + * reset the flags. + */ + hdd_info("TDLS NSS switch is fully completed"); + pHddCtx->tdls_nss_switch_in_progress = false; + pHddCtx->tdls_nss_teardown_complete = false; + } else { + /* TDLS NSS switch is not yet completed, but + * tdls teardown is completed for all the + * peers. + */ + hdd_info("TDLS teardown is completed and NSS switch still in progress"); + pHddCtx->tdls_nss_teardown_complete = true; + } + } mutex_unlock(&pHddCtx->tdls_lock); } @@ -5829,11 +5847,16 @@ static int wlan_hdd_tdls_teardown_links(hdd_context_t *hddctx, hdd_info("TDLS peers to be torn down = %d", hddctx->tdls_teardown_peers_cnt); /* Antenna switch 2x2 to 1x1 */ - if (mode == HDD_ANTENNA_MODE_1X1) + if (mode == HDD_ANTENNA_MODE_1X1) { + hddctx->tdls_nss_transition_mode = + TDLS_NSS_TRANSITION_2x2_to_1x1; ret = -EAGAIN; - else + } else { /* Antenna switch 1x1 to 2x2 */ + hddctx->tdls_nss_transition_mode = + TDLS_NSS_TRANSITION_1x1_to_2x2; ret = 0; + } hdd_info("TDLS teardown for antenna switch operation starts"); } mutex_unlock(&hddctx->tdls_lock); @@ -5858,8 +5881,12 @@ int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx, /* Check whether TDLS antenna switch is in progress */ if (hdd_ctx->tdls_nss_switch_in_progress) { - hdd_err("TDLS antenna switch is in progress"); - return -EAGAIN; + if (hdd_ctx->tdls_nss_teardown_complete == false) { + hdd_err("TDLS antenna switch is in progress"); + return -EAGAIN; + } else { + goto tdls_ant_sw_done; + } } /* Check whether TDLS is connected or not */