Przeglądaj źródła

qca-wifi: Move DFS_BANGRADAR from common code to WIN code

Bangradar is used to simulate actual radar. For partial-offlload the
simulation happens within the host itself. For full-offload a WMI
command is sent to the FW and it responds with radar found event.

CRs-Fixed: 2829436
Change-Id: I5a2c7e50df2ee06d236e45a47608c9c53f57ba99
Vijay Krishnan 4 lat temu
rodzic
commit
d3dc1a400d
1 zmienionych plików z 208 dodań i 0 usunięć
  1. 208 0
      umac/dfs/core/src/misc/dfs_bangradar.c

+ 208 - 0
umac/dfs/core/src/misc/dfs_bangradar.c

@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2002-2006, Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: This file contains the DFS Bangradar functionality.
+ *
+ */
+
+#include "dfs.h"
+#include "dfs_zero_cac.h"
+#include "wlan_dfs_lmac_api.h"
+#include "wlan_dfs_mlme_api.h"
+#include "wlan_dfs_tgt_api.h"
+#include "dfs_internal.h"
+
+/**
+ * dfs_check_bangradar_sanity() - Check the sanity of bangradar
+ * @dfs: Pointer to wlan_dfs structure.
+ * @bangradar_params: Parameters of the radar to be simulated.
+ */
+static QDF_STATUS
+dfs_check_bangradar_sanity(struct wlan_dfs *dfs,
+			   struct dfs_bangradar_params *bangradar_params)
+{
+	if (!bangradar_params) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			  "bangradar params is NULL");
+		return -EINVAL;
+	}
+	if (dfs_is_true_160mhz_supported(dfs)) {
+		if (abs(bangradar_params->freq_offset) >
+		    FREQ_OFFSET_BOUNDARY_FOR_160MHZ) {
+			dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
+				  "Frequency Offset out of bound");
+			return -EINVAL;
+		}
+	} else if (abs(bangradar_params->freq_offset) >
+		   FREQ_OFFSET_BOUNDARY_FOR_80MHZ) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			  "Frequency Offset out of bound");
+		return -EINVAL;
+	}
+	if (bangradar_params->seg_id > SEG_ID_SECONDARY) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "Invalid segment ID");
+		return -EINVAL;
+	}
+	if ((bangradar_params->detector_id > dfs_get_agile_detector_id(dfs)) ||
+	    ((bangradar_params->detector_id ==
+	      dfs_get_agile_detector_id(dfs)) &&
+	      !dfs->dfs_is_offload_enabled)) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "Invalid detector ID");
+		return -EINVAL;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * dfs_start_host_based_bangradar() - Mark as bangradar and start
+ * wlan_dfs_task_timer.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
+static int dfs_start_host_based_bangradar(struct wlan_dfs *dfs)
+{
+	dfs->wlan_radar_tasksched = 1;
+	qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
+
+	return 0;
+}
+#else
+static inline int dfs_start_host_based_bangradar(struct wlan_dfs *dfs)
+{
+	return 0;
+}
+#endif
+
+/**
+ * dfs_fill_emulate_bang_radar_test() - Update dfs unit test arguments and
+ * send bangradar command to firmware.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @bangradar_params: Parameters of the radar to be simulated.
+ *
+ * Return: If the event is received return 0.
+ */
+#if defined(WLAN_DFS_FULL_OFFLOAD)
+#define ADD_TO_32BYTE(_arg, _shift, _mask) (((_arg) & (_mask)) << (_shift))
+static int
+dfs_fill_emulate_bang_radar_test(struct wlan_dfs *dfs,
+				 struct dfs_bangradar_params *bangradar_params)
+{
+	struct dfs_emulate_bang_radar_test_cmd dfs_unit_test;
+	uint32_t packed_args = 0;
+
+	if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(dfs->dfs_curchan))) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			"Ignore bangradar on a NON-DFS channel");
+		return -EINVAL;
+	}
+
+	packed_args =
+		ADD_TO_32BYTE(bangradar_params->seg_id,
+			      SEG_ID_SHIFT,
+			      SEG_ID_MASK) |
+		ADD_TO_32BYTE(bangradar_params->is_chirp,
+			      IS_CHIRP_SHIFT,
+			      IS_CHIRP_MASK) |
+		ADD_TO_32BYTE(bangradar_params->freq_offset,
+			      FREQ_OFF_SHIFT,
+			      FREQ_OFFSET_MASK) |
+		ADD_TO_32BYTE(bangradar_params->detector_id,
+			      DET_ID_SHIFT,
+			      DET_ID_MASK);
+
+	qdf_mem_zero(&dfs_unit_test, sizeof(dfs_unit_test));
+	dfs_unit_test.num_args = DFS_UNIT_TEST_NUM_ARGS;
+	dfs_unit_test.args[IDX_CMD_ID] =
+			DFS_PHYERR_OFFLOAD_TEST_SET_RADAR;
+	dfs_unit_test.args[IDX_PDEV_ID] =
+			wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj);
+	dfs_unit_test.args[IDX_RADAR_PARAM1_ID] = packed_args;
+
+	if (tgt_dfs_process_emulate_bang_radar_cmd(dfs->dfs_pdev_obj,
+						   &dfs_unit_test) ==
+			QDF_STATUS_E_FAILURE) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#else
+static inline int
+dfs_fill_emulate_bang_radar_test(struct wlan_dfs *dfs,
+				 struct dfs_bangradar_params *bangradar_params)
+{
+	return 0;
+}
+#endif
+
+/*
+ * Handle all types of Bangradar here.
+ * Bangradar arguments:
+ * seg_id      : Segment ID where radar should be injected.
+ * is_chirp    : Is chirp radar or non chirp radar.
+ * freq_offset : Frequency offset from center frequency.
+ *
+ * Type 1 (DFS_BANGRADAR_FOR_ALL_SUBCHANS): To add all subchans.
+ * Type 2 (DFS_BANGRADAR_FOR_ALL_SUBCHANS_OF_SEGID): To add all
+ *               subchans of given segment_id.
+ * Type 3 (DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS): To add specific
+ *               subchans based on the arguments.
+ *
+ * The arguments will already be filled in the indata structure
+ * based on the type.
+ * If an argument is not specified by user, it will be set to
+ * default (0) in the indata already and correspondingly,
+ * the type will change.
+ */
+
+int dfs_bang_radar(struct wlan_dfs *dfs, void *indata, uint32_t insize)
+{
+	struct dfs_bangradar_params *bangradar_params;
+	int error = -EINVAL;
+
+	if (!dfs) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return error;
+	}
+
+	if (insize < sizeof(struct dfs_bangradar_params) || !indata) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS1,
+			  "insize = %d, expected = %zu bytes, indata = %pK",
+			  insize,
+			  sizeof(struct dfs_bangradar_params),
+			  indata);
+		return error;
+	}
+	bangradar_params = (struct dfs_bangradar_params *)indata;
+	error = dfs_check_bangradar_sanity(dfs, bangradar_params);
+	if (error != QDF_STATUS_SUCCESS)
+		return error;
+	dfs->dfs_bangradar_type = bangradar_params->bangradar_type;
+	dfs->dfs_seg_id = bangradar_params->seg_id;
+	dfs->dfs_is_chirp = bangradar_params->is_chirp;
+	dfs->dfs_freq_offset = bangradar_params->freq_offset;
+
+	if (dfs->dfs_is_offload_enabled) {
+		error = dfs_fill_emulate_bang_radar_test(
+				dfs,
+				bangradar_params);
+	} else {
+		error = dfs_start_host_based_bangradar(dfs);
+	}
+	return error;
+}