Răsfoiți Sursa

qca-wifi: Configure proper agile preCAC timeout value

According to the ETSI speculation, off-channel CAC  has a
minimum timeout value of 6 mins (non-weather) and 1 hour (weather). The
maximum timeout value is 4 hours (non-weather) and 24 hours (weather).

Current implementation always took 60 seconds (1 min) as the default
preCAC timeout value. Add changes to implement proper timeout values
based on the channel (weather or non-weather). As part of this change,
add an API to determine if a channel is within this range based on
the edge channels of the given bandwidth.

The API (dfs_start_agile_precac_timer) is called inside
dfs_get_ieeechan_for_agilecac which is used to find the next channel
for agile CAC. Move dfs_start_agile_precac_timer outside
to functionally differentiate each APIs.

Change-Id: Idf3f371b0ab839a746cfba69e86f58202698f3c3
CRs-Fixed: 2482929
Vignesh Mohan 6 ani în urmă
părinte
comite
fb2c9f9864
1 a modificat fișierele cu 100 adăugiri și 28 ștergeri
  1. 100 28
      umac/dfs/core/src/misc/dfs_zero_cac.c

+ 100 - 28
umac/dfs/core/src/misc/dfs_zero_cac.c

@@ -508,6 +508,7 @@ void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs)
 	uint8_t cur_dfs_idx = 0;
 	uint8_t vhtop_ch_freq_seg1, vhtop_ch_freq_seg2;
 	int i;
+	struct dfs_agile_cac_params adfs_param;
 
 	psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj);
 	dfs_soc_obj = dfs->dfs_soc_obj;
@@ -551,10 +552,15 @@ void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs)
 	}
 
 	if (ch_freq) {
+		adfs_param.precac_chan = ch_freq;
+		adfs_param.precac_chwidth = dfs->dfs_precac_chwidth;
+		dfs_start_agile_precac_timer(temp_dfs,
+					     dfs->dfs_soc_obj->ocac_status,
+					     &adfs_param);
 		qdf_info("%s : %d ADFS channel set request sent for pdev: %pK ch_freq: %d",
 			 __func__, __LINE__, pdev, ch_freq);
 		if (dfs_tx_ops && dfs_tx_ops->dfs_agile_ch_cfg_cmd)
-			dfs_tx_ops->dfs_agile_ch_cfg_cmd(pdev, &ch_freq);
+			dfs_tx_ops->dfs_agile_ch_cfg_cmd(pdev, &adfs_param);
 		else
 			dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
 				"dfs_tx_ops=%pK", dfs_tx_ops);
@@ -930,6 +936,7 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 			       uint32_t center_freq)
 {
 	struct wlan_dfs *dfs = NULL;
+	struct dfs_agile_cac_params adfs_param;
 
 	dfs = wlan_pdev_get_dfs_obj(pdev);
 
@@ -950,7 +957,11 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 		 * TRIGGER agile precac timer with 0sec timeout
 		 * with ocac_status 0 for old pdev
 		 */
-		dfs_start_agile_precac_timer(dfs, center_freq, ocac_status);
+		adfs_param.precac_chan = center_freq;
+		adfs_param.precac_chwidth = dfs->dfs_precac_chwidth;
+		dfs_start_agile_precac_timer(dfs,
+					     ocac_status,
+					     &adfs_param);
 	} else {
 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS, "Error Unknown");
 	}
@@ -1627,28 +1638,94 @@ void dfs_cancel_precac_timer(struct wlan_dfs *dfs)
 }
 
 #ifdef QCA_SUPPORT_AGILE_DFS
-#define DEFAULT_CAC_DURATION 62
-void dfs_start_agile_precac_timer(struct wlan_dfs *dfs, uint8_t precac_chan,
-				  uint8_t ocac_status)
+/* FIND_IF_OVERLAP_WITH_WEATHER_RANGE() - Find if the given channel range
+ * overlaps with the weather channel range.
+ * @first_ch: First subchannel of the channel range.
+ * @last_ch:  Last subchannel of the channel range.
+ *
+ * Algorithm:
+ * If the first channel of given range is left of last weather channel
+ * and if the last channel of given range is right of the first weather channel,
+ * return true, else false.
+ */
+#define FIND_IF_OVERLAP_WITH_WEATHER_RANGE(first_ch, last_ch) \
+((first_ch <= WEATHER_CHAN_START) && (WEATHER_CHAN_END <= last_ch))
+
+/* dfs_is_precac_on_weather_channel() - Given a channel number, find if
+ * it's a weather radar channel.
+ * @dfs: Pointer to WLAN_DFS structure.
+ * @chwidth: PreCAC channel width enum.
+ * @precac_chan: Channel for preCAC.
+ *
+ * Based on the precac_width, find the first and last subchannels of the given
+ * preCAC channel and check if this range overlaps with weather channel range.
+ *
+ * Return: True if weather channel, else false.
+ */
+static bool dfs_is_precac_on_weather_channel(struct wlan_dfs *dfs,
+					     enum phy_ch_width chwidth,
+					     uint8_t precac_chan)
+{
+	uint8_t first_subch, last_subch;
+
+	switch (chwidth) {
+	case CH_WIDTH_20MHZ:
+		first_subch = precac_chan;
+		last_subch = precac_chan;
+		break;
+	case CH_WIDTH_40MHZ:
+		first_subch = precac_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		last_subch = precac_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+		break;
+	case CH_WIDTH_80MHZ:
+		first_subch = precac_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
+		last_subch = precac_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
+		break;
+	default:
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			"Precac channel width invalid!");
+		return false;
+	}
+	return FIND_IF_OVERLAP_WITH_WEATHER_RANGE(first_subch, last_subch);
+}
+
+void dfs_start_agile_precac_timer(struct wlan_dfs *dfs,
+				  uint8_t ocac_status,
+				  struct dfs_agile_cac_params *adfs_param)
 {
-	int agile_cac_timeout;
+	uint8_t precac_chan = adfs_param->precac_chan;
+	enum phy_ch_width chwidth = adfs_param->precac_chwidth;
+	uint32_t min_precac_timeout, max_precac_timeout;
 	struct dfs_soc_priv_obj *dfs_soc_obj;
 
 	dfs_soc_obj = dfs->dfs_soc_obj;
 	dfs_soc_obj->dfs_precac_timer_running = 1;
 
-	agile_cac_timeout = (dfs->dfs_precac_timeout_override != -1) ?
-				dfs->dfs_precac_timeout_override :
-				DEFAULT_CAC_DURATION;
 	if (ocac_status == OCAC_SUCCESS) {
 		dfs_soc_obj->ocac_status = OCAC_SUCCESS;
-		agile_cac_timeout = 0;
+		min_precac_timeout = 0;
+		max_precac_timeout = 0;
+	} else {
+		/* Find the minimum and maximum precac timeout. */
+		max_precac_timeout = MAX_PRECAC_DURATION;
+		if (dfs->dfs_precac_timeout_override != -1) {
+			min_precac_timeout =
+				dfs->dfs_precac_timeout_override * 1000;
+		} else if (dfs_is_precac_on_weather_channel(dfs,
+							    chwidth,
+							    precac_chan)) {
+			min_precac_timeout = MIN_WEATHER_PRECAC_DURATION;
+			max_precac_timeout = MAX_WEATHER_PRECAC_DURATION;
+		} else {
+			min_precac_timeout = MIN_PRECAC_DURATION;
+		}
 	}
 
 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
-		 "precactimeout = %d", (agile_cac_timeout) * 1000);
-	qdf_timer_mod(&dfs_soc_obj->dfs_precac_timer,
-		      (agile_cac_timeout) * 1000);
+		 "precactimeout = %d ms", (min_precac_timeout));
+	qdf_timer_mod(&dfs_soc_obj->dfs_precac_timer, min_precac_timeout);
+	adfs_param->min_precac_timeout = min_precac_timeout;
+	adfs_param->max_precac_timeout = max_precac_timeout;
 }
 #endif
 
@@ -2172,15 +2249,10 @@ void dfs_get_ieeechan_for_agilecac(struct wlan_dfs *dfs,
 						pri_ch_ieee,
 						sec_ch_ieee,
 						chwidth_val);
-	if (ieee_chan) {
+	if (ieee_chan)
 		dfs->dfs_agile_precac_freq = ieee_chan;
-		/* Start the pre_cac_timer */
-		dfs_start_agile_precac_timer(dfs,
-					     dfs->dfs_agile_precac_freq,
-					     dfs->dfs_soc_obj->ocac_status);
-	} else {
+	else
 		dfs->dfs_agile_precac_freq = 0;
-	}
 
 	*ch_ieee = dfs->dfs_agile_precac_freq;
 }
@@ -2374,16 +2446,12 @@ void dfs_set_precac_enable(struct wlan_dfs *dfs, uint32_t value)
 #ifdef QCA_SUPPORT_AGILE_DFS
 void dfs_agile_precac_start(struct wlan_dfs *dfs)
 {
-	uint8_t agile_freq = 0;
+	struct dfs_agile_cac_params adfs_param;
 	uint8_t ocac_status = 0;
 	struct dfs_soc_priv_obj *dfs_soc_obj;
 	uint8_t cur_dfs_idx;
 
 	dfs_soc_obj = dfs->dfs_soc_obj;
-	/*
-	 * Initiate first call to start preCAC here, for agile_freq as 0,
-	 * and ocac_status as 0
-	 */
 
 	qdf_info("%s : %d agile_precac_started: %d",
 		 __func__, __LINE__,
@@ -2400,12 +2468,16 @@ void dfs_agile_precac_start(struct wlan_dfs *dfs)
 		 dfs->dfs_soc_obj->dfs_priv[cur_dfs_idx].dfs);
 
 	if (!dfs->dfs_soc_obj->precac_state_started) {
+		/*
+		 * Initiate first call to start preCAC here, for channel as 0,
+		 * and ocac_status as 0
+		 */
+		adfs_param.precac_chan = 0;
+		adfs_param.precac_chwidth = CH_WIDTH_INVALID;
 		qdf_info("%s : %d Initiated agile precac",
 			 __func__, __LINE__);
 		dfs->dfs_soc_obj->precac_state_started = true;
-		dfs_start_agile_precac_timer(dfs,
-					     agile_freq,
-					     ocac_status);
+		dfs_start_agile_precac_timer(dfs, ocac_status, &adfs_param);
 	}
 }
 #endif