Просмотр исходного кода

qcacmn: Drop 6 GHz beacon out of BSS operating BW

Duplicated 6 GHz beacons with poor RSSI are received in frequency far away
from primary channel, they are not dropped because HE duplicate beacon
field is set, which makes poor RSSI saved in scan entry.

To fix it, if 6 GHz HE duplicate beacon field is set, compare band width
and center frequency from EHT ops and HE ops with current frequency beacon
received, if current frequency is outside of the BSS operating BW, drop the
leaked beacon.

Change-Id: I580df7efbbe5a7b56cfd14795474ad9a4d432fdc
CRs-Fixed: 3299236
Jianmin Zhu 2 лет назад
Родитель
Сommit
5551df9af9
1 измененных файлов с 210 добавлено и 12 удалено
  1. 210 12
      umac/scan/dispatcher/src/wlan_scan_utils_api.c

+ 210 - 12
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -34,6 +34,7 @@
 #include <wlan_utility.h>
 #endif
 #include "wlan_psoc_mlme_api.h"
+#include "reg_services_public_struct.h"
 
 #define MAX_IE_LEN 1024
 #define SHORT_SSID_LEN 4
@@ -339,16 +340,189 @@ static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops)
 	return (struct he_oper_6g_param *)he_ops;
 }
 
+#ifdef WLAN_FEATURE_11BE
+/*
+ * util_scan_is_out_of_band_leak_eht() - Check if eht beacon out of BSS BW
+ * @pdev: pointer to pdev.
+ * @scan_params: scan entry generated by beacon/probe rsp
+ * @band_mask: band mask of frequency beacon/probe rsp received
+ * @current_freq: frequency beacon/probe rsp received
+ *
+ * 1. If BSS BW <= 80MHz
+ * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
+ * BSS BW/2 then eht beacon in BSS operating BW
+ * else eht beacon out of BSS operating BW
+ *
+ * 2. If BSS BW > 80MHz
+ * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
+ * BSS BW/2 then eht beacon in BSS operating BW
+ * else eht beacon out of BSS operating BW
+ *
+ * Return: bool, whether eht beacon out of BSS operating BW
+ */
+static bool
+util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
+				  struct scan_cache_entry *scan_params,
+				  uint8_t band_mask,
+				  qdf_freq_t current_freq)
+{
+	struct wlan_ie_ehtops *eht_ops;
+	uint8_t ch_width;
+	uint32_t bw;
+	uint32_t freq_diff;
+	qdf_freq_t freq_seg0;
+	qdf_freq_t freq_seg1;
+
+	eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
+	if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
+		return false;
+
+	if (!QDF_GET_BITS(eht_ops->ehtop_param,
+			  EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS))
+		return false;
+
+	ch_width = QDF_GET_BITS(eht_ops->control,
+				EHTOP_INFO_CHAN_WIDTH_IDX,
+				EHTOP_INFO_CHAN_WIDTH_BITS);
+	freq_seg0 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs0,
+					       band_mask);
+	freq_seg1 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs1,
+					       band_mask);
+	if (ch_width == WLAN_EHT_CHWIDTH_320)
+		bw = BW_320_MHZ;
+	else if (ch_width == WLAN_EHT_CHWIDTH_160)
+		bw = BW_160_MHZ;
+	else if (ch_width == WLAN_EHT_CHWIDTH_80)
+		bw = BW_80_MHZ;
+	else  if (ch_width == WLAN_EHT_CHWIDTH_40)
+		bw = BW_40_MHZ;
+	else  if (ch_width == WLAN_EHT_CHWIDTH_20)
+		bw = BW_20_MHZ;
+	else
+		bw = BW_20_MHZ;
+
+	if (bw <= BW_80_MHZ)
+		freq_diff = abs(freq_seg0 - current_freq);
+	else
+		freq_diff = abs(freq_seg1 - current_freq);
+	if (freq_diff <= bw / 2)
+		return false;
+
+	scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
+		  current_freq, bw, freq_seg0, freq_seg1);
+	return true;
+}
+#else
+static bool
+util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
+				  struct scan_cache_entry *scan_params,
+				  uint8_t band_mask,
+				  qdf_freq_t current_freq)
+{
+	return false;
+}
+#endif
+
+/*
+ * util_scan_is_out_of_band_leak_he() - Check if HE beacon out of BSS BW
+ * @pdev: pointer to pdev.
+ * @he_6g_params: HE 6 GHz params
+ * @band_mask: band mask of frequency beacon/probe rsp received
+ * @current_freq: frequency beacon/probe rsp received
+ *
+ * 1. If BSS BW <= 80MHz
+ * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
+ * BSS BW/2 then HE beacon in BSS operating BW
+ *
+ * 2. If BSS BW is 160MHz
+ * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
+ * BSS BW/2 then HE beacon in BSS operating BW
+ *
+ * 3. If BSS BW is 80+80MHz
+ * If absolute value of (Current Channel - Channel Center Frequency Segment 0)
+ * <= 40 or absolute value of (Current Channel - Channel Center Frequency
+ *  Segment 1) <= 40, then HE beacon in BSS operating BW
+ *
+ * Return: bool, whether HE beacon out of BSS operating BW
+ */
+static bool
+util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev *pdev,
+				 struct he_oper_6g_param *he_6g_params,
+				 uint8_t band_mask,
+				 qdf_freq_t current_freq)
+{
+	uint8_t ch_width;
+	uint32_t bw;
+	uint32_t freq_diff;
+	qdf_freq_t freq_seg0;
+	qdf_freq_t freq_seg1;
+
+	ch_width = he_6g_params->width;
+	freq_seg0 = wlan_reg_chan_band_to_freq(pdev,
+					       he_6g_params->chan_freq_seg0,
+					       band_mask);
+	freq_seg1 = wlan_reg_chan_band_to_freq(pdev,
+					       he_6g_params->chan_freq_seg1,
+					       band_mask);
+	if (ch_width == WLAN_HE_6GHZ_CHWIDTH_160_80_80)
+		bw = BW_160_MHZ;
+	else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_80)
+		bw = BW_80_MHZ;
+	else  if (ch_width == WLAN_HE_6GHZ_CHWIDTH_40)
+		bw = BW_40_MHZ;
+	else  if (ch_width == WLAN_HE_6GHZ_CHWIDTH_20)
+		bw = BW_20_MHZ;
+	else
+		bw = BW_20_MHZ;
+
+	if (bw <= BW_80_MHZ) {
+		freq_diff = abs(freq_seg0 - current_freq);
+		if (freq_diff <= bw / 2)
+			return false;
+	} else if (WLAN_IS_HE160(he_6g_params)) {
+		freq_diff = abs(freq_seg1 - current_freq);
+		if (freq_diff <= bw / 2)
+			return false;
+	} else if (WLAN_IS_HE80_80(he_6g_params)) {
+		freq_diff = abs(freq_seg0 - current_freq);
+		if (freq_diff <= BW_40_MHZ)
+			return false;
+		freq_diff = abs(freq_seg1 - current_freq);
+		if (freq_diff <= BW_40_MHZ)
+			return false;
+	}
+
+	scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
+		  current_freq, bw, freq_seg0, freq_seg1);
+
+	return true;
+}
+
+/*
+ * util_scan_get_chan_from_he_6g_params() - Get chan info from 6 GHz param
+ * @pdev: pointer to pdev.
+ * @scan_params: scan entry generated by beacon/probe rsp
+ * @chan_freq: output parmeter, primary freq from 6 GHz he params
+ * @is_6g_dup_bcon: output parmeter, bool, if false, invalid 6g duplicated
+	beacon out of BSS operating BW or not duplicated beacon, can drop if
+	channel mismatch
+ * @band_mask: band mask of frequency beacon/probe rsp received
+ * @current_freq: frequency beacon/probe rsp received
+ *
+ * Return: QDF_STATUS
+ */
 static QDF_STATUS
 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
 				     struct scan_cache_entry *scan_params,
 				     qdf_freq_t *chan_freq,
-				     bool *he_6g_dup_bcon, uint8_t band_mask)
+				     bool *is_6g_dup_bcon, uint8_t band_mask,
+				     qdf_freq_t current_freq)
 {
 	struct he_oper_6g_param *he_6g_params;
 	uint8_t *he_ops;
 	struct wlan_scan_obj *scan_obj;
 	struct wlan_objmgr_psoc *psoc;
+	bool is_out_of_band_leak = true;
 
 	psoc = wlan_pdev_get_psoc(pdev);
 	if (!psoc) {
@@ -362,7 +536,7 @@ util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	*he_6g_dup_bcon = false;
+	*is_6g_dup_bcon = false;
 
 	he_ops = util_scan_entry_heop(scan_params);
 	if (!util_scan_entry_hecap(scan_params) || !he_ops)
@@ -383,7 +557,27 @@ util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
 			     he_6g_params->primary_channel, *chan_freq);
 		return QDF_STATUS_E_INVAL;
 	}
-	*he_6g_dup_bcon = he_6g_params->duplicate_beacon ? true : false;
+
+	if (!he_6g_params->duplicate_beacon) {
+		*is_6g_dup_bcon = false;
+		return QDF_STATUS_SUCCESS;
+	}
+	is_out_of_band_leak =
+		util_scan_is_out_of_band_leak_eht(pdev, scan_params, band_mask,
+						  current_freq);
+	if (is_out_of_band_leak) {
+		*is_6g_dup_bcon = false;
+		return QDF_STATUS_SUCCESS;
+	}
+	is_out_of_band_leak =
+		util_scan_is_out_of_band_leak_he(pdev, he_6g_params, band_mask,
+						 current_freq);
+	if (is_out_of_band_leak) {
+		*is_6g_dup_bcon = false;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	*is_6g_dup_bcon = true;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -463,8 +657,9 @@ static QDF_STATUS
 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
 				     struct scan_cache_entry *scan_params,
 				     qdf_freq_t *chan_freq,
-				     bool *he_6g_dup_bcon,
-				     uint8_t band_mask)
+				     bool *is_6g_dup_bcon,
+				     uint8_t band_mask,
+				     qdf_freq_t current_freq)
 {
 	return QDF_STATUS_SUCCESS;
 }
@@ -2090,8 +2285,9 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 	struct scan_cache_node *scan_node;
 	uint8_t i;
 	qdf_freq_t chan_freq = 0;
-	bool he_6g_dup_bcon = false;
+	bool is_6g_dup_bcon = false;
 	uint8_t band_mask;
+	qdf_freq_t recv_freq = 0;
 
 	scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry));
 	if (!scan_entry) {
@@ -2130,10 +2326,11 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 	scan_entry->tsf_delta = rx_param->tsf_delta;
 	scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
 
+	recv_freq = rx_param->chan_freq;
 	/* Copy per chain rssi to scan entry */
 	qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl,
 		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
-	band_mask = BIT(wlan_reg_freq_to_band(rx_param->chan_freq));
+	band_mask = BIT(wlan_reg_freq_to_band(recv_freq));
 
 	if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev),
 					  WLAN_SOC_CEXT_HW_DB2DBM)) {
@@ -2195,8 +2392,9 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 	if (!chan_freq && util_scan_entry_hecap(scan_entry)) {
 		status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry,
 							      &chan_freq,
-							      &he_6g_dup_bcon,
-							      band_mask);
+							      &is_6g_dup_bcon,
+							      band_mask,
+							      recv_freq);
 		if (QDF_IS_STATUS_ERROR(status)) {
 			qdf_mem_free(scan_entry->raw_frame.ptr);
 			qdf_mem_free(scan_entry);
@@ -2209,11 +2407,11 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 
 	/* If no channel info is present in beacon use meta channel */
 	if (!scan_entry->channel.chan_freq) {
-		scan_entry->channel.chan_freq = rx_param->chan_freq;
-	} else if (rx_param->chan_freq !=
+		scan_entry->channel.chan_freq = recv_freq;
+	} else if (recv_freq !=
 	   scan_entry->channel.chan_freq) {
 		if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq) &&
-		    !he_6g_dup_bcon)
+		    !is_6g_dup_bcon)
 			scan_entry->channel_mismatch = true;
 	}