瀏覽代碼

qca-wifi: Move WIN specific DFS features to WIN code

Move the WIN only DFS features from common code to WIN specific
Component dev. The following features are moved.
1. WIN Hardware mode switch.
2. StaDFS
3. dfs_set_nol
4. nol_history

CRs-Fixed: 2834312
Change-Id: Ia68f5620a9321199b8e5cb0934fc044b9da7ff4a
Vijay Krishnan 4 年之前
父節點
當前提交
24b4852dda
共有 2 個文件被更改,包括 386 次插入0 次删除
  1. 171 0
      umac/dfs/core/src/misc/dfs_misc.c
  2. 215 0
      umac/dfs/dispatcher/src/dfs_postnol_ucfg.c

+ 171 - 0
umac/dfs/core/src/misc/dfs_misc.c

@@ -32,6 +32,9 @@
 #include "ieee80211_channel.h"
 #include "wlan_mlme_if.h"
 #include "dfs_postnol_ucfg.h"
+#include "wlan_dfs_lmac_api.h"
+#include "dfs_process_radar_found_ind.h"
+#include "wlan_dfs_utils_api.h"
 
 #if defined(QCA_SUPPORT_DFS_CHAN_POSTNOL)
 void dfs_postnol_attach(struct wlan_dfs *dfs)
@@ -217,3 +220,171 @@ bool dfs_switch_to_postnol_chan_if_nol_expired(struct wlan_dfs *dfs)
 	return true;
 }
 #endif
+
+#ifdef QCA_HW_MODE_SWITCH
+bool dfs_is_hw_mode_switch_in_progress(struct wlan_dfs *dfs)
+{
+	return lmac_dfs_is_hw_mode_switch_in_progress(dfs->dfs_pdev_obj);
+}
+
+
+void dfs_complete_deferred_tasks(struct wlan_dfs *dfs)
+{
+	if (dfs->dfs_defer_params.is_radar_detected) {
+		/* Handle radar event that was deferred and free the temporary
+		 * storage of the radar event parameters.
+		 */
+		dfs_process_radar_ind(dfs, dfs->dfs_defer_params.radar_params);
+		qdf_mem_free(dfs->dfs_defer_params.radar_params);
+		dfs->dfs_defer_params.is_radar_detected = false;
+	} else if (dfs->dfs_defer_params.is_cac_completed) {
+		/* Handle CAC completion event that was deferred for HW mode
+		 * switch.
+		 */
+		dfs_process_cac_completion(dfs);
+		dfs->dfs_defer_params.is_cac_completed = false;
+	}
+}
+
+void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios)
+{
+	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
+
+	if (WLAN_UMAC_MAX_PDEVS < num_radios) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			"num_radios (%u) exceeds limit", num_radios);
+		return;
+	}
+
+	/* Allocate the temporary psoc NOL copy structure for the number
+	 * of radios provided.
+	 */
+	dfs_soc_obj->dfs_psoc_nolinfo =
+		qdf_mem_malloc(sizeof(struct dfsreq_nolinfo) * num_radios);
+}
+
+void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs)
+{
+	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
+
+	if (!dfs_soc_obj->dfs_psoc_nolinfo)
+		return;
+
+	qdf_mem_free(dfs_soc_obj->dfs_psoc_nolinfo);
+	dfs_soc_obj->dfs_psoc_nolinfo = NULL;
+}
+
+void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs,
+			      uint8_t pdev_id)
+{
+	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
+	struct dfsreq_nolinfo tmp_nolinfo, *nolinfo;
+	uint32_t i, num_chans = 0;
+
+	if (!dfs->dfs_nol_count)
+		return;
+
+	if (!dfs_soc_obj->dfs_psoc_nolinfo)
+		return;
+
+	nolinfo = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id];
+	/* Fetch the NOL entries for the DFS object. */
+	dfs_getnol(dfs, &tmp_nolinfo);
+
+	/* nolinfo might already have some data. Do not overwrite it */
+	num_chans = nolinfo->dfs_ch_nchans;
+	for (i = 0; i < tmp_nolinfo.dfs_ch_nchans; i++) {
+		/* Figure out the completed duration of each NOL. */
+		uint32_t nol_completed_ms = qdf_do_div(
+			qdf_get_monotonic_boottime() -
+			tmp_nolinfo.dfs_nol[i].nol_start_us, 1000);
+
+		nolinfo->dfs_nol[num_chans] = tmp_nolinfo.dfs_nol[i];
+		/* Remember the remaining NOL time in the timeout
+		 * variable.
+		 */
+		nolinfo->dfs_nol[num_chans++].nol_timeout_ms -=
+			nol_completed_ms;
+	}
+
+	nolinfo->dfs_ch_nchans = num_chans;
+}
+
+void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs,
+				   uint8_t pdev_id,
+				   uint16_t low_5ghz_freq,
+				   uint16_t high_5ghz_freq)
+{
+	struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj;
+	struct dfsreq_nolinfo *nol, req_nol;
+	uint8_t i, j = 0;
+
+	if (!dfs_soc_obj->dfs_psoc_nolinfo)
+		return;
+
+	if (!dfs_soc_obj->dfs_psoc_nolinfo[pdev_id].dfs_ch_nchans)
+		return;
+
+	nol = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id];
+
+	for (i = 0; i < nol->dfs_ch_nchans; i++) {
+		uint16_t tmp_freq = nol->dfs_nol[i].nol_freq;
+
+		/* Add to nol only if within the tgt pdev's frequency range. */
+		if ((low_5ghz_freq < tmp_freq) && (high_5ghz_freq > tmp_freq)) {
+			/* The NOL timeout value in each entry points to the
+			 * remaining time of the NOL. This is to indicate that
+			 * the NOL entries are paused and are not left to
+			 * continue.
+			 * While adding these NOL, update the start ticks to
+			 * current time to avoid losing entries which might
+			 * have timed out during the pause and resume mechanism.
+			 */
+			nol->dfs_nol[i].nol_start_us =
+				qdf_get_monotonic_boottime();
+			req_nol.dfs_nol[j++] = nol->dfs_nol[i];
+		}
+	}
+	dfs_set_nol(dfs, req_nol.dfs_nol, j);
+}
+#endif
+
+#ifdef QCA_RADARTOOL_CMD
+#ifdef CONFIG_CHAN_FREQ_API
+void dfs_set_nol(struct wlan_dfs *dfs,
+		 struct dfsreq_nolelem *dfs_nol,
+		 int nchan)
+{
+#define TIME_IN_MS 1000
+	uint32_t nol_time_lft_ms;
+	struct dfs_channel chan;
+	int i;
+
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return;
+	}
+
+	for (i = 0; i < nchan; i++) {
+		nol_time_lft_ms = qdf_do_div(qdf_get_monotonic_boottime() -
+					     dfs_nol[i].nol_start_us, 1000);
+
+		if (nol_time_lft_ms < dfs_nol[i].nol_timeout_ms) {
+			chan.dfs_ch_freq = dfs_nol[i].nol_freq;
+			chan.dfs_ch_flags = 0;
+			chan.dfs_ch_flagext = 0;
+			nol_time_lft_ms =
+				(dfs_nol[i].nol_timeout_ms - nol_time_lft_ms);
+
+			DFS_NOL_ADD_CHAN_LOCKED(dfs, chan.dfs_ch_freq,
+						(nol_time_lft_ms / TIME_IN_MS));
+			utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
+							     &chan.dfs_ch_freq,
+							     1, DFS_NOL_SET);
+		}
+	}
+#undef TIME_IN_MS
+	dfs_nol_update(dfs);
+}
+#endif
+#endif

+ 215 - 0
umac/dfs/dispatcher/src/dfs_postnol_ucfg.c

@@ -143,3 +143,218 @@ QDF_STATUS ucfg_dfs_get_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
 qdf_export_symbol(ucfg_dfs_get_postnol_cfreq2);
 #endif
 
+#ifdef QCA_HW_MODE_SWITCH
+bool lmac_dfs_is_hw_mode_switch_in_progress(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
+	bool is_hw_mode_switch_in_progress = false;
+	struct wlan_lmac_if_tx_ops *tx_ops;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	if (!tx_ops) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "tx_ops is null");
+		return is_hw_mode_switch_in_progress;
+	}
+
+	dfs_tx_ops = &tx_ops->dfs_tx_ops;
+
+	if (dfs_tx_ops->dfs_check_mode_switch_state)
+		dfs_tx_ops->dfs_check_mode_switch_state(
+			pdev,
+			&is_hw_mode_switch_in_progress);
+
+	return is_hw_mode_switch_in_progress;
+}
+
+void dfs_mlme_acquire_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev)
+{
+	if (!global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock)
+		return;
+
+	global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock(pdev);
+}
+
+void dfs_mlme_release_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev)
+{
+	if (!global_dfs_to_mlme.mlme_release_radar_mode_switch_lock)
+		return;
+
+	global_dfs_to_mlme.mlme_release_radar_mode_switch_lock(pdev);
+}
+
+void tgt_dfs_init_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev,
+			       uint8_t num_radios)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_init_tmp_psoc_nol(dfs, num_radios);
+}
+
+qdf_export_symbol(tgt_dfs_init_tmp_psoc_nol);
+
+void tgt_dfs_deinit_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_deinit_tmp_psoc_nol(dfs);
+}
+
+qdf_export_symbol(tgt_dfs_deinit_tmp_psoc_nol);
+
+void tgt_dfs_save_dfs_nol_in_psoc(struct wlan_objmgr_pdev *pdev,
+				  uint8_t pdev_id)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_save_dfs_nol_in_psoc(dfs, pdev_id);
+}
+
+qdf_export_symbol(tgt_dfs_save_dfs_nol_in_psoc);
+
+void tgt_dfs_reinit_nol_from_psoc_copy(struct wlan_objmgr_pdev *pdev,
+				       uint8_t pdev_id,
+				       uint16_t low_5ghz_freq,
+				       uint16_t high_5ghz_freq)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_reinit_nol_from_psoc_copy(dfs,
+				      pdev_id,
+				      low_5ghz_freq,
+				      high_5ghz_freq);
+}
+
+qdf_export_symbol(tgt_dfs_reinit_nol_from_psoc_copy);
+
+void tgt_dfs_reinit_precac_lists(struct wlan_objmgr_pdev *src_pdev,
+				 struct wlan_objmgr_pdev *dest_pdev,
+				 uint16_t low_5g_freq,
+				 uint16_t high_5g_freq)
+{
+	struct wlan_dfs *src_dfs, *dest_dfs;
+
+	src_dfs = wlan_pdev_get_dfs_obj(src_pdev);
+	if (!src_dfs) {
+		dfs_err(src_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+	dest_dfs = wlan_pdev_get_dfs_obj(dest_pdev);
+	if (!dest_dfs) {
+		dfs_err(dest_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_reinit_precac_lists(src_dfs, dest_dfs, low_5g_freq, high_5g_freq);
+}
+
+void tgt_dfs_complete_deferred_tasks(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_complete_deferred_tasks(dfs);
+}
+#endif
+
+#ifdef QCA_SUPPORT_STA_DFS
+void tgt_dfs_enable_stadfs(struct wlan_objmgr_pdev *pdev, bool val)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs->dfs_is_stadfs_enabled = val;
+}
+
+bool tgt_dfs_is_stadfs_enabled(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return false;
+	}
+
+	return dfs->dfs_is_stadfs_enabled;
+}
+#endif
+
+#ifdef QCA_SUPPORT_STA_DFS
+void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev,
+					 void *clist, uint32_t *num_chan)
+{
+	int i, j = 0;
+	struct regulatory_channel *cur_chan_list;
+	struct wlan_dfs *dfs;
+	struct dfs_channel *chan_list = (struct dfs_channel *)clist;
+
+	*num_chan = 0;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs)
+		return;
+
+	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list));
+	if (!cur_chan_list)
+		return;
+
+	if (wlan_reg_get_current_chan_list(
+			pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
+		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			  "failed to get cur_chan list");
+		qdf_mem_free(cur_chan_list);
+		return;
+	}
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (cur_chan_list[i].nol_history) {
+			chan_list[j].dfs_ch_freq = cur_chan_list[i].center_freq;
+			j++;
+		}
+	}
+
+	*num_chan = j;
+	qdf_mem_free(cur_chan_list);
+}
+#else
+void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev,
+					 void *clist, uint32_t *num_chan)
+{
+}
+#endif