瀏覽代碼

qcacmn: Move dfs cac start condition checks to dfs component

Move dfs-cac-start-condition checks to dfs component from MLME component.

Change-Id: Iaab45ce8e298a237b110f3046593fc5801e1673e
CRs-Fixed: 2299517
Shashikala Prabhu 6 年之前
父節點
當前提交
c80456220e

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

@@ -2429,6 +2429,18 @@ void dfs_nol_free_list(struct wlan_dfs *dfs);
  */
 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs);
 
+/**
+ * dfs_check_for_cac_start() - Check for DFS CAC start conditions.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @continue_current_cac: If AP can start CAC then this variable indicates
+ * whether to continue with the current CAC or restart the CAC. This variable
+ * is valid only if this function returns true.
+ *
+ * Return: true if AP can start or continue the current CAC, else false.
+ */
+bool dfs_check_for_cac_start(struct wlan_dfs *dfs,
+			     bool *continue_current_cac);
+
 /**
  * dfs_task_testtimer_reset() - stop dfs test timer.
  * @dfs: Pointer to wlan_dfs structure.

+ 106 - 0
umac/dfs/core/src/misc/dfs_cac.c

@@ -326,3 +326,109 @@ void dfs_clear_cac_started_chan(struct wlan_dfs *dfs)
 	qdf_mem_zero(&dfs->dfs_cac_started_chan,
 		     sizeof(dfs->dfs_cac_started_chan));
 }
+
+bool dfs_check_for_cac_start(struct wlan_dfs *dfs,
+			     bool *continue_current_cac)
+{
+	if (!WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(dfs->dfs_curchan)) {
+		/* Consider a case where AP was up in a DFS channel and in CAC
+		 * period (DFS-WAIT state) and the workque to initiate CAC is
+		 * scheduled. At this time, real radar/spoof radar pulses from
+		 * bottom-half/tasklet context are received which is given
+		 * higher priority than Workque context. Due to radar, channel
+		 * change happened, AP switched to non-DFS channel and curchan
+		 * is non-DFS. The scheduled workque gets executed now, starts
+		 * a CAC on non-DFS curchan(curchan has changed from DFS to
+		 * non-DFS work queue func not aware of this !!). Though the
+		 * vap state machine moves the state of the vap from DFS-WAIT
+		 * to RUN state as curchan is non-DFS, the cac timer is not
+		 * cancelled. CAC timer on non-DFS channel runs and it expires.
+		 * So cancelling CAC here if chan is not DFS to avoid this
+		 * unexpected run and expiry of CAC.
+		 */
+		dfs_cac_stop(dfs);
+		dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0);
+
+		/* Clear the old dfs cac started channel if the current channel
+		 * is NON-DFS.
+		 * For example: AP sets the cac started channel as 100. It does
+		 * cac on channel 100 and starts beaconing. User changes the AP
+		 * channel to 36 and after sometime if user changes the channel
+		 * back to 100, AP does  not do the CAC since user channel and
+		 * cac started channel is same.
+		 */
+		dfs_clear_cac_started_chan(dfs);
+		dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC on NON-DFS chan");
+		return false;
+	}
+
+	if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS,
+			  "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d",
+			  dfs->dfs_ignore_dfs, dfs->dfs_cac_valid,
+			  dfs->dfs_ignore_cac);
+		return false;
+	}
+
+	if (dfs_is_etsi_precac_done(dfs)) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS,
+			  "ETSI PRE-CAC alreay done on this channel %d",
+			  dfs->dfs_curchan->dfs_ch_ieee);
+		return false;
+	}
+
+	/* If the channel has completed PRE-CAC then CAC can be skipped here. */
+	if (dfs_is_precac_done(dfs, dfs->dfs_curchan)) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS,
+			  "PRE-CAC alreay done on this channel %d",
+			  dfs->dfs_curchan->dfs_ch_ieee);
+		return false;
+	}
+
+	if (dfs_is_ap_cac_timer_running(dfs)) {
+		/* Check if we should continue the existing CAC or
+		 * cancel the existing CAC.
+		 * For example: - if an existing VAP(0) is already in
+		 * DFS wait state (which means the radio(wifi) is
+		 * running the CAC) and it is in channel A and another
+		 * VAP(1) comes up in the same channel then instead of
+		 * cancelling the CAC we can let the CAC continue.
+		 */
+		if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) {
+			*continue_current_cac = true;
+		} else {
+			/* New CAC is needed, cancel the running CAC
+			 * timer.
+			 * 1) When AP is in DFS_WAIT state and it is in
+			 *    channel A and user restarts the AP vap in
+			 *    channel B, then cancel the running CAC in
+			 *    channel A and start new CAC in channel B.
+			 *
+			 * 2) When AP detects the RADAR during CAC in
+			 *    channel A, it cancels the running CAC and
+			 *    tries to find channel B with the reduced
+			 *    bandwidth with of channel A.
+			 *    In this case, since the CAC is aborted by
+			 *    the RADAR, AP should start the CAC again.
+			 */
+			dfs_cancel_cac_timer(dfs);
+		}
+	} else { /* CAC timer is not running. */
+		if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) {
+			/* AP bandwidth reduce case:
+			 * When AP detects the RADAR in in-service monitoring
+			 * mode in channel A, it cancels the running CAC and
+			 * tries to find the channel B with the reduced
+			 * bandwidth of channel A.
+			 * If the new channel B is subset of the channel A
+			 * then AP skips the CAC.
+			 */
+			if (!dfs->dfs_cac_aborted) {
+				dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC");
+				return false;
+			}
+		}
+	}
+
+	return true;
+}

+ 12 - 81
umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h

@@ -160,16 +160,6 @@ QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev);
  */
 QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev);
 
-/**
- * utils_dfs_is_precac_done() - Is precac done.
- * @pdev: Pointer to DFS pdev object.
- *
- * wrapper function for dfs_is_precac_done(). this
- * function called from outside of dfs component.
- */
-QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev,
-		bool *is_precac_done);
-
 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
 /**
  * utils_dfs_precac_decide_pref_chan() - Choose preferred channel
@@ -187,25 +177,6 @@ QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev,
 					     uint8_t *ch_ieee);
 #endif
 
-/**
- * utils_dfs_is_esti_precac_done() - Is ETSI precac done.
- * @pdev: Pointer to DFS pdev object.
- *
- * wrapper function for dfs_is_etsi_precac_done(). This
- * function called from outside of dfs component.
- */
-#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS
-QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev,
-					 bool *is_etsi_precac_done);
-#else
-static inline QDF_STATUS utils_dfs_is_etsi_precac_done(
-		struct wlan_objmgr_pdev *pdev,
-		bool *is_etsi_precac_done)
-{
-	return QDF_STATUS_SUCCESS;
-}
-#endif
-
 /**
  * utils_dfs_cancel_cac_timer() - Cancels the CAC timer.
  * @pdev: Pointer to DFS pdev object.
@@ -242,34 +213,6 @@ 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.
@@ -366,30 +309,6 @@ QDF_STATUS utils_dfs_nol_update(struct wlan_objmgr_pdev *pdev);
 QDF_STATUS utils_dfs_second_segment_radar_disable(
 		struct wlan_objmgr_pdev *pdev);
 
-/**
- * utils_dfs_is_ignore_dfs() - Get Ignore DFS value.
- * @pdev: Pointer to DFS pdev object.
- * @ignore_dfs: Fill ignore_dfs value in this variable.
- */
-QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev,
-		bool *ignore_dfs);
-
-/**
- * utils_dfs_is_cac_valid() - Gets the value of is_cac_valid.
- * @pdev: Pointer to DFS pdev object.
- * @is_cac_valid: Fill is_cac_valid in this variable.
- */
-QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev,
-		bool *is_cac_valid);
-
-/**
- * utils_dfs_is_ignore_cac() - Gets the value of is_ignore_cac.
- * @pdev: Pointer to DFS pdev object.
- * @ignore_cac: Fill ignore_cac value in this variable.
- */
-QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev,
-		bool *ignore_cac);
-
 /**
  * utils_dfs_set_cac_timer_running() - Sets the cac timer running.
  * @pdev: Pointer to DFS pdev object.
@@ -640,4 +559,16 @@ int dfs_get_num_chans(void);
 void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev,
 			     void *clist,
 			     uint32_t *num_chan);
+
+/**
+ * utils_dfs_check_for_cac_start() - Check for DFS CAC start conditions.
+ * @pdev: pdev ptr
+ * @continue_current_cac: If AP can start CAC then this variable indicates
+ * whether to continue with the current CAC or restart the CAC. This variable
+ * is valid only if this function returns true.
+ *
+ * Return: true if AP can start or continue the current CAC, else false.
+ */
+bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev,
+				   bool *continue_current_cac);
 #endif /* _WLAN_DFS_UTILS_API_H_ */

+ 8 - 117
umac/dfs/dispatcher/src/wlan_dfs_utils_api.c

@@ -159,39 +159,6 @@ QDF_STATUS utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev,
 }
 #endif
 
-QDF_STATUS utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev,
-		bool *is_precac_done)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	*is_precac_done = dfs_is_precac_done(dfs, dfs->dfs_curchan);
-
-	return QDF_STATUS_SUCCESS;
-}
-qdf_export_symbol(utils_dfs_is_precac_done);
-
-#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS
-QDF_STATUS utils_dfs_is_etsi_precac_done(struct wlan_objmgr_pdev *pdev,
-					 bool *is_etsi_precac_done)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	*is_etsi_precac_done = dfs_is_etsi_precac_done(dfs);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-qdf_export_symbol(utils_dfs_is_etsi_precac_done);
-#endif
-
 QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev)
 {
 	struct wlan_dfs *dfs;
@@ -233,22 +200,8 @@ QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev)
 }
 qdf_export_symbol(utils_dfs_cac_stop);
 
-QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	dfs_stacac_stop(dfs);
-
-	return QDF_STATUS_SUCCESS;
-}
-qdf_export_symbol(utils_dfs_stacac_stop);
-
-bool utils_dfs_is_curchan_subset_of_cac_started_chan(
-		struct wlan_objmgr_pdev *pdev)
+bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev,
+				   bool *continue_current_cac)
 {
 	struct wlan_dfs *dfs;
 
@@ -256,30 +209,22 @@ bool utils_dfs_is_curchan_subset_of_cac_started_chan(
 	if (!dfs)
 		return false;
 
-	return dfs_is_curchan_subset_of_cac_started_chan(dfs);
+	return dfs_check_for_cac_start(dfs, continue_current_cac);
 }
 
-bool utils_dfs_is_cac_aborted(struct wlan_objmgr_pdev *pdev)
+QDF_STATUS utils_dfs_stacac_stop(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;
+		return  QDF_STATUS_E_FAILURE;
 
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return;
+	dfs_stacac_stop(dfs);
 
-	dfs_clear_cac_started_chan(dfs);
+	return QDF_STATUS_SUCCESS;
 }
+qdf_export_symbol(utils_dfs_stacac_stop);
 
 QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol)
 {
@@ -412,60 +357,6 @@ QDF_STATUS utils_dfs_second_segment_radar_disable(struct wlan_objmgr_pdev *pdev)
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS utils_dfs_is_ignore_dfs(struct wlan_objmgr_pdev *pdev,
-		bool *ignore_dfs)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	*ignore_dfs = dfs->dfs_ignore_dfs;
-
-	return QDF_STATUS_SUCCESS;
-}
-qdf_export_symbol(utils_dfs_is_ignore_dfs);
-
-QDF_STATUS utils_dfs_is_cac_valid(struct wlan_objmgr_pdev *pdev,
-		bool *is_cac_valid)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	*is_cac_valid = dfs->dfs_cac_valid;
-
-	return QDF_STATUS_SUCCESS;
-}
-qdf_export_symbol(utils_dfs_is_cac_valid);
-
-QDF_STATUS utils_dfs_is_ignore_cac(struct wlan_objmgr_pdev *pdev,
-		bool *ignore_cac)
-{
-	struct wlan_dfs *dfs;
-
-	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
-		return  QDF_STATUS_E_FAILURE;
-
-	*ignore_cac = dfs->dfs_ignore_cac;
-
-	/*
-	 * This is needed as, if after channel bandwidth reduction, channel
-	 * change occurs using dothchanswitch or chan commands, resetting.
-	 * dfs->dfs_ignore_cac will make sure we not skip CAC on the new channel
-	 */
-
-	if (dfs->dfs_bw_reduced)
-		dfs->dfs_ignore_cac = 0;
-
-	return QDF_STATUS_SUCCESS;
-}
-qdf_export_symbol(utils_dfs_is_ignore_cac);
-
 QDF_STATUS utils_dfs_set_cac_timer_running(struct wlan_objmgr_pdev *pdev,
 		int val)
 {