Prechádzať zdrojové kódy

qcacld-3.0: Add support for TDLS offchannel

Add support for TDLS offchannel changes required
for supporting TDLS offchannel on 6 GHz band.

Change-Id: Ie150ff7e5a8237dab445ccb0ab6a4959a7c7fbf0
CRs-Fixed: 3223640
Utkarsh Bhatnagar 2 rokov pred
rodič
commit
50885ab717

+ 11 - 36
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,
+				&reg_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);

+ 45 - 1
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;

+ 17 - 0
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

+ 45 - 7
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,

+ 35 - 5
components/tdls/dispatcher/inc/cfg_tdls.h

@@ -461,19 +461,48 @@
 	CFG_VALUE_OR_DEFAULT, \
 	"Preferred TDLS channel number")
 
+/*
+ * <ini>
+ * 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
+ *
+ * </ini>
+ */
+#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")
+
 /*
  * <ini>
  * 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) \

+ 3 - 0
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;

+ 2 - 0
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 =

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