Browse Source

qcacmn: Validate the proposed bitmap and enable puncturing

When radar is found in any DFS channel, a radar bitmap is
generated based on the radar infected channels. For example,
if operating channel is 100 HT160 and radar found in 112,
then the generated bitmap is B0000_0010. This proposed bitmap
is compared with the valid puncturing patterns. In this case,
the proposed bitmap is valid puncturing pattern.

In case of a valid puncturing pattern, send the final
bitmap to DFS module and the module updates the DFS channel
puncturing pattern. If an invalid puncturing pattern is
found, return value zero and do not update DFS channel
puncturing pattern.

CRs-Fixed: 3273800
Change-Id: Iee23ac267bfea1b4815a72c2728555f96bed6466
Vijay Krishnan 2 years ago
parent
commit
ef864278aa

+ 2 - 1
umac/dfs/core/src/misc/dfs_cac.c

@@ -104,7 +104,8 @@ void dfs_process_cac_completion(void *context)
 				  dfs_curchan->dfs_ch_ieee,
 				  dfs_curchan->dfs_ch_freq,
 				  dfs_curchan->dfs_ch_mhz_freq_seg2,
-				  dfs_curchan->dfs_ch_flags);
+				  dfs_curchan->dfs_ch_flags,
+				  0);
 		dfs_debug(dfs, WLAN_DEBUG_DFS,
 			  "CAC timer on chan %u (%u MHz) stopped due to radar",
 			  dfs_curchan->dfs_ch_ieee,

+ 60 - 5
umac/dfs/core/src/misc/dfs_process_radar_found_ind.c

@@ -1010,6 +1010,51 @@ dfs_process_radar_ind(struct wlan_dfs *dfs,
 	return status;
 }
 
+#ifdef QCA_DFS_BW_PUNCTURE
+/**
+ * dfs_is_ignore_radar_for_punctured_chans: Store the radar bitmap and check
+ * if radar is found in already punctured channel and ignore the radar.
+ *
+ * dfs: Wlan_dfs structure
+ * dfs_radar_bitmap: Variable to store radar bitmap.
+ * freq_list: output array of sub-channel frequencies.
+ * num_channels: Number of sub-channels in target DFS channel.
+ *
+ * Return: If radar is found on punctured channel then return true.
+ * Else return false.
+ */
+static
+bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
+					     uint16_t *dfs_radar_bitmap,
+					     uint16_t *freq_list,
+					     uint8_t num_channels)
+{
+	uint16_t dfs_punc_pattern = dfs->dfs_curchan->dfs_ch_punc_pattern;
+
+	*dfs_radar_bitmap = dfs_generate_radar_bitmap(dfs,
+						      freq_list,
+						      num_channels);
+	*dfs_radar_bitmap |= dfs_punc_pattern;
+
+	if (*dfs_radar_bitmap == dfs_punc_pattern) {
+		dfs_err(dfs, WLAN_DEBUG_DFS,
+			"radar event received on invalid channel");
+		return true;
+	}
+
+	return false;
+}
+#else
+static
+bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
+					     uint16_t *dfs_radar_bitmap,
+					     uint16_t *freq_list,
+					     uint8_t num_channels)
+{
+	return false;
+}
+#endif /* QCA_DFS_BW_PUNCTURE */
+
 QDF_STATUS
 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 				   struct radar_found_info *radar_found)
@@ -1022,6 +1067,7 @@ dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 	uint32_t freq_center;
 	uint32_t radarfound_freq;
 	struct dfs_channel *dfs_curchan;
+	uint16_t dfs_radar_bitmap = 0;
 
 	dfs_curchan = dfs->dfs_curchan;
 
@@ -1047,6 +1093,18 @@ dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 			  radarfound_freq, dfs_curchan->dfs_ch_ieee,
 			  dfs_curchan->dfs_ch_freq);
 
+	num_channels = dfs_find_radar_affected_channels(dfs,
+							radar_found,
+							freq_list,
+							freq_center);
+
+	if (dfs->dfs_use_puncture &&
+	    dfs_is_ignore_radar_for_punctured_chans(dfs,
+						    &dfs_radar_bitmap,
+						    freq_list,
+						    num_channels))
+		goto exit;
+
 	if (!dfs->dfs_use_nol) {
 		if (!dfs->dfs_is_offload_enabled) {
 			dfs_radar_disable(dfs);
@@ -1058,10 +1116,6 @@ dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 		status = QDF_STATUS_SUCCESS;
 		goto exit;
 	}
-	num_channels = dfs_find_radar_affected_channels(dfs,
-							radar_found,
-							freq_list,
-							freq_center);
 
 	dfs_reset_bangradar(dfs);
 
@@ -1150,7 +1204,8 @@ dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 			  dfs->dfs_curchan->dfs_ch_ieee,
 			  dfs->dfs_curchan->dfs_ch_freq,
 			  dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
-			  dfs->dfs_curchan->dfs_ch_flags);
+			  dfs->dfs_curchan->dfs_ch_flags,
+			  dfs_radar_bitmap);
 
 exit:
 	if (QDF_IS_STATUS_SUCCESS(status))

+ 4 - 1
umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-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
@@ -45,12 +46,14 @@ void dfs_mlme_start_rcsa(struct wlan_objmgr_pdev *pdev,
  * @freq: Channel frequency.
  * @vhtop_ch_freq_seg2: VHT80 Cfreq2.
  * @flags: channel flags.
+ * @dfs_radar_bitmap: Radar bitmap.
  */
 void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev,
 			uint8_t ieee,
 			uint16_t freq,
 			uint16_t vhtop_ch_freq_seg2,
-			uint64_t flags);
+			uint64_t flags,
+			uint16_t dfs_radar_bitmap);
 
 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
 /**

+ 2 - 1
umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h

@@ -86,7 +86,8 @@ struct dfs_to_mlme {
 			uint8_t ieee,
 			uint16_t freq,
 			uint16_t vhtop_ch_freq_seg2,
-			uint64_t flags);
+			uint64_t flags,
+			uint16_t dfs_radar_bitmap);
 #ifdef CONFIG_CHAN_FREQ_API
 	QDF_STATUS (*mlme_start_csa_for_freq)(struct wlan_objmgr_pdev *pdev,
 					      uint8_t ieee_chan, uint16_t freq,

+ 7 - 3
umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-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
@@ -53,14 +54,16 @@ void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev,
 		uint8_t ieee,
 		uint16_t freq,
 		uint16_t vhtop_ch_freq_seg2,
-		uint64_t flags)
+		uint64_t flags,
+		uint16_t dfs_radar_bitmap)
 {
 	if (global_dfs_to_mlme.mlme_mark_dfs)
 		global_dfs_to_mlme.mlme_mark_dfs(pdev,
 				ieee,
 				freq,
 				vhtop_ch_freq_seg2,
-				flags);
+				flags,
+				dfs_radar_bitmap);
 }
 #else /* Else of ndef MCL_DFS_SUPPORT */
 static void dfs_send_radar_ind(struct wlan_objmgr_pdev *pdev,
@@ -84,7 +87,8 @@ void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev,
 		uint8_t ieee,
 		uint16_t freq,
 		uint16_t vhtop_ch_freq_seg2,
-		uint64_t flags)
+		uint64_t flags,
+		uint16_t dfs_radar_bitmap)
 {
 	struct wlan_objmgr_vdev *vdev;
 

+ 45 - 2
umac/regulatory/core/src/reg_services_common.c

@@ -286,14 +286,14 @@ static const uint16_t chan_320mhz_puncture_bitmap[] = {
 	0xf0,
 	0xf00,
 	0xf000,
-	/* 80+40Mhz puncturing pattern: Right 80MHz punctured */
+	/* 80+40Mhz puncturing pattern: Left 80MHz punctured */
 	0x3f,
 	0xcf,
 	0x30f,
 	0xc0f,
 	0x300f,
 	0xc00f,
-	/* 80+40Mhz puncturing pattern: Left 80MHz punctured */
+	/* 80+40Mhz puncturing pattern: Right 80MHz punctured */
 	0xf003,
 	0xf00c,
 	0xf030,
@@ -4390,6 +4390,49 @@ bool reg_is_punc_bitmap_valid(enum phy_ch_width bw, uint16_t puncture_bitmap)
 	return is_punc_bitmap_valid;
 }
 
+#ifdef QCA_DFS_BW_PUNCTURE
+uint16_t reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+					   uint16_t proposed_bitmap)
+{
+	int i, num_bws;
+	const uint16_t *bonded_puncture_bitmap = NULL;
+	uint16_t array_size;
+	uint16_t final_bitmap;
+
+	/* An input pattern = 0 will match any pattern
+	 * Therefore, ignore '0' pattern and return '0', as '0' matches '0'.
+	 */
+	if (!proposed_bitmap)
+		return 0;
+
+	array_size = 0;
+	final_bitmap = 0;
+
+	num_bws = QDF_ARRAY_SIZE(bw_puncture_bitmap_pair_map);
+	for (i = 0; i < num_bws; i++) {
+		if (bw == bw_puncture_bitmap_pair_map[i].chwidth) {
+			bonded_puncture_bitmap =
+			    bw_puncture_bitmap_pair_map[i].puncture_bitmap_arr;
+			array_size = bw_puncture_bitmap_pair_map[i].array_size;
+			break;
+		}
+	}
+
+	if (array_size && bonded_puncture_bitmap) {
+		for (i = 0; i < array_size; i++) {
+			uint16_t valid_bitmap = bonded_puncture_bitmap[i];
+
+			if ((proposed_bitmap | valid_bitmap) == valid_bitmap) {
+				final_bitmap = valid_bitmap;
+				break;
+			}
+		}
+	}
+
+	return final_bitmap;
+}
+#endif /* QCA_DFS_BW_PUNCTURE */
+
 /**
  * reg_update_5g_bonded_channel_state_punc_for_freq() - update channel state
  * with static puncturing feature

+ 19 - 0
umac/regulatory/core/src/reg_services_common.h

@@ -1110,6 +1110,25 @@ reg_fill_channel_list_for_pwrmode(struct wlan_objmgr_pdev *pdev,
  */
 bool reg_is_punc_bitmap_valid(enum phy_ch_width bw, uint16_t puncture_bitmap);
 
+#ifdef QCA_DFS_BW_PUNCTURE
+/**
+ * reg_find_nearest_puncture_pattern() - is generated bitmap is valid or not
+ * @bw: Input channel width.
+ * @proposed_bitmap: Input puncture bitmap.
+ *
+ * Return: Radar bitmap if it is valid.
+ */
+uint16_t reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+					   uint16_t proposed_bitmap);
+#else
+static inline
+uint16_t reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+					   uint16_t proposed_bitmap)
+{
+	return 0;
+}
+#endif /* QCA_DFS_BW_PUNCTURE */
+
 /**
  * reg_extract_puncture_by_bw() - generate new puncture bitmap from original
  *                                puncture bitmap and bandwidth based on new

+ 19 - 0
umac/regulatory/dispatcher/inc/wlan_reg_services_api.h

@@ -1559,6 +1559,25 @@ void wlan_reg_fill_channel_list(struct wlan_objmgr_pdev *pdev,
 bool wlan_reg_is_punc_bitmap_valid(enum phy_ch_width bw,
 				   uint16_t puncture_bitmap);
 
+#ifdef QCA_DFS_BW_PUNCTURE
+/**
+ * wlan_reg_find_nearest_puncture_pattern() - is proposed bitmap valid or not
+ * @bw: Input channel width.
+ * @proposed_bitmap: Input puncture bitmap.
+ *
+ * Return: Radar bitmap if it is valid.
+ */
+uint16_t wlan_reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+						uint16_t proposed_bitmap);
+#else
+static inline
+uint16_t wlan_reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+						uint16_t proposed_bitmap)
+{
+	return 0;
+}
+#endif /* QCA_DFS_BW_PUNCTURE */
+
 /**
  * wlan_reg_extract_puncture_by_bw() - generate new puncture bitmap from
  *                                     original puncture bitmap and bandwidth

+ 8 - 0
umac/regulatory/dispatcher/src/wlan_reg_services_api.c

@@ -1313,6 +1313,14 @@ bool wlan_reg_is_punc_bitmap_valid(enum phy_ch_width bw,
 	return reg_is_punc_bitmap_valid(bw, puncture_bitmap);
 }
 
+#ifdef QCA_DFS_BW_PUNCTURE
+uint16_t wlan_reg_find_nearest_puncture_pattern(enum phy_ch_width bw,
+						uint16_t proposed_bitmap)
+{
+	return reg_find_nearest_puncture_pattern(bw, proposed_bitmap);
+}
+#endif /* QCA_DFS_BW_PUNCTURE */
+
 QDF_STATUS wlan_reg_extract_puncture_by_bw(enum phy_ch_width ori_bw,
 					   uint16_t ori_puncture_bitmap,
 					   qdf_freq_t freq,