qcacld-3.0: Add initial checks for TDLS concurrencies

Check if TDLS is allowed for the current existing concurrency
combination. In below combinations, TDLS is not allowed:
1. MCC on STA vdev
2. STA + STA
3. Total connection count > 3
4. No STA vdev exists

If existing TDLS connection exists when 4th port is coming up,
then teardown the TDLS connection and disable off channel.

Change-Id: Iabe174bedecfa6147bd9de3cb2a3716b63145456
CRs-Fixed: 3435864
This commit is contained in:
Pragaspathi Thilagaraj
2023-02-08 03:53:48 +05:30
committed by Madan Koyyalamudi
parent c92b309cfa
commit 37a1c90ea3
4 changed files with 128 additions and 86 deletions

View File

@@ -1966,10 +1966,7 @@ static QDF_STATUS tdls_config_force_peer(
req->op_class, req->min_bandwidth); req->op_class, req->min_bandwidth);
tdls_set_callback(peer, req->callback); tdls_set_callback(peer, req->callback);
tdls_set_ct_mode(soc_obj->soc, vdev);
tdls_set_ct_mode(soc_obj->soc);
if (soc_obj->enable_tdls_connection_tracker)
tdls_implicit_enable(vdev_obj);
return status; return status;
error: error:
@@ -2146,9 +2143,7 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
qdf_mem_free(peer_update_param); qdf_mem_free(peer_update_param);
goto error; goto error;
} }
tdls_set_ct_mode(soc_obj->soc); tdls_set_ct_mode(soc_obj->soc, vdev);
if (!soc_obj->enable_tdls_connection_tracker)
tdls_implicit_disable(vdev_obj);
error: error:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);

View File

@@ -958,6 +958,7 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
bool state = false; bool state = false;
qdf_freq_t ch_freq; qdf_freq_t ch_freq;
QDF_STATUS status; QDF_STATUS status;
uint32_t connection_count;
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID); status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) if (QDF_IS_STATUS_ERROR(status))
@@ -979,14 +980,22 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
goto exit; goto exit;
} }
if (policy_mgr_get_connection_count(tdls_soc_obj->soc) == 1) connection_count = policy_mgr_get_connection_count(tdls_soc_obj->soc);
if (connection_count == 1 ||
(connection_count > 1 &&
tdls_is_concurrency_allowed(tdls_soc_obj->soc))) {
state = true; state = true;
else } else {
tdls_warn("Concurrent sessions exist disable TDLS"); tdls_warn("Concurrent sessions exist disable TDLS");
goto exit;
}
ch_freq = wlan_get_operation_chan_freq(vdev); ch_freq = wlan_get_operation_chan_freq(vdev);
if (wlan_reg_is_6ghz_chan_freq(ch_freq)) if (wlan_reg_is_6ghz_chan_freq(ch_freq) &&
state &= tdls_is_6g_freq_allowed(vdev, ch_freq); !tdls_is_6g_freq_allowed(vdev, ch_freq)) {
tdls_debug("6GHz freq:%d not allowed for TDLS", ch_freq);
state = false;
}
exit: exit:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
@@ -994,72 +1003,105 @@ exit:
return state; return state;
} }
/** #ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
* tdls_set_ct_mode() - Set the tdls connection tracker mode bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
* @psoc: psoc context
*
* This routine is called to set the tdls connection tracker operation status
*
* Return: NONE
*/
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc)
{ {
bool state = false; if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
struct tdls_soc_priv_obj *tdls_soc_obj; WLAN_TDLS_CONCURRENCIES_SUPPORT))
return false;
tdls_soc_obj = wlan_psoc_get_tdls_soc_obj(psoc); if (policy_mgr_get_connection_count(psoc) >
if (!tdls_soc_obj) WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED)
return false;
if (policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
NULL) > 1) {
tdls_debug("More than one STA exist. Don't allow TDLS");
return false;
}
if (policy_mgr_current_concurrency_is_mcc(psoc)) {
tdls_debug("Base channel MCC. Don't allow TDLS");
return false;
}
/*
* Don't enable TDLS for P2P_CLI in concurrency cases
*/
if (policy_mgr_get_connection_count(psoc) > 1 &&
!policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
NULL))
return false;
return true;
}
#endif
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev)
{
struct tdls_soc_priv_obj *tdls_soc_obj;
struct tdls_vdev_priv_obj *tdls_vdev_obj;
uint32_t tdls_feature_flags = 0, sta_count, p2p_count;
bool state = false;
QDF_STATUS status;
if (!tdls_check_is_tdls_allowed(vdev))
return; return;
/* If any concurrency is detected, skip tdls pkt tracker */ status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
if (policy_mgr_get_connection_count(psoc) > 1) { if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("Failed to get TDLS objects");
state = false; state = false;
goto set_state; goto set_state;
} }
tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode || if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode || TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
!TDLS_IS_IMPLICIT_TRIG_ENABLED( !TDLS_IS_IMPLICIT_TRIG_ENABLED(tdls_feature_flags)) {
tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
state = false;
goto set_state;
} else if (policy_mgr_mode_specific_connection_count(psoc,
PM_STA_MODE,
NULL) == 1) {
state = true;
} else if (policy_mgr_mode_specific_connection_count(psoc,
PM_P2P_CLIENT_MODE,
NULL) == 1){
state = true;
} else {
state = false; state = false;
goto set_state; goto set_state;
} }
/* In case of TDLS external control, peer should be added sta_count = policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
* by the user space to start connection tracker. NULL);
*/ p2p_count =
if (TDLS_IS_EXTERNAL_CONTROL_ENABLED( policy_mgr_mode_specific_connection_count(psoc,
tdls_soc_obj->tdls_configs.tdls_feature_flags)) { PM_P2P_CLIENT_MODE,
if (tdls_soc_obj->tdls_external_peer_count) NULL);
state = true; if (sta_count == 1 ||
else (policy_mgr_get_connection_count(psoc) == 1 && p2p_count == 1)) {
state = true;
/*
* In case of TDLS external control, peer should be added
* by the user space to start connection tracker.
*/
if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(tdls_feature_flags) &&
!tdls_soc_obj->tdls_external_peer_count)
state = false; state = false;
goto set_state;
} }
state = false;
set_state: set_state:
tdls_soc_obj->enable_tdls_connection_tracker = state; tdls_soc_obj->enable_tdls_connection_tracker = state;
if (tdls_soc_obj->enable_tdls_connection_tracker)
tdls_implicit_enable(tdls_vdev_obj);
else
tdls_implicit_disable(tdls_vdev_obj);
tdls_debug("enable_tdls_connection_tracker %d", tdls_debug("enable_tdls_connection_tracker %d current_mode:%d feature_flags:0x%x",
tdls_soc_obj->enable_tdls_connection_tracker); tdls_soc_obj->enable_tdls_connection_tracker,
tdls_soc_obj->tdls_current_mode, tdls_feature_flags);
} }
QDF_STATUS QDF_STATUS
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc) tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
{ {
struct tdls_vdev_priv_obj *tdls_priv_vdev;
struct wlan_objmgr_vdev *tdls_obj_vdev; struct wlan_objmgr_vdev *tdls_obj_vdev;
struct tdls_soc_priv_obj *tdls_priv_soc;
if (!psoc) { if (!psoc) {
tdls_err("psoc: %pK", psoc); tdls_err("psoc: %pK", psoc);
@@ -1078,11 +1120,7 @@ tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
} }
tdls_debug("enter "); tdls_debug("enter ");
tdls_set_ct_mode(psoc); tdls_set_ct_mode(psoc, tdls_obj_vdev);
if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
&tdls_priv_soc) == QDF_STATUS_SUCCESS &&
tdls_priv_soc->enable_tdls_connection_tracker)
tdls_implicit_enable(tdls_priv_vdev);
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID); wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
@@ -1137,21 +1175,23 @@ struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
{ {
uint32_t vdev_id; uint32_t vdev_id;
if (policy_mgr_get_connection_count(psoc) > 1) if (policy_mgr_get_connection_count(psoc) > 1 &&
!tdls_is_concurrency_allowed(psoc))
return NULL; return NULL;
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE); vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE);
if (WLAN_INVALID_VDEV_ID != vdev_id) if (WLAN_INVALID_VDEV_ID != vdev_id)
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
vdev_id,
dbg_id); dbg_id);
/*
* For P2P_Client mode, TDLS is not supported on concurrency
* so return P2P_client vdev only if P2P client mode exists without
* any concurreny
*/
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE); vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE);
if (WLAN_INVALID_VDEV_ID != vdev_id &&
if (WLAN_INVALID_VDEV_ID != vdev_id) policy_mgr_get_connection_count(psoc) == 1)
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
vdev_id,
dbg_id); dbg_id);
return NULL; return NULL;
@@ -1369,9 +1409,7 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
notify->session_id); notify->session_id);
/* check and set the connection tracker */ /* check and set the connection tracker */
tdls_set_ct_mode(tdls_soc_obj->soc); tdls_set_ct_mode(tdls_soc_obj->soc, notify->vdev);
if (tdls_soc_obj->enable_tdls_connection_tracker)
tdls_implicit_enable(tdls_vdev_obj);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
@@ -1458,16 +1496,11 @@ tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
} }
/* Check and set the connection tracker and implicit timers */ /* Check and set the connection tracker and implicit timers */
tdls_set_ct_mode(curr_tdls_soc->soc); if (temp_vdev) {
if (curr_tdls_soc->enable_tdls_connection_tracker) tdls_set_ct_mode(curr_tdls_soc->soc, temp_vdev);
tdls_implicit_enable(curr_tdls_vdev);
else
tdls_implicit_disable(curr_tdls_vdev);
/* release the vdev ref , if temp vdev was acquired */
if (temp_vdev)
wlan_objmgr_vdev_release_ref(temp_vdev, wlan_objmgr_vdev_release_ref(temp_vdev,
WLAN_TDLS_NB_ID); WLAN_TDLS_NB_ID);
}
return status; return status;
} }
@@ -1657,18 +1690,15 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
/* If tdls implicit mode is disabled, then /* If tdls implicit mode is disabled, then
* stop the connection tracker. * stop the connection tracker.
*/ */
tdls_soc->enable_tdls_connection_tracker = tdls_soc->enable_tdls_connection_tracker = false;
false; } else if (TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_mode) {
} else if (TDLS_SUPPORT_EXP_TRIG_ONLY ==
tdls_mode) {
clear_bit((unsigned long)source, clear_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap); &tdls_soc->tdls_source_bitmap);
tdls_implicit_disable(tdls_vdev); tdls_implicit_disable(tdls_vdev);
/* If tdls implicit mode is disabled, then /* If tdls implicit mode is disabled, then
* stop the connection tracker. * stop the connection tracker.
*/ */
tdls_soc->enable_tdls_connection_tracker = tdls_soc->enable_tdls_connection_tracker = false;
false;
/* /*
* Check if any TDLS source bit is set and if * Check if any TDLS source bit is set and if
@@ -1679,7 +1709,6 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
return; return;
} }
tdls_debug("exit "); tdls_debug("exit ");
} }
/** /**

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -566,12 +566,14 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
/** /**
* tdls_set_ct_mode() - Set the tdls connection tracker mode * tdls_set_ct_mode() - Set the tdls connection tracker mode
* @psoc: objmgr psoc object * @psoc: objmgr psoc object
* @vdev: Pointer to vdev object
* *
* This routine is called to set the tdls connection tracker operation status * This routine is called to set the tdls connection tracker operation status
* *
* Return: NONE * Return: NONE
*/ */
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc); void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev);
/** /**
* tdls_set_operation_mode() - set tdls operating mode * tdls_set_operation_mode() - set tdls operating mode
@@ -825,4 +827,20 @@ QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev, uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq, uint8_t bw_offset, qdf_freq_t freq, uint8_t bw_offset,
uint8_t *reg_bw_offset); uint8_t *reg_bw_offset);
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
/**
* tdls_is_concurrency_allowed() - Is TDLS allowed with the current concurrency
* @psoc: Pointer to PSOC
*
* Return: True or False
*/
bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc);
#else
static inline bool
tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
{
return false;
}
#endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
#endif #endif

View File

@@ -54,7 +54,7 @@
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX 165 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX 165
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF 36 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF 36
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF 5180 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF 5180
#define WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED 3
#define AC_PRIORITY_NUM 4 #define AC_PRIORITY_NUM 4