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);