Browse Source

qcacmn: Big-endian mode changes for Beryllium Spectral

On Beryllium architecture, PHY DMA applies a 32-bit byte swap to assist
in efficient Host reads when connected to a big-endian Host.
This is done to avoid byte swapping at the Host.
So, if the Host reads this data 32-bit word at a time, the byte order
would be intact. Report headers are not a problem because as they are
composed of 32-bit words. For FFT bins, read each DWORD at a time and
extract FFT bins out of that DWORD. Make this change in a generic way to
keep the design uniform across different chipsets and endian modes.

CRs-Fixed: 3042188
Change-Id: Idff1ac7eb5e18c692c9ee8b19b9ae9e6b962d486
Shiva Krishna Pittala 3 năm trước cách đây
mục cha
commit
d36115b849

+ 83 - 18
target_if/spectral/target_if_spectral.c

@@ -2574,33 +2574,89 @@ target_if_init_spectral_ops_gen2(void)
 }
 
 #ifdef BIG_ENDIAN_HOST
+/**
+ * spectral_is_host_byte_swap_required() - Check if byte swap has to be done
+ * on the Host
+ * @pdev: pdev pointer
+ * @is_swap_required: Pointer to caller variable
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev *pdev,
+				    bool *is_swap_required)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+
+	if (!pdev) {
+		spectral_err("pdev is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err("psoc is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle =  get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		spectral_err("wmi handle is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/**
+	 * If a chipset supports byte-swap inside the target itself, then no
+	 * need to apply byte swap on the Host.
+	 */
+	*is_swap_required = !target_if_spectral_wmi_service_enabled(
+				psoc, wmi_handle,
+				wmi_service_phy_dma_byte_swap_support);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * target_if_spectral_init_byte_swap_funcs_gen3() - Initialize byte-swap
  * operations for Spectral chipset generation 3.
- *
+ * @spectral: Spectral LMAC object
  * @p_sops: Spectral function pointer table
  *
  * Return: None
  */
 static void
 target_if_spectral_init_byte_swap_funcs_gen3(
+	struct target_if_spectral *spectral,
 	struct target_if_spectral_ops *p_sops)
 {
+	bool is_swap_required;
+	QDF_STATUS status;
+
+	qdf_assert_always(spectral);
 	qdf_assert_always(p_sops);
 
-	/* None of current Gen3 chipsets support byte-swap inside the target.
-	 * so, Host would have to implement the byte-swap for these chipsets.
-	 *
-	 * If a chipset supports byte-swap inside the target itself in future,
-	 * then, for that chipset, initialize these function pointers with
-	 * NULL based on the capability advertisement.
-	 */
-	p_sops->byte_swap_headers = target_if_byte_swap_spectral_headers_gen3;
-	p_sops->byte_swap_fft_bins = target_if_byte_swap_spectral_fft_bins_gen3;
+	status = spectral_is_host_byte_swap_required(spectral->pdev_obj,
+						     &is_swap_required);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		spectral_err("Failed to check whether byte swap is required");
+		return;
+	}
+
+	if (is_swap_required) {
+		p_sops->byte_swap_headers =
+			target_if_byte_swap_spectral_headers_gen3;
+		p_sops->byte_swap_fft_bins =
+			target_if_byte_swap_spectral_fft_bins_gen3;
+	} else {
+		p_sops->byte_swap_headers = NULL;
+		p_sops->byte_swap_fft_bins = NULL;
+	}
 }
 #else
 static void
 target_if_spectral_init_byte_swap_funcs_gen3(
+	struct target_if_spectral *spectral,
 	struct target_if_spectral_ops *p_sops)
 {
 	qdf_assert_always(p_sops);
@@ -2614,20 +2670,21 @@ target_if_spectral_init_byte_swap_funcs_gen3(
 /**
  * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
  * operations specific to Spectral chipset generation 3.
+ * @spectral: Spectral LMAC object
  *
  * Initializes target_if_spectral_ops specific to Spectral chipset generation 3.
  *
  * Return: None
  */
 static void
-target_if_init_spectral_ops_gen3(void)
+target_if_init_spectral_ops_gen3(struct target_if_spectral *spectral)
 {
 	struct target_if_spectral_ops *p_sops = &spectral_ops;
 
 	p_sops->process_spectral_report =
 			target_if_spectral_process_report_gen3;
 
-	target_if_spectral_init_byte_swap_funcs_gen3(p_sops);
+	target_if_spectral_init_byte_swap_funcs_gen3(spectral, p_sops);
 }
 
 /**
@@ -2647,7 +2704,7 @@ target_if_init_spectral_ops(struct target_if_spectral *spectral)
 	if (spectral->spectral_gen == SPECTRAL_GEN2)
 		target_if_init_spectral_ops_gen2();
 	else if (spectral->spectral_gen == SPECTRAL_GEN3)
-		target_if_init_spectral_ops_gen3();
+		target_if_init_spectral_ops_gen3(spectral);
 	else
 		spectral_err("Invalid Spectral generation");
 }
@@ -3028,6 +3085,7 @@ target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
  * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment
  * related info
  * @swar: Pointer to Spectral FFT bin length adjustment SWAR params
+ * @rparams: Pointer to Spectral report parameter object
  * @target_type: Target type
  *
  * Function to Initialize parameters related to Spectral FFT bin
@@ -3037,6 +3095,7 @@ target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
  */
 static void
 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar,
+				     struct spectral_report_params *rparams,
 				     uint32_t target_type)
 {
 	if (target_type == TARGET_TYPE_QCA8074V2 ||
@@ -3045,14 +3104,18 @@ target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar,
 	    target_type == TARGET_TYPE_QCN6122 ||
 	    target_type == TARGET_TYPE_QCA5018 ||
 	    target_type == TARGET_TYPE_QCA6750 ||
-	    target_type == TARGET_TYPE_QCA6490)
+	    target_type == TARGET_TYPE_QCA6490) {
 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE;
-	else if (target_type == TARGET_TYPE_QCA8074 ||
+		rparams->hw_fft_bin_width = 2;
+	} else if (target_type == TARGET_TYPE_QCA8074 ||
 		 target_type == TARGET_TYPE_QCA6018 ||
-		 target_type == TARGET_TYPE_QCA6390)
+		 target_type == TARGET_TYPE_QCA6390) {
 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE;
-	else
+		rparams->hw_fft_bin_width = 4;
+	} else {
 		swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR;
+		rparams->hw_fft_bin_width = 1;
+	}
 
 	if (target_type == TARGET_TYPE_QCA8074 ||
 	    target_type == TARGET_TYPE_QCA8074V2 ||
@@ -3564,9 +3627,11 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
 	    target_type == TARGET_TYPE_QCA6750)
 		spectral->direct_dma_support = true;
 
+	target_if_spectral_report_params_init(&spectral->rparams,
+					      target_type);
 	target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar,
+					     &spectral->rparams,
 					     target_type);
-	target_if_spectral_report_params_init(&spectral->rparams, target_type);
 
 	if ((target_type == TARGET_TYPE_QCA8074) ||
 	    (target_type == TARGET_TYPE_QCA8074V2) ||

+ 29 - 1
target_if/spectral/target_if_spectral.h

@@ -99,6 +99,7 @@
 #define SPECTRAL_PARAM_RPT_MODE_MIN               (0)
 #define SPECTRAL_PARAM_RPT_MODE_MAX               (3)
 #define MAX_FFTBIN_VALUE                          (255)
+#define SPECTRAL_DWORD_SIZE                       (4)
 
 /* DBR ring debug size for Spectral */
 #define SPECTRAL_DBR_RING_DEBUG_SIZE 512
@@ -606,6 +607,7 @@ struct spectral_fft_bin_len_adj_swar {
  * @detid_mode_table: Detector ID to Spectral scan mode table
  * @num_spectral_detectors: Total number of Spectral detectors
  * @marker: Describes the boundaries of pri80, 5 MHz and sec80 bins
+ * @hw_fft_bin_width: FFT bin width reported by the HW
  */
 struct spectral_report_params {
 	enum spectral_report_format_version version;
@@ -616,6 +618,7 @@ struct spectral_report_params {
 	uint8_t num_spectral_detectors;
 	struct spectral_fft_bin_markers_160_165mhz
 				marker[SPECTRAL_SCAN_MODE_MAX];
+	uint8_t hw_fft_bin_width;
 };
 
 /**
@@ -787,7 +790,7 @@ struct target_if_spectral_ops {
 		struct target_if_spectral *spectral,
 		void *data);
 	QDF_STATUS (*byte_swap_fft_bins)(
-		struct spectral_fft_bin_len_adj_swar *swar,
+		const struct spectral_report_params *rparams,
 		void *bin_pwr_data, size_t num_fftbins);
 };
 
@@ -2844,5 +2847,30 @@ QDF_STATUS target_if_byte_swap_spectral_fft_bins_gen3(
 #undef __ATTRIB_PACK
 #endif
 
+/**
+ * target_if_spectral_copy_fft_bins() - Copy FFT bins from source buffer to
+ * destination buffer
+ * @spectral: Pointer to Spectral LMAC object
+ * @src_fft_buf: Pointer to source FFT buffer
+ * @dest_fft_buf: Pointer to destination FFT buffer
+ * @fft_bin_count: Number of FFT bins to copy
+ * @bytes_copied: Number of bytes copied by this API
+ *
+ * Different targets supports different FFT bin widths. This API encapsulates
+ * all those details and copies 8-bit FFT value into the destination buffer.
+ * Also, this API takes care of handling big-endian mode.
+ * In essence, it does the following.
+ *   - Read DWORDs one by one
+ *   - Extract individual FFT bins out of it
+ *   - Copy the FFT bin to destination buffer
+ *
+ * Return: QDF_STATUS_SUCCESS in case of success, else QDF_STATUS_E_FAILURE
+ */
+QDF_STATUS
+target_if_spectral_copy_fft_bins(struct target_if_spectral *spectral,
+				 const void *src_fft_buf,
+				 void *dest_fft_buf,
+				 uint32_t fft_bin_count,
+				 uint32_t *bytes_copied);
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 #endif /* _TARGET_IF_SPECTRAL_H_ */

+ 55 - 97
target_if/spectral/target_if_spectral_netlink.c

@@ -102,13 +102,10 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 		struct samp_edge_extra_bin_info *lb_edge_bins;
 		struct samp_edge_extra_bin_info *rb_edge_bins;
 		uint8_t *bin_pwr_data;
-		uint32_t *binptr_32;
-		uint16_t *binptr_16;
-		uint16_t pwr_16;
 		size_t pwr_count;
 		uint16_t num_edge_bins;
-		uint16_t idx;
 		uint16_t start_bin_index;
+		uint32_t bytes_copied;
 
 		swar = &spectral->len_adj_swar;
 
@@ -160,102 +157,63 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 			    detector_info->start_bin_idx + 1;
 		num_edge_bins = lb_edge_bins->num_bins +
 				rb_edge_bins->num_bins;
-		/*
-		 * To check whether FFT bin values exceed 8 bits, we add a
-		 * check before copying values to samp_data->bin_pwr.
-		 * If it crosses 8 bits, we cap the values to maximum value
-		 * supported by 8 bits ie. 255. This needs to be done as the
-		 * destination array in SAMP message is 8 bits. This is a
-		 * temporary solution till an array of 16 bits is used for
-		 * SAMP message.
-		 */
-		if (swar->fftbin_size_war ==
-				SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) {
-			binptr_32 = (uint32_t *)bin_pwr_data;
-			if (lb_edge_bins->num_bins > 0) {
-				for (idx = 0; idx < lb_edge_bins->num_bins;
-				     idx++) {
-				/* Read only the first 2 bytes of the DWORD */
-					pwr_16 = *((uint16_t *)binptr_32++);
-					if (qdf_unlikely(pwr_16 >
-					    MAX_FFTBIN_VALUE))
-						pwr_16 = MAX_FFTBIN_VALUE;
-					spec_samp_msg->bin_pwr
-					  [lb_edge_bins->start_bin_idx + idx]
-					  = pwr_16;
-				}
-			}
-			for (idx = 0; idx < pwr_count; idx++) {
-				/* Read only the first 2 bytes of the DWORD */
-				pwr_16 = *((uint16_t *)binptr_32++);
-				if (qdf_unlikely(pwr_16 > MAX_FFTBIN_VALUE))
-					pwr_16 = MAX_FFTBIN_VALUE;
-				spec_samp_msg->bin_pwr[start_bin_index + idx]
-							= pwr_16;
-			}
-			if (rb_edge_bins->num_bins > 0) {
-				for (idx = 0; idx < rb_edge_bins->num_bins;
-				     idx++) {
-				/* Read only the first 2 bytes of the DWORD */
-					pwr_16 = *((uint16_t *)binptr_32++);
-					if (qdf_unlikely(pwr_16 >
-					    MAX_FFTBIN_VALUE))
-						pwr_16 = MAX_FFTBIN_VALUE;
-					spec_samp_msg->bin_pwr
-					  [rb_edge_bins->start_bin_idx + idx]
-					  = pwr_16;
-				}
-			}
-		} else if (swar->fftbin_size_war ==
-				SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) {
-			binptr_16 = (uint16_t *)bin_pwr_data;
-			if (lb_edge_bins->num_bins > 0) {
-				for (idx = 0; idx < lb_edge_bins->num_bins;
-				     idx++) {
-					pwr_16 = *(binptr_16++);
-					if (qdf_unlikely(pwr_16 >
-					    MAX_FFTBIN_VALUE))
-						pwr_16 = MAX_FFTBIN_VALUE;
-					spec_samp_msg->bin_pwr
-					  [lb_edge_bins->start_bin_idx + idx]
-					  = pwr_16;
-				}
-			}
-			for (idx = 0; idx < pwr_count; idx++) {
-				pwr_16 = *(binptr_16++);
-				if (qdf_unlikely(pwr_16 > MAX_FFTBIN_VALUE))
-					pwr_16 = MAX_FFTBIN_VALUE;
-				spec_samp_msg->bin_pwr[start_bin_index + idx]
-							= pwr_16;
+
+		/* Copy left edge bins */
+		if (lb_edge_bins->num_bins > 0) {
+			ret = target_if_spectral_copy_fft_bins(
+					spectral, bin_pwr_data,
+					&spec_samp_msg->bin_pwr[
+					lb_edge_bins->start_bin_idx],
+					lb_edge_bins->num_bins,
+					&bytes_copied);
+
+			if (QDF_IS_STATUS_ERROR(ret)) {
+				qdf_spin_unlock_bh(
+					&spectral->session_det_map_lock);
+				spectral_err_rl("Unable to copy left edge FFT bins");
+				return QDF_STATUS_E_FAILURE;
 			}
-			if (rb_edge_bins->num_bins > 0) {
-				for (idx = 0; idx < rb_edge_bins->num_bins;
-				     idx++) {
-					pwr_16 = *(binptr_16++);
-					if (qdf_unlikely(pwr_16 >
-					    MAX_FFTBIN_VALUE))
-						pwr_16 = MAX_FFTBIN_VALUE;
-					spec_samp_msg->bin_pwr
-					  [rb_edge_bins->start_bin_idx + idx]
-					  = pwr_16;
-				}
+
+			/* Advance the fft bin pointer in the report */
+			bin_pwr_data += bytes_copied;
+		}
+
+		/* Copy the in-band and out-band bins */
+		ret = target_if_spectral_copy_fft_bins(
+				spectral, bin_pwr_data,
+				&spec_samp_msg->bin_pwr[start_bin_index],
+				pwr_count,
+				&bytes_copied);
+
+		if (QDF_IS_STATUS_ERROR(ret)) {
+			qdf_spin_unlock_bh(
+				&spectral->session_det_map_lock);
+			spectral_err_rl("Unable to copy in-band/out-band FFT bins");
+			return QDF_STATUS_E_FAILURE;
+		}
+		/* Advance the fft bin pointer in the report */
+		bin_pwr_data += bytes_copied;
+
+		/* Copy right edge bins */
+		if (rb_edge_bins->num_bins > 0) {
+			ret = target_if_spectral_copy_fft_bins(
+					spectral, bin_pwr_data,
+					&spec_samp_msg->bin_pwr[
+					rb_edge_bins->start_bin_idx],
+					rb_edge_bins->num_bins,
+					&bytes_copied);
+
+			if (QDF_IS_STATUS_ERROR(ret)) {
+				qdf_spin_unlock_bh(
+					&spectral->session_det_map_lock);
+				spectral_err_rl("Unable to copy right edge FFT bins");
+				return QDF_STATUS_E_FAILURE;
 			}
-		} else {
-			if (lb_edge_bins->num_bins > 0)
-				qdf_mem_copy(&spec_samp_msg->bin_pwr
-					     [lb_edge_bins->start_bin_idx],
-					     &bin_pwr_data[0],
-					     lb_edge_bins->num_bins);
-			qdf_mem_copy(&spec_samp_msg->bin_pwr[start_bin_index],
-				     &bin_pwr_data[lb_edge_bins->num_bins],
-				     pwr_count);
-			if (rb_edge_bins->num_bins > 0)
-				qdf_mem_copy(&spec_samp_msg->bin_pwr
-					     [rb_edge_bins->start_bin_idx],
-					     &bin_pwr_data[pwr_count +
-					     lb_edge_bins->num_bins],
-					     rb_edge_bins->num_bins);
+
+			/* Advance the fft bin pointer in the report */
+			bin_pwr_data += bytes_copied;
 		}
+
 		spec_samp_msg->bin_pwr_count += (pwr_count + num_edge_bins);
 	}
 

+ 105 - 88
target_if/spectral/target_if_spectral_phyerr.c

@@ -2171,6 +2171,75 @@ target_if_spectral_dump_phyerr_data_gen2(uint8_t *data, uint32_t datalen,
 	return 0;
 }
 
+QDF_STATUS
+target_if_spectral_copy_fft_bins(struct target_if_spectral *spectral,
+				 const void *src_fft_buf,
+				 void *dest_fft_buf,
+				 uint32_t fft_bin_count,
+				 uint32_t *bytes_copied)
+{
+	uint16_t idx, dword_idx, fft_bin_idx;
+	uint8_t num_bins_per_dword, hw_fft_bin_width_bits;
+	uint32_t num_dwords;
+	uint16_t fft_bin_val;
+	struct spectral_report_params *rparams;
+	const uint32_t *dword_ptr;
+	uint32_t dword;
+	uint8_t *fft_bin_buf;
+
+	*bytes_copied = 0;
+
+	if (!spectral) {
+		spectral_err("spectral lmac object is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!src_fft_buf) {
+		spectral_err("source fft bin buffer is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!dest_fft_buf) {
+		spectral_err("destination fft bin buffer is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	rparams = &spectral->rparams;
+	num_bins_per_dword = SPECTRAL_DWORD_SIZE / rparams->hw_fft_bin_width;
+	num_dwords = fft_bin_count / num_bins_per_dword;
+	hw_fft_bin_width_bits = rparams->hw_fft_bin_width * QDF_CHAR_BIT;
+
+	fft_bin_idx = 0;
+	dword_ptr = src_fft_buf;
+	fft_bin_buf = dest_fft_buf;
+	for (dword_idx = 0; dword_idx < num_dwords; dword_idx++) {
+		dword = *dword_ptr++; /* Read a DWORD */
+		for (idx = 0; idx < num_bins_per_dword; idx++) {
+			fft_bin_val = (uint16_t)QDF_GET_BITS(
+					dword,
+					idx * hw_fft_bin_width_bits,
+					hw_fft_bin_width_bits);
+			/**
+			 * To check whether FFT bin values exceed 8 bits,
+			 * we add a check before copying values to fft_bin_buf.
+			 * If it crosses 8 bits, we cap the values to maximum
+			 * value supported by 8 bits ie. 255. This needs to be
+			 * done as the destination array in SAMP message is
+			 * 8 bits. This is a temporary solution till an array
+			 * of 16 bits is used for SAMP message.
+			 */
+			if (qdf_unlikely(fft_bin_val > MAX_FFTBIN_VALUE))
+				fft_bin_val = MAX_FFTBIN_VALUE;
+
+			fft_bin_buf[fft_bin_idx++] = fft_bin_val;
+		}
+	}
+
+	*bytes_copied = num_dwords *  SPECTRAL_DWORD_SIZE;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #ifdef DIRECT_BUF_RX_ENABLE
 /**
  * target_if_get_spectral_mode() - Get Spectral scan mode corresponding to a
@@ -2361,8 +2430,6 @@ target_if_dump_fft_report_gen3(struct target_if_spectral *spectral,
 	size_t fft_bin_count;
 	size_t fft_bin_size;
 	size_t fft_bin_len_inband_tfer = 0;
-	uint8_t *fft_bin_buf = NULL;
-	size_t fft_bin_buf_size;
 	uint8_t tag, signature;
 
 	qdf_assert_always(spectral);
@@ -2434,68 +2501,30 @@ target_if_dump_fft_report_gen3(struct target_if_spectral *spectral,
 	spectral_debug("fft_avgpwr_db = %u", p_sfft->fft_avgpwr_db);
 	spectral_debug("fft_relpwr_db = %u", p_sfft->fft_relpwr_db);
 
-	fft_bin_buf_size = fft_bin_count;
-
 	if (fft_bin_count > 0) {
-		int idx;
-
-		if (spectral->len_adj_swar.fftbin_size_war ==
-				SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) {
-			uint32_t *binptr_32 = (uint32_t *)&p_fft_report->buf;
-			uint16_t *fft_bin_buf_16 = NULL;
-
-			/* Useful width of FFT bin is 10 bits, increasing it to
-			 * byte boundary makes it 2 bytes. Hence, buffer to be
-			 * allocated should be of size fft_bin_count
-			 * multiplied by 2.
-			 */
-			fft_bin_buf_size <<= 1;
-
-			fft_bin_buf_16 = (uint16_t *)qdf_mem_malloc(
-						fft_bin_buf_size);
-			if (!fft_bin_buf_16) {
-				spectral_err("Failed to allocate memory");
-				return;
-			}
-
-			for (idx = 0; idx < fft_bin_count; idx++)
-				fft_bin_buf_16[idx] =
-					*((uint16_t *)binptr_32++);
-
-			fft_bin_buf = (uint8_t *)fft_bin_buf_16;
-		} else if (spectral->len_adj_swar.fftbin_size_war ==
-				SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) {
-			uint16_t *binptr_16 = (uint16_t *)&p_fft_report->buf;
-			uint16_t *fft_bin_buf_16 = NULL;
-
-			/* Useful width of FFT bin is 10 bits, increasing it to
-			 * byte boundary makes it 2 bytes. Hence, buffer to be
-			 * allocated should be of size fft_bin_count
-			 * multiplied by 2.
-			 */
-			fft_bin_buf_size <<= 1;
-
-			fft_bin_buf_16 = (uint16_t *)qdf_mem_malloc(
-						fft_bin_buf_size);
-			if (!fft_bin_buf_16) {
-				spectral_err("Failed to allocate memory");
-				return;
-			}
-
-			for (idx = 0; idx < fft_bin_count; idx++)
-				fft_bin_buf_16[idx] = *(binptr_16++);
+		uint8_t *fft_bin_buf;
+		uint32_t bytes_copied;
+		QDF_STATUS status;
+
+		fft_bin_buf = qdf_mem_malloc(fft_bin_count);
+		if (!fft_bin_buf) {
+			spectral_err_rl("memory allocation failed");
+			return;
+		}
 
-			fft_bin_buf = (uint8_t *)fft_bin_buf_16;
-		} else {
-			fft_bin_buf = (uint8_t *)&p_fft_report->buf;
+		status = target_if_spectral_copy_fft_bins(
+				spectral, &p_fft_report->buf,
+				fft_bin_buf, fft_bin_count, &bytes_copied);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			spectral_err_rl("Unable to populate FFT bins");
+			qdf_mem_free(fft_bin_buf);
+			return;
 		}
 
-		spectral_debug("FFT bin buffer size = %zu", fft_bin_buf_size);
+		spectral_debug("FFT bin buffer size = %zu", fft_bin_count);
 		spectral_debug("FFT bins:");
-		target_if_spectral_hexdump(fft_bin_buf, fft_bin_buf_size);
-		if ((spectral->len_adj_swar.fftbin_size_war !=
-				SPECTRAL_FFTBIN_SIZE_NO_WAR) && fft_bin_buf)
-			qdf_mem_free(fft_bin_buf);
+		target_if_spectral_hexdump(fft_bin_buf, fft_bin_count);
+		qdf_mem_free(fft_bin_buf);
 	}
 }
 #endif
@@ -2958,36 +2987,24 @@ QDF_STATUS target_if_byte_swap_spectral_headers_gen3(
 }
 
 QDF_STATUS target_if_byte_swap_spectral_fft_bins_gen3(
-	struct spectral_fft_bin_len_adj_swar *swar,
+	const struct spectral_report_params *rparams,
 	void *bin_pwr_data, size_t num_fftbins)
 {
-	int i;
-	uint16_t *binptr_16;
-	uint32_t *binptr_32;
+	uint16_t dword_idx, num_dwords;
+	uint8_t num_bins_per_dword;
+	uint32_t *dword_ptr;
 
 	qdf_assert_always(bin_pwr_data);
-	qdf_assert_always(swar);
-
-	if (swar->fftbin_size_war ==
-			SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) {
-		binptr_32 = (uint32_t *)bin_pwr_data;
-
-		for (i = 0; i < num_fftbins; i++) {
-			/* Get the useful first 2 bytes of the DWORD */
-			binptr_16 = ((uint16_t *)binptr_32);
-			/* Byteswap and copy it back */
-			*binptr_16 = qdf_le16_to_cpu(*binptr_16);
-			++binptr_32; /* Go to next DWORD */
-		}
-	} else if (swar->fftbin_size_war ==
-			SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) {
-		binptr_16 = (uint16_t *)bin_pwr_data;
-
-		for (i = 0; i < num_fftbins; i++) {
-			/* Byteswap the FFT bin and copy it back */
-			*binptr_16 = qdf_le16_to_cpu(*binptr_16);
-			++binptr_16;
-		}
+	qdf_assert_always(rparams);
+
+	num_bins_per_dword = SPECTRAL_DWORD_SIZE / rparams->hw_fft_bin_width;
+	num_dwords = pwr_count / num_bins_per_dword;
+	dword_ptr = (uint32_t *)bin_pwr_data;
+
+	for (dword_idx = 0; dword_idx < num_dwords; dword_idx++) {
+		/* Read a DWORD, byteswap it, and copy it back */
+		*dword_ptr = qdf_le32_to_cpu(*dword_ptr);
+		++dword_ptr;
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -3284,7 +3301,7 @@ target_if_process_sfft_report_gen3(
 	 *       they should use them only after this point.
 	 */
 	if (p_sops->byte_swap_fft_bins) {
-		ret = p_sops->byte_swap_fft_bins(&spectral->len_adj_swar,
+		ret = p_sops->byte_swap_fft_bins(&spectral->rparams,
 						 &p_sfft->bin_pwr_data,
 						 p_sfft->fft_bin_count);
 		if (QDF_IS_STATUS_ERROR(ret)) {
@@ -3849,7 +3866,7 @@ target_if_consume_spectral_report_gen3(
 		 */
 		if (p_sops->byte_swap_fft_bins) {
 			ret = p_sops->byte_swap_fft_bins(
-						&spectral->len_adj_swar,
+						&spectral->rparams,
 						temp, fft_bin_count);
 			if (QDF_IS_STATUS_ERROR(ret)) {
 				spectral_err_rl("Byte-swap on the FFT bins failed");
@@ -3970,7 +3987,7 @@ target_if_consume_spectral_report_gen3(
 		 */
 		if (p_sops->byte_swap_fft_bins) {
 			ret = p_sops->byte_swap_fft_bins(
-					&spectral->len_adj_swar,
+					&spectral->rparams,
 					params.bin_pwr_data_sec80,
 					fft_bin_count);
 			if (QDF_IS_STATUS_ERROR(ret)) {

+ 1 - 0
wmi/inc/wmi_unified_param.h

@@ -5209,6 +5209,7 @@ typedef enum {
 #endif
 	wmi_service_hw_mode_policy_offload_support,
 	wmi_service_mgmt_rx_reo_supported,
+	wmi_service_phy_dma_byte_swap_support,
 	wmi_services_max,
 } wmi_conv_service_ids;
 #define WMI_SERVICE_UNAVAILABLE 0xFFFF

+ 2 - 0
wmi/src/wmi_unified_tlv.c

@@ -17322,6 +17322,8 @@ static void populate_tlv_service(uint32_t *wmi_service)
 			WMI_SERVICE_HW_MODE_POLICY_OFFLOAD_SUPPORT;
 	wmi_service[wmi_service_mgmt_rx_reo_supported] =
 			WMI_SERVICE_MGMT_RX_REO_SUPPORTED;
+	wmi_service[wmi_service_phy_dma_byte_swap_support] =
+			WMI_SERVICE_UNAVAILABLE;
 }
 
 /**