Forráskód Böngészése

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

Linux Build Service Account 4 éve
szülő
commit
fb1f29ceb3

+ 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