diff --git a/components/tdls/core/src/wlan_tdls_cmds_process.c b/components/tdls/core/src/wlan_tdls_cmds_process.c
index 11b796d717..dcc028b5de 100644
--- a/components/tdls/core/src/wlan_tdls_cmds_process.c
+++ b/components/tdls/core/src/wlan_tdls_cmds_process.c
@@ -46,39 +46,6 @@ static uint16_t tdls_get_connected_peer(struct tdls_soc_priv_obj *soc_obj)
}
#ifdef WLAN_FEATURE_11AX
-static uint32_t tdls_get_6g_pwr(struct wlan_objmgr_vdev *vdev,
- qdf_freq_t freq,
- enum supported_6g_pwr_types pwr_typ)
-{
- struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
- struct regulatory_channel chan[NUM_CHANNELS] = {0};
- uint8_t chn_idx, num_chan;
- uint8_t band_mask = BIT(REG_BAND_6G);
-
- if (!pdev)
- return 0;
-
- /* No power check is required for non 6 Ghz channel */
- if (!wlan_reg_is_6ghz_chan_freq(freq))
- return 0;
-
- num_chan = wlan_reg_get_band_channel_list_for_pwrmode(pdev,
- band_mask,
- chan,
- REG_CLI_DEF_VLP);
-
- for (chn_idx = 0; chn_idx < num_chan; chn_idx++) {
- if (chan[chn_idx].center_freq == freq) {
- tdls_debug("VLP power for channel %d is %d",
- chan[chn_idx].center_freq,
- chan[chn_idx].tx_power);
- return chan[chn_idx].tx_power;
- }
- }
-
- return 0;
-}
-
static
uint8_t tdls_get_mlme_ch_power(struct vdev_mlme_obj *mlme_obj, qdf_freq_t freq)
{
@@ -107,8 +74,8 @@ void tdls_set_mlme_ch_power(struct wlan_objmgr_vdev *vdev,
struct reg_tpc_power_info *reg_power_info = &mlme_obj->reg_tpc_obj;
if (REG_VERY_LOW_POWER_AP == reg_power_info->power_type_6g)
- tx_power = tdls_get_6g_pwr(vdev, freq,
- REG_CLI_DEF_VLP);
+ tx_power = tdls_get_6g_pwr_for_power_type(vdev, freq,
+ REG_CLI_DEF_VLP);
else
tx_power = tdls_soc_obj->bss_sta_power;
@@ -1987,6 +1954,7 @@ QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req)
struct tdls_soc_priv_obj *soc_obj;
struct wlan_objmgr_vdev *vdev;
QDF_STATUS status;
+ uint8_t reg_bw_offset;
tdls_debug("Configure external TDLS peer " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(req->peer_addr));
@@ -2011,7 +1979,14 @@ QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req)
}
peer_req.chan = soc_obj->tdls_configs.tdls_pre_off_chan_num;
+ if (!peer_req.op_class)
+ peer_req.op_class = tdls_get_opclass_from_bandwidth(
+ soc_obj, peer_req.chan,
+ soc_obj->tdls_configs.tdls_pre_off_chan_bw,
+ ®_bw_offset);
+ tdls_debug("peer chan %d peer opclass %d", peer_req.chan,
+ peer_req.op_class);
status = tdls_config_force_peer(&peer_req);
error:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
diff --git a/components/tdls/core/src/wlan_tdls_main.c b/components/tdls/core/src/wlan_tdls_main.c
index 7965c6c8de..6019682de1 100644
--- a/components/tdls/core/src/wlan_tdls_main.c
+++ b/components/tdls/core/src/wlan_tdls_main.c
@@ -846,6 +846,39 @@ QDF_STATUS tdls_update_fw_tdls_state(struct tdls_soc_priv_obj *tdls_soc_obj,
}
#ifdef WLAN_FEATURE_11AX
+uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
+ qdf_freq_t freq,
+ enum supported_6g_pwr_types pwr_typ)
+{
+ struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
+ struct regulatory_channel chan[NUM_CHANNELS] = {0};
+ uint8_t chn_idx, num_chan;
+ uint8_t band_mask = BIT(REG_BAND_6G);
+
+ if (!pdev)
+ return 0;
+
+ /* No power check is required for non 6 Ghz channel */
+ if (!wlan_reg_is_6ghz_chan_freq(freq))
+ return 0;
+
+ num_chan = wlan_reg_get_band_channel_list_for_pwrmode(pdev,
+ band_mask,
+ chan,
+ REG_CLI_DEF_VLP);
+
+ for (chn_idx = 0; chn_idx < num_chan; chn_idx++) {
+ if (chan[chn_idx].center_freq == freq) {
+ tdls_debug("VLP power for channel %d is %d",
+ chan[chn_idx].center_freq,
+ chan[chn_idx].tx_power);
+ return chan[chn_idx].tx_power;
+ }
+ }
+
+ return 0;
+}
+
bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq)
{
@@ -897,6 +930,13 @@ bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev,
{
return false;
}
+
+uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
+ qdf_freq_t freq,
+ enum supported_6g_pwr_types pwr_typ)
+{
+ return 0;
+}
#endif
bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
@@ -1923,7 +1963,11 @@ uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj,
{
uint8_t opclass;
- if (bw_offset & (1 << BW_80_OFFSET_BIT)) {
+ if (bw_offset & (1 << BW_160_OFFSET_BIT)) {
+ opclass = tdls_find_opclass(soc_obj->soc,
+ channel, BWALL);
+ *reg_bw_offset = BWALL;
+ } else if (bw_offset & (1 << BW_80_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc,
channel, BW80);
*reg_bw_offset = BW80;
diff --git a/components/tdls/core/src/wlan_tdls_main.h b/components/tdls/core/src/wlan_tdls_main.h
index c7f8b35d5c..87772b6198 100644
--- a/components/tdls/core/src/wlan_tdls_main.h
+++ b/components/tdls/core/src/wlan_tdls_main.h
@@ -318,6 +318,7 @@ struct tdls_peer_mlme_info {
* @is_forced_peer: is forced peer
* @op_class_for_pref_off_chan: op class for preferred off channel
* @pref_off_chan_num: preferred off channel number
+ * @pref_off_chan_width: preferred off channel width
* @peer_idle_timer: time to check idle traffic in tdls peers
* @is_peer_idle_timer_initialised: Flag to check idle timer init
* @spatial_streams: Number of TX/RX spatial streams for TDLS
@@ -349,6 +350,7 @@ struct tdls_peer {
bool is_forced_peer;
uint8_t op_class_for_pref_off_chan;
uint8_t pref_off_chan_num;
+ uint8_t pref_off_chan_width;
qdf_mc_timer_t peer_idle_timer;
bool is_peer_idle_timer_initialised;
uint8_t spatial_streams;
@@ -664,6 +666,21 @@ void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
*/
void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc);
+/**
+ * tdls_get_6g_pwr_for_power_type() - get power for a 6g freq for paticular
+ * power type
+ * @vdev: vdev object
+ * @freq: 6g freq
+ * @pwr_typ: power type
+ *
+ * Function that gets power for a 6g freq for paticular power type
+ *
+ * Return: true or false
+ */
+uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
+ qdf_freq_t freq,
+ enum supported_6g_pwr_types pwr_typ);
+
/**
* tdls_is_6g_freq_allowed() - check is tdls 6ghz allowed or not
* @vdev: vdev object
diff --git a/components/tdls/core/src/wlan_tdls_peer.c b/components/tdls/core/src/wlan_tdls_peer.c
index 9ae058473f..bdb5a577c5 100644
--- a/components/tdls/core/src/wlan_tdls_peer.c
+++ b/components/tdls/core/src/wlan_tdls_peer.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 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
@@ -146,6 +147,33 @@ uint8_t tdls_find_opclass(struct wlan_objmgr_psoc *psoc, uint8_t channel,
bw_offset);
}
+static void tdls_fill_pref_off_chan_num(struct tdls_vdev_priv_obj *vdev_obj,
+ struct tdls_soc_priv_obj *soc_obj,
+ struct tdls_peer *peer)
+{
+ struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
+
+ /*
+ * Fill preffered offchannel number here and prefferd bw here.
+ * Bw and channel number can be used to later calculate Op_class
+ * which will be used to identify the channels
+ */
+ peer->pref_off_chan_width = soc_obj->tdls_configs.tdls_pre_off_chan_bw;
+
+ if (soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g &&
+ tdls_is_6g_freq_allowed(vdev_obj->vdev,
+ soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g)) {
+ peer->pref_off_chan_num =
+ wlan_reg_freq_to_chan(pdev,
+ soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g);
+ } else {
+ peer->pref_off_chan_num =
+ soc_obj->tdls_configs.tdls_pre_off_chan_num;
+ if (CHECK_BIT(peer->pref_off_chan_width, BW_160_OFFSET_BIT))
+ peer->pref_off_chan_width &= ~(1 << BW_160_OFFSET_BIT);
+ }
+}
+
/**
* tdls_add_peer() - add TDLS peer in TDLS vdev object
* @vdev_obj: TDLS vdev object
@@ -180,8 +208,7 @@ static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
qdf_mem_copy(&peer->peer_mac, macaddr, sizeof(peer->peer_mac));
peer->vdev_priv = vdev_obj;
- peer->pref_off_chan_num =
- soc_obj->tdls_configs.tdls_pre_off_chan_num;
+ tdls_fill_pref_off_chan_num(vdev_obj, soc_obj, peer);
peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth(
soc_obj, peer->pref_off_chan_num,
@@ -479,6 +506,7 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
uint8_t chan_id;
uint32_t cur_band;
qdf_freq_t ch_freq;
+ uint32_t tx_power = 0;
vdev_obj = peer->vdev_priv;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
@@ -501,10 +529,11 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
peer_param->peer_cap.peer_off_chan_support =
peer->off_channel_capable;
peer_param->peer_cap.peer_curr_operclass = 0;
- peer_param->peer_cap.self_curr_operclass = 0;
+ peer_param->peer_cap.self_curr_operclass =
+ peer->op_class_for_pref_off_chan;
peer_param->peer_cap.pref_off_channum = peer->pref_off_chan_num;
peer_param->peer_cap.pref_off_chan_bandwidth =
- soc_obj->tdls_configs.tdls_pre_off_chan_bw;
+ peer->pref_off_chan_width;
peer_param->peer_cap.opclass_for_prefoffchan =
peer->op_class_for_pref_off_chan;
@@ -539,8 +568,17 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
CHANNEL_STATE_DFS != ch_state &&
!wlan_reg_is_dsrc_freq(ch_freq)) {
peer_param->peer_cap.peer_chan[num].chan_id = chan_id;
- peer_param->peer_cap.peer_chan[num].pwr =
- wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq);
+ if (!wlan_reg_is_6ghz_chan_freq(ch_freq)) {
+ tx_power =
+ wlan_reg_get_channel_reg_power_for_freq(pdev,
+ ch_freq);
+ } else {
+ tx_power =
+ tdls_get_6g_pwr_for_power_type(vdev_obj->vdev,
+ ch_freq,
+ REG_CLI_DEF_VLP);
+ }
+ peer_param->peer_cap.peer_chan[num].pwr = tx_power;
peer_param->peer_cap.peer_chan[num].dfs_set = false;
peer_param->peer_cap.peer_chanlen++;
num++;
@@ -860,7 +898,7 @@ QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
if (!curr_peer->is_forced_peer) {
config = &soc_obj->tdls_configs;
- curr_peer->pref_off_chan_num = config->tdls_pre_off_chan_num;
+ tdls_fill_pref_off_chan_num(vdev_obj, soc_obj, curr_peer);
curr_peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth(
soc_obj, curr_peer->pref_off_chan_num,
diff --git a/components/tdls/dispatcher/inc/cfg_tdls.h b/components/tdls/dispatcher/inc/cfg_tdls.h
index 5e6f7d97ab..8a0622047b 100644
--- a/components/tdls/dispatcher/inc/cfg_tdls.h
+++ b/components/tdls/dispatcher/inc/cfg_tdls.h
@@ -461,19 +461,48 @@
CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel number")
+/*
+ *
+ * tdls_pref_off_chan_num_6g - Preferred TDLS 6g channel freq when off-channel
+ * support is enabled.
+ * @Min: 0
+ * @Max: 7115
+ * @Default: 5975
+ *
+ * This ini is used to configure preferred TDLS 6G channel number when
+ * off-channel support is enabled. If this is set to 0, 6Ghz offchannel is
+ * disabled.
+ *
+ * Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
+ *
+ * Supported Feature: TDLS
+ *
+ * Usage: Internal/External
+ *
+ *
+ */
+#define CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G CFG_INI_UINT( \
+ "tdls_pref_off_chan_freq_6g", \
+ 0, \
+ 7115, \
+ 5975, \
+ CFG_VALUE_OR_DEFAULT, \
+ "Preferred TDLS channel frequency for 6ghz channels")
+
/*
*
* gTDLSPrefOffChanBandwidth - Preferred TDLS channel bandwidth when
* off-channel support is enabled.
- * @Min: 0x01
- * @Max: 0x0F
- * @Default: 0x07
+ * @Min: 1
+ * @Max: 15
+ * @Default: 15
*
* This ini is used to configure preferred TDLS channel bandwidth when
* off-channel support is enabled.
* 0x1: 20 MHz 0x2: 40 MHz 0x4: 80 MHz 0x8: 160 MHz
* When more than one bits are set then firmware starts from the highest and
- * selects one based on capability of peer.
+ * selects one based on capability of peer. So, that means if 0xF is set that
+ * means fw will try intersect with 160 MHz BW and the peer supported BW.
*
* Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
*
@@ -487,7 +516,7 @@
"gTDLSPrefOffChanBandwidth", \
1, \
15, \
- 7, \
+ 15, \
CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel bandwidth")
@@ -734,6 +763,7 @@
CFG(CFG_TDLS_RSSI_TEARDOWN_THRESHOLD) \
CFG(CFG_TDLS_RSSI_DELTA) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM) \
+ CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_BW) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT) \
diff --git a/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h b/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h
index 6b90a74b86..5d9ff9b5f9 100644
--- a/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h
+++ b/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 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
@@ -467,6 +468,7 @@ enum tdls_feature_bit {
* @tdls_uapsd_ptr_timeout: tdls peer response timeout
* @tdls_feature_flags: tdls feature flags
* @tdls_pre_off_chan_num: tdls off channel number
+ * @tdls_pre_off_chan_freq_6g: tdls pref off channel freq for 6g band
* @tdls_pre_off_chan_bw: tdls off channel bandwidth
* @tdls_peer_kickout_threshold: sta kickout threshold for tdls peer
* @tdls_discovery_wake_timeout: tdls discovery wake timeout
@@ -499,6 +501,7 @@ struct tdls_user_config {
uint32_t tdls_uapsd_ptr_timeout;
uint32_t tdls_feature_flags;
uint32_t tdls_pre_off_chan_num;
+ uint32_t tdls_pre_off_chan_freq_6g;
uint32_t tdls_pre_off_chan_bw;
uint32_t tdls_peer_kickout_threshold;
uint32_t tdls_discovery_wake_timeout;
diff --git a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
index 816fa40a84..b4e76c2e30 100644
--- a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
+++ b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
@@ -202,6 +202,8 @@ static QDF_STATUS tdls_object_init_params(
cfg_get(psoc, CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT);
tdls_soc_obj->tdls_configs.tdls_pre_off_chan_num =
cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM);
+ tdls_soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g =
+ cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G);
tdls_soc_obj->tdls_configs.tdls_pre_off_chan_bw =
cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_BW);
tdls_soc_obj->tdls_configs.tdls_peer_kickout_threshold =
diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c
index 60e2359b1d..c4250367cd 100644
--- a/core/mac/src/pe/lim/lim_process_tdls.c
+++ b/core/mac/src/pe/lim/lim_process_tdls.c
@@ -213,10 +213,10 @@ static void populate_dot11f_tdls_offchannel_params(
mac->mlme_cfg->reg.valid_channel_freq_list[i]);
}
- if (wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq))
- band = BAND_5G;
- else
+ if (wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq))
band = BAND_2G;
+ else
+ band = BAND_5G;
nss_5g = QDF_MIN(mac->vdev_type_nss_5g.tdls,
mac->user_configured_nss);