Explorar el Código

qcacmn: Add APIs to skip DFS CAC

Skip CAC if cac is already started on the same channel or the new channel
is subset of CAC started channel.

Change-Id: I8f6121f1f8d034acf3f0514a60401a3232becaa2
CRs-Fixed: 2309911
Shashikala Prabhu hace 6 años
padre
commit
6b4d64dbfa

+ 37 - 0
umac/dfs/core/src/dfs.h

@@ -942,6 +942,9 @@ struct dfs_event_log {
  * @dfs_precac_required_list:        PreCAC required list.
  * @dfs_precac_done_list:            PreCAC done list.
  * @dfs_precac_nol_list:             PreCAC NOL List.
+ * @dfs_curchan:                     DFS current channel.
+ * @dfs_cac_started_chan:            CAC started channel.
+ * @dfs_pdev_obj:                    DFS pdev object.
  * @dfs_is_offload_enabled:          Set if DFS offload enabled.
  * @dfs_use_nol:                     Use the NOL when radar found(default: TRUE)
  * @dfs_nol_lock:                    Lock to protect nol list.
@@ -974,6 +977,7 @@ struct dfs_event_log {
  * @dfs_bw_reduced:                  DFS bandwidth reduced channel bit.
  * @dfs_freq_offset:                 Frequency offset where radar was found.
  * @dfs_enhanced_bangradar:          DFS enhance bagradar bit for Full offload.
+ * @dfs_cac_aborted:                 DFS cac is aborted.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1076,6 +1080,7 @@ struct wlan_dfs {
 #endif
 
 	struct dfs_channel *dfs_curchan;
+	struct dfs_channel dfs_cac_started_chan;
 	struct wlan_objmgr_pdev *dfs_pdev_obj;
 	bool           dfs_is_offload_enabled;
 	int            dfs_use_nol;
@@ -1102,6 +1107,7 @@ struct wlan_dfs {
 	uint8_t        dfs_bw_reduced;
 	int32_t        dfs_freq_offset;
 	uint8_t        dfs_enhanced_bangradar;
+	bool           dfs_cac_aborted;
 };
 
 /**
@@ -1857,6 +1863,37 @@ void dfs_cancel_cac_timer(struct wlan_dfs *dfs);
  */
 void dfs_start_cac_timer(struct wlan_dfs *dfs);
 
+/**
+ * dfs_is_subset_channel() - Check if the new_chan is subset of the old_chan.
+ * @old_chan: Pointer to old channel.
+ * @new_chan: Pointer to new channel.
+ *
+ * Return: true if the new channel is subset of or same as the old channel,
+ * else false.
+ */
+bool dfs_is_subset_channel(struct dfs_channel *old_chan,
+			   struct dfs_channel *new_chan);
+
+/**
+ * dfs_is_curchan_subset_of_cac_started_chan() - Check if the dfs current
+ * channel is subset of cac started channel.
+ * @dfs: Pointer to wlan_dfs structure.
+ *
+ * If the current channel and the cac_started_chan is same or
+ * if the current channel is subset of the cac_started_chan then
+ * this function returns true.
+ *
+ * Return: true if current channel is same or subset of  cac started channel,
+ * else false.
+ */
+bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs);
+
+/**
+ * dfs_clear_cac_started_chan() - Clear dfs cac started channel.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+void dfs_clear_cac_started_chan(struct wlan_dfs *dfs);
+
 /**
  * dfs_set_update_nol_flag() - Sets update_nol flag.
  * @dfs: Pointer to wlan_dfs structure.

+ 0 - 19
umac/dfs/core/src/dfs_etsi_precac.h

@@ -216,23 +216,4 @@ static inline void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs)
 }
 #endif
 
-/**
- * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in curchan
- * @curchan: Pointer to dfs_channel structure.
- * @channels: channel array holding list of bonded channels.
- *
- * Return: number of sub channels in the current channel.
- */
-#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS
-uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan,
-						  uint8_t *channels);
-#else
-static inline uint8_t
-dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan,
-					  uint8_t *channels)
-{
-	return 0;
-}
-#endif
-
 #endif /* _DFS_ETSI_PRECAC_H_ */

+ 14 - 0
umac/dfs/core/src/dfs_process_radar_found_ind.h

@@ -23,6 +23,9 @@
  * DFS component.
  */
 
+#ifndef _DFS_PROCESS_RADAR_FOUND_IND_H_
+#define _DFS_PROCESS_RADAR_FOUND_IND_H_
+
 /* Number of channel marking offsets */
 #define DFS_NUM_FREQ_OFFSET   3
 
@@ -144,3 +147,14 @@ void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id);
 uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
 				 uint32_t segment_id,
 				 uint8_t *channels);
+
+/**
+ * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in chan
+ * @chan: Pointer to dfs_channel structure.
+ * @channels: channel array holding list of bonded channels.
+ *
+ * Return: number of sub channels in the input channel.
+ */
+uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan,
+						  uint8_t *channels);
+#endif /*_DFS_PROCESS_RADAR_FOUND_IND_H_ */

+ 97 - 5
umac/dfs/core/src/misc/dfs_cac.c

@@ -34,6 +34,7 @@
 #include "wlan_dfs_utils_api.h"
 #include "wlan_dfs_mlme_api.h"
 #include "../dfs_internal.h"
+#include "../dfs_process_radar_found_ind.h"
 
 #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650))
 #define ADJACENT_WEATHER_RADAR_CHANNEL   5580
@@ -183,6 +184,8 @@ void dfs_cac_timer_reset(struct wlan_dfs *dfs)
 	qdf_timer_stop(&dfs->dfs_cac_timer);
 	dfs_get_override_cac_timeout(dfs,
 			&(dfs->dfs_cac_timeout_override));
+	qdf_mem_zero(&dfs->dfs_cac_started_chan,
+		     sizeof(dfs->dfs_cac_started_chan));
 
 }
 
@@ -201,11 +204,24 @@ int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs)
 
 void dfs_start_cac_timer(struct wlan_dfs *dfs)
 {
-	qdf_timer_mod(&dfs->dfs_cac_timer,
-			dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj,
-				dfs->dfs_curchan->dfs_ch_freq,
-				dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
-				dfs->dfs_curchan->dfs_ch_flags) * 1000);
+	int cac_timeout = 0;
+	struct dfs_channel *chan = dfs->dfs_curchan;
+
+	cac_timeout = dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj,
+					       chan->dfs_ch_freq,
+					       chan->dfs_ch_vhtop_ch_freq_seg2,
+					       chan->dfs_ch_flags);
+
+	dfs->dfs_cac_started_chan = *chan;
+
+	dfs_debug(dfs, WLAN_DEBUG_DFS,
+		  "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec",
+		  chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2,
+		  cac_timeout,
+		  qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000);
+
+	qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000);
+	dfs->dfs_cac_aborted = 0;
 }
 
 void dfs_cancel_cac_timer(struct wlan_dfs *dfs)
@@ -222,6 +238,8 @@ void dfs_cac_stop(struct wlan_dfs *dfs)
 		"Stopping CAC Timer %d procphyerr 0x%08x",
 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
 	qdf_timer_stop(&dfs->dfs_cac_timer);
+	if (dfs->dfs_cac_timer_running)
+		dfs->dfs_cac_aborted = 1;
 	dfs->dfs_cac_timer_running = 0;
 }
 
@@ -234,3 +252,77 @@ void dfs_stacac_stop(struct wlan_dfs *dfs)
 		"Stopping STA CAC Timer %d procphyerr 0x%08x",
 		 dfs->dfs_curchan->dfs_ch_freq, phyerr);
 }
+
+bool dfs_is_subset_channel(struct dfs_channel *old_chan,
+			   struct dfs_channel *new_chan)
+{
+	uint8_t old_subchans[NUM_CHANNELS_160MHZ];
+	uint8_t new_subchans[NUM_CHANNELS_160MHZ];
+	uint8_t old_n_chans;
+	uint8_t new_n_chans;
+	int i = 0, j = 0;
+	bool is_found = false;
+
+	if (WLAN_IS_CHAN_11AC_VHT160(old_chan) ||
+	    WLAN_IS_CHAN_11AC_VHT80_80(old_chan)) {
+		/* If primary segment is NON-DFS */
+		if (!WLAN_IS_CHAN_DFS(old_chan))
+			old_n_chans = dfs_get_bonding_channels(old_chan,
+							       SEG_ID_SECONDARY,
+							       old_subchans);
+		else
+			old_n_chans = dfs_get_bonding_channels_without_seg_info(
+					old_chan, old_subchans);
+	} else {
+		old_n_chans = dfs_get_bonding_channels_without_seg_info(
+				old_chan, old_subchans);
+	}
+
+	if (WLAN_IS_CHAN_11AC_VHT160(new_chan) ||
+	    WLAN_IS_CHAN_11AC_VHT80_80(new_chan)) {
+		/* If primary segment is NON-DFS */
+		if (WLAN_IS_CHAN_DFS(new_chan))
+			new_n_chans = dfs_get_bonding_channels(
+					new_chan, SEG_ID_SECONDARY,
+					new_subchans);
+		else
+			new_n_chans = dfs_get_bonding_channels_without_seg_info(
+					new_chan, new_subchans);
+	} else {
+		new_n_chans = dfs_get_bonding_channels_without_seg_info(
+				new_chan, new_subchans);
+	}
+
+	if (new_n_chans > old_n_chans)
+		return false;
+
+	for (i = 0; i < new_n_chans; i++) {
+		is_found = false;
+		for (j = 0; j < old_n_chans; j++) {
+			if (new_subchans[i] == old_subchans[j]) {
+				is_found = true;
+				break;
+			}
+		}
+
+		/* If new_subchans[i] is not found in old_subchans, then,
+		 * new_chan is not subset of old_chan.
+		 */
+		if (!is_found)
+			break;
+	}
+
+	return is_found;
+}
+
+bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs)
+{
+	return dfs_is_subset_channel(&dfs->dfs_cac_started_chan,
+				     dfs->dfs_curchan);
+}
+
+void dfs_clear_cac_started_chan(struct wlan_dfs *dfs)
+{
+	qdf_mem_zero(&dfs->dfs_cac_started_chan,
+		     sizeof(dfs->dfs_cac_started_chan));
+}

+ 0 - 48
umac/dfs/core/src/misc/dfs_etsi_precac.c

@@ -346,51 +346,3 @@ void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs)
 		dfs_add_chan_to_etsi_done_list(dfs, channels[i]);
 	}
 }
-
-uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *curchan,
-						  uint8_t *channels)
-{
-	uint8_t center_chan;
-	uint8_t nchannels = 0;
-
-	center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1;
-
-	if (WLAN_IS_CHAN_MODE_20(curchan)) {
-		nchannels = 1;
-		channels[0] = center_chan;
-	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
-		nchannels = 2;
-		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
-	} else if (WLAN_IS_CHAN_MODE_80(curchan)) {
-		nchannels = 4;
-		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
-		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
-	} else if (WLAN_IS_CHAN_MODE_80_80(curchan)) {
-		nchannels = 8;
-		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
-		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
-		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
-		channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
-		channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
-	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
-		nchannels = 8;
-		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
-		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
-		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
-		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
-		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
-		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
-		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
-		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
-	}
-
-	return nchannels;
-}

+ 48 - 0
umac/dfs/core/src/misc/dfs_process_radar_found_ind.c

@@ -360,6 +360,54 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs,
 	return i;
 }
 
+uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan,
+						  uint8_t *channels)
+{
+	uint8_t center_chan;
+	uint8_t nchannels = 0;
+
+	center_chan = chan->dfs_ch_vhtop_ch_freq_seg1;
+
+	if (WLAN_IS_CHAN_MODE_20(chan)) {
+		nchannels = 1;
+		channels[0] = center_chan;
+	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
+		nchannels = 2;
+		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
+		nchannels = 4;
+		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
+		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
+	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
+		nchannels = 8;
+		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
+		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
+		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
+		channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
+		channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
+	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
+		nchannels = 8;
+		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
+		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
+		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
+		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
+		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
+		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
+		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
+		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
+	}
+
+	return nchannels;
+}
+
 uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
 				 uint32_t segment_id,
 				 uint8_t *channels)

+ 28 - 0
umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h

@@ -242,6 +242,34 @@ QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev);
  */
 QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev);
 
+/**
+ * utils_dfs_is_curchan_subset_of_cac_started_chan() - Check if the dfs current
+ * channel is subset of cac started channel.
+ * @pdev: Pointer to DFS pdev object.
+ *
+ * wrapper function for dfs_is_curchan_subset_of_cac_started_chan(). this
+ * function called from outside of dfs component.
+ *
+ * Return: true if current channel is same or subset of  cac started channel,
+ * else false.
+ */
+bool utils_dfs_is_curchan_subset_of_cac_started_chan(
+		struct wlan_objmgr_pdev *pdev);
+
+/**
+ * utils_dfs_is_cac_aborted() - Check if previous CAC was aborted.
+ * @pdev: Pointer to DFS pdev object.
+ *
+ * Return: true if previous CAC was aborted, else false.
+ */
+bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * utils_dfs_clear_cac_started_chan() - Clear dfs cac started channel.
+ * @pdev: Pointer to DFS pdev object.
+ */
+void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev);
+
 /**
  * utils_dfs_get_usenol() - Returns use_nol flag.
  * @pdev: Pointer to DFS pdev object.

+ 34 - 4
umac/dfs/dispatcher/src/wlan_dfs_utils_api.c

@@ -247,6 +247,40 @@ QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev)
 }
 qdf_export_symbol(utils_dfs_stacac_stop);
 
+bool utils_dfs_is_curchan_subset_of_cac_started_chan(
+		struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs)
+		return false;
+
+	return dfs_is_curchan_subset_of_cac_started_chan(dfs);
+}
+
+bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs)
+		return false;
+
+	return dfs->dfs_cac_aborted;
+}
+
+void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs)
+		return;
+
+	dfs_clear_cac_started_chan(dfs);
+}
+
 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol)
 {
 	struct wlan_dfs *dfs;
@@ -794,10 +828,6 @@ QDF_STATUS utils_dfs_bw_reduced_channel(
 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1;
 		ch_params->center_freq_seg1 =
 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2;
-		/*If bandwidth reduction is applied,
-		 * dfs_ignore_cac ensures we skip CAC.
-		 */
-		dfs->dfs_ignore_cac = 1;
 		dfs->dfs_bw_reduced = 1;
 		wlan_reg_set_channel_params(pdev,
 					    dfs->dfs_curchan->dfs_ch_ieee,