Browse Source

qcacmn: Retrieve DFS channel parameters such as CAC, NOL, state

Add APIs to fetch the DFS channel parameters such as CAC, NOL and the
channel state to the user application.
struct dfs_cacelem is defined to store all the CAC related information
such as cac start time, cac completed time and the cac timeout.
dfs_cacelems is stored for NUM_5GHZ_CHANS in the dfs pdev object.
dfs_handle_cac_events() API is used to handle CAC related events such
as WLAN_EV_CAC_COMPLETED, WLAN_EV_CAC_RESET and radar during CAC.

CRs-Fixed: 3428828
Change-Id: I82f7aafeb20222d9722bed5a1a8c10b5703ac975
Priyadarshnee Srinivasan 2 years ago
parent
commit
70a7674b32

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

@@ -978,6 +978,18 @@ struct dfs_rcac_params {
 };
 #endif
 
+#ifdef WLAN_DISP_CHAN_INFO
+/**
+ * struct dfs_cacelem - CAC parameters of a DFS channel (20 MHz channel).
+ * @cac_start_us: Time in microseconds when cac started (monotonic boot time).
+ * @cac_completed_time: CAC completed time in ms (monotonic boot time).
+ */
+struct dfs_cacelem {
+	uint64_t cac_start_us;
+	uint64_t cac_completed_time;
+};
+#endif
+
 /*
  * NB: not using kernel-doc format since the kernel-doc script doesn't
  *     handle the TAILQ_HEAD() or STAILQ_HEAD() macros
@@ -1160,6 +1172,9 @@ struct dfs_rcac_params {
  *                                   CAC REQUIRED, CAC COMPLETED, NOL,
  *                                   PRECAC STARTED, PRECAC COMPLETED etc. of
  *                                   all the DFS channels.
+ * @dfs_cacelems:                    Stores the CAC related parameters of a
+ *                                   channel such as: CAC started time, CAC
+ *                                   completed time.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1335,6 +1350,7 @@ struct wlan_dfs {
 #endif
 #if defined(WLAN_DISP_CHAN_INFO)
 	enum channel_dfs_state dfs_channel_state_array[NUM_DFS_CHANS];
+	struct dfs_cacelem dfs_cacelems[NUM_DFS_CHANS];
 #endif /* WLAN_DISP_CHAN_INFO */
 #ifdef QCA_SUPPORT_AGILE_DFS
 #endif
@@ -2188,6 +2204,32 @@ bool dfs_is_cac_required(struct wlan_dfs *dfs,
 			 bool *continue_current_cac,
 			 bool is_vap_restart);
 
+/**
+ * dfs_update_cac_elements() - Fill the dfs_cacelem data structure based
+ * on the dfs_ev events posted.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @freq_list: Pointer to a list of frequencies in MHz
+ * @num_chan: Number of frequencies
+ * @dfs_chan: Pointer to dfs_channel
+ * @dfs_ev: DFS events
+ *
+ * Return: QDF STATUS
+ */
+#if defined(WLAN_DISP_CHAN_INFO)
+QDF_STATUS
+dfs_update_cac_elements(struct wlan_dfs *dfs, uint16_t *freq_list,
+			uint8_t num_chan, struct dfs_channel *dfs_chan,
+			enum WLAN_DFS_EVENTS dfs_ev);
+#else
+static inline QDF_STATUS
+dfs_update_cac_elements(struct wlan_dfs *dfs, uint16_t *freq_list,
+			uint8_t num_chan, struct dfs_channel *dfs_chan,
+			enum WLAN_DFS_EVENTS dfs_ev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * dfs_send_dfs_events_for_chan() - Send CAC RESET events
  * @dfs: Pointer to wlan_dfs structure.
@@ -2289,6 +2331,14 @@ void dfs_stacac_stop(struct wlan_dfs *dfs)
 {
 }
 
+static inline QDF_STATUS
+dfs_update_cac_elements(struct wlan_dfs *dfs, uint16_t *freq_list,
+			uint8_t num_chan, struct dfs_channel *dfs_chan,
+			enum WLAN_DFS_EVENTS dfs_ev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 static inline
 bool dfs_is_cac_required(struct wlan_dfs *dfs,
 			 struct dfs_channel *cur_chan,

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

@@ -36,6 +36,9 @@
 #include "wlan_dfs_mlme_api.h"
 #include "../dfs_internal.h"
 #include "../dfs_process_radar_found_ind.h"
+#ifdef CONFIG_HOST_FIND_CHAN
+#include <wlan_reg_channel_api.h>
+#endif
 
 #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650))
 #define ADJACENT_WEATHER_RADAR_CHANNEL   5580
@@ -146,6 +149,8 @@ void dfs_process_cac_completion(struct wlan_dfs *dfs)
 						      ch_width);
 	}
 
+	dfs_update_cac_elements(dfs, NULL, 0, dfs->dfs_curchan, WLAN_EV_CAC_COMPLETED);
+
 	dfs_clear_cac_started_chan(dfs);
 
 	/* Clear NOL history for current channel on successful CAC completion */
@@ -207,6 +212,7 @@ void dfs_cac_timer_reset(struct wlan_dfs *dfs)
 	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
 	dfs_get_override_cac_timeout(dfs,
 			&(dfs->dfs_cac_timeout_override));
+	dfs_update_cac_elements(dfs, NULL, 0, dfs->dfs_curchan, WLAN_EV_CAC_RESET);
 	dfs_clear_cac_started_chan(dfs);
 }
 
@@ -253,6 +259,7 @@ void dfs_start_cac_timer(struct wlan_dfs *dfs)
 void dfs_cancel_cac_timer(struct wlan_dfs *dfs)
 {
 	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
+	dfs_update_cac_elements(dfs, NULL, 0, dfs->dfs_curchan, WLAN_EV_CAC_RESET);
 	dfs_clear_cac_started_chan(dfs);
 }
 
@@ -266,10 +273,20 @@ void dfs_send_dfs_events_for_chan(struct wlan_dfs *dfs,
 	nchannels =
 		dfs_get_bonding_channel_without_seg_info_for_freq(chan,
 								  freq_list);
-	for (i = 0; i < nchannels; i++)
+
+	/* If radar is found during CAC period, CAC cancel is invoked and hence
+	 * dfs_cac_stop posts WLAN_EV_CAC_RESET. However, since the channel is
+	 * radar infected and is added to the NOL, the most appropriate state of
+	 * the channel should be WLAN_EV_NOL_STARTED.
+	 * After NOL timeout, WLAN_EV_CAC_RESET should be posted.
+	 */
+	for (i = 0; i < nchannels; i++) {
+		if (wlan_reg_is_nol_for_freq(dfs->dfs_pdev_obj, freq_list[i]))
+			event = WLAN_EV_NOL_STARTED;
 		utils_dfs_deliver_event(dfs->dfs_pdev_obj,
 					freq_list[i],
 					event);
+	}
 }
 
 void dfs_cac_stop(struct wlan_dfs *dfs)
@@ -285,6 +302,7 @@ void dfs_cac_stop(struct wlan_dfs *dfs)
 	qdf_hrtimer_cancel(&dfs->dfs_cac_timer);
 
 	dfs_send_dfs_events_for_chan(dfs, chan, WLAN_EV_CAC_RESET);
+	dfs_update_cac_elements(dfs, NULL, 0, chan, WLAN_EV_CAC_RESET);
 
 	if (dfs->dfs_cac_timer_running)
 		dfs->dfs_cac_aborted = 1;

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

@@ -197,6 +197,8 @@ dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs,
 	}
 	*num_channels = num_ch;
 
+	dfs_update_cac_elements(dfs, nol_freq_list, num_ch, NULL, WLAN_EV_NOL_STARTED);
+
 	if (!dfs_get_disable_radar_marking(dfs)) {
 		utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
 						       nol_freq_list, num_ch,

+ 2 - 0
umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h

@@ -186,6 +186,7 @@ struct dfs_agile_cac_params {
  *                           DFS channel.
  * @CH_DFS_S_PRECAC_COMPLETED: Indicates that the PreCAC has been completed for
  *                             the DFS channel.
+ * @CH_DFS_S_NON_DFS: Indicates that it is a non-DFS channel.
  */
 enum channel_dfs_state {
 	CH_DFS_S_INVALID,
@@ -195,5 +196,6 @@ enum channel_dfs_state {
 	CH_DFS_S_NOL,
 	CH_DFS_S_PRECAC_STARTED,
 	CH_DFS_S_PRECAC_COMPLETED,
+	CH_DFS_S_NON_DFS,
 };
 #endif

+ 13 - 1
umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h

@@ -81,7 +81,7 @@
 /* WLAN 5GHz channel number 170 freq */
 #define DFS_CHAN_170_FREQ        (5852)
 
-
+#define IS_CHAN_DFS(_flags) ((_flags) & REGULATORY_CHAN_RADAR)
 
 extern struct dfs_to_mlme global_dfs_to_mlme;
 
@@ -977,4 +977,16 @@ QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev)
  * Return: QDF_STATUS.
  */
 QDF_STATUS utils_dfs_radar_enable(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * utils_dfs_convert_freq_to_index() - Converts a channel frequency
+ * to the DFS channel state array index. The input frequency should be a 5 GHz
+ * channel frequency and this check should be done in the caller.
+ *
+ * @freq: Input DFS channel frequency.
+ * @index: Output DFS channel state array index.
+ *
+ * Return: None.
+ */
+void utils_dfs_convert_freq_to_index(qdf_freq_t freq, int8_t *index);
 #endif /* _WLAN_DFS_UTILS_API_H_ */

+ 9 - 14
umac/dfs/dispatcher/src/wlan_dfs_utils_api.c

@@ -1440,17 +1440,8 @@ utils_dfs_precac_status_for_channel(struct wlan_objmgr_pdev *pdev,
 #define FIRST_DFS_CHAN_NUM  52
 #define CHAN_NUM_SPACING     4
 #define INVALID_INDEX     (-1)
-#define IS_CHAN_DFS(_flags) ((_flags) & REGULATORY_CHAN_RADAR)
-/**
- * utils_dfs_convert_freq_to_index() - Converts a DFS channel frequency
- * to the DFS channel state array index. The input frequency should be a DFS
- * channel frequency and this check should be done in the caller.
- * @freq: Input DFS channel frequency.
- * @index: Output DFS channel state array index.
- *
- * Return: QDF_STATUS.
- */
-static void utils_dfs_convert_freq_to_index(qdf_freq_t freq, int8_t *index)
+
+void utils_dfs_convert_freq_to_index(qdf_freq_t freq, int8_t *index)
 {
 	uint16_t chan_num;
 	int8_t tmp_index;
@@ -1470,7 +1461,7 @@ static void utils_dfs_convert_freq_to_index(qdf_freq_t freq, int8_t *index)
  * @state: Input DFS state with which the value indexed by frequency will be
  * updated with.
  *
- * Return: void.
+ * Return: QDF_STATUS
  */
 static QDF_STATUS
 utils_dfs_update_chan_state_array_element(struct wlan_dfs *dfs,
@@ -1478,10 +1469,16 @@ utils_dfs_update_chan_state_array_element(struct wlan_dfs *dfs,
 					  enum channel_dfs_state state)
 {
 	int8_t index;
+	enum channel_enum chan_enum;
 
 	if (state == CH_DFS_S_INVALID)
 		return QDF_STATUS_E_INVAL;
 
+	chan_enum = wlan_reg_get_chan_enum_for_freq(freq);
+	/* Do not send DFS events on invalid IEEE channels */
+	if (chan_enum == INVALID_CHANNEL)
+		return QDF_STATUS_E_INVAL;
+
 	utils_dfs_convert_freq_to_index(freq, &index);
 
 	if (index == INVALID_INDEX)
@@ -1499,13 +1496,11 @@ QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev)
 	int i;
 
 	dfs = wlan_pdev_get_dfs_obj(pdev);
-
 	if (!dfs)
 		return QDF_STATUS_E_FAILURE;
 
 	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
 			sizeof(struct regulatory_channel));
-
 	if (!cur_chan_list)
 		return QDF_STATUS_E_NOMEM;