ソースを参照

qcacmn: Store and populate the DFS channel state array

Add an enum to encode various DFS channel states.

The dfs channel states are represented using a per dfs array object rather
than maintaining a channel state field for each channel (since dfs channel
states are not required for 2G and 6G channels).

The size of the array is approximately 30 because
first_dfs_chan = 52
last_dfs_chan = 161(in case of ETSI EN302 502)
channel_spacing = difference between 2 consecutive 5G channels = 4

size_of_the_array = (last_dfs_chan - first_dfs_chan) / channel_spacing
                  = (161 - 52) / 4
                  = 27.25
                  ~= 30;

The dfs channel array is indexed by hashing the frequency. The conversion
(hash function) is as follows:

given_chan_number = (given_chan_frequency - 5000) / 5;
where 5 is: 5Mhz  = minimum IEEE chan bandwidth.

array_index = (given_chan_number - first_dfs_chan) / channel_spacing;

Add the following functionalities:
1) initialize the DFS channel state array.
2) update the channel state array.
3) read the channel state array.
4) convert the channel frequency to channel state array index.
5) convert the dfs channel event to dfs channel state.

Change-Id: I7921571fcc80b43a7ef7caf92c34b016fe396e45
CRs-Fixed: 2823529
Vignesh U 4 年 前
コミット
336f699034

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

@@ -1143,6 +1143,10 @@ struct dfs_rcac_params {
  * @dfs_chan_postnol_mode:           Phymode the AP switches to, post NOL.
  * @dfs_chan_postnol_cfreq2:         Secondary center frequency the AP
  *                                   switches to, post NOL.
+ * @dfs_channel_state_array:         Stores the channel states like CAC STARTED,
+ *                                   CAC REQUIRED, CAC COMPLETED, NOL,
+ *                                   PRECAC STARTED, PRECAC COMPLETED etc. of
+ *                                   all the DFS channels.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1322,6 +1326,9 @@ struct wlan_dfs {
 	enum phy_ch_width dfs_chan_postnol_mode;
 	qdf_freq_t     dfs_chan_postnol_cfreq2;
 #endif
+#if defined(WLAN_DISP_CHAN_INFO)
+	enum channel_dfs_state dfs_channel_state_array[NUM_DFS_CHANS];
+#endif /* WLAN_DISP_CHAN_INFO */
 };
 
 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS)

+ 6 - 0
umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h

@@ -280,20 +280,26 @@ struct wlan_dfs_phyerr_param {
 /**
  * enum WLAN_DFS_EVENTS - DFS Events that will be sent to userspace
  * @WLAN_EV_RADAR_DETECTED: Radar is detected
+ * @WLAN_EV_CAC_RESET:      CAC started or CAC completed status is reset
  * @WLAN_EV_CAC_STARTED:    CAC timer has started
  * @WLAN_EV_CAC_COMPLETED:  CAC timer completed
  * @WLAN_EV_NOL_STARTED:    NOL started
  * @WLAN_EV_NOL_FINISHED:   NOL Completed
+ * @WLAN_EV_PCAC_STARTED:   PreCAC Started
+ * @WLAN_EV_PCAC_COMPLETED: PreCAC Completed
  *
  * DFS events such as radar detected, CAC started,
  * CAC completed, NOL started, NOL finished
  */
 enum WLAN_DFS_EVENTS {
 	WLAN_EV_RADAR_DETECTED,
+	WLAN_EV_CAC_RESET,
 	WLAN_EV_CAC_STARTED,
 	WLAN_EV_CAC_COMPLETED,
 	WLAN_EV_NOL_STARTED,
 	WLAN_EV_NOL_FINISHED,
+	WLAN_EV_PCAC_STARTED,
+	WLAN_EV_PCAC_COMPLETED,
 };
 
 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR)

+ 32 - 1
umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h

@@ -23,7 +23,7 @@
 
 #ifndef __WLAN_DFS_PUBLIC_STRUCT_H_
 #define __WLAN_DFS_PUBLIC_STRUCT_H_
-
+#include <wlan_cmn.h>
 /* TODO: This structure has many redundant variables, needs cleanup */
 /**
  * struct radar_found_info - radar found info
@@ -164,4 +164,35 @@ struct dfs_agile_cac_params {
 	uint32_t max_precac_timeout;
 	enum adfs_ocac_mode ocac_mode;
 };
+
+/* The first DFS channel number is 52 and the last DFS channel number is 161(in
+ * case of ETSI EN302502). So, the array size is taken as (161 - 52) / 4 ~= 30.
+ */
+#define NUM_DFS_CHANS 30
+
+/**
+ * enum channel_dfs_state - DFS  channel states.
+ * @CH_DFS_S_INVALID: The DFS state for invalid channel numbers that are not
+ *                    part of the radio's channel list.
+ * @CH_DFS_S_CAC_REQ: Indicates that the CAC/Off-channel CAC has to performed
+ *                    before Tx on the DFS channel.
+ * @CH_DFS_S_CAC_STARTED: Indicates that the CAC has been started for the DFS
+ *                        channel.
+ * @CH_DFS_S_CAC_COMPLETED: Indicates that the CAC has been completed for the
+ *                          DFS channel.
+ * @CH_DFS_S_NOL: Indicates that the DFS channel is in NOL.
+ * @CH_DFS_S_PRECAC_STARTED: Indicates that the PreCAC has been started for the
+ *                           DFS channel.
+ * @CH_DFS_S_PRECAC_COMPLETED: Indicates that the PreCAC has been completed for
+ *                             the DFS channel.
+ */
+enum channel_dfs_state {
+	CH_DFS_S_INVALID,
+	CH_DFS_S_CAC_REQ,
+	CH_DFS_S_CAC_STARTED,
+	CH_DFS_S_CAC_COMPLETED,
+	CH_DFS_S_NOL,
+	CH_DFS_S_PRECAC_STARTED,
+	CH_DFS_S_PRECAC_COMPLETED,
+};
 #endif

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

@@ -1051,4 +1051,60 @@ utils_dfs_precac_status_for_channel(struct wlan_objmgr_pdev *pdev,
 }
 #endif
 
+#if defined(WLAN_DISP_CHAN_INFO)
+/**
+ * utils_dfs_get_chan_dfs_state() - Get the channel state array of the channels
+ * in a radio.
+ * @pdev: Pointer to the pdev.
+ * @dfs_ch_s: Output channel state array of the dfs channels in the radio.
+ *
+ * Return: QDF_STATUS.
+ */
+QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev,
+					enum channel_dfs_state *dfs_ch_s);
+
+/**
+ * utils_dfs_update_chan_state_array() - Update the channel state of the dfs
+ * channel indicated by the frequency. The dfs event is converted to
+ * appropriate dfs state.
+ * @pdev: Pointer to the pdev.
+ * @freq: Input frequency.
+ * @event: Input dfs event.
+ *
+ * Return: QDF_STATUS.
+ */
+QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev,
+					     qdf_freq_t freq,
+					     enum WLAN_DFS_EVENTS event);
+
+/**
+ * dfs_init_chan_state_array() - Initialize the dfs channel state array.
+ *
+ * @pdev: Pointer to the pdev.
+ *
+ * Return: QDF_STATUS.
+ */
+QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev);
+#else
+static inline
+QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev,
+					enum channel_dfs_state *dfs_ch_s)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline
+QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev,
+					     uint16_t freq,
+					     enum WLAN_DFS_EVENTS event)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline
+QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif /* WLAN_DISP_CHAN_INFO */
 #endif /* _WLAN_DFS_UTILS_API_H_ */

+ 159 - 0
umac/dfs/dispatcher/src/wlan_dfs_utils_api.c

@@ -55,6 +55,7 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev)
 	dfs_reset(dfs);
 	dfs_nol_update(dfs);
 	dfs_reset_precaclists(dfs);
+	dfs_init_chan_state_array(pdev);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1733,3 +1734,161 @@ utils_dfs_precac_status_for_channel(struct wlan_objmgr_pdev *pdev,
 	return dfs_precac_status_for_channel(dfs, &chan);
 }
 #endif
+
+#if defined(WLAN_DISP_CHAN_INFO)
+#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)
+{
+	uint16_t chan_num;
+	int8_t tmp_index;
+
+	chan_num = (freq - WLAN_5_GHZ_BASE_FREQ) / WLAN_CHAN_SPACING_5MHZ;
+	tmp_index = (chan_num - FIRST_DFS_CHAN_NUM) / CHAN_NUM_SPACING;
+	*index = ((tmp_index >= 0) && (tmp_index < NUM_DFS_CHANS)) ?
+		  tmp_index : INVALID_INDEX;
+}
+
+/**
+ * utils_dfs_update_chan_state_array_element() - Update the per dfs channel
+ * state array element indexed by the frequency with the new state.
+ *
+ * @freq: Input DFS Channel frequency which will converted to channel state
+ * array index.
+ * @state: Input DFS state with which the value indexed by frequency will be
+ * updated with.
+ *
+ * Return: void.
+ */
+static QDF_STATUS
+utils_dfs_update_chan_state_array_element(struct wlan_dfs *dfs,
+					  qdf_freq_t freq,
+					  enum channel_dfs_state state)
+{
+	int8_t index;
+
+	if (state == CH_DFS_S_INVALID)
+		return QDF_STATUS_E_INVAL;
+
+	utils_dfs_convert_freq_to_index(freq, &index);
+
+	if (index == INVALID_INDEX)
+		return QDF_STATUS_E_INVAL;
+
+	dfs->dfs_channel_state_array[index] = state;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS dfs_init_chan_state_array(struct wlan_objmgr_pdev *pdev)
+{
+	struct regulatory_channel *cur_chan_list;
+	struct wlan_dfs *dfs;
+	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;
+
+	if (wlan_reg_get_current_chan_list(
+				pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
+		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			  "failed to get curr channel list");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		qdf_freq_t freq = cur_chan_list[i].center_freq;
+
+		if (!IS_CHAN_DFS(cur_chan_list[i].chan_flags))
+			continue;
+
+		utils_dfs_update_chan_state_array_element(dfs,
+							  freq,
+							  CH_DFS_S_CAC_REQ);
+	}
+
+	qdf_mem_free(cur_chan_list);
+	qdf_err("channel state array initialized");
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS utils_dfs_get_chan_dfs_state(struct wlan_objmgr_pdev *pdev,
+					enum channel_dfs_state *dfs_ch_s)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+
+	if (!dfs)
+		return QDF_STATUS_E_FAILURE;
+
+	qdf_mem_copy(dfs_ch_s,
+		     dfs->dfs_channel_state_array,
+		     sizeof(dfs->dfs_channel_state_array));
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(utils_dfs_get_chan_dfs_state);
+
+/**
+ * convert_event_to_state() - Coverts the dfs events WLAN_DFS_EVENTS to dfs
+ * states channel_dfs_state.
+ * @event: Input DFS event.
+ * @state: Output DFS state.
+ *
+ * Return: void.
+ */
+static
+void convert_event_to_state(enum WLAN_DFS_EVENTS event,
+			    enum channel_dfs_state *state)
+{
+	static const
+	enum channel_dfs_state ev_to_state[WLAN_EV_PCAC_COMPLETED + 1] = {
+	[WLAN_EV_RADAR_DETECTED] = CH_DFS_S_INVALID,
+	[WLAN_EV_CAC_RESET]      = CH_DFS_S_CAC_REQ,
+	[WLAN_EV_CAC_STARTED]    = CH_DFS_S_CAC_STARTED,
+	[WLAN_EV_CAC_COMPLETED]  = CH_DFS_S_CAC_COMPLETED,
+	[WLAN_EV_NOL_STARTED]    = CH_DFS_S_NOL,
+	[WLAN_EV_NOL_FINISHED]   = CH_DFS_S_CAC_REQ,
+	[WLAN_EV_PCAC_STARTED]   = CH_DFS_S_PRECAC_STARTED,
+	[WLAN_EV_PCAC_COMPLETED] = CH_DFS_S_PRECAC_COMPLETED,
+	};
+
+	*state = ev_to_state[event];
+}
+
+QDF_STATUS utils_dfs_update_chan_state_array(struct wlan_objmgr_pdev *pdev,
+					     qdf_freq_t freq,
+					     enum WLAN_DFS_EVENTS event)
+{
+	enum channel_dfs_state state;
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs)
+		return QDF_STATUS_E_FAILURE;
+
+	convert_event_to_state(event, &state);
+	return utils_dfs_update_chan_state_array_element(dfs, freq, state);
+}
+#endif /* WLAN_DISP_CHAN_INFO */