Browse Source

Merge "qcacmn: Define test config attribute to configure Tx beamformee"

Linux Build Service Account 6 years ago
parent
commit
771ab45972
34 changed files with 1406 additions and 46 deletions
  1. 3 0
      dp/inc/cdp_txrx_stats_struct.h
  2. 6 0
      os_if/linux/qca_vendor.h
  3. 47 3
      target_if/dfs/inc/target_if_dfs_partial_offload.h
  4. 43 0
      target_if/dfs/src/target_if_dfs.c
  5. 99 0
      target_if/dfs/src/target_if_dfs_partial_offload.c
  6. 75 0
      umac/dfs/core/src/dfs.h
  7. 145 1
      umac/dfs/core/src/dfs_partial_offload_radar.h
  8. 24 0
      umac/dfs/core/src/dfs_process_radar_found_ind.h
  9. 222 0
      umac/dfs/core/src/filtering/dfs_partial_offload_radar.c
  10. 5 0
      umac/dfs/core/src/filtering/dfs_process_phyerr.c
  11. 90 19
      umac/dfs/core/src/filtering/dfs_process_radarevent.c
  12. 5 1
      umac/dfs/core/src/misc/dfs.c
  13. 3 0
      umac/dfs/core/src/misc/dfs_filter_init.c
  14. 30 0
      umac/dfs/core/src/misc/dfs_nol.c
  15. 3 3
      umac/dfs/core/src/misc/dfs_process_radar_found_ind.c
  16. 16 0
      umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h
  17. 35 1
      umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h
  18. 18 0
      umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h
  19. 56 0
      umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h
  20. 55 0
      umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h
  21. 18 0
      umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h
  22. 4 0
      umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c
  23. 17 0
      umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c
  24. 22 0
      umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c
  25. 91 0
      umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c
  26. 45 2
      umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c
  27. 20 0
      umac/dfs/dispatcher/src/wlan_dfs_utils_api.c
  28. 44 16
      umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
  29. 8 0
      umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c
  30. 27 0
      wmi/inc/wmi_unified_api.h
  31. 5 0
      wmi/inc/wmi_unified_param.h
  32. 10 0
      wmi/inc/wmi_unified_priv.h
  33. 27 0
      wmi/src/wmi_unified_api.c
  34. 88 0
      wmi/src/wmi_unified_non_tlv.c

+ 3 - 0
dp/inc/cdp_txrx_stats_struct.h

@@ -1239,6 +1239,9 @@ enum _ol_ath_param_t {
 	OL_ATH_PARAM_PAPI_ENABLE = 364,
 	OL_ATH_PARAM_ISOLATION = 365,
 	OL_ATH_PARAM_MAX_CLIENTS_PER_RADIO = 366,
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	OL_ATH_PARAM_DFS_HOST_WAIT_TIMEOUT = 367,
+#endif
 };
 
 /* Enumeration of PDEV Configuration parameter */

+ 6 - 0
os_if/linux/qca_vendor.h

@@ -5991,6 +5991,12 @@ enum qca_wlan_vendor_attr_wifi_test_config {
 	 */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF = 12,
 
+	/* 8-bit unsigned value to configure the tx beamformee.
+	 * This attribute is used to configure the testbed device.
+	 * 1 - enable, 0 - disable.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE = 13,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =

+ 47 - 3
target_if/dfs/inc/target_if_dfs_partial_offload.h

@@ -50,10 +50,54 @@ target_if_dfs_reg_phyerr_events(struct wlan_objmgr_psoc *psoc)
  */
 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
 QDF_STATUS target_if_dfs_get_caps(struct wlan_objmgr_pdev *pdev,
-		struct wlan_dfs_caps *dfs_caps);
+				  struct wlan_dfs_caps *dfs_caps);
 #else
-static QDF_STATUS target_if_dfs_get_caps(struct wlan_objmgr_pdev *pdev,
-		struct wlan_dfs_caps *dfs_caps)
+static inline QDF_STATUS target_if_dfs_get_caps(struct wlan_objmgr_pdev *pdev,
+						struct wlan_dfs_caps *dfs_caps)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * target_if_dfs_status_check_event_handler() - Host dfs confirmation event
+ * handler.
+ * @scn: Handle to HIF context
+ * @data: radar event buffer
+ * @datalen: radar event buffer length
+ *
+ * Return: 0 on success
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+int target_if_dfs_status_check_event_handler(ol_scn_t scn,
+					     uint8_t *data,
+					     uint32_t datalen);
+#else
+static inline
+int target_if_dfs_status_check_event_handler(ol_scn_t scn,
+					     uint8_t *data,
+					     uint32_t datalen)
+{
+	return 0;
+}
+#endif
+
+/**
+ * target_if_dfs_send_avg_params_to_fw() - Send average parameters to FW.
+ * @pdev: pdev pointer
+ * @params: Pointer to dfs_radar_found_params structure.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS target_if_dfs_send_avg_params_to_fw(
+		struct wlan_objmgr_pdev *pdev,
+		struct dfs_radar_found_params *params);
+#else
+static inline
+QDF_STATUS target_if_dfs_send_avg_params_to_fw(
+		struct wlan_objmgr_pdev *pdev,
+		struct dfs_radar_found_params *params)
 {
 	return QDF_STATUS_SUCCESS;
 }

+ 43 - 0
target_if/dfs/src/target_if_dfs.c

@@ -40,6 +40,44 @@
 #include <target_if_dfs_full_offload.h>
 #include <target_if_dfs_partial_offload.h>
 
+/**
+ * target_if_dfs_register_host_status_check_event() - Register host dfs
+ * confirmation event.
+ * @psoc: pointer to psoc.
+ *
+ * Return: QDF_STATUS.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+static QDF_STATUS target_if_dfs_register_host_status_check_event(
+		struct wlan_objmgr_psoc *psoc)
+
+{
+	wmi_unified_t wmi_handle;
+	QDF_STATUS retval;
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("null wmi_handle");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	retval = wmi_unified_register_event(wmi_handle,
+			wmi_host_dfs_status_check_event_id,
+			target_if_dfs_status_check_event_handler);
+	if (QDF_IS_STATUS_ERROR(retval))
+		target_if_err("wmi_dfs_radar_detection_event_id ret=%d",
+			      retval);
+
+	return retval;
+}
+#else
+static QDF_STATUS target_if_dfs_register_host_status_check_event(
+		struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * target_if_is_dfs_3() - Is dfs3 support or not
  * @target_type: target type being used.
@@ -174,6 +212,9 @@ static QDF_STATUS target_if_dfs_register_event_handler(
 			target_if_err("null tgt_psoc_info");
 			return QDF_STATUS_E_FAILURE;
 		}
+
+		target_if_dfs_register_host_status_check_event(psoc);
+
 		if (target_if_is_dfs_3(
 				target_psoc_get_target_type(tgt_psoc_info)))
 			return target_if_dfs_reg_phyerr_events(psoc);
@@ -316,6 +357,8 @@ QDF_STATUS target_if_register_dfs_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 				&target_if_dfs_set_phyerr_filter_offload;
 
 	dfs_tx_ops->dfs_get_caps = &target_if_dfs_get_caps;
+	dfs_tx_ops->dfs_send_avg_radar_params_to_fw =
+		&target_if_dfs_send_avg_params_to_fw;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 99 - 0
target_if/dfs/src/target_if_dfs_partial_offload.c

@@ -25,6 +25,7 @@
 #include <target_if.h>
 #include "target_type.h"
 #include "target_if_dfs_partial_offload.h"
+#include "target_if_dfs.h"
 
 QDF_STATUS target_if_dfs_reg_phyerr_events(struct wlan_objmgr_psoc *psoc)
 {
@@ -87,3 +88,101 @@ QDF_STATUS target_if_dfs_get_caps(struct wlan_objmgr_pdev *pdev,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+#if defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS target_if_dfs_send_avg_params_to_fw(
+		struct wlan_objmgr_pdev *pdev,
+		struct dfs_radar_found_params *params)
+{
+	QDF_STATUS status;
+	wmi_unified_t wmi_handle;
+
+	if (!pdev) {
+		target_if_err("null pdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
+	if (!wmi_handle) {
+		target_if_err("null wmi_handle");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wmi_unified_dfs_send_avg_params_cmd(wmi_handle,
+						     params);
+	if (QDF_IS_STATUS_ERROR(status))
+		target_if_err("dfs radar found average parameters send failed: %d",
+			      status);
+
+	return status;
+}
+
+int target_if_dfs_status_check_event_handler(ol_scn_t scn,
+					     uint8_t *data,
+					     uint32_t datalen)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
+	u_int32_t dfs_status_check;
+	wmi_unified_t wmi_hdl;
+
+	if (!scn || !data) {
+		target_if_err("scn: %pK, data: %pK", scn, data);
+		return -EINVAL;
+	}
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("null psoc");
+		return -EINVAL;
+	}
+
+	/* Since Partial Offload chipsets have only one pdev per psoc, the first
+	 * pdev from the pdev list is used.
+	 */
+	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_DFS_ID);
+	if (!pdev) {
+		target_if_err("null pdev");
+		return -EINVAL;
+	}
+
+	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
+	if (!dfs_rx_ops) {
+		target_if_err("null dfs_rx_ops");
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+		return -EINVAL;
+	}
+
+	if (!dfs_rx_ops->dfs_action_on_status) {
+		target_if_err("dfs_rx_ops->dfs_action_on_status is NULL");
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+		return -EINVAL;
+	}
+
+	wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev);
+	if (!wmi_hdl) {
+		target_if_err("wmi_hdl is NULL");
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+		return -EINVAL;
+	}
+
+	if (wmi_extract_dfs_status_from_fw(wmi_hdl, data, &dfs_status_check) !=
+			QDF_STATUS_SUCCESS) {
+		target_if_err("failed to extract status response from FW");
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+		return -EINVAL;
+	}
+
+	if (dfs_rx_ops->dfs_action_on_status(pdev, &dfs_status_check) !=
+		QDF_STATUS_SUCCESS) {
+		target_if_err("dfs action on host dfs status from FW failed");
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+		return -EINVAL;
+	}
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
+
+	return 0;
+}
+#endif

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

@@ -353,6 +353,13 @@
 		WLAN_DFSNOL_UNLOCK(dfs);                    \
 	} while (0)
 
+/* Host sends the average parameters of the radar pulses and starts the status
+ * wait timer with this timeout.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+#define HOST_DFS_STATUS_WAIT_TIMER_MS 100
+#endif
+
 /**
  * struct dfs_pulseparams - DFS pulse param structure.
  * @p_time:        Time for start of pulse in usecs.
@@ -921,6 +928,26 @@ struct dfs_event_log {
  * @dfs_use_nol_subchannel_marking:  Use subchannel marking logic to add only
  *                                   radar affected subchannel instead of all
  *                                   bonding channels.
+ * @dfs_host_wait_timer:             The timer that is started from host after
+ *                                   sending the average radar parameters.
+ *                                   Before this timeout host expects its dfs
+ *                                   status from fw.
+ * @dfs_average_pri:                 Average pri value of the received radar
+ *                                   pulses.
+ * @dfs_average_duration:            Average duration of the received radar
+ *                                   pulses.
+ * @dfs_average_sidx:                Average sidx of the received radar pulses.
+ * @dfs_is_host_wait_running:        Indicates if host dfs status wait timer is
+ *                                   running.
+ * @dfs_average_params_sent:         Indicates if host has sent the average
+ *                                   radar parameters.
+ * @dfs_no_res_from_fw:              Indicates no response from fw.
+ * @dfs_spoof_check_failed:          Indicates if the spoof check has failed.
+ * @dfs_spoof_test_done:             Indicates if the sppof test is done.
+ * @dfs_seg_id:                      Segment ID of the radar hit channel.
+ * @dfs_false_radar_found:           Indicates if false radar is found.
+ * @dfs_status_timeout_override:     Used to change the timeout value of
+ *                                   dfs_host_wait_timer.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1020,6 +1047,21 @@ struct wlan_dfs {
 	qdf_spinlock_t dfs_nol_lock;
 	uint16_t tx_leakage_threshold;
 	bool dfs_use_nol_subchannel_marking;
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	os_timer_t     dfs_host_wait_timer;
+	uint32_t       dfs_average_pri;
+	uint32_t       dfs_average_duration;
+	uint32_t       dfs_average_sidx;
+	uint8_t        dfs_is_host_wait_running:1,
+				   dfs_average_params_sent:1,
+				   dfs_no_res_from_fw:1,
+				   dfs_spoof_check_failed:1,
+				   dfs_spoof_test_done:1;
+	uint8_t        dfs_seg_id;
+	int            dfs_false_radar_found;
+	struct dfs_channel dfs_radar_found_chan;
+	int            dfs_status_timeout_override;
+#endif
 };
 
 /**
@@ -1076,6 +1118,24 @@ enum {
 	WLAN_DEBUG_DFS_ALWAYS     = WLAN_DEBUG_DFS_MAX
 };
 
+/**
+ * enum host dfs spoof check status.
+ * @HOST_DFS_CHECK_PASSED: Host indicates RADAR detected and the FW
+ *                         confirms it to be spoof radar to host.
+ * @HOST_DFS_CHECK_FAILED: Host doesn't indicate RADAR detected or spoof
+ *                         radar parameters by
+ *                         WMI_HOST_DFS_RADAR_FOUND_CMDID doesn't match.
+ * @HOST_DFS_STATUS_CHECK_HW_RADAR: Host indicates RADAR detected and the
+ *                             FW confirms it to be real HW radar to host.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+enum {
+	HOST_DFS_STATUS_CHECK_PASSED = 0,
+	HOST_DFS_STATUS_CHECK_FAILED = 1,
+	HOST_DFS_STATUS_CHECK_HW_RADAR = 2
+};
+#endif
+
 /**
  * struct dfs_phy_err - DFS phy error.
  * @fulltsf:             64-bit TSF as read from MAC.
@@ -1575,6 +1635,21 @@ void dfs_reset_ar(struct wlan_dfs *dfs);
  */
 void dfs_reset_arq(struct wlan_dfs *dfs);
 
+/**
+ * dfs_is_radar_enabled() - check if radar detection is enabled.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @ignore_dfs: if 1 then radar detection is disabled..
+ */
+#if defined(WLAN_DFS_DIRECT_ATTACH) || defined(WLAN_DFS_PARTIAL_OFFLOAD)
+void dfs_is_radar_enabled(struct wlan_dfs *dfs,
+			  int *ignore_dfs);
+#else
+static inline void dfs_is_radar_enabled(struct wlan_dfs *dfs,
+					int *ignore_dfs)
+{
+}
+#endif
+
 /**
  * dfs_process_phyerr_bb_tlv() - Parses the PHY error and populates the
  *                               dfs_phy_err struct.

+ 145 - 1
umac/dfs/core/src/dfs_partial_offload_radar.h

@@ -32,7 +32,151 @@
 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
 void dfs_get_po_radars(struct wlan_dfs *dfs);
 #else
-static void dfs_get_po_radars(struct wlan_dfs *dfs)
+static inline void dfs_get_po_radars(struct wlan_dfs *dfs)
+{
+}
+#endif
+
+/**
+ * dfs_send_avg_params_to_fw - send avg radar parameters to FW.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @params: Pointer to dfs_radar_found_params.
+ *
+ * Return: None
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_send_avg_params_to_fw(struct wlan_dfs *dfs,
+			       struct dfs_radar_found_params *params);
+#else
+static inline
+void dfs_send_avg_params_to_fw(struct wlan_dfs *dfs,
+			       struct dfs_radar_found_params *params)
+{
+}
+#endif
+
+/**
+ * dfs_host_wait_timer_init() - Initialize dfs host status wait timer.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_host_wait_timer_init(struct wlan_dfs *dfs);
+#else
+static inline void dfs_host_wait_timer_init(struct wlan_dfs *dfs)
+{
+}
+#endif
+
+/**
+ * dfs_set_override_status_timeout() - Change the dfs host status timeout.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @status_timeout: timeout value.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS dfs_set_override_status_timeout(struct wlan_dfs *dfs,
+				       int status_timeout);
+#else
+static inline QDF_STATUS dfs_set_override_status_timeout(struct wlan_dfs *dfs,
+						     int status_timeout)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * dfs_get_override_status_timeout() - Get the dfs host status timeout value.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @status_timeout: Pointer to  timeout value.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS dfs_get_override_status_timeout(struct wlan_dfs *dfs,
+					   int *status_timeout);
+#else
+static inline
+QDF_STATUS dfs_get_override_status_timeout(struct wlan_dfs *dfs,
+					   int *status_timeout)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * dfs_radarfound_action_fcc() - The dfs action on radar detection by host for
+ * FCC domain.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @seg_id: segment id.
+ * @false_radar_found: Indicates if false radar is found.
+ *
+ * Return: None
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_radarfound_action_fcc(struct wlan_dfs *dfs, uint8_t seg_id,
+			       int false_radar_found);
+#else
+static inline void dfs_radarfound_action_fcc(struct wlan_dfs *dfs,
+					     uint8_t seg_id,
+					     int false_radar_found)
+{
+}
+#endif
+
+/**
+ * dfs_host_wait_timer_reset() - Stop dfs host wait timer.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_host_wait_timer_reset(struct wlan_dfs *dfs);
+#else
+static inline void dfs_host_wait_timer_reset(struct wlan_dfs *dfs)
+{
+}
+#endif
+
+/**
+ * dfs_remove_spoof_channel_from_nol() - Remove the spoofed radar hit channel
+ * from NOL.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs);
+#else
+static inline void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs)
+{
+}
+#endif
+
+/**
+ * dfs_reset_spoof_test() - reset the spoof test variables.
+ * @dfs: Pointer to wlan_dfs structure.
+ *
+ * Return: None.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_reset_spoof_test(struct wlan_dfs *dfs);
+#else
+static inline void dfs_reset_spoof_test(struct wlan_dfs *dfs)
+{
+}
+#endif
+
+/**
+ * dfs_action_on_fw_radar_status_check() - The dfs action on host dfs
+ * confirmation by fw.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @status: pointer to host dfs status.
+ *
+ * Return: None
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_action_on_fw_radar_status_check(struct wlan_dfs *dfs,
+					 uint32_t *status);
+#else
+static inline void dfs_action_on_fw_radar_status_check(struct wlan_dfs *dfs,
+						       uint32_t *status)
 {
 }
 #endif

+ 24 - 0
umac/dfs/core/src/dfs_process_radar_found_ind.h

@@ -120,3 +120,27 @@ void dfs_process_radar_found_indication(struct wlan_dfs *dfs,
  */
 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
 		struct radar_found_info *radar_found);
+
+/**
+ * dfs_radarfound_action_generic() - The dfs action on radar detection by host
+ * for domains other than FCC.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @seg_id: segment id.
+ * @false_radar_found: Indicates detection of false radar.
+ *
+ * Return: None
+ */
+void dfs_radarfound_action_generic(struct wlan_dfs *dfs,
+				   uint8_t seg_id, int false_radar_found);
+
+/**
+ * dfs_get_bonding_channels() - Get bonding channels.
+ * @curchan: Pointer to dfs_channels to know width and primary channel.
+ * @segment_id: Segment id, useful for 80+80/160 MHz operating band.
+ * @channels: Pointer to save radar affected channels.
+ *
+ * Return: Number of channels.
+ */
+uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
+				 uint32_t segment_id,
+				 uint8_t *channels);

+ 222 - 0
umac/dfs/core/src/filtering/dfs_partial_offload_radar.c

@@ -26,6 +26,9 @@
 #include "wlan_dfs_lmac_api.h"
 #include "../dfs_internal.h"
 #include "../dfs_partial_offload_radar.h"
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+#include "../dfs_process_radar_found_ind.h"
+#endif
 
 /**
  * struct dfs_pulse dfs_fcc_radars - FCC radar table for Offload chipsets.
@@ -425,3 +428,222 @@ void dfs_get_po_radars(struct wlan_dfs *dfs)
 
 	dfs_init_radar_filters(dfs, &rinfo);
 }
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_send_avg_params_to_fw(struct wlan_dfs *dfs,
+			       struct dfs_radar_found_params *params)
+{
+	tgt_dfs_send_avg_params_to_fw(dfs->dfs_pdev_obj, params);
+}
+
+/**
+ * dfs_no_res_from_fw_task() - The timer function that is called if there is no
+ * response from fw after sending the average radar pulse parameters.
+ */
+static os_timer_func(dfs_no_res_from_fw_task)
+{
+	struct wlan_dfs *dfs = NULL;
+
+	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
+
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return;
+	}
+
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Host wait timer expired");
+
+	dfs->dfs_is_host_wait_running = 0;
+	dfs->dfs_no_res_from_fw = 1;
+	dfs_radarfound_action_generic(dfs, dfs->dfs_seg_id,
+				      dfs->dfs_false_radar_found);
+	dfs->dfs_seg_id = 0;
+	dfs->dfs_false_radar_found = 0;
+}
+
+void dfs_host_wait_timer_init(struct wlan_dfs *dfs)
+{
+	qdf_timer_init(NULL,
+		       &(dfs->dfs_host_wait_timer),
+			dfs_no_res_from_fw_task,
+			(void *)(dfs),
+			QDF_TIMER_TYPE_WAKE_APPS);
+	dfs->dfs_status_timeout_override = -1;
+}
+
+QDF_STATUS dfs_set_override_status_timeout(struct wlan_dfs *dfs,
+				       int status_timeout)
+{
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs->dfs_status_timeout_override = status_timeout;
+
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+		 "Host wait status timeout is now %s : %d",
+		(status_timeout == -1) ? "default" : "overridden",
+		status_timeout);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS dfs_get_override_status_timeout(struct wlan_dfs *dfs,
+					   int *status_timeout)
+{
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	*status_timeout = dfs->dfs_status_timeout_override;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * dfs_extract_radar_found_params() - Copy the contents of average radar
+ * parameters to dfs_radar_found_params parameter structure.
+ *
+ * @dfs: Pointer to wlan_dfs structure which contains the average radar
+ * parameters.
+ * @params: Pointer to dfs_radar_found_params structure.
+ */
+static
+void dfs_extract_radar_found_params(struct wlan_dfs *dfs,
+				    struct dfs_radar_found_params *params)
+{
+	qdf_mem_zero(params, sizeof(*params));
+	params->pri_min = dfs->dfs_average_pri;
+	params->pri_max = dfs->dfs_average_pri;
+	params->duration_min = dfs->dfs_average_duration;
+	params->duration_max = dfs->dfs_average_duration;
+	params->sidx_min = dfs->dfs_average_sidx;
+	params->sidx_max = dfs->dfs_average_sidx;
+
+	/* Bangradar will not populate any of these average
+	 * parameters as pulse is not received. If these variables
+	 * are not resetted here, these go as radar_found params
+	 * for bangradar if bangradar is issued after real radar.
+	 */
+	dfs->dfs_average_sidx = 0;
+	dfs->dfs_average_duration = 0;
+	dfs->dfs_average_pri = 0;
+}
+
+void dfs_radarfound_action_fcc(struct wlan_dfs *dfs, uint8_t seg_id,
+			       int false_radar_found)
+{
+	struct dfs_radar_found_params params;
+
+	qdf_mem_copy(&dfs->dfs_radar_found_chan, dfs->dfs_curchan,
+		     sizeof(dfs->dfs_radar_found_chan));
+	dfs_extract_radar_found_params(dfs, &params);
+	dfs_send_avg_params_to_fw(dfs, &params);
+	dfs->dfs_is_host_wait_running = 1;
+	dfs->dfs_seg_id = seg_id;
+	dfs->dfs_false_radar_found = false_radar_found;
+	qdf_timer_mod(&dfs->dfs_host_wait_timer,
+		      (dfs->dfs_status_timeout_override ==
+		       -1) ? HOST_DFS_STATUS_WAIT_TIMER_MS :
+		      dfs->dfs_status_timeout_override);
+}
+
+void dfs_host_wait_timer_reset(struct wlan_dfs *dfs)
+{
+	dfs->dfs_is_host_wait_running = 0;
+	qdf_timer_stop(&dfs->dfs_host_wait_timer);
+}
+
+/**
+ * dfs_action_on_spoof_success() - DFS action on spoof test pass
+ * @dfs: Pointer to DFS object
+ */
+static void dfs_action_on_spoof_success(struct wlan_dfs *dfs)
+{
+	dfs->dfs_spoof_test_done = 1;
+	if (dfs->dfs_radar_found_chan.dfs_ch_freq ==
+			dfs->dfs_curchan->dfs_ch_freq) {
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "cac timer started for channel %d",
+			 dfs->dfs_curchan->dfs_ch_ieee);
+		dfs_start_cac_timer(dfs);
+	} else{
+		dfs_remove_spoof_channel_from_nol(dfs);
+	}
+}
+
+void dfs_action_on_fw_radar_status_check(struct wlan_dfs *dfs,
+					 uint32_t *status)
+{
+	struct wlan_objmgr_pdev *dfs_pdev;
+	int no_chans_avail = 0;
+	int error_flag = 0;
+
+	dfs_host_wait_timer_reset(dfs);
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Host DFS status = %d",
+		 *status);
+
+	dfs_pdev = dfs->dfs_pdev_obj;
+	if (!dfs_pdev) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_pdev_obj is NULL");
+		return;
+	}
+
+	switch (*status) {
+	case HOST_DFS_STATUS_CHECK_PASSED:
+		if (dfs->dfs_average_params_sent)
+			dfs_action_on_spoof_success(dfs);
+		else
+			error_flag = 1;
+		break;
+	case HOST_DFS_STATUS_CHECK_FAILED:
+		dfs->dfs_spoof_check_failed = 1;
+		no_chans_avail =
+		    dfs_mlme_rebuild_chan_list_with_non_dfs_channels(dfs_pdev);
+		dfs_mlme_restart_vaps_with_non_dfs_chan(dfs_pdev,
+							no_chans_avail);
+		break;
+	case HOST_DFS_STATUS_CHECK_HW_RADAR:
+		if (dfs->dfs_average_params_sent) {
+			if (dfs->dfs_radar_found_chan.dfs_ch_freq ==
+			    dfs->dfs_curchan->dfs_ch_freq) {
+				dfs_radarfound_action_generic(
+						dfs,
+						dfs->dfs_seg_id,
+						dfs->dfs_false_radar_found);
+			} else {
+				/* Else of this case, no action is needed as
+				 * dfs_action would have been done at timer
+				 * expiry itself.
+				 */
+				dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+					 "DFS Action already taken");
+			}
+		} else {
+			error_flag = 1;
+		}
+		break;
+	default:
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "Status event mismatch:%d, Ignoring it",
+			 *status);
+	}
+
+	dfs->dfs_average_params_sent = 0;
+	qdf_mem_zero(&dfs->dfs_radar_found_chan, sizeof(struct dfs_channel));
+
+	if (error_flag == 1) {
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "Received imroper response %d. Discarding it",
+			 *status);
+	}
+}
+
+void dfs_reset_spoof_test(struct wlan_dfs *dfs)
+{
+	dfs->dfs_spoof_test_done = 0;
+	dfs->dfs_spoof_check_failed = 0;
+}
+#endif

+ 5 - 0
umac/dfs/core/src/filtering/dfs_process_phyerr.c

@@ -981,3 +981,8 @@ void dfs_process_phyerr_filter_offload(struct wlan_dfs *dfs,
 	}
 }
 #endif
+
+void dfs_is_radar_enabled(struct wlan_dfs *dfs, int *ignore_dfs)
+{
+	*ignore_dfs = dfs->dfs_ignore_dfs;
+}

+ 90 - 19
umac/dfs/core/src/filtering/dfs_process_radarevent.c

@@ -26,6 +26,9 @@
 #include "../dfs_channel.h"
 #include "../dfs_internal.h"
 #include "../dfs_process_radar_found_ind.h"
+#include "wlan_dfs_utils_api.h"
+#include "wlan_dfs_lmac_api.h"
+#include "../dfs_partial_offload_radar.h"
 
 #define FREQ_5500_MHZ  5500
 #define FREQ_5500_MHZ       5500
@@ -440,6 +443,53 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs,
 	return;
 }
 
+/**
+ * dfs_cal_average_radar_parameters() - Calculate the average radar parameters.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs)
+{
+	int i, count = 0;
+	u_int32_t total_pri = 0;
+	u_int32_t total_duration = 0;
+	u_int32_t total_sidx = 0;
+
+	/* Calculating average PRI, Duration, SIDX from
+	 * the 2nd pulse, ignoring the 1st pulse (radar_log[0]).
+	 * This is because for the first pulse, the diff_ts will be
+	 * (0 - current_ts) which will be a huge value.
+	 * Average PRI computation will be wrong. FW returns a
+	 * failure test result as PRI does not match their expected
+	 * value.
+	 */
+
+	for (i = 1; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count);
+			i++) {
+		total_pri +=  dfs->radar_log[i].diff_ts;
+		total_duration += dfs->radar_log[i].dur;
+		total_sidx +=  dfs->radar_log[i].sidx;
+		count++;
+	}
+
+	if (count > 0) {
+		dfs->dfs_average_pri = total_pri / count;
+		dfs->dfs_average_duration = total_duration / count;
+		dfs->dfs_average_sidx = total_sidx / count;
+
+		dfs_info(dfs, WLAN_DEBUG_DFS2,
+			 "Avg.PRI =%u, Avg.duration =%u Avg.sidx =%u",
+			 dfs->dfs_average_pri,
+			 dfs->dfs_average_duration,
+			 dfs->dfs_average_sidx);
+	}
+}
+#else
+static void dfs_cal_average_radar_parameters(struct wlan_dfs *dfs)
+{
+}
+#endif
+
 /**
  * dfs_radarfound_reset_vars() - Reset dfs variables after radar found
  * @dfs: Pointer to wlan_dfs structure.
@@ -473,8 +523,10 @@ static inline void dfs_radarfound_reset_vars(
 	 * filter match. This can be used to collect information
 	 * on false radar detection.
 	 */
-	if (dfs->dfs_event_log_on)
+	if (dfs->dfs_event_log_on) {
+		dfs_cal_average_radar_parameters(dfs);
 		dfs_print_radar_events(dfs);
+	}
 
 	dfs_reset_radarq(dfs);
 	dfs_reset_alldelaylines(dfs);
@@ -1196,6 +1248,30 @@ static inline void dfs_false_radarfound_reset_vars(
 	dfs->dfs_phyerr_w53_counter  = 0;
 }
 
+void dfs_radarfound_action_generic(struct wlan_dfs *dfs,
+		uint8_t seg_id, int false_radar_found)
+{
+	struct radar_found_info *radar_found;
+
+	radar_found = qdf_mem_malloc(sizeof(*radar_found));
+	if (!radar_found) {
+		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			  "radar_found allocation failed");
+		return;
+	}
+
+	qdf_mem_zero(radar_found, sizeof(*radar_found));
+	radar_found->segment_id = seg_id;
+	radar_found->pdev_id =
+		wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj);
+
+	dfs_process_radar_ind(dfs, radar_found);
+	qdf_mem_free(radar_found);
+
+	if (false_radar_found)
+		dfs_false_radarfound_reset_vars(dfs);
+}
+
 void dfs_process_radarevent(
 	struct wlan_dfs *dfs,
 	struct dfs_channel *chan)
@@ -1222,26 +1298,21 @@ void dfs_process_radarevent(
 
 dfsfound:
 	if (retval) {
-		struct radar_found_info *radar_found;
-
 		dfs_radarfound_reset_vars(dfs, rs, chan, seg_id);
-
-		radar_found = qdf_mem_malloc(sizeof(*radar_found));
-		if (!radar_found) {
-			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
-					"radar_found allocation failed");
-			return;
+		/* If Host DFS confirmation is supported, save the curchan as
+		 * radar found chan, send radar found indication along with
+		 * average radar parameters to FW and start the host status
+		 * wait timer.
+		 */
+		if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_FCC_DOMAIN &&
+		    lmac_is_host_dfs_check_support_enabled(
+				dfs->dfs_pdev_obj)) {
+			dfs_radarfound_action_fcc(dfs, seg_id,
+				false_radar_found);
+		} else {
+			dfs_radarfound_action_generic(dfs, seg_id,
+				false_radar_found);
 		}
-
-		qdf_mem_zero(radar_found, sizeof(*radar_found));
-		radar_found->segment_id = seg_id;
-		radar_found->pdev_id =
-			wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj);
-
-		dfs_process_radar_ind(dfs, radar_found);
-		qdf_mem_free(radar_found);
 	}
 
-	if (false_radar_found)
-		dfs_false_radarfound_reset_vars(dfs);
 }

+ 5 - 1
umac/dfs/core/src/misc/dfs.c

@@ -29,7 +29,7 @@
 #include "../dfs_internal.h"
 #include "../dfs_filter_init.h"
 #include "../dfs_full_offload.h"
-
+#include "wlan_dfs_utils_api.h"
 
 /**
  * dfs_testtimer_task() - Sends CSA in the current channel.
@@ -290,6 +290,10 @@ int dfs_control(struct wlan_dfs *dfs,
 		if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) {
 			/* Enable debug Radar Event */
 			dfs->dfs_event_log_on = 1;
+		} else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
+		    DFS_FCC_DOMAIN) &&
+		    lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) {
+			dfs->dfs_event_log_on = 1;
 		} else {
 			dfs->dfs_event_log_on = 0;
 		}

+ 3 - 0
umac/dfs/core/src/misc/dfs_filter_init.c

@@ -28,6 +28,7 @@
 #include "wlan_dfs_tgt_api.h"
 #include "../dfs_internal.h"
 #include "../dfs_filter_init.h"
+#include "../dfs_partial_offload_radar.h"
 
 /*
  * Channel switch announcement (CSA)
@@ -103,6 +104,8 @@ int dfs_main_attach(struct wlan_dfs *dfs)
 	/*Verify : Passing NULL to qdf_timer_init().*/
 	dfs_main_task_timer_init(dfs);
 
+	dfs_host_wait_timer_init(dfs);
+
 	WLAN_DFSQ_LOCK_CREATE(dfs);
 	STAILQ_INIT(&dfs->dfs_radarq);
 	WLAN_ARQ_LOCK_CREATE(dfs);

+ 30 - 0
umac/dfs/core/src/misc/dfs_nol.c

@@ -34,6 +34,10 @@
 #include <wlan_dfs_mlme_api.h>
 #include <wlan_dfs_utils_api.h>
 #include <wlan_reg_services_api.h>
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+#include "../dfs_process_radar_found_ind.h"
+#include "../dfs_partial_offload_radar.h"
+#endif
 
 /**
  * dfs_nol_timeout() - NOL timeout function.
@@ -585,3 +589,29 @@ void dfs_clear_nolhistory(struct wlan_dfs *dfs)
 		WLAN_CHAN_CLR_HISTORY_RADAR(c);
 	}
 }
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs)
+{
+	struct dfs_nolelem *nol;
+	uint8_t channels[NUM_CHANNELS_160MHZ];
+	int i, nchans = 0;
+
+	nchans = dfs_get_bonding_channels(&dfs->dfs_radar_found_chan, 0,
+					  channels);
+
+	WLAN_DFSNOL_LOCK(dfs);
+	for (i = 0; i < nchans && i < NUM_CHANNELS_160MHZ; i++) {
+		nol = dfs->dfs_nol;
+		while (nol) {
+			if (nol->nol_freq == (uint16_t)utils_dfs_chan_to_freq(
+				    channels[i])) {
+				OS_SET_TIMER(&nol->nol_timer, 0);
+				break;
+			}
+			nol = nol->nol_next;
+		}
+	}
+	WLAN_DFSNOL_UNLOCK(dfs);
+}
+#endif

+ 3 - 3
umac/dfs/core/src/misc/dfs_process_radar_found_ind.c

@@ -366,9 +366,9 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs,
  *
  * Return: Number of channels.
  */
-static uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
-					uint32_t segment_id,
-					uint8_t *channels)
+uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
+				 uint32_t segment_id,
+				 uint8_t *channels)
 {
 	uint8_t center_chan;
 	uint8_t nchannels = 0;

+ 16 - 0
umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h

@@ -116,4 +116,20 @@ uint32_t lmac_get_target_type(struct wlan_objmgr_pdev *pdev);
 uint32_t lmac_get_phymode_info(struct wlan_objmgr_pdev *pdev,
 		uint32_t chan_mode);
 
+/**
+ * lmac_is_host_dfs_check_support_enabled() - Check if Host DFS confirmation
+ * feature is supported.
+ * @pdev: Pointer to PDEV structure.
+ *
+ * Return: true, host dfs check supported, else false.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+bool lmac_is_host_dfs_check_support_enabled(struct wlan_objmgr_pdev *pdev);
+#else
+static inline bool lmac_is_host_dfs_check_support_enabled(
+		struct wlan_objmgr_pdev *pdev)
+{
+	return false;
+}
+#endif
 #endif /* _WLAN_DFS_LMAC_API_H_ */

+ 35 - 1
umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -221,4 +221,38 @@ int dfs_mlme_get_cac_timeout(struct wlan_objmgr_pdev *pdev,
 		uint8_t dfs_ch_vhtop_ch_freq_seg2,
 		uint64_t dfs_ch_flags);
 
+/**
+ * dfs_mlme_rebuild_chan_list_with_non_dfs_channels() - Rebuild the channel list
+ * with only non DFS channels.
+ * @pdev: Pointer to DFS pdev object.
+ *
+ * return: On success return 1 or 0, else failure.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+int dfs_mlme_rebuild_chan_list_with_non_dfs_channels(
+		struct wlan_objmgr_pdev *pdev);
+#else
+static inline int dfs_mlme_rebuild_chan_list_with_non_dfs_channels(
+		struct wlan_objmgr_pdev *pdev)
+{
+	return 0;
+}
+#endif
+
+/**
+ * dfs_mlme_restart_vaps_with_non_dfs_chan() - Restart vaps with non DFS
+ * channels
+ * @pdev: Pointer to DFS pdev object.
+ * @no_chans_avail: Indicates if no channel is available.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+void dfs_mlme_restart_vaps_with_non_dfs_chan(struct wlan_objmgr_pdev *pdev,
+					     int no_chans_avail);
+#else
+static inline
+void dfs_mlme_restart_vaps_with_non_dfs_chan(struct wlan_objmgr_pdev *pdev,
+					     int no_chans_avail)
+{
+}
+#endif
 #endif /* _WLAN_DFS_MLME_API_H_ */

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

@@ -100,4 +100,22 @@ struct radar_event_info {
 struct dfs_user_config {
 	bool dfs_is_phyerr_filter_offload;
 };
+
+/**
+ * struct dfs_radar_found_params - radar found parameters.
+ * @pri_min: Minimum PRI of detected radar pulse.
+ * @pri_max: Max PRI of detected radar pulse.
+ * @duration_min: Min duration of detected pulse in us.
+ * @duration_max: Max duration of detected pulse in us.
+ * @sidx_min: Min softare index of detected radar pulse.
+ * @sidx_max: Max software index of detected radar pulse.
+ */
+struct dfs_radar_found_params {
+	u_int32_t pri_min;
+	u_int32_t pri_max;
+	u_int32_t duration_min;
+	u_int32_t duration_max;
+	u_int32_t sidx_min;
+	u_int32_t sidx_max;
+};
 #endif

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

@@ -284,4 +284,60 @@ QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev,
  */
 QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev);
 #endif
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+/**
+ * tgt_dfs_send_avg_params_to_fw() - send average radar parameters to fw.
+ * @pdev: Pointer to DFS pdev object.
+ * @params: Pointer to dfs radar average parameters.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+tgt_dfs_send_avg_params_to_fw(struct wlan_objmgr_pdev *pdev,
+			      struct dfs_radar_found_params *params);
+#endif
+
+/**
+ * tgt_dfs_action_on_status_from_fw() - trigger the action to be taken based on
+ * host dfs status received from fw.
+ * @pdev: Pointer to pdev object.
+ * @status: Pointer to the host dfs status received from fw.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS tgt_dfs_action_on_status_from_fw(struct wlan_objmgr_pdev *pdev,
+					    uint32_t *status);
+#else
+static inline
+QDF_STATUS tgt_dfs_action_on_status_from_fw(struct wlan_objmgr_pdev *pdev,
+					    uint32_t *status)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * tgt_dfs_is_radar_enabled() - checks if radar detection is enabled.
+ * @pdev: Pointer to pdev object.
+ * @ignore_dfs: Pointer to check the value. If 1, radar detection is disabled.
+ */
+void tgt_dfs_is_radar_enabled(struct wlan_objmgr_pdev *pdev, int *ignore_dfs);
+
+/**
+ * tgt_dfs_reset_spoof_test() - reset the dfs spoof check variables
+ * @pdev: Pointer to pdev object.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev);
+#else
+static inline
+QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif /* _WLAN_DFS_TGT_API_H_ */

+ 55 - 0
umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h

@@ -52,6 +52,9 @@
  * @mlme_nol_timeout_notification:     NOL timeout notification.
  * @mlme_clist_update:                 Updates the channel list.
  * @mlme_get_cac_timeout:              Gets the CAC timeout.
+ * @mlme_rebuild_chan_list_with_non_dfs_channel: Rebuild channels with non-dfs
+ *                                     channels.
+ * @mlme_restart_vaps_with_non_dfs_chan: Restart vaps with non-dfs channel.
  */
 struct dfs_to_mlme {
 	QDF_STATUS (*pdev_component_obj_attach)(struct wlan_objmgr_pdev *pdev,
@@ -128,6 +131,12 @@ struct dfs_to_mlme {
 			uint8_t c_vhtop_ch_freq_seg2,
 			uint64_t dfs_ch_flags,
 			int *cac_timeout);
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	QDF_STATUS (*mlme_rebuild_chan_list_with_non_dfs_channels)
+			(struct wlan_objmgr_pdev *pdev);
+	QDF_STATUS (*mlme_restart_vaps_with_non_dfs_chan)
+			(struct wlan_objmgr_pdev *pdev, int no_chans_avail);
+#endif
 };
 
 extern struct dfs_to_mlme global_dfs_to_mlme;
@@ -243,4 +252,50 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, int *buff);
 QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc,
 		struct dfs_user_config *req);
 #endif
+
+/**
+ * ucfg_dfs_set_override_status_timeout() - override the value of host dfs
+ * status wait timeout.
+ * @pdev: Pointer to DFS pdev object.
+ * @status_timeout: timeout value.
+ *
+ * Wrapper function for dfs_set_override_status_timeout().
+ * This function called from outside of dfs component.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS ucfg_dfs_set_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+					    int status_timeout);
+#else
+static inline
+QDF_STATUS ucfg_dfs_set_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+					    int status_timeout)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * ucfg_dfs_get_override_status_timeout() - Get the value of host dfs status
+ * wait timeout.
+ * @pdev: Pointer to DFS pdev object.
+ * @status_timeout: Pointer to save the timeout value.
+ *
+ * Wrapper function for dfs_get_override_status_timeout().
+ * This function called from outside of dfs component.
+ *
+ * Return: QDF_STATUS
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS ucfg_dfs_get_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+						int *status_timeout);
+#else
+static inline
+QDF_STATUS ucfg_dfs_get_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+						int *status_timeout)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif /* _WLAN_DFS_UCFG_API_H_ */

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

@@ -452,4 +452,22 @@ int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev);
  */
 uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev);
 
+/**
+ * utils_dfs_is_spoof_check_failed() - get spoof check status.
+ * @pdev: pdev ptr
+ * @is_spoof_check_failed: pointer containing the status.
+ *
+ * Return: QDF_STATUS.
+ */
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev,
+					   bool *is_spoof_check_failed);
+#else
+static inline
+QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev,
+					   bool *is_spoof_check_failed)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif /* _WLAN_DFS_UTILS_API_H_ */

+ 4 - 0
umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c

@@ -80,6 +80,10 @@ void register_dfs_callbacks(void)
 		mlme_dfs_nol_timeout_notification;
 	tmp_dfs_to_mlme->mlme_clist_update = mlme_dfs_clist_update;
 	tmp_dfs_to_mlme->mlme_get_cac_timeout = mlme_dfs_get_cac_timeout;
+	tmp_dfs_to_mlme->mlme_rebuild_chan_list_with_non_dfs_channels =
+		mlme_dfs_rebuild_chan_list_with_non_dfs_channels;
+	tmp_dfs_to_mlme->mlme_restart_vaps_with_non_dfs_chan =
+		mlme_dfs_restart_vaps_with_non_dfs_chan;
 }
 #else
 void register_dfs_callbacks(void)

+ 17 - 0
umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c

@@ -209,3 +209,20 @@ uint32_t lmac_get_phymode_info(struct wlan_objmgr_pdev *pdev,
 
 	return mode_info;
 }
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+bool lmac_is_host_dfs_check_support_enabled(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
+	bool enabled = false;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	dfs_tx_ops = &psoc->soc_cb.tx_ops.dfs_tx_ops;
+
+	if (dfs_tx_ops->dfs_host_dfs_check_support)
+		dfs_tx_ops->dfs_host_dfs_check_support(pdev, &enabled);
+
+	return enabled;
+}
+#endif

+ 22 - 0
umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c

@@ -295,3 +295,25 @@ int dfs_mlme_get_cac_timeout(struct wlan_objmgr_pdev *pdev,
 
 	return cac_timeout;
 }
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+int dfs_mlme_rebuild_chan_list_with_non_dfs_channels(
+		struct wlan_objmgr_pdev *pdev)
+{
+	if (!global_dfs_to_mlme.mlme_rebuild_chan_list_with_non_dfs_channels)
+		return 1;
+
+	return global_dfs_to_mlme.mlme_rebuild_chan_list_with_non_dfs_channels(
+			pdev);
+}
+
+void dfs_mlme_restart_vaps_with_non_dfs_chan(struct wlan_objmgr_pdev *pdev,
+					     int no_chans_avail)
+{
+	if (!global_dfs_to_mlme.mlme_restart_vaps_with_non_dfs_chan)
+		return;
+
+	global_dfs_to_mlme.mlme_restart_vaps_with_non_dfs_chan(pdev,
+							       no_chans_avail);
+}
+#endif

+ 91 - 0
umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c

@@ -30,6 +30,7 @@
 #include "../../core/src/dfs_zero_cac.h"
 #include "../../core/src/dfs_process_radar_found_ind.h"
 #include <qdf_module.h>
+#include "../../core/src/dfs_partial_offload_radar.h"
 
 struct wlan_lmac_if_dfs_tx_ops *
 wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc)
@@ -106,6 +107,21 @@ QDF_STATUS tgt_dfs_radar_enable(struct wlan_objmgr_pdev *pdev,
 }
 qdf_export_symbol(tgt_dfs_radar_enable);
 
+void tgt_dfs_is_radar_enabled(struct wlan_objmgr_pdev *pdev, int *ignore_dfs)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return;
+	}
+
+	dfs_is_radar_enabled(dfs, ignore_dfs);
+}
+
+qdf_export_symbol(tgt_dfs_is_radar_enabled);
+
 QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev,
 				  void *buf,
 				  uint16_t datalen,
@@ -446,3 +462,78 @@ QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev)
 }
 qdf_export_symbol(tgt_dfs_set_phyerr_filter_offload);
 #endif
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS
+tgt_dfs_send_avg_params_to_fw(struct wlan_objmgr_pdev *pdev,
+			      struct dfs_radar_found_params *params)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
+	struct wlan_dfs *dfs;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return  status;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null");
+		return status;
+	}
+
+	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
+	if (dfs_tx_ops && dfs_tx_ops->dfs_send_avg_radar_params_to_fw)
+		status = dfs_tx_ops->dfs_send_avg_radar_params_to_fw(pdev,
+			params);
+
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		dfs->dfs_average_params_sent = 1;
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "Average radar parameters sent %d",
+			 dfs->dfs_average_params_sent);
+	}
+
+	return status;
+}
+
+qdf_export_symbol(tgt_dfs_send_avg_params_to_fw);
+
+QDF_STATUS tgt_dfs_action_on_status_from_fw(struct wlan_objmgr_pdev *pdev,
+					    uint32_t *status)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return  QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_action_on_fw_radar_status_check(dfs, status);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(tgt_dfs_action_on_status_from_fw);
+
+QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
+		return  QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_reset_spoof_test(dfs);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(tgt_dfs_reset_spoof_test);
+#endif

+ 45 - 2
umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c

@@ -25,6 +25,7 @@
 #include "wlan_dfs_ucfg_api.h"
 #include "../../core/src/dfs.h"
 #include "../../core/src/dfs_zero_cac.h"
+#include "../../core/src/dfs_partial_offload_radar.h"
 #include <qdf_module.h>
 
 QDF_STATUS ucfg_dfs_is_ap_cac_timer_running(struct wlan_objmgr_pdev *pdev,
@@ -125,8 +126,10 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev,
 	struct wlan_dfs *dfs;
 
 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
 		return  QDF_STATUS_E_FAILURE;
+	}
 
 	dfs_set_precac_enable(dfs, value);
 
@@ -140,8 +143,10 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev,
 	struct wlan_dfs *dfs;
 
 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
-	if (!dfs)
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
 		return  QDF_STATUS_E_FAILURE;
+	}
 
 	*buff = dfs_get_precac_enable(dfs);
 
@@ -176,3 +181,41 @@ QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc,
 }
 qdf_export_symbol(ucfg_dfs_update_config);
 #endif
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS ucfg_dfs_set_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+					    int status_timeout)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
+		return  QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_set_override_status_timeout(dfs, status_timeout);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_set_override_status_timeout);
+
+QDF_STATUS ucfg_dfs_get_override_status_timeout(struct wlan_objmgr_pdev *pdev,
+						int *status_timeout)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
+		return  QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_get_override_status_timeout(dfs, status_timeout);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_get_override_status_timeout);
+#endif

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

@@ -889,3 +889,23 @@ uint16_t utils_dfs_get_cur_rd(struct wlan_objmgr_pdev *pdev)
 
 	return cur_regdmn.regdmn_pair_id;
 }
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS utils_dfs_is_spoof_check_failed(struct wlan_objmgr_pdev *pdev,
+					   bool *is_spoof_check_failed)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "null dfs");
+		return  QDF_STATUS_E_FAILURE;
+	}
+
+	*is_spoof_check_failed = dfs->dfs_spoof_check_failed;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(utils_dfs_is_spoof_check_failed);
+#endif

+ 44 - 16
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -573,6 +573,9 @@ struct wlan_lmac_if_reg_tx_ops {
  * @dfs_is_pdev_5ghz:                   Check if the given pdev is 5GHz.
  * @dfs_set_phyerr_filter_offload:      Config phyerr filter offload.
  * @dfs_send_offload_enable_cmd:        Send dfs offload enable command to fw.
+ * @dfs_host_dfs_check_support:         To check Host DFS confirmation feature
+ *                                      support.
+ * @dfs_send_avg_radar_params_to_fw:    Send average radar parameters to FW.
  */
 
 struct wlan_lmac_if_dfs_tx_ops {
@@ -616,6 +619,11 @@ struct wlan_lmac_if_dfs_tx_ops {
 	QDF_STATUS (*dfs_send_offload_enable_cmd)(
 			struct wlan_objmgr_pdev *pdev,
 			bool enable);
+	QDF_STATUS (*dfs_host_dfs_check_support)(struct wlan_objmgr_pdev *pdev,
+						 bool *enabled);
+	QDF_STATUS (*dfs_send_avg_radar_params_to_fw)(
+			struct wlan_objmgr_pdev *pdev,
+			struct dfs_radar_found_params *params);
 };
 
 /**
@@ -1023,6 +1031,7 @@ struct wlan_lmac_if_nan_rx_ops {
  * @dfs_process_phyerr:               Process phyerr.
  * @dfs_destroy_object:               Destroys the DFS object.
  * @dfs_radar_enable:                 Enables the radar.
+ * @dfs_is_radar_enabled:             Check if the radar is enabled.
  * @dfs_control:                      Used to process ioctls related to DFS.
  * @dfs_is_precac_timer_running:      Check whether precac timer is running.
  * @dfs_find_vht80_chan_for_precac:   Find VHT80 channel for precac.
@@ -1037,6 +1046,13 @@ struct wlan_lmac_if_nan_rx_ops {
  * @dfs_stop:                         Clear dfs timers.
  * @dfs_process_phyerr_filter_offload:Process radar event.
  * @dfs_is_phyerr_filter_offload:     Check whether phyerr filter is offload.
+ * @dfs_action_on_status:             Trigger the action to be taken based on
+ *                                    on host dfs status received from fw.
+ * @dfs_override_status_timeout:      Override the value of host dfs status
+ *                                    wait timeout.
+ * @dfs_get_override_status_timeout:  Get the value of host dfs status wait
+ *                                    timeout.
+ * @dfs_reset_spoof_test:             Checks if radar detection is enabled.
  */
 struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev);
@@ -1051,24 +1067,27 @@ struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_radar_enable)(struct wlan_objmgr_pdev *pdev,
 			int no_cac,
 			uint32_t opmode);
+	void (*dfs_is_radar_enabled)(struct wlan_objmgr_pdev *pdev,
+				     int *ignore_dfs);
 	QDF_STATUS (*dfs_control)(struct wlan_objmgr_pdev *pdev,
-			u_int id,
-			void *indata,
-			uint32_t insize,
-			void *outdata,
-			uint32_t *outsize,
-			int *error);
+				  u_int id,
+				  void *indata,
+				  uint32_t insize,
+				  void *outdata,
+				  uint32_t *outsize,
+				  int *error);
 	QDF_STATUS (*dfs_is_precac_timer_running)(struct wlan_objmgr_pdev *pdev,
-			bool *is_precac_timer_running);
-	QDF_STATUS (*dfs_find_vht80_chan_for_precac)(
-			struct wlan_objmgr_pdev *pdev,
-			uint32_t chan_mode,
-			uint8_t ch_freq_seg1,
-			uint32_t *cfreq1,
-			uint32_t *cfreq2,
-			uint32_t *phy_mode,
-			bool *dfs_set_cfreq2,
-			bool *set_agile);
+						  bool *is_precac_timer_running
+						  );
+	QDF_STATUS
+	    (*dfs_find_vht80_chan_for_precac)(struct wlan_objmgr_pdev *pdev,
+					      uint32_t chan_mode,
+					      uint8_t ch_freq_seg1,
+					      uint32_t *cfreq1,
+					      uint32_t *cfreq2,
+					      uint32_t *phy_mode,
+					      bool *dfs_set_cfreq2,
+					      bool *set_agile);
 	QDF_STATUS (*dfs_cancel_precac_timer)(struct wlan_objmgr_pdev *pdev);
 	QDF_STATUS (*dfs_override_precac_timeout)(
 			struct wlan_objmgr_pdev *pdev,
@@ -1100,6 +1119,15 @@ struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_is_phyerr_filter_offload)(
 			struct wlan_objmgr_psoc *psoc,
 			bool *is_phyerr_filter_offload);
+	QDF_STATUS (*dfs_action_on_status)(struct wlan_objmgr_pdev *pdev,
+			u_int32_t *dfs_status_check);
+	QDF_STATUS (*dfs_override_status_timeout)(
+			struct wlan_objmgr_pdev *pdev,
+			int status_timeout);
+	QDF_STATUS (*dfs_get_override_status_timeout)(
+			struct wlan_objmgr_pdev *pdev,
+			int *status_timeout);
+	QDF_STATUS (*dfs_reset_spoof_test)(struct wlan_objmgr_pdev *pdev);
 };
 
 struct wlan_lmac_if_mlme_rx_ops {

+ 8 - 0
umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c

@@ -312,6 +312,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 	dfs_rx_ops->dfs_process_phyerr = tgt_dfs_process_phyerr;
 	dfs_rx_ops->dfs_destroy_object = tgt_dfs_destroy_object;
 	dfs_rx_ops->dfs_radar_enable = tgt_dfs_radar_enable;
+	dfs_rx_ops->dfs_is_radar_enabled = tgt_dfs_is_radar_enabled;
 	dfs_rx_ops->dfs_control = tgt_dfs_control;
 	dfs_rx_ops->dfs_is_precac_timer_running =
 		tgt_dfs_is_precac_timer_running;
@@ -332,6 +333,13 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 		tgt_dfs_process_phyerr_filter_offload;
 	dfs_rx_ops->dfs_is_phyerr_filter_offload =
 		tgt_dfs_is_phyerr_filter_offload;
+	dfs_rx_ops->dfs_action_on_status = tgt_dfs_action_on_status_from_fw;
+	dfs_rx_ops->dfs_override_status_timeout =
+		ucfg_dfs_set_override_status_timeout;
+	dfs_rx_ops->dfs_get_override_status_timeout =
+		ucfg_dfs_get_override_status_timeout;
+	dfs_rx_ops->dfs_reset_spoof_test =
+		tgt_dfs_reset_spoof_test;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 27 - 0
wmi/inc/wmi_unified_api.h

@@ -2260,4 +2260,31 @@ QDF_STATUS wmi_extract_cca_stats(wmi_unified_t wmi_handle, void *evt_buf,
 				 struct wmi_host_congestion_stats *stats);
 #endif /* QCA_SUPPORT_CP_STATS */
 
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+/**
+ * wmi_unified_dfs_send_avg_params_cmd() - send average radar parameters cmd.
+ * @wmi_hdl: wmi handle
+ * @params: radar found params
+ *
+ * This function passes the average radar parameters to fw
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_unified_dfs_send_avg_params_cmd(void *wmi_hdl,
+				    struct dfs_radar_found_params *params);
+
+/**
+ * wmi_extract_dfs_status_from_fw() - extract host dfs status from fw.
+ * @wmi_hdl: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @dfs_status_check: pointer to the host dfs status
+ *
+ * This function extracts the result of host dfs from fw
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS wmi_extract_dfs_status_from_fw(void *wmi_hdl, void *evt_buf,
+					  uint32_t  *dfs_status_check);
+#endif
 #endif /* _WMI_UNIFIED_API_H_ */

+ 5 - 0
wmi/inc/wmi_unified_param.h

@@ -432,6 +432,7 @@ typedef enum {
 typedef enum {
 	WMI_HOST_VDEV_START_OK = 0,
 	WMI_HOST_VDEV_START_CHAN_INVALID,
+	WMI_HOST_VDEV_START_CHAN_BLOCKED,
 } WMI_HOST_VDEV_START_STATUS;
 
 /*
@@ -5519,6 +5520,9 @@ typedef enum {
 	wmi_host_swfda_event_id,
 	wmi_sar_get_limits_event_id,
 	wmi_pdev_div_rssi_antid_event_id,
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	wmi_host_dfs_status_check_event_id,
+#endif
 
 	wmi_events_max,
 } wmi_conv_event_id;
@@ -5944,6 +5948,7 @@ typedef enum {
 	wmi_service_ap_obss_detection_offload,
 	wmi_service_bss_color_offload,
 	wmi_service_gmac_offload_support,
+	wmi_service_host_dfs_check_support,
 
 	wmi_services_max,
 } wmi_conv_service_ids;

+ 10 - 0
wmi/inc/wmi_unified_priv.h

@@ -1616,6 +1616,16 @@ QDF_STATUS (*extract_twt_resume_dialog_comp_event)(wmi_unified_t wmi_handle,
 QDF_STATUS (*extract_cca_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 				struct wmi_host_congestion_stats *stats);
 #endif /* QCA_SUPPORT_CP_STATS */
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS (*send_dfs_average_radar_params_cmd)(
+		wmi_unified_t wmi_handle,
+		struct dfs_radar_found_params *params);
+
+QDF_STATUS (*extract_dfs_status_from_fw)(wmi_unified_t wmi_handle,
+					 void *evt_buf,
+					 uint32_t *dfs_status_check);
+#endif
 };
 
 /* Forward declartion for psoc*/

+ 27 - 0
wmi/src/wmi_unified_api.c

@@ -7507,3 +7507,30 @@ QDF_STATUS wmi_extract_cca_stats(wmi_unified_t wmi_handle, void *evt_buf,
 	return QDF_STATUS_E_FAILURE;
 }
 #endif /* QCA_SUPPORT_CP_STATS */
+
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+QDF_STATUS
+wmi_unified_dfs_send_avg_params_cmd(void *wmi_hdl,
+				    struct dfs_radar_found_params *params)
+{
+	wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl;
+
+	if (wmi_handle->ops->send_dfs_average_radar_params_cmd)
+		return wmi_handle->ops->send_dfs_average_radar_params_cmd(
+			wmi_handle, params);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS wmi_extract_dfs_status_from_fw(void *wmi_hdl, void *evt_buf,
+					  uint32_t *dfs_status_check)
+{
+	wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl;
+
+	if (wmi_handle->ops->extract_dfs_status_from_fw)
+		return wmi_handle->ops->extract_dfs_status_from_fw(wmi_handle,
+				evt_buf, dfs_status_check);
+
+	return QDF_STATUS_E_FAILURE;
+}
+#endif

+ 88 - 0
wmi/src/wmi_unified_non_tlv.c

@@ -8413,6 +8413,83 @@ QDF_STATUS send_wds_entry_list_cmd_non_tlv(wmi_unified_t wmi_handle)
 	return QDF_STATUS_SUCCESS;
 }
 
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+/**
+ * send_dfs_average_radar_params_cmd_non_tlv() - send average radar params to
+ * fw.
+ * @wmi_handle: wmi handle
+ * @params: pointer to dfs_radar_found_params.
+ *
+ * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
+ */
+static QDF_STATUS send_dfs_average_radar_params_cmd_non_tlv(
+		wmi_unified_t wmi_handle,
+		struct dfs_radar_found_params *params)
+{
+	wmi_host_dfs_radar_found_cmd *cmd;
+	wmi_buf_t buf;
+
+	int len = sizeof(wmi_host_dfs_radar_found_cmd);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		WMI_LOGD("%s:wmi_buf_alloc failed\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cmd = (wmi_host_dfs_radar_found_cmd *)wmi_buf_data(buf);
+
+	/* Fill the WMI structure (PRI, duration, SIDX) from
+	 * the radar_found_param structure and then send
+	 * out.
+	 */
+	cmd->pri_min_value = params->pri_min;
+	cmd->pri_max_value = params->pri_max;
+	cmd->duration_min_value = params->duration_min;
+	cmd->duration_max_value = params->duration_max;
+	cmd->sidx_min_value = params->sidx_min;
+	cmd->sidx_max_value = params->sidx_max;
+
+	if (wmi_unified_cmd_send(wmi_handle, buf, len,
+				WMI_HOST_DFS_RADAR_FOUND_CMDID)) {
+		WMI_LOGD("%s:Failed to send WMI command\n", __func__);
+		wmi_buf_free(buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * extract_dfs_status_from_fw_non_tlv() - extract the result of host dfs check
+ * from fw
+ * @wmi_handle: wmi handle
+ * @evt_buf:  pointer to event buffer
+ * @fw_dfs_status_code: pointer to the status received from fw.
+ *
+ * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
+ */
+static QDF_STATUS
+extract_dfs_status_from_fw_non_tlv(wmi_unified_t wmi_handle,
+				   void *evt_buf,
+				   uint32_t *fw_dfs_status_code)
+{
+	wmi_host_dfs_status_check_event *ev =
+		(wmi_host_dfs_status_check_event *)evt_buf;
+
+	if ((ev->status == WMI_HOST_DFS_CHECK_PASSED) ||
+			(ev->status == WMI_HOST_DFS_CHECK_FAILED) ||
+			(ev->status == WMI_HOST_DFS_CHECK_HW_RADAR)) {
+		*fw_dfs_status_code = ev->status;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	WMI_LOGD("%s..Invalid status code : %d received\n", __func__,
+		 ev->status);
+
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
 
 /**
  * wmi_non_tlv_pdev_id_conversion_enable() - Enable pdev_id conversion
@@ -8659,6 +8736,11 @@ struct wmi_ops non_tlv_ops =  {
 	.extract_swfda_vdev_id = extract_swfda_vdev_id_non_tlv,
 #endif /* WLAN_SUPPORT_FILS */
 	.wmi_pdev_id_conversion_enable = wmi_non_tlv_pdev_id_conversion_enable,
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	.send_dfs_average_radar_params_cmd =
+		send_dfs_average_radar_params_cmd_non_tlv,
+	.extract_dfs_status_from_fw = extract_dfs_status_from_fw_non_tlv,
+#endif
 };
 
 /**
@@ -8852,6 +8934,8 @@ static void populate_non_tlv_service(uint32_t *wmi_service)
 	wmi_service[wmi_service_widebw_scan] = WMI_SERVICE_UNAVAILABLE;
 	wmi_service[wmi_service_support_dma] =
 				WMI_SERVICE_UNAVAILABLE;
+	wmi_service[wmi_service_host_dfs_check_support] =
+		WMI_SERVICE_HOST_DFS_CHECK_SUPPORT;
 }
 
 /**
@@ -8951,6 +9035,10 @@ static void populate_non_tlv_events_id(uint32_t *event_ids)
 	event_ids[wmi_pdev_wds_entry_list_event_id] =
 					WMI_PDEV_WDS_ENTRY_LIST_EVENTID;
 	event_ids[wmi_host_swfda_event_id] = WMI_HOST_SWFDA_EVENTID;
+#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
+	event_ids[wmi_host_dfs_status_check_event_id] =
+		WMI_HOST_DFS_STATUS_CHECK_EVENTID;
+#endif
 }
 
 /**