Procházet zdrojové kódy

qcacmn: Restore WMI_DFS_RADAR_EVENTID for Rome FW

Currently WMI handler for WMI_PHYERR_EVENTID is used to handle DFS and
spectral scan phy errors; but Rome FW still uses WMI_PHYERR_EVENTID
and WMI_DFS_RADAR_EVENTID and does not have spectral scan phy errors.

Restore WMI_PHYERR_EVENTID and WMI_DFS_RADAR_EVENTID as Rome FW
requirement.

Change-Id: I16761f6da947619a5969ac8dcd09498d508ad715
CRs-Fixed: 2160954
bings před 7 roky
rodič
revize
9c524f5fc4

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

@@ -1011,6 +1011,23 @@ struct wlan_dfs {
 	qdf_spinlock_t dfs_nol_lock;
 };
 
+/**
+ * struct dfs_soc_priv_obj - dfs private data
+ * @psoc: pointer to PSOC object information
+ * @pdev: pointer to PDEV object information
+ * @dfs_is_phyerr_filter_offload: For some chip like Rome indicates too many
+ *                                phyerr packets in a short time, which causes
+ *                                OS hang. If this feild is configured as true,
+ *                                FW will do the pre-check, filter out some
+ *                                kinds of invalid phyerrors and indicate
+ *                                radar detection related information to host.
+ */
+struct dfs_soc_priv_obj {
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_pdev *pdev;
+	bool dfs_is_phyerr_filter_offload;
+};
+
 /**
  * enum DFS debug - This should match the table from if_ath.c.
  * @WLAN_DEBUG_DFS:             Minimal DFS debug.
@@ -1590,6 +1607,18 @@ void dfs_process_phyerr(struct wlan_dfs *dfs,
 		uint32_t r_rs_tstamp,
 		uint64_t r_fulltsf);
 
+#ifdef QCA_MCL_DFS_SUPPORT
+/**
+ * dfs_process_phyerr_filter_offload() - Process radar event.
+ * @dfs: Pointer to wlan_dfs structure.
+ * @wlan_radar_event: Pointer to radar_event_info structure.
+ *
+ * Return: None
+ */
+void dfs_process_phyerr_filter_offload(struct wlan_dfs *dfs,
+		struct radar_event_info *wlan_radar_event);
+#endif
+
 /**
  * dfs_is_precac_timer_running() - Check whether precac timer is running.
  * @dfs: Pointer to wlan_dfs structure.
@@ -2118,4 +2147,12 @@ wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc);
  * @dfs: Pointer to wlan_dfs structure.
  */
 void dfs_nol_free_list(struct wlan_dfs *dfs);
+
+/**
+ * dfs_set_phyerr_filter_offload - config phyerr filter offload.
+ * @dfs: Pointer to wlan_dfs structure.
+ *
+ * Return: None
+ */
+void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs);
 #endif  /* _DFS_H_ */

+ 137 - 1
umac/dfs/core/src/filtering/dfs_process_phyerr.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  * Copyright (c) 2002-2010, Atheros Communications Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -845,3 +845,139 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen,
 #undef PRI_CH_RADAR_FOUND
 #undef EXT_CH_RADAR_EARLY_FOUND
 }
+
+#ifdef QCA_MCL_DFS_SUPPORT
+void dfs_process_phyerr_filter_offload(struct wlan_dfs *dfs,
+	struct radar_event_info *wlan_radar_event)
+{
+	struct dfs_event *event;
+	int empty;
+	int do_check_chirp = 0;
+	int is_hw_chirp = 0;
+	int is_sw_chirp = 0;
+	int is_pri = 0;
+
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
+		return;
+	}
+
+	if (dfs->dfs_ignore_dfs) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs");
+		return;
+	}
+
+	if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS1,
+			"DFS_RADAR_EN not set in dfs->dfs_proc_phyerr");
+		return;
+	}
+
+	if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) {
+		dfs_debug(dfs, WLAN_DEBUG_DFS1,
+			"Radar already found in the channel, do not queue radar data");
+		return;
+	}
+
+	dfs->wlan_dfs_stats.total_phy_errors++;
+	if (dfs->dfs_caps.wlan_chip_is_bb_tlv) {
+		do_check_chirp = 1;
+		is_pri = 1;
+		is_hw_chirp = wlan_radar_event->pulse_is_chirp;
+
+		if ((uint32_t) dfs->dfs_phyerr_freq_min >
+		    wlan_radar_event->pulse_center_freq) {
+			dfs->dfs_phyerr_freq_min =
+				(int)wlan_radar_event->pulse_center_freq;
+		}
+
+		if (dfs->dfs_phyerr_freq_max <
+		    (int)wlan_radar_event->pulse_center_freq) {
+			dfs->dfs_phyerr_freq_max =
+				(int)wlan_radar_event->pulse_center_freq;
+		}
+	}
+
+	/*
+	 * Now, add the parsed, checked and filtered
+	 * radar phyerror event radar pulse event list.
+	 * This event will then be processed by
+	 * dfs_radar_processevent() to see if the pattern
+	 * of pulses in radar pulse list match any radar
+	 * singnature in the current regulatory domain.
+	 */
+
+	WLAN_DFSEVENTQ_LOCK(dfs);
+	empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
+	WLAN_DFSEVENTQ_UNLOCK(dfs);
+	if (empty)
+		return;
+	/*
+	 * Add the event to the list, if there's space.
+	 */
+	WLAN_DFSEVENTQ_LOCK(dfs);
+	event = STAILQ_FIRST(&(dfs->dfs_eventq));
+	if (!event) {
+		WLAN_DFSEVENTQ_UNLOCK(dfs);
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			"%s: No more space left for queuing DFS Phyerror events",
+			__func__);
+		return;
+	}
+	STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
+	WLAN_DFSEVENTQ_UNLOCK(dfs);
+	dfs->dfs_phyerr_queued_count++;
+	dfs->dfs_phyerr_w53_counter++;
+	event->re_dur = (uint8_t) wlan_radar_event->pulse_duration;
+	event->re_rssi = wlan_radar_event->rssi;
+	event->re_ts = wlan_radar_event->pulse_detect_ts & DFS_TSMASK;
+	event->re_full_ts = (((uint64_t) wlan_radar_event->upload_fullts_high)
+				<< 32) | wlan_radar_event->upload_fullts_low;
+
+	/*
+	 * Index of peak magnitude
+	 */
+	event->re_sidx = wlan_radar_event->peak_sidx;
+	event->re_delta_diff = 0;
+	event->re_delta_peak = 0;
+	event->re_flags = 0;
+
+	/*
+	 * Handle chirp flags.
+	 */
+	if (do_check_chirp) {
+		event->re_flags |= DFS_EVENT_CHECKCHIRP;
+		if (is_hw_chirp)
+			event->re_flags |= DFS_EVENT_HW_CHIRP;
+		if (is_sw_chirp)
+			event->re_flags |= DFS_EVENT_SW_CHIRP;
+	}
+	/*
+	 * Correctly set which channel is being reported on
+	 */
+	if (is_pri) {
+		event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex;
+	} else {
+		if (dfs->dfs_extchan_radindex == -1)
+			dfs_debug(dfs, WLAN_DEBUG_DFS1,
+				"%s phyerr on ext channel", __func__);
+		event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex;
+		dfs_debug(dfs, WLAN_DEBUG_DFS1,
+			"%s:New extension channel event is added to queue",
+			 __func__);
+	}
+
+	WLAN_DFSQ_LOCK(dfs);
+
+	STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
+
+	empty = STAILQ_EMPTY(&dfs->dfs_radarq);
+
+	WLAN_DFSQ_UNLOCK(dfs);
+
+	if (!empty && !dfs->wlan_radar_tasksched) {
+		dfs->wlan_radar_tasksched = 1;
+		qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
+	}
+}
+#endif

+ 12 - 0
umac/dfs/core/src/misc/dfs.c

@@ -276,6 +276,7 @@ int dfs_main_attach(struct wlan_dfs *dfs)
 	dfs->dfs_phyerr_w53_counter  = 0;
 	dfs->dfs_pri_multiplier      = 2;
 	dfs_get_radars(dfs);
+	dfs_set_phyerr_filter_offload(dfs);
 
 	return 0;
 
@@ -1079,3 +1080,14 @@ void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
 	dfs->dfs_curchan->dfs_ch_flags = flags;
 	dfs->dfs_curchan->dfs_ch_flagext = flagext;
 }
+
+#ifdef QCA_MCL_DFS_SUPPORT
+void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs)
+{
+	tgt_dfs_set_phyerr_filter_offload(dfs->dfs_pdev_obj);
+}
+#else
+void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs)
+{
+}
+#endif

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

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -64,4 +64,38 @@ struct dfs_acs_info {
 	uint8_t start_ch;
 	uint8_t end_ch;
 };
+
+/**
+ * struct radar_event_info - radar event info.
+ * @pulse_is_chirp: flag to indicate if this pulse is chirp.
+ * @pulse_center_freq: the center frequency of the radar pulse detected, KHz.
+ * @pulse_duration: the duaration of the pulse in us.
+ * @rssi: RSSI recorded in the ppdu.
+ * @pulse_detect_ts: timestamp indicates the time when DFS pulse is detected.
+ * @upload_fullts_low: low 32 tsf timestamp get from MAC tsf timer indicates
+ *  the time that the radar event uploading to host.
+ * @upload_fullts_high: high 32 tsf timestamp get from MAC tsf timer indicates
+ *  the time that the radar event uploading to host.
+ * @peak_sidx: index of peak magnitude bin (signed)
+ * @pdev_id: pdev_id for identifying the MAC.
+ */
+struct radar_event_info {
+	uint8_t  pulse_is_chirp;
+	uint32_t pulse_center_freq;
+	uint32_t pulse_duration;
+	uint8_t  rssi;
+	uint32_t pulse_detect_ts;
+	uint32_t upload_fullts_low;
+	uint32_t upload_fullts_high;
+	int32_t  peak_sidx;
+	uint8_t  pdev_id;
+};
+
+/**
+ * struct dfs_user_config - user configuration required for for DFS.
+ * @dfs_is_phyerr_filter_offload: flag to indicate DFS phyerr filtering offload.
+ */
+struct dfs_user_config {
+	bool dfs_is_phyerr_filter_offload;
+};
 #endif

+ 32 - 1
umac/dfs/dispatcher/inc/wlan_dfs_tgt_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
@@ -116,6 +116,28 @@ QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev,
 	uint32_t r_rs_tstamp,
 	uint64_t r_fulltsf);
 
+/**
+ * tgt_dfs_process_phyerr_filter_offload() - Process radar event.
+ * Wrapper function for dfs_process_phyerr_filter_offload(). This function
+ * called from outside of DFS component.
+ * @pdev: Pointer to DFS pdev object.
+ * @wlan_radar_event: pointer to radar_event_info.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
+	struct radar_event_info *wlan_radar_event);
+
+/**
+ * tgt_dfs_is_phyerr_filter_offload() - Is phyerr filter offload.
+ * @pdev: Pointer to DFS pdev object.
+ * @is_phyerr_filter_offload: Pointer to is_phyerr_filter_offload.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
+	bool *is_phyerr_filter_offload);
+
 /**
  * tgt_dfs_destroy_object() - Destroys the DFS object.
  * @pdev: Pointer to DFS pdev object.
@@ -241,4 +263,13 @@ QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev);
 QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev,
 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test);
 
+#ifdef QCA_MCL_DFS_SUPPORT
+/**
+ * tgt_dfs_set_phyerr_filter_offload() - config phyerr filter offload
+ * @pdev: Pointer to DFS pdev object.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev);
+#endif
 #endif /* _WLAN_DFS_TGT_API_H_ */

+ 12 - 1
umac/dfs/dispatcher/inc/wlan_dfs_ucfg_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
@@ -232,4 +232,15 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev,
  */
 QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, int *buff);
 
+#ifdef QCA_MCL_DFS_SUPPORT
+/**
+ * ucfg_dfs_update_config() - Update DFS user config.
+ * @psoc: Pointer to psoc.
+ * @req: DFS user config.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc,
+		struct dfs_user_config *req);
+#endif
 #endif /* _WLAN_DFS_UCFG_API_H_ */

+ 170 - 27
umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c

@@ -94,49 +94,192 @@ void register_dfs_callbacks(void)
 }
 #endif
 
+/**
+ * dfs_psoc_obj_create_notification() - dfs psoc create notification handler
+ * @psoc: psoc object
+ * @arg_list: Argument list
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS dfs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
+					     void *arg_list)
+{
+	QDF_STATUS status;
+	struct dfs_soc_priv_obj *dfs_soc_obj;
+
+	dfs_soc_obj = qdf_mem_malloc(sizeof(*dfs_soc_obj));
+	if (!dfs_soc_obj) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to allocate memory for dfs object");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	dfs_soc_obj->psoc = psoc;
+
+	status = wlan_objmgr_psoc_component_obj_attach(psoc,
+						       WLAN_UMAC_COMP_DFS,
+						       (void *)dfs_soc_obj,
+						       QDF_STATUS_SUCCESS);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to attach psoc dfs component");
+		qdf_mem_free(dfs_soc_obj);
+		return status;
+	}
+
+	dfs_debug(NULL, WLAN_DEBUG_DFS1,
+		"DFS obj attach to psoc successfully");
+
+	return status;
+}
+
+/**
+ * dfs_psoc_obj_destroy_notification() - dfs psoc destroy notification handler
+ * @psoc: psoc object
+ * @arg_list: Argument list
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
+					      void *arg_list)
+{
+	QDF_STATUS status;
+	struct dfs_soc_priv_obj *dfs_soc_obj;
+
+	dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+						WLAN_UMAC_COMP_DFS);
+	if (!dfs_soc_obj) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to get dfs obj in psoc");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_psoc_component_obj_detach(psoc,
+						       WLAN_UMAC_COMP_DFS,
+						       dfs_soc_obj);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to detach psoc dfs component");
+
+	qdf_mem_free(dfs_soc_obj);
+
+	return status;
+}
+
 QDF_STATUS dfs_init(void)
 {
-	QDF_STATUS res;
+	QDF_STATUS status;
+
+	status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_create_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to register psoc create handler for dfs");
+		goto err_psoc_create;
+	}
+
+	status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_destroy_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to register psoc delete handler for dfs");
+		goto err_psoc_delete;
+	}
 
 	register_dfs_callbacks();
 
-	if (wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS,
-				wlan_dfs_pdev_obj_create_notification,
-				NULL)
-			!= QDF_STATUS_SUCCESS) {
-		return QDF_STATUS_E_FAILURE;
+	status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_create_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to register pdev create handler for dfs");
+		goto err_pdev_create;
 	}
-	if (wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
-				wlan_dfs_pdev_obj_destroy_notification,
-				NULL)
-			!= QDF_STATUS_SUCCESS) {
-		return QDF_STATUS_E_FAILURE;
+
+	status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_destroy_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to register pdev delete handler for dfs");
+		goto err_pdev_delete;
 	}
 
-	res = qdf_print_set_category_verbose(qdf_get_pidx(),
+	status = qdf_print_set_category_verbose(qdf_get_pidx(),
 			QDF_MODULE_ID_DFS, QDF_TRACE_LEVEL_INFO, true);
-	if (res) {
-		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "Failed to set verbose for category");
-		return QDF_STATUS_E_FAILURE;
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to set verbose for category");
+		goto err_category_verbose;
 	}
 
 	return QDF_STATUS_SUCCESS;
+
+err_category_verbose:
+	wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_destroy_notification,
+			NULL);
+err_pdev_delete:
+	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_create_notification,
+			NULL);
+err_pdev_create:
+	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_destroy_notification,
+			NULL);
+err_psoc_delete:
+	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_create_notification,
+			NULL);
+err_psoc_create:
+	return status;
 }
 
 QDF_STATUS dfs_deinit(void)
 {
-	if (wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS,
-				wlan_dfs_pdev_obj_create_notification,
-				NULL)
-			!= QDF_STATUS_SUCCESS) {
-		return QDF_STATUS_E_FAILURE;
-	}
-	if (wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
-				wlan_dfs_pdev_obj_destroy_notification,
-				NULL)
-			!= QDF_STATUS_SUCCESS) {
-		return QDF_STATUS_E_FAILURE;
-	}
+	QDF_STATUS status;
+
+	status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_create_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to deregister dfs psoc obj create");
+
+	status = wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS,
+			dfs_psoc_obj_destroy_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to deregister dfs psoc obj destroy");
+
+	status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_create_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to deregister dfs pdev obj create");
+
+	status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS,
+			wlan_dfs_pdev_obj_destroy_notification,
+			NULL);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to deregister dfs pdev obj destroy");
 
 	return QDF_STATUS_SUCCESS;
 }

+ 96 - 1
umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c

@@ -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
@@ -110,6 +110,68 @@ QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev,
 }
 EXPORT_SYMBOL(tgt_dfs_process_phyerr);
 
+#ifdef QCA_MCL_DFS_SUPPORT
+QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
+		struct radar_event_info *wlan_radar_event)
+{
+	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;
+	}
+	if (!dfs->dfs_is_offload_enabled)
+		dfs_process_phyerr_filter_offload(dfs, wlan_radar_event);
+	else
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+				"Received a pulse from firmware even though the DFS is offloaded"
+			);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(tgt_dfs_process_phyerr_filter_offload);
+
+QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
+		bool *is_phyerr_filter_offload)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct dfs_soc_priv_obj *soc_obj;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "psoc is null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+						WLAN_UMAC_COMP_DFS);
+	if (!soc_obj) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to get dfs psoc component");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	*is_phyerr_filter_offload = soc_obj->dfs_is_phyerr_filter_offload;
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(tgt_dfs_is_phyerr_filter_offload);
+#else
+QDF_STATUS tgt_dfs_process_phyerr_filter_offload(
+		struct wlan_objmgr_pdev *pdev,
+		struct radar_event_info *wlan_radar_event)
+{
+	return QDF_STATUS_SUCCESS;
+}
+QDF_STATUS tgt_dfs_is_phyerr_filter_offload(
+		struct wlan_objmgr_pdev *pdev,
+		bool *is_phyerr_filter_offload)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev,
 		bool *is_precac_timer_running)
 {
@@ -313,3 +375,36 @@ QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev,
 	return QDF_STATUS_E_FAILURE;
 }
 EXPORT_SYMBOL(tgt_dfs_process_emulate_bang_radar_cmd);
+
+#ifdef QCA_MCL_DFS_SUPPORT
+QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
+	struct dfs_soc_priv_obj *soc_obj;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "psoc is null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+							WLAN_UMAC_COMP_DFS);
+	if (!soc_obj) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to get dfs psoc component");
+		return QDF_STATUS_E_FAILURE;
+	}
+	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
+	if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload)
+		return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev,
+				soc_obj->dfs_is_phyerr_filter_offload);
+	else
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+				"dfs_tx_ops=%pK", dfs_tx_ops);
+
+	return QDF_STATUS_E_FAILURE;
+}
+EXPORT_SYMBOL(tgt_dfs_set_phyerr_filter_offload);
+#endif

+ 29 - 1
umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c

@@ -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
@@ -147,3 +147,31 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev,
 	return QDF_STATUS_SUCCESS;
 }
 EXPORT_SYMBOL(ucfg_dfs_get_precac_enable);
+
+#ifdef QCA_MCL_DFS_SUPPORT
+QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc,
+		struct dfs_user_config *req)
+{
+	struct dfs_soc_priv_obj *soc_obj;
+
+	if (!psoc || !req) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"psoc: 0x%pK, req: 0x%pK", psoc, req);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+							WLAN_UMAC_COMP_DFS);
+	if (!soc_obj) {
+		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
+			"Failed to get dfs psoc component");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	soc_obj->dfs_is_phyerr_filter_offload =
+			req->dfs_is_phyerr_filter_offload;
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(ucfg_dfs_update_config);
+#endif

+ 12 - 0
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -520,6 +520,7 @@ struct wlan_lmac_if_reg_tx_ops {
  * @dfs_reg_ev_handler:                 Register dfs event handler.
  * @dfs_process_emulate_bang_radar_cmd: Process emulate bang radar test command.
  * @dfs_is_pdev_5ghz:                   Check if the given pdev is 5GHz.
+ * @dfs_set_phyerr_filter_offload:      Config phyerr filter offload.
  */
 
 struct wlan_lmac_if_dfs_tx_ops {
@@ -554,6 +555,9 @@ struct wlan_lmac_if_dfs_tx_ops {
 			struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test);
 	QDF_STATUS (*dfs_is_pdev_5ghz)(struct wlan_objmgr_pdev *pdev,
 			bool *is_5ghz);
+	QDF_STATUS (*dfs_set_phyerr_filter_offload)(
+			struct wlan_objmgr_pdev *pdev,
+			bool dfs_phyerr_filter_offload);
 };
 
 /**
@@ -963,6 +967,8 @@ struct wlan_lmac_if_nan_rx_ops {
  * @dfs_process_radar_ind:            Process radar found indication.
  * @dfs_dfs_cac_complete_ind:         Process cac complete indication.
  * @dfs_stop:                         Clear dfs timers.
+ * @dfs_process_phyerr_filter_offload:Process radar event.
+ * @dfs_is_phyerr_filter_offload:     Check whether phyerr filter is offload.
  */
 struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev);
@@ -1019,6 +1025,12 @@ struct wlan_lmac_if_dfs_rx_ops {
 			uint32_t vdev_id);
 #endif
 	QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev);
+	QDF_STATUS (*dfs_process_phyerr_filter_offload)(
+			struct wlan_objmgr_pdev *pdev,
+			struct radar_event_info *wlan_radar_info);
+	QDF_STATUS (*dfs_is_phyerr_filter_offload)(
+			struct wlan_objmgr_pdev *pdev,
+			bool *is_phyerr_filter_offload);
 };
 
 struct wlan_lmac_if_mlme_rx_ops {

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

@@ -301,6 +301,10 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 	dfs_rx_ops->dfs_process_radar_ind = tgt_dfs_process_radar_ind;
 	dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete;
 	dfs_rx_ops->dfs_stop = tgt_dfs_stop;
+	dfs_rx_ops->dfs_process_phyerr_filter_offload =
+		tgt_dfs_process_phyerr_filter_offload;
+	dfs_rx_ops->dfs_is_phyerr_filter_offload =
+		tgt_dfs_is_phyerr_filter_offload;
 
 	return QDF_STATUS_SUCCESS;
 }