qcacld-3.0: Handle SAP + TDLS concurrencies

Disable TDLS offchannel on SAP start if concurrent STA with
TDLS exist.
Enable TDLS off channel after SAP start if SAP and
STA are not in MCC.

If TDLS is enabled, and off channel is required, update
TDLS off channel to be the SAP channel.

Change-Id: Ica508889acbae5e2dc4269d4d7518cf01d62714f
CRs-Fixed: 3444747
This commit is contained in:
Pragaspathi Thilagaraj
2023-02-13 03:05:28 +05:30
committed by Madan Koyyalamudi
parent f5de86a061
commit c2976a7b2d
10 changed files with 254 additions and 104 deletions

View File

@@ -1080,11 +1080,11 @@ tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev,
if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
WLAN_TDLS_CONCURRENCIES_SUPPORT))
return false;
return QDF_STATUS_SUCCESS;
if (!policy_mgr_get_allowed_tdls_offchannel_freq(psoc, vdev, &freq)) {
tdls_debug("off channel not allowed for current concurrency");
return false;
return QDF_STATUS_E_NOSUPPORT;
}
/*
@@ -1129,7 +1129,8 @@ tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev,
(!wlan_reg_is_24ghz_ch_freq(peer_freq) ||
(wlan_reg_is_6ghz_chan_freq(peer_freq) &&
tdls_is_6g_freq_allowed(vdev, peer_freq)))) {
off_channels[i] = peer_info->peer_cap.peer_chan[i];
off_channels[params->num_off_channels] =
peer_info->peer_cap.peer_chan[i];
params->num_off_channels++;
}
}
@@ -1244,9 +1245,17 @@ int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
conn_peer->op_class_for_pref_off_chan =
chan_switch_params->oper_class;
tdls_update_peer_off_channel_list(pdev, tdls_soc, vdev,
conn_peer,
chan_switch_params);
/*
* Don't enable TDLS off channel if concurrency is not allowed
*/
status = tdls_update_peer_off_channel_list(pdev, tdls_soc, vdev,
conn_peer,
chan_switch_params);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(chan_switch_params);
return -EINVAL;
}
break;
case DISABLE_CHANSWITCH:
case DISABLE_ACTIVE_CHANSWITCH:

View File

@@ -93,7 +93,8 @@ static char *tdls_get_cmd_type_str(enum tdls_command_type cmd_type)
return "TDLS_NOTIFY_RESET_ADAPTERS";
case TDLS_CMD_ANTENNA_SWITCH:
return "TDLS_CMD_ANTENNA_SWITCH";
case TDLS_CMD_START_BSS:
return "TDLS_CMD_START_BSS";
default:
return "Invalid TDLS command";
}
@@ -571,6 +572,24 @@ static QDF_STATUS tdls_reset_all_peers(
return status;
}
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc)
{
struct wlan_objmgr_vdev *tdls_vdev;
tdls_vdev = tdls_get_vdev(psoc, WLAN_TDLS_NB_ID);
if (!tdls_vdev) {
tdls_err("Unable get the tdls vdev");
return QDF_STATUS_E_FAILURE;
}
tdls_set_tdls_offchannelmode(tdls_vdev, DISABLE_ACTIVE_CHANSWITCH);
wlan_objmgr_vdev_release_ref(tdls_vdev, WLAN_TDLS_NB_ID);
return QDF_STATUS_SUCCESS;
}
#endif
QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -655,6 +674,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
case TDLS_DELETE_ALL_PEERS_INDICATION:
tdls_reset_all_peers(msg->bodyptr);
break;
case TDLS_CMD_START_BSS:
tdls_handle_start_bss(msg->bodyptr);
break;
default:
break;
}
@@ -959,6 +981,7 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
qdf_freq_t ch_freq;
QDF_STATUS status;
uint32_t connection_count;
uint8_t sta_count, p2p_cli_count;
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status))
@@ -981,7 +1004,14 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
}
connection_count = policy_mgr_get_connection_count(tdls_soc_obj->soc);
if (connection_count == 1 ||
sta_count =
policy_mgr_mode_specific_connection_count(tdls_soc_obj->soc,
PM_STA_MODE, NULL);
p2p_cli_count =
policy_mgr_mode_specific_connection_count(tdls_soc_obj->soc,
PM_P2P_CLIENT_MODE,
NULL);
if ((connection_count == 1 && (sta_count || p2p_cli_count)) ||
(connection_count > 1 &&
tdls_is_concurrency_allowed(tdls_soc_obj->soc))) {
state = true;
@@ -1020,7 +1050,7 @@ bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
return false;
}
if (policy_mgr_current_concurrency_is_mcc(psoc)) {
if (policy_mgr_is_mcc_on_any_sta_vdev(psoc)) {
tdls_debug("Base channel MCC. Don't allow TDLS");
return false;
}
@@ -1115,10 +1145,13 @@ tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
}
if (!tdls_check_is_tdls_allowed(tdls_obj_vdev)) {
tdls_disable_offchan_and_teardown_links(tdls_obj_vdev);
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
return QDF_STATUS_E_NULL_VALUE;
}
tdls_set_tdls_offchannelmode(tdls_obj_vdev, ENABLE_CHANSWITCH);
tdls_debug("enter ");
tdls_set_ct_mode(psoc, tdls_obj_vdev);
@@ -1139,24 +1172,41 @@ tdls_process_decrement_active_session(struct wlan_objmgr_psoc *psoc)
tdls_debug("Enter");
if (!psoc)
return QDF_STATUS_E_NULL_VALUE;
if(!policy_mgr_is_hw_dbs_2x2_capable(psoc) &&
!policy_mgr_is_hw_dbs_required_for_band(
psoc, HW_MODE_MAC_BAND_2G) &&
!policy_mgr_is_hw_dbs_required_for_band(psoc, HW_MODE_MAC_BAND_2G) &&
policy_mgr_is_current_hwmode_dbs(psoc)) {
tdls_debug("Current HW mode is 1*1 DBS. Wait for Opportunistic timer to expire to enable TDLS in FW");
return QDF_STATUS_SUCCESS;
}
tdls_obj_vdev = tdls_get_vdev(psoc, WLAN_TDLS_NB_ID);
if (tdls_obj_vdev) {
tdls_debug("Enable TDLS in FW and host as only one active sta/p2p_cli interface is present");
vdev_id = wlan_vdev_get_id(tdls_obj_vdev);
if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
&tdls_priv_soc) == QDF_STATUS_SUCCESS)
tdls_send_update_to_fw(tdls_priv_vdev, tdls_priv_soc,
false, false, true, vdev_id);
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
if (!tdls_obj_vdev)
return QDF_STATUS_E_FAILURE;
if (!tdls_check_is_tdls_allowed(tdls_obj_vdev))
goto release_ref;
/*
* 2 Port MCC -> 1 port scenario or
* 3 Port MCC -> 2 port SCC scenario or
* 4 Port -> 3 Port SCC scenario
* So enable TDLS in firmware
*/
tdls_debug("Enable TDLS in FW and host as active sta/p2p_cli interface is present");
vdev_id = wlan_vdev_get_id(tdls_obj_vdev);
if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
&tdls_priv_soc) == QDF_STATUS_SUCCESS) {
tdls_send_update_to_fw(tdls_priv_vdev, tdls_priv_soc,
false, false, true, vdev_id);
if (tdls_priv_soc->connected_peer_count == 1)
tdls_set_tdls_offchannelmode(tdls_obj_vdev,
ENABLE_CHANSWITCH);
}
release_ref:
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
return QDF_STATUS_SUCCESS;
}
@@ -1331,11 +1381,12 @@ void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
tdls_info_to_fw->tdls_state = tdls_soc_obj->tdls_current_mode;
tdls_info_to_fw->tdls_options = 0;
/* Do not enable TDLS offchannel, if AP prohibited TDLS
/*
* Do not enable TDLS offchannel, if AP prohibited TDLS
* channel switch
*/
if (TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) &&
(!tdls_chan_swit_prohibited))
!tdls_chan_swit_prohibited)
tdls_info_to_fw->tdls_options = ENA_TDLS_OFFCHAN;
if (TDLS_IS_BUFFER_STA_ENABLED(tdls_feature_flags))

View File

@@ -829,6 +829,15 @@ uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
uint8_t *reg_bw_offset);
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
/**
* tdls_handle_start_bss() - Handle start BSS event to act on concurrent
* session offchannel mode
* @psoc: Pointer to PSOC object
*
* Return: None
*/
QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc);
/**
* tdls_is_concurrency_allowed() - Is TDLS allowed with the current concurrency
* @psoc: Pointer to PSOC
@@ -837,10 +846,17 @@ uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
*/
bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc);
#else
static inline
QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
static inline bool
tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
{
return false;
}
#endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, 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 any
* purpose with or without fee is hereby granted, provided that the above
@@ -110,6 +110,13 @@ void wlan_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *mac_addr,
struct qdf_mac_addr *dest_mac_addr);
/**
* wlan_tdls_notify_start_bss() - Notify TDLS module on start bss
* @psoc: Pointer to PSOC object
*
* Return: None
*/
void wlan_tdls_notify_start_bss(struct wlan_objmgr_psoc *psoc);
#else
#ifdef FEATURE_SET
@@ -153,5 +160,8 @@ void wlan_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
{
}
static inline
void wlan_tdls_notify_start_bss(struct wlan_objmgr_psoc *psoc)
{}
#endif
#endif

View File

@@ -46,8 +46,20 @@
#define WLAN_MAC_MAX_SUPP_RATES 32
#define WLAN_CHANNEL_14 14
/* Enable TDLS off-channel switch */
#define ENABLE_CHANSWITCH 1
/*
* Passive(peer requested) responder mode off-channel switch.
* If peer initiates off channel request, that will be honored in
* this mode
*/
#define DISABLE_CHANSWITCH 2
/*
* Disable TDLS off-channel operation completely.
* Peer initiated requests will also be discarded.
*/
#define DISABLE_ACTIVE_CHANSWITCH 3
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN 1
@@ -228,6 +240,7 @@ enum tdls_feature_mode {
* @TDLS_CMD_SET_OFFCHANMODE: tdls offchannel mode
* @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
* @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication
* @TDLS_CMD_START_BSS: SAP start indication to tdls module
*/
enum tdls_command_type {
TDLS_CMD_TX_ACTION = 1,
@@ -253,7 +266,8 @@ enum tdls_command_type {
TDLS_CMD_SET_OFFCHANNEL,
TDLS_CMD_SET_OFFCHANMODE,
TDLS_CMD_SET_SECOFFCHANOFFSET,
TDLS_DELETE_ALL_PEERS_INDICATION
TDLS_DELETE_ALL_PEERS_INDICATION,
TDLS_CMD_START_BSS
};
/**

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, 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 any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,6 +29,7 @@
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_cmn.h>
#include "wlan_tdls_cfg_api.h"
#include "wlan_policy_mgr_api.h"
static QDF_STATUS tdls_teardown_flush_cb(struct scheduler_msg *msg)
{
@@ -112,6 +113,39 @@ release_ref:
WLAN_TDLS_NB_ID);
}
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
static void wlan_tdls_handle_sap_start(struct wlan_objmgr_psoc *psoc)
{
QDF_STATUS status;
struct scheduler_msg msg = {0};
msg.callback = tdls_process_cmd;
msg.type = TDLS_CMD_START_BSS;
msg.bodyptr = psoc;
status = scheduler_post_message(QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TARGET_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("post start bss msg fail");
return;
}
}
#else
static inline void
wlan_tdls_handle_sap_start(struct wlan_objmgr_psoc *psoc)
{}
#endif
void wlan_tdls_notify_start_bss(struct wlan_objmgr_psoc *psoc)
{
if (tdls_is_concurrency_allowed(psoc)) {
wlan_tdls_handle_sap_start(psoc);
return;
}
wlan_tdls_teardown_links_sync(psoc);
}
static QDF_STATUS tdls_notify_flush_cb(struct scheduler_msg *msg)
{
struct tdls_sta_notify_params *notify = msg->bodyptr;