Ver Fonte

qcacmn: Add support to process spectral scan chan info TLV

FW sends Spectral scan chan info TLV in WMI_PDEV_SSCAN_FW_PARAM_EVENTID
event to indicate the channel information for a spectral scan session.
Add support to process the TLV and update the spectral host data structures
accordingly.

CRs-Fixed: 3044162
Change-Id: Ibbf7f6bbbb267123bbdf44bcfffa2cfb1c2926df
Shiva Krishna Pittala há 3 anos atrás
pai
commit
e991ce3cdd

+ 281 - 36
target_if/spectral/target_if_spectral.c

@@ -5508,6 +5508,46 @@ target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral,
 	return QDF_STATUS_SUCCESS;
 }
 
+#define INVALID_SPAN_NUM (-1)
+/**
+ * target_if_spectral_get_num_spans() - Get number of spans for a given sscan_bw
+ * @pdev: Pointer to pdev object
+ * @sscan_bw: Spectral scan bandwidth
+ *
+ * Return: Number of spans on success, INVALID_SPAN_NUM on failure
+ */
+static int
+target_if_spectral_get_num_spans(
+		struct wlan_objmgr_pdev *pdev,
+		enum phy_ch_width sscan_bw)
+{
+	struct wlan_objmgr_psoc *psoc;
+	int num_spans;
+
+	if (!pdev) {
+		spectral_err_rl("pdev is null");
+		return INVALID_SPAN_NUM;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err_rl("psoc is null");
+		return INVALID_SPAN_NUM;
+	}
+
+	if (sscan_bw == CH_WIDTH_80P80MHZ) {
+		num_spans = 2;
+		if (wlan_psoc_nif_fw_ext_cap_get(
+		    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT))
+			/* 5 MHz frequency span in restricted 80p80 case */
+			num_spans += 1;
+	} else {
+		num_spans = 1;
+	}
+
+	return num_spans;
+}
+
 #ifdef OPTIMIZED_SAMP_MESSAGE
 /**
  * target_if_spectral_populate_session_report_info() - Populate per-session
@@ -5524,7 +5564,6 @@ target_if_spectral_populate_session_report_info(
 				enum spectral_scan_mode smode)
 {
 	struct per_session_report_info *rpt_info;
-	struct wlan_objmgr_psoc *psoc;
 
 	if (!spectral) {
 		spectral_err_rl("Spectral LMAC object is null");
@@ -5535,16 +5574,6 @@ target_if_spectral_populate_session_report_info(
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (!spectral->pdev_obj) {
-		spectral_err_rl("Spectral PDEV is null");
-		return QDF_STATUS_E_NULL_VALUE;
-	}
-
-	psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
-	if (!psoc) {
-		spectral_err_rl("psoc is null");
-		return QDF_STATUS_E_NULL_VALUE;
-	}
 
 	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	/* Fill per-session report information, based on the spectral mode */
@@ -5554,15 +5583,12 @@ target_if_spectral_populate_session_report_info(
 	rpt_info->sscan_bw = spectral->ch_width[smode];
 	rpt_info->sscan_cfreq1 = spectral->params[smode].ss_frequency.cfreq1;
 	rpt_info->sscan_cfreq2 = spectral->params[smode].ss_frequency.cfreq2;
-	if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ) {
-		rpt_info->num_spans = 2;
-		if (wlan_psoc_nif_fw_ext_cap_get(
-		    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT))
-			/* 5 MHz frequency span in restricted 80p80 case */
-			rpt_info->num_spans += 1;
-	} else {
-		rpt_info->num_spans = 1;
-	}
+	rpt_info->num_spans = target_if_spectral_get_num_spans(
+						spectral->pdev_obj,
+						rpt_info->sscan_bw);
+
+	qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM);
+	rpt_info->valid = true;
 
 	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 
@@ -5696,6 +5722,45 @@ target_if_spectral_populate_session_detector_info(
 }
 #endif /* OPTIMIZED_SAMP_MESSAGE */
 
+/**
+ * spectral_is_session_info_expected_from_target() - Check if spectral scan
+ * session is expected from target
+ * @pdev: pdev pointer
+ * @is_session_info_expected: Pointer to caller variable
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev *pdev,
+					      bool *is_session_info_expected)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+
+	if (!pdev) {
+		spectral_err("pdev is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		spectral_err("wmi handle is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	*is_session_info_expected = target_if_spectral_wmi_service_enabled(
+				psoc, wmi_handle,
+				wmi_service_spectral_session_info_support);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS
 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
 			      uint8_t vdev_id,
@@ -5707,6 +5772,7 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
 	struct wlan_objmgr_psoc *psoc;
 	enum reg_wifi_band band;
 	QDF_STATUS ret;
+	bool is_session_info_expected;
 
 	if (!err) {
 		spectral_err("Error code argument is null");
@@ -5910,19 +5976,32 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
 		return ret;
 	}
 
-	ret = target_if_spectral_populate_session_report_info(spectral, smode);
+	ret = spectral_is_session_info_expected_from_target(
+				spectral->pdev_obj,
+				&is_session_info_expected);
 	if (QDF_IS_STATUS_ERROR(ret)) {
 		qdf_spin_unlock(&spectral->spectral_lock);
-		spectral_err("Failed to populate per-session report info");
-		return QDF_STATUS_E_FAILURE;
+		spectral_err("Failed to check if session info is expected");
+		return ret;
 	}
 
-	ret = target_if_spectral_populate_session_detector_info(spectral,
-								smode);
-	if (QDF_IS_STATUS_ERROR(ret)) {
-		qdf_spin_unlock(&spectral->spectral_lock);
-		spectral_err("Failed to populate per-session report info");
-		return QDF_STATUS_E_FAILURE;
+	/* If FW doesn't send session info, populate it */
+	if (!is_session_info_expected) {
+		ret = target_if_spectral_populate_session_report_info(spectral,
+								      smode);
+		if (QDF_IS_STATUS_ERROR(ret)) {
+			qdf_spin_unlock(&spectral->spectral_lock);
+			spectral_err("Failed to populate per-session report info");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		ret = target_if_spectral_populate_session_detector_info(
+					spectral, smode);
+		if (QDF_IS_STATUS_ERROR(ret)) {
+			qdf_spin_unlock(&spectral->spectral_lock);
+			spectral_err("Failed to populate per-session detector info");
+			return QDF_STATUS_E_FAILURE;
+		}
 	}
 
 	target_if_spectral_scan_enable_params(spectral,
@@ -5994,6 +6073,11 @@ target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev,
 
 	qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 
+	/* Mark report info as invalid */
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
+	spectral->report_info[smode].valid = false;
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	qdf_spin_unlock(&spectral->spectral_lock);
 
 	return QDF_STATUS_SUCCESS;
@@ -6811,6 +6895,41 @@ target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
 
 	return ops_tgt.tgt_get_psoc_from_scn_hdl(scn);
 }
+
+/**
+ * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
+ * function to extract channel information for a spectral scan session
+ * @psoc: Pointer to psoc object
+ * @evt_buf: Event buffer
+ * @chan_info: Spectral session channel information data structure to be filled
+ * by this API
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_extract_pdev_spectral_session_chan_info(
+			struct wlan_objmgr_psoc *psoc,
+			void *evt_buf,
+			struct spectral_session_chan_info *chan_info)
+{
+	wmi_unified_t wmi_handle;
+	struct target_if_psoc_spectral *psoc_spectral;
+
+	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
+	if (!wmi_handle) {
+		spectral_err("WMI handle is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
+	if (!psoc_spectral) {
+		spectral_err("spectral object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return psoc_spectral->wmi_ops.extract_pdev_spectral_session_chan_info(
+			wmi_handle, evt_buf, chan_info);
+}
 #else
 /**
  * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
@@ -6993,8 +7112,88 @@ target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
 
 	return target_if_get_psoc_from_scn_hdl(scn);
 }
+
+/**
+ * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
+ * function to extract channel information for a spectral scan session
+ * @psoc: Pointer to psoc object
+ * @evt_buf: Event buffer
+ * @chan_info: Spectral session channel information data structure to be fille
+ * by this API
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_extract_pdev_spectral_session_chan_info(
+			struct wlan_objmgr_psoc *psoc,
+			void *evt_buf,
+			struct spectral_session_chan_info *chan_info)
+{
+	wmi_unified_t wmi_handle;
+
+	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
+	if (!wmi_handle) {
+		spectral_err("WMI handle is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return wmi_extract_pdev_spectral_session_chan_info(
+			wmi_handle, evt_buf, chan_info);
+}
 #endif
 
+/**
+ * target_if_update_chan_info_in_spectral_session() - Update channel information
+ * in spectral scan session
+ * @spectral: Spectral LMAC object
+ * @chan_info: Pointer to spectral session channel information
+ * @smode: Spectral scan mode
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_update_chan_info_in_spectral_session(
+	struct target_if_spectral *spectral,
+	const struct spectral_session_chan_info *chan_info,
+	enum spectral_scan_mode smode)
+{
+	struct per_session_report_info *rpt_info;
+
+	if (!spectral) {
+		spectral_err_rl("Spectral LMAC object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (smode >= SPECTRAL_SCAN_MODE_MAX) {
+		spectral_err_rl("Invalid Spectral scan mode :%u", smode);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
+	rpt_info = &spectral->report_info[smode];
+
+	/* Update per-session report info */
+	rpt_info->pri20_freq = chan_info->operating_pri20_freq;
+	rpt_info->cfreq1 = chan_info->operating_cfreq1;
+	rpt_info->cfreq2 = chan_info->operating_cfreq2;
+	rpt_info->operating_bw = chan_info->operating_bw;
+	rpt_info->sscan_cfreq1 = chan_info->sscan_cfreq1;
+	rpt_info->sscan_cfreq2 = chan_info->sscan_cfreq2;
+	rpt_info->sscan_bw = chan_info->sscan_bw;
+
+	/* num_spans depends on sscan_bw, update it */
+	rpt_info->num_spans = target_if_spectral_get_num_spans(
+					spectral->pdev_obj,
+					rpt_info->sscan_bw);
+	qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM);
+
+	rpt_info->valid = true;
+
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * target_if_spectral_fw_param_event_handler() - WMI event handler to
  * process start scan response event
@@ -7015,6 +7214,7 @@ target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
 	struct spectral_startscan_resp_params event_params = {0};
 	struct target_if_psoc_spectral *psoc_spectral;
 	struct target_if_spectral *spectral;
+	bool is_session_info_expected;
 
 	if (!scn) {
 		spectral_err("scn handle is null");
@@ -7035,7 +7235,7 @@ target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
 	psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
 	if (!psoc_spectral) {
 		spectral_err("spectral object is null");
-		return QDF_STATUS_E_FAILURE;
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
 	}
 
 	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
@@ -7067,8 +7267,8 @@ target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
 	spectral = get_target_if_spectral_handle_from_pdev(pdev);
 	if (!spectral) {
 		spectral_err("spectral object is null");
-		wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
-		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+		status = QDF_STATUS_E_FAILURE;
+		goto release_pdev_ref;
 	}
 
 	if (event_params.num_fft_bin_index == 1) {
@@ -7078,16 +7278,61 @@ target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
 				&spectral->rparams.marker[event_params.smode]);
 		if (QDF_IS_STATUS_ERROR(status)) {
 			spectral_err("unable to extract sscan fw fixed params");
-			wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
-			return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+			goto release_pdev_ref;
 		}
 	} else {
 		spectral->rparams.marker[event_params.smode].is_valid = false;
 	}
 
-	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
+	status = spectral_is_session_info_expected_from_target(
+					pdev, &is_session_info_expected);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		spectral_err("Failed to check if session info is expected");
+		goto release_pdev_ref;
+	}
 
-	return qdf_status_to_os_return(QDF_STATUS_SUCCESS);
+	if (is_session_info_expected) {
+		struct spectral_session_chan_info chan_info;
+
+		status = target_if_extract_pdev_spectral_session_chan_info(
+				psoc, data_buf, &chan_info);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			spectral_err("Unable to extract spectral session channel info");
+			goto release_pdev_ref;
+		}
+
+		status = target_if_update_chan_info_in_spectral_session(
+				spectral, &chan_info, event_params.smode);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			spectral_err("Unable to update channel info");
+			goto release_pdev_ref;
+		}
+
+		/* FFT bins depend upon chan info, so update them */
+		status = target_if_populate_fft_bins_info(spectral,
+							  event_params.smode);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			spectral_err("Failed to populate FFT bins info");
+			goto release_pdev_ref;
+		}
+
+		/**
+		 * per-session det info that depends on sscan_bw needs to be
+		 * updated here
+		 */
+		status = target_if_spectral_populate_session_detector_info(
+					spectral, event_params.smode);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			spectral_err("Failed to populate per-session det info");
+			goto release_pdev_ref;
+		}
+	}
+
+	status = QDF_STATUS_SUCCESS;
+
+release_pdev_ref:
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
+	return qdf_status_to_os_return(status);
 }
 
 static QDF_STATUS

+ 30 - 0
target_if/spectral/target_if_spectral.h

@@ -934,6 +934,8 @@ struct vdev_spectral_enable_params;
  * @wmi_unified_register_event_handler: Register WMI event handler
  * @wmi_unified_unregister_event_handler: Unregister WMI event handler
  * @wmi_service_enabled: API to check whether a given WMI service is enabled
+ * @extract_pdev_spectral_session_chan_info: Extract Spectral scan session
+ * channel information
  */
 struct spectral_wmi_ops {
 	QDF_STATUS (*wmi_spectral_configure_cmd_send)(
@@ -960,6 +962,9 @@ struct spectral_wmi_ops {
 				wmi_conv_event_id event_id);
 	bool (*wmi_service_enabled)(wmi_unified_t wmi_handle,
 				    uint32_t service_id);
+	QDF_STATUS (*extract_pdev_spectral_session_chan_info)(
+			wmi_unified_t wmi_handle, void *event,
+			struct spectral_session_chan_info *chan_info);
 };
 
 /**
@@ -1065,6 +1070,7 @@ struct per_session_det_map {
  * @sscan_bw: Normal/Agile Scan BW based on Spectral scan mode.
  * Valid values = enum phy_ch_width
  * @num_spans: Number of frequency spans
+ * @valid: Indicated whether report info is valid
  */
 struct per_session_report_info {
 	uint32_t pri20_freq;
@@ -1075,6 +1081,7 @@ struct per_session_report_info {
 	uint32_t sscan_cfreq2;
 	enum phy_ch_width sscan_bw;
 	uint8_t num_spans;
+	bool valid;
 };
 
 /**
@@ -2840,6 +2847,29 @@ QDF_STATUS target_if_byte_swap_spectral_fft_bins_gen3(
 	void *bin_pwr_data, size_t pwr_count);
 #endif /* BIG_ENDIAN_HOST */
 
+#ifdef OPTIMIZED_SAMP_MESSAGE
+/**
+ * target_if_populate_fft_bins_info() - Populate the start and end bin
+ * indices, on per-detector level.
+ * @spectral: Pointer to target_if spectral internal structure
+ * @smode: Spectral scan mode
+ *
+ * Populate the start and end bin indices, on per-detector level.
+ *
+ * Return: Success/Failure
+ */
+QDF_STATUS
+target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
+				 enum spectral_scan_mode smode);
+#else
+static inline QDF_STATUS
+target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
+				 enum spectral_scan_mode smode)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 #ifdef WIN32
 #pragma pack(pop, target_if_spectral)
 #endif

+ 8 - 0
target_if/spectral/target_if_spectral_netlink.c

@@ -227,6 +227,14 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 		qdf_spin_lock_bh(&spectral->session_report_info_lock);
 
 		rpt_info = &spectral->report_info[spectral_mode];
+
+		if (!rpt_info->valid) {
+			qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+			qdf_spin_unlock_bh(&spectral->session_det_map_lock);
+			spectral_info("per-session report info is not valid");
+			return QDF_STATUS_E_FAILURE;
+		}
+
 		spec_samp_msg->signature = SPECTRAL_SIGNATURE;
 		p_sops->get_mac_address(spectral, spec_samp_msg->macaddr);
 		spec_samp_msg->spectral_mode = spectral_mode;

+ 1 - 11
target_if/spectral/target_if_spectral_phyerr.c

@@ -1034,17 +1034,7 @@ target_if_populate_det_start_end_freqs(struct target_if_spectral *spectral,
 	return QDF_STATUS_SUCCESS;
 }
 
-/**
- * target_if_populate_fft_bins_info() - Populate the start and end bin
- * indices, on per-detector level.
- * @spectral: Pointer to target_if spectral internal structure
- * @smode: Spectral scan mode
- *
- * Populate the start and end bin indices, on per-detector level.
- *
- * Return: Success/Failure
- */
-static QDF_STATUS
+QDF_STATUS
 target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
 				 enum spectral_scan_mode smode)
 {

+ 14 - 0
wmi/inc/wmi_unified_api.h

@@ -2208,6 +2208,20 @@ QDF_STATUS wmi_extract_pdev_sscan_fft_bin_index(
 			wmi_unified_t wmi_handle,
 			uint8_t *evt_buf,
 			struct spectral_fft_bin_markers_160_165mhz *param);
+
+/**
+ * wmi_extract_pdev_spectral_session_chan_info() - Extract channel information
+ * for a spectral scan session
+ * @wmi_handle: handle to WMI.
+ * @evt_buf: Event buffer
+ * @chan_info: Spectral session channel information data structure to be filled
+ * by this API
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS wmi_extract_pdev_spectral_session_chan_info(
+			wmi_unified_t wmi_handle, void *event,
+			struct spectral_session_chan_info *chan_info);
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
 #if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ)

+ 37 - 0
wmi/inc/wmi_unified_param.h

@@ -2945,6 +2945,42 @@ struct spectral_startscan_resp_params {
 	enum spectral_scan_mode smode;
 	uint8_t num_fft_bin_index;
 };
+
+/**
+ * struct spectral_session_chan_info - Spectral scan session channel information
+ * @operating_pri20_freq: frequency of primary 20MHz channel (in MHz)
+ * @operating_cfreq1: center frequency 1 of operating channel (in MHz)
+ * @operating_cfreq2: center frequency 2 of operating channel (in MHz).
+ * For contiguous channels, @operating_cfreq1 should be represent the center of
+ * the entire span and @operating_cfreq2 should be 0, whereas for non-contiguous
+ * channels, @operating_cfreq1 should represent the center of primary segment
+ * and @@operating_cfreq2 should represent the center of secondary segment.
+ * @operating_bw: operating bandwidth enumeration
+ * @operating_puncture_20mhz_bitmap: Puncture bitmap of operating channel.
+ * Each bit indicates one 20 MHz punctured channel
+ * @sscan_cfreq1: center frequency 1 (in MHz) of the channel in which spectral
+ * scan is done
+ * @sscan_cfreq2: center frequency 2 (in MHz) of the channel in which spectral
+ * scan is done. For contiguous channels, @sscan_cfreq1 should be represent the
+ * center of the entire span and @sscan_cfreq2 should be 0, whereas for
+ * non-contiguous channels, @sscan_cfreq1 should represent the center of primary
+ * segment and @sscan_cfreq2 should represent the center of secondary segment.
+ * @sscan_bw: bandwidth of the channel in which spectral scan is done
+ * @sscan_puncture_20mhz_bitmap: Puncture bitmap of channel in which spectral
+ * scan is done. Each bit indicates one 20 MHz punctured channel.
+ */
+struct spectral_session_chan_info {
+	qdf_freq_t operating_pri20_freq;
+	qdf_freq_t operating_cfreq1;
+	qdf_freq_t operating_cfreq2;
+	enum phy_ch_width operating_bw;
+	uint16_t operating_puncture_20mhz_bitmap;
+
+	qdf_freq_t sscan_cfreq1;
+	qdf_freq_t sscan_cfreq2;
+	enum phy_ch_width sscan_bw;
+	uint16_t sscan_puncture_20mhz_bitmap;
+};
 #endif
 
 /**
@@ -5210,6 +5246,7 @@ typedef enum {
 	wmi_service_hw_mode_policy_offload_support,
 	wmi_service_mgmt_rx_reo_supported,
 	wmi_service_phy_dma_byte_swap_support,
+	wmi_service_spectral_session_info_support,
 	wmi_services_max,
 } wmi_conv_service_ids;
 #define WMI_SERVICE_UNAVAILABLE 0xFFFF

+ 12 - 0
wmi/inc/wmi_unified_priv.h

@@ -1476,6 +1476,10 @@ QDF_STATUS (*extract_pdev_sscan_fft_bin_index)(
 			wmi_unified_t wmi_handle,
 			uint8_t *evt_buf,
 			struct spectral_fft_bin_markers_160_165mhz *params);
+
+QDF_STATUS (*extract_pdev_spectral_session_chan_info)(
+			wmi_unified_t wmi_handle, void *event,
+			struct spectral_session_chan_info *chan_info);
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
 QDF_STATUS (*send_vdev_spectral_configure_cmd)(wmi_unified_t wmi_handle,
@@ -3303,4 +3307,12 @@ static inline void wmi_mc_cp_stats_attach_tlv(struct wmi_unified *wmi_handle)
 {
 }
 #endif /* QCA_SUPPORT_MC_CP_STATS */
+
+/*
+ * wmi_map_ch_width() - map wmi channel width to host channel width
+ * @wmi_width: wmi channel width
+ *
+ * Return: host channel width, enum phy_ch_width
+ */
+enum phy_ch_width wmi_map_ch_width(A_UINT32 wmi_width);
 #endif

+ 12 - 0
wmi/src/wmi_unified_api.c

@@ -2584,6 +2584,18 @@ QDF_STATUS wmi_extract_pdev_sscan_fft_bin_index(
 
 	return QDF_STATUS_E_FAILURE;
 }
+
+QDF_STATUS wmi_extract_pdev_spectral_session_chan_info(
+			wmi_unified_t wmi_handle, void *event,
+			struct spectral_session_chan_info *chan_info)
+{
+	if (wmi_handle->ops->extract_pdev_spectral_session_chan_info)
+		return wmi_handle->ops->extract_pdev_spectral_session_chan_info(
+				wmi_handle,
+				event, chan_info);
+
+	return QDF_STATUS_E_FAILURE;
+}
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
 QDF_STATUS wmi_extract_spectral_scaling_params_service_ready_ext(

+ 0 - 36
wmi/src/wmi_unified_dcs_tlv.c

@@ -100,42 +100,6 @@ static QDF_STATUS extract_dcs_im_tgt_stats_tlv(
 	return QDF_STATUS_SUCCESS;
 }
 
-#ifdef WLAN_FEATURE_11BE
-#define WLAN_PHY_CH_WIDTH_320MHZ CH_WIDTH_320MHZ
-#else
-#define WLAN_PHY_CH_WIDTH_320MHZ CH_WIDTH_INVALID
-#endif
-
-/*
- * wmi_map_ch_width() - map wmi channel width to host channel width
- * @wmi_width: wmi channel width enum
- *
- * Return: host channel width, enum phy_ch_width
- */
-static inline enum phy_ch_width wmi_map_ch_width(wmi_channel_width wmi_width)
-{
-	switch (wmi_width) {
-	case WMI_CHAN_WIDTH_20:
-		return CH_WIDTH_20MHZ;
-	case WMI_CHAN_WIDTH_40:
-		return CH_WIDTH_40MHZ;
-	case WMI_CHAN_WIDTH_80:
-		return CH_WIDTH_80MHZ;
-	case WMI_CHAN_WIDTH_160:
-		return CH_WIDTH_160MHZ;
-	case WMI_CHAN_WIDTH_80P80:
-		return CH_WIDTH_80P80MHZ;
-	case WMI_CHAN_WIDTH_5:
-		return CH_WIDTH_5MHZ;
-	case WMI_CHAN_WIDTH_10:
-		return CH_WIDTH_10MHZ;
-	case WMI_CHAN_WIDTH_320:
-		return WLAN_PHY_CH_WIDTH_320MHZ;
-	default:
-		return CH_WIDTH_INVALID;
-	}
-}
-
 /*
  * extract_dcs_awgn_info_tlv() - extract DCS AWGN interference from event
  * @wmi_handle: wmi handle

+ 90 - 0
wmi/src/wmi_unified_tlv.c

@@ -6950,6 +6950,35 @@ static QDF_STATUS send_simulation_test_cmd_tlv(wmi_unified_t wmi_handle,
 }
 #endif
 
+#ifdef WLAN_FEATURE_11BE
+#define WLAN_PHY_CH_WIDTH_320MHZ CH_WIDTH_320MHZ
+#else
+#define WLAN_PHY_CH_WIDTH_320MHZ CH_WIDTH_INVALID
+#endif
+enum phy_ch_width wmi_map_ch_width(A_UINT32 wmi_width)
+{
+	switch (wmi_width) {
+	case WMI_CHAN_WIDTH_20:
+		return CH_WIDTH_20MHZ;
+	case WMI_CHAN_WIDTH_40:
+		return CH_WIDTH_40MHZ;
+	case WMI_CHAN_WIDTH_80:
+		return CH_WIDTH_80MHZ;
+	case WMI_CHAN_WIDTH_160:
+		return CH_WIDTH_160MHZ;
+	case WMI_CHAN_WIDTH_80P80:
+		return CH_WIDTH_80P80MHZ;
+	case WMI_CHAN_WIDTH_5:
+		return CH_WIDTH_5MHZ;
+	case WMI_CHAN_WIDTH_10:
+		return CH_WIDTH_10MHZ;
+	case WMI_CHAN_WIDTH_320:
+		return WLAN_PHY_CH_WIDTH_320MHZ;
+	default:
+		return CH_WIDTH_INVALID;
+	}
+}
+
 /**
  * send_vdev_spectral_configure_cmd_tlv() - send VDEV spectral configure
  * command to fw
@@ -7182,6 +7211,61 @@ extract_pdev_sscan_fft_bin_index_tlv(
 
 	return QDF_STATUS_SUCCESS;
 }
+
+#ifdef SPECTRAL_BERYLLIUM
+/**
+ * extract_pdev_spectral_session_chan_info_tlv() - Extract channel information
+ * for a spectral scan session
+ * @wmi_handle: handle to WMI.
+ * @event: Event buffer
+ * @chan_info: Spectral session channel information data structure to be filled
+ * by this API
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+extract_pdev_spectral_session_chan_info_tlv(
+			wmi_unified_t wmi_handle, void *event,
+			struct spectral_session_chan_info *chan_info)
+{
+	WMI_PDEV_SSCAN_FW_PARAM_EVENTID_param_tlvs *param_buf = event;
+	wmi_pdev_sscan_chan_info *chan_info_tlv;
+
+	if (!param_buf) {
+		wmi_err("param_buf is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!chan_info) {
+		wmi_err("chan_info is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	chan_info_tlv = param_buf->chan_info;
+	if (!chan_info_tlv) {
+		wmi_err("chan_info tlv is not present in the event");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	chan_info->operating_pri20_freq =
+			(qdf_freq_t)chan_info_tlv->operating_pri20_freq;
+	chan_info->operating_cfreq1 =
+			(qdf_freq_t)chan_info_tlv->operating_cfreq1;
+	chan_info->operating_cfreq2 =
+			(qdf_freq_t)chan_info_tlv->operating_cfreq2;
+	chan_info->operating_bw = wmi_map_ch_width(chan_info_tlv->operating_bw);
+	chan_info->operating_puncture_20mhz_bitmap =
+		chan_info_tlv->operating_puncture_20mhz_bitmap;
+
+	chan_info->sscan_cfreq1 = (qdf_freq_t)chan_info_tlv->sscan_cfreq1;
+	chan_info->sscan_cfreq2 = (qdf_freq_t)chan_info_tlv->sscan_cfreq2;
+	chan_info->sscan_bw = wmi_map_ch_width(chan_info_tlv->sscan_bw);
+	chan_info->sscan_puncture_20mhz_bitmap =
+		chan_info_tlv->sscan_puncture_20mhz_bitmap;
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* SPECTRAL_BERYLLIUM */
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
 #ifdef FEATURE_WPSS_THERMAL_MITIGATION
@@ -16217,6 +16301,10 @@ struct wmi_ops tlv_ops =  {
 				extract_pdev_sscan_fw_cmd_fixed_param_tlv,
 	.extract_pdev_sscan_fft_bin_index =
 				extract_pdev_sscan_fft_bin_index_tlv,
+#ifdef SPECTRAL_BERYLLIUM
+	.extract_pdev_spectral_session_chan_info =
+				extract_pdev_spectral_session_chan_info_tlv,
+#endif /* SPECTRAL_BERYLLIUM */
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 	.send_thermal_mitigation_param_cmd =
 		send_thermal_mitigation_param_cmd_tlv,
@@ -17326,6 +17414,8 @@ static void populate_tlv_service(uint32_t *wmi_service)
 			WMI_SERVICE_MGMT_RX_REO_SUPPORTED;
 	wmi_service[wmi_service_phy_dma_byte_swap_support] =
 			WMI_SERVICE_UNAVAILABLE;
+	wmi_service[wmi_service_spectral_session_info_support] =
+			WMI_SERVICE_UNAVAILABLE;
 }
 
 /**