Browse Source

qcacmn: Control path support for Spectral DMA debug

All gen III chipsets use Direct-DMA mechanism to copy Spectral reports to
the Host for further processing. This mechanism involves ring and buffer
management in the Host, FW, and uCode, where improper/incomplete DMA and
improper tail update issues are seen. DBR framework provides support to
debug such issues. Add Spectral control path support to facilitate the
configuration of these debug options.

CRs-Fixed: 2478596 2478595
Change-Id: I094616c4137145389b6984ccab933e5ebd0aa1ab
Shwetha G K 5 years ago
parent
commit
8db4b4ac32

+ 14 - 1
os_if/linux/spectral/inc/wlan_cfg80211_spectral.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019 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
@@ -135,4 +135,17 @@ int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
 					   struct wlan_objmgr_pdev *pdev,
 					   const void *data,
 					   int data_len);
+
+/**
+ * wlan_cfg80211_spectral_scan_dma_debug_config() - configure DMA debug
+ * @pdev:       Pointer to pdev
+ * @tb:         Pointer to Spectral Scan config attribute
+ * @sscan_mode: Spectral scan mode
+ *
+ * Return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
+ */
+QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
+		struct wlan_objmgr_pdev *pdev,
+		struct nlattr **tb,
+		enum spectral_scan_mode sscan_mode);
 #endif

+ 61 - 1
os_if/linux/spectral/src/wlan_cfg80211_spectral.c

@@ -84,7 +84,11 @@ static const struct nla_policy spectral_scan_policy[
 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY] = {
 							.type = NLA_U32},
 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE] = {
-						.type = NLA_U32},
+							.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG] = {
+							.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG] = {
+							.type = NLA_U8},
 };
 
 static void wlan_spectral_intit_config(struct spectral_config *config_req)
@@ -182,6 +186,57 @@ convert_spectral_err_code_internal_to_nl
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef DIRECT_BUF_RX_DEBUG
+QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
+	struct wlan_objmgr_pdev *pdev,
+	struct nlattr **tb,
+	enum spectral_scan_mode sscan_mode)
+{
+	struct spectral_cp_request sscan_req;
+	uint8_t dma_debug_enable;
+	QDF_STATUS status;
+
+	if (!tb || !pdev)
+		return QDF_STATUS_E_FAILURE;
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]) {
+		dma_debug_enable = nla_get_u8(tb[
+		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]);
+		sscan_req.ss_mode = sscan_mode;
+		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
+		sscan_req.dma_debug_req.dma_debug_type =
+				SPECTRAL_DMA_RING_DEBUG;
+		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
+		status = ucfg_spectral_control(pdev, &sscan_req);
+		if (status != QDF_STATUS_SUCCESS) {
+			osif_err("Could not configure dma ring debug");
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]) {
+		dma_debug_enable = nla_get_u8(tb[
+		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]);
+		sscan_req.ss_mode = sscan_mode;
+		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
+		sscan_req.dma_debug_req.dma_debug_type =
+				SPECTRAL_DMA_BUFFER_DEBUG;
+		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
+		return ucfg_spectral_control(pdev, &sscan_req);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
+	struct wlan_objmgr_pdev *pdev,
+	struct nlattr **tb,
+	enum spectral_scan_mode sscan_mode)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* DIRECT_BUF_RX_DEBUG */
+
 int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
 						 struct wlan_objmgr_pdev *pdev,
 						 const void *data,
@@ -328,6 +383,11 @@ int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
 		return -ENOMEM;
 	}
 
+	status = wlan_cfg80211_spectral_scan_dma_debug_config(
+			pdev, tb, sscan_mode);
+	if (QDF_IS_STATUS_ERROR(status))
+		return -EINVAL;
+
 	if (CONFIG_REQUESTED(scan_req_type)) {
 		sscan_req.ss_mode = sscan_mode;
 		sscan_req.req_id = SPECTRAL_SET_CONFIG;

+ 8 - 0
spectral/core/spectral_common.c

@@ -471,6 +471,14 @@ spectral_control_cmn(struct wlan_objmgr_pdev *pdev,
 		}
 		break;
 
+	case SPECTRAL_SET_DMA_DEBUG:
+		if (sc->sptrlc_set_dma_debug)
+			sc->sptrlc_set_dma_debug(
+			     pdev,
+			     sscan_req->dma_debug_req.dma_debug_type,
+			     sscan_req->dma_debug_req.dma_debug_enable);
+		break;
+
 	default:
 		goto bad;
 		break;

+ 10 - 5
spectral/core/spectral_defs_i.h

@@ -118,6 +118,7 @@ struct wmi_spectral_cmd_ops;
  * @sptrlc_use_nl_bcast: Check whether to use Netlink broadcast/unicast
  * @sptrlc_deregister_netlink_cb: De-register Netlink callbacks
  * @sptrlc_process_spectral_report: Process spectral report
+ * @sptrlc_set_dma_debug: Set DMA debug
  */
 struct spectral_context {
 	struct wlan_objmgr_psoc *psoc_obj;
@@ -163,13 +164,17 @@ struct spectral_context {
 			struct wlan_objmgr_pdev *pdev,
 			struct wmi_spectral_cmd_ops *cmd_ops);
 	void (*sptrlc_register_netlink_cb)(
-		struct wlan_objmgr_pdev *pdev,
-		struct spectral_nl_cb *nl_cb);
+			struct wlan_objmgr_pdev *pdev,
+			struct spectral_nl_cb *nl_cb);
 	bool (*sptrlc_use_nl_bcast)(struct wlan_objmgr_pdev *pdev);
 	void (*sptrlc_deregister_netlink_cb)(struct wlan_objmgr_pdev *pdev);
 	int (*sptrlc_process_spectral_report)(
-		struct wlan_objmgr_pdev *pdev,
-		void *payload);
+			struct wlan_objmgr_pdev *pdev,
+			void *payload);
+	QDF_STATUS (*sptrlc_set_dma_debug)(
+			struct wlan_objmgr_pdev *pdev,
+			enum spectral_dma_debug dma_debug_type,
+			bool dma_debug_enable);
 };
 
-#endif				/* _SPECTRAL_DEFS_I_H_ */
+#endif /* _SPECTRAL_DEFS_I_H_ */

+ 19 - 1
spectral/core/spectral_offload.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -21,6 +21,23 @@
 #include "spectral_ol_api_i.h"
 #include "../dispatcher/inc/wlan_spectral_tgt_api.h"
 
+#ifdef DIRECT_BUF_RX_DEBUG
+static void
+spectral_ctx_init_ol_dma_debug(struct spectral_context *sc)
+{
+	if (!sc) {
+		spectral_err("spectral context is null!");
+		return;
+	}
+	sc->sptrlc_set_dma_debug = tgt_set_spectral_dma_debug;
+}
+#else
+static void
+spectral_ctx_init_ol_dma_debug(struct spectral_context *sc)
+{
+}
+#endif
+
 void
 spectral_ctx_init_ol(struct spectral_context *sc)
 {
@@ -47,4 +64,5 @@ spectral_ctx_init_ol(struct spectral_context *sc)
 	sc->sptrlc_use_nl_bcast = tgt_spectral_use_nl_bcast;
 	sc->sptrlc_deregister_netlink_cb = tgt_spectral_deregister_nl_cb;
 	sc->sptrlc_process_spectral_report = tgt_spectral_process_report;
+	spectral_ctx_init_ol_dma_debug(sc);
 }

+ 1 - 0
spectral/dispatcher/inc/spectral_ioctl.h

@@ -51,6 +51,7 @@
 #define SPECTRAL_SET_ICM_ACTIVE          (DFS_LAST_IOCTL + 21)
 #define SPECTRAL_GET_NOMINAL_NOISEFLOOR  (DFS_LAST_IOCTL + 22)
 #define SPECTRAL_GET_DEBUG_LEVEL         (DFS_LAST_IOCTL + 23)
+#define SPECTRAL_SET_DMA_DEBUG           (DFS_LAST_IOCTL + 24)
 
 /*
  * ioctl parameter types

+ 24 - 0
spectral/dispatcher/inc/wlan_spectral_public_structs.h

@@ -232,6 +232,16 @@ enum spectral_cp_error_code {
 	SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED,
 };
 
+/**
+ * enum spectral_dma_debug -   Spectral DMA debug
+ * @SPECTRAL_DMA_RING_DEBUG:   Spectral DMA ring debug
+ * @SPECTRAL_DMA_BUFFER_DEBUG: Spectral DMA buffer debug
+ */
+enum spectral_dma_debug {
+	SPECTRAL_DMA_RING_DEBUG,
+	SPECTRAL_DMA_BUFFER_DEBUG,
+};
+
 /**
  * struct spectral_chan_stats - channel status info
  * @cycle_count:         Cycle count
@@ -378,12 +388,25 @@ struct spectral_scan_debug_request {
 	enum spectral_cp_error_code sscan_err_code;
 };
 
+/**
+ * struct spectral_scan_dma_debug_request - DMA debug request
+ * @dma_debug_enable: Enable/disable @dma_debug_type
+ * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
+ * @sscan_err_code: Spectral scan error code
+ */
+struct spectral_scan_dma_debug_request {
+	bool dma_debug_enable;
+	enum spectral_dma_debug dma_debug_type;
+	enum spectral_cp_error_code sscan_err_code;
+};
+
 /**
  * struct spectral_cp_request - Spectral control path request
  *                              Creating request and extracting response has to
  *                              be atomic.
  * @ss_mode: Spectral scan mode
  * @req_id: Request identifier
+ * @dma_debug_req: Spectral DMA debug request
  */
 struct spectral_cp_request {
 	enum spectral_scan_mode ss_mode;
@@ -396,6 +419,7 @@ struct spectral_cp_request {
 		struct spectral_scan_get_chan_width_request chan_width_req;
 		struct spectral_scan_get_status_request status_req;
 		struct spectral_scan_debug_request debug_req;
+		struct spectral_scan_dma_debug_request dma_debug_req;
 	};
 };
 

+ 12 - 0
spectral/dispatcher/inc/wlan_spectral_tgt_api.h

@@ -273,4 +273,16 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev);
  */
 uint32_t
 tgt_spectral_get_target_type(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * tgt_set_spectral_dma_debug() - Set DMA debug for Spectral
+ * @pdev: Pointer to pdev object
+ * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
+ * @dma_debug_enable: Value to be set for @dma_debug_type
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev,
+				      enum spectral_dma_debug dma_debug_type,
+				      bool dma_debug_enable);
 #endif /* _WLAN_SPECTRAL_TGT_API_H_ */

+ 54 - 11
spectral/dispatcher/src/wlan_spectral_tgt_api.c

@@ -298,23 +298,26 @@ tgt_spectral_register_to_dbr(struct wlan_objmgr_pdev *pdev)
 {
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
+	struct wlan_lmac_if_sptrl_tx_ops *sptrl_tx_ops = NULL;
 	struct dbr_module_config dbr_config = {0};
-	uint32_t target_type;
 
 	psoc = wlan_pdev_get_psoc(pdev);
 	dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops;
+	sptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops;
 	dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_SPECTRAL;
 	dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_SPECTRAL;
-	target_type = tgt_spectral_get_target_type(psoc);
 
-	if ((target_type == TARGET_TYPE_QCA8074) ||
-	    (target_type == TARGET_TYPE_QCA8074V2) ||
-	    (target_type == TARGET_TYPE_QCA6018) ||
-	    (target_type == TARGET_TYPE_QCA6390))
+	if ((sptrl_tx_ops->sptrlto_direct_dma_support) &&
+	    (sptrl_tx_ops->sptrlto_direct_dma_support(pdev))) {
+		if (sptrl_tx_ops->sptrlto_check_and_do_dbr_buff_debug)
+			sptrl_tx_ops->sptrlto_check_and_do_dbr_buff_debug(pdev);
 		if (dbr_tx_ops->direct_buf_rx_module_register)
-			return dbr_tx_ops->direct_buf_rx_module_register
+			dbr_tx_ops->direct_buf_rx_module_register
 				(pdev, 0, &dbr_config,
 				 spectral_dbr_event_handler);
+		if (sptrl_tx_ops->sptrlto_check_and_do_dbr_ring_debug)
+			sptrl_tx_ops->sptrlto_check_and_do_dbr_ring_debug(pdev);
+	}
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -324,17 +327,29 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
 {
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
+	struct wlan_lmac_if_sptrl_tx_ops *sptrl_tx_ops = NULL;
 
 	psoc = wlan_pdev_get_psoc(pdev);
 	dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops;
+	sptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops;
+
+	if ((sptrl_tx_ops->sptrlto_direct_dma_support) &&
+	    (sptrl_tx_ops->sptrlto_direct_dma_support(pdev))) {
+		/* Stop DBR debug as the buffers itself are freed now */
+		if (dbr_tx_ops->direct_buf_rx_stop_ring_debug)
+			dbr_tx_ops->direct_buf_rx_stop_ring_debug(pdev, 0);
 
-	if ((tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA8074) ||
-	    (tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA8074V2) ||
-	    (tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA6018))
+		/*No need to zero-out as buffers are anyway getting freed*/
+		if (dbr_tx_ops->direct_buf_rx_stop_buffer_poisoning)
+			dbr_tx_ops->direct_buf_rx_stop_buffer_poisoning
+				(pdev, 0);
 		if (dbr_tx_ops->direct_buf_rx_module_unregister)
-			return dbr_tx_ops->direct_buf_rx_module_unregister
+			dbr_tx_ops->direct_buf_rx_module_unregister
 				(pdev, 0);
 
+		return QDF_STATUS_SUCCESS;
+	}
+
 	return QDF_STATUS_E_FAILURE;
 }
 #else
@@ -349,4 +364,32 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
 {
 	return QDF_STATUS_SUCCESS;
 }
+#endif /* DIRECT_BUF_RX_ENABLE */
+
+#ifdef DIRECT_BUF_RX_DEBUG
+QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev,
+				      enum spectral_dma_debug dma_debug_type,
+				      bool dma_debug_enable)
+{
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	if (!psoc) {
+		spectral_err("psoc is NULL!");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_dma_debug(
+			pdev,
+			dma_debug_type,
+			dma_debug_enable);
+}
+#else
+QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev,
+				      enum spectral_dma_debug dma_debug_type,
+				      bool dma_debug_enable)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif

+ 276 - 1
target_if/spectral/target_if_spectral.c

@@ -2082,6 +2082,12 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
 	qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
 	target_if_spectral_clear_stats(spectral);
 
+	if (target_type == TARGET_TYPE_QCA8074 ||
+	    target_type == TARGET_TYPE_QCA8074V2 ||
+	    target_type == TARGET_TYPE_QCA6018 ||
+	    target_type == TARGET_TYPE_QCA6390)
+		spectral->direct_dma_support = true;
+
 	if (target_type == TARGET_TYPE_QCA8074V2)
 		spectral->fftbin_size_war =
 			SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE;
@@ -3734,6 +3740,251 @@ target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev,
 	return p_sops->is_spectral_enabled(spectral, smode);
 }
 
+#ifdef DIRECT_BUF_RX_DEBUG
+/**
+ * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug
+ * @pdev: Pointer to pdev object
+ * @enable: Enable/Disable Spectral DMA ring debug
+ *
+ * Start/stop Spectral DMA ring debug based on @enable.
+ * Also save the state for future use.
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable)
+{
+	struct target_if_spectral *spectral;
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev)
+		return QDF_STATUS_E_FAILURE;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err("psoc is null");
+		return QDF_STATUS_E_INVAL;
+	}
+	tx_ops = &psoc->soc_cb.tx_ops;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectal LMAC object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* Save the state */
+	spectral->dbr_ring_debug = enable;
+
+	if (enable)
+		return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug(
+				pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE);
+	else
+		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug(
+				pdev, 0);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug
+ * @pdev: Pointer to pdev object
+ * @enable: Enable/Disable Spectral DMA buffer debug
+ *
+ * Start/stop Spectral DMA buffer debug based on @enable.
+ * Also save the state for future use.
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable)
+{
+	struct target_if_spectral *spectral;
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev)
+		return QDF_STATUS_E_FAILURE;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err("psoc is null");
+		return QDF_STATUS_E_INVAL;
+	}
+	tx_ops = &psoc->soc_cb.tx_ops;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectal LMAC object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* Save the state */
+	spectral->dbr_buff_debug = enable;
+
+	if (enable)
+		return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning(
+				pdev, 0, MEM_POISON_SIGNATURE);
+	else
+		return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning(
+				pdev, 0);
+}
+
+/**
+ * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer
+ * debug based on the previous state
+ * @pdev: Pointer to pdev object
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral;
+
+	if (!pdev) {
+		spectral_err("pdev is NULL!");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectal LMAC object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (spectral->dbr_buff_debug)
+		return target_if_spectral_do_dbr_buff_debug(pdev, true);
+	else
+		return target_if_spectral_do_dbr_buff_debug(pdev, false);
+}
+
+/**
+ * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring
+ * debug based on the previous state
+ * @pdev: Pointer to pdev object
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral;
+
+	if (!pdev) {
+		spectral_err("pdev is NULL!");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectal LMAC object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (spectral->dbr_ring_debug)
+		return target_if_spectral_do_dbr_ring_debug(pdev, true);
+	else
+		return target_if_spectral_do_dbr_ring_debug(pdev, false);
+}
+
+/**
+ * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral
+ * @pdev: Pointer to pdev object
+ * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
+ * @debug_value: Value to be set for @dma_debug_type
+ *
+ * Set DMA debug for Spectral and start/stop Spectral DMA debug function
+ * based on @debug_value
+ *
+ * Return: QDF_STATUS of operation
+ */
+static QDF_STATUS
+target_if_spectral_set_dma_debug(
+	struct wlan_objmgr_pdev *pdev,
+	enum spectral_dma_debug dma_debug_type,
+	bool debug_value)
+{
+	struct target_if_spectral_ops *p_sops;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct target_if_spectral *spectral;
+
+	if (!pdev)
+		return QDF_STATUS_E_FAILURE;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		spectral_err("psoc is null");
+		return QDF_STATUS_E_INVAL;
+	}
+	tx_ops = &psoc->soc_cb.tx_ops;
+
+	if (!tx_ops->target_tx_ops.tgt_get_tgt_type) {
+		spectral_err("Unable to fetch target type");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectal LMAC object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (spectral->direct_dma_support) {
+		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
+		if (p_sops->is_spectral_active(spectral,
+					       SPECTRAL_SCAN_MODE_NORMAL) ||
+		    p_sops->is_spectral_active(spectral,
+					       SPECTRAL_SCAN_MODE_AGILE)) {
+			spectral_err("Altering DBR debug config isn't allowed during an ongoing scan");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		switch (dma_debug_type) {
+		case SPECTRAL_DMA_RING_DEBUG:
+			target_if_spectral_do_dbr_ring_debug(pdev, debug_value);
+			break;
+
+		case SPECTRAL_DMA_BUFFER_DEBUG:
+			target_if_spectral_do_dbr_buff_debug(pdev, debug_value);
+			break;
+
+		default:
+			spectral_err("Unsupported DMA debug type : %d",
+				     dma_debug_type);
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* DIRECT_BUF_RX_DEBUG */
+
+/**
+ * target_if_spectral_direct_dma_support() - Get Direct-DMA support
+ * @pdev: Pointer to pdev object
+ *
+ * Return: Whether Direct-DMA is supported on this radio
+ */
+static bool
+target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral;
+
+	if (!pdev) {
+		spectral_err("pdev is NULL!");
+		return false;
+	}
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("Spectral LMAC object is NULL");
+		return false;
+	}
+	return spectral->direct_dma_support;
+}
+
 /**
  * target_if_set_debug_level() - Set debug level for Spectral
  * @pdev: Pointer to pdev object
@@ -3904,6 +4155,27 @@ target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
 	return p_sops->process_spectral_report(pdev, payload);
 }
 
+#ifdef DIRECT_BUF_RX_DEBUG
+static inline void
+target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	if (!tx_ops)
+		return;
+
+	tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug =
+		target_if_spectral_set_dma_debug;
+	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug =
+		target_if_spectral_check_and_do_dbr_ring_debug;
+	tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug =
+		target_if_spectral_check_and_do_dbr_buff_debug;
+}
+#else
+static inline void
+target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+}
+#endif
+
 void
 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 {
@@ -3940,7 +4212,10 @@ target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
 	    target_if_deregister_netlink_cb;
 	tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
-		target_if_process_spectral_report;
+	    target_if_process_spectral_report;
+	tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support =
+		target_if_spectral_direct_dma_support;
+	target_if_sptrl_debug_register_tx_ops(tx_ops);
 }
 qdf_export_symbol(target_if_sptrl_register_tx_ops);
 

+ 5 - 0
target_if/spectral/target_if_spectral.h

@@ -87,6 +87,9 @@
 #define SPECTRAL_PARAM_RPT_MODE_MIN        (0)
 #define SPECTRAL_PARAM_RPT_MODE_MAX        (3)
 
+/* DBR ring debug size for Spectral */
+#define SPECTRAL_DBR_RING_DEBUG_SIZE 512
+
 #ifdef BIG_ENDIAN_HOST
 #define SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(destp, srcp, len)  do { \
 	int j; \
@@ -837,6 +840,7 @@ struct spectral_param_properties {
  * @timestamp_war_offset: Offset to be added to correct timestamp
  * @dbr_ring_debug: Whether Spectral DBR ring debug is enabled
  * @dbr_buff_debug: Whether Spectral DBR buffer debug is enabled
+ * @direct_dma_support: Whether Direct-DMA is supported on the current radio
  */
 struct target_if_spectral {
 	struct wlan_objmgr_pdev *pdev_obj;
@@ -953,6 +957,7 @@ struct target_if_spectral {
 	uint16_t fft_size_max;
 	bool  dbr_ring_debug;
 	bool  dbr_buff_debug;
+	bool direct_dma_support;
 };
 
 /**

+ 17 - 1
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -514,6 +514,12 @@ struct wmi_spectral_cmd_ops;
  * @sptrlto_use_nl_bcast: Get whether to use Netlink broadcast/unicast
  * @sptrlto_deregister_netlink_cb: De-register Spectral Netlink callbacks
  * @sptrlto_process_spectral_report: Process spectral report
+ * @sptrlto_set_dma_debug: Set DMA debug for Spectral
+ * @sptrlto_direct_dma_support: Whether Direct-DMA is supported on this radio
+ * @sptrlto_check_and_do_dbr_ring_debug: Start/Stop Spectral ring debug based
+ *                                       on the previous state
+ * @sptrlto_check_and_do_dbr_buff_debug: Start/Stop Spectral buffer debug based
+ *                                       on the previous state
  **/
 struct wlan_lmac_if_sptrl_tx_ops {
 	void *(*sptrlto_pdev_spectral_init)(struct wlan_objmgr_pdev *pdev);
@@ -560,6 +566,16 @@ struct wlan_lmac_if_sptrl_tx_ops {
 	int (*sptrlto_process_spectral_report)(
 		struct wlan_objmgr_pdev *pdev,
 		void *payload);
+	QDF_STATUS (*sptrlto_set_dma_debug)(
+		struct wlan_objmgr_pdev *pdev,
+		enum spectral_dma_debug dma_debug_type,
+		bool dma_debug_enable);
+	bool (*sptrlto_direct_dma_support)(struct wlan_objmgr_pdev *pdev);
+	QDF_STATUS (*sptrlto_check_and_do_dbr_ring_debug)(
+		struct wlan_objmgr_pdev *pdev);
+	QDF_STATUS (*sptrlto_check_and_do_dbr_buff_debug)(
+		struct wlan_objmgr_pdev *pdev);
+
 };
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
@@ -627,7 +643,7 @@ struct wlan_lmac_if_direct_buf_rx_tx_ops {
 	QDF_STATUS (*direct_buf_rx_stop_buffer_poisoning)(
 		struct wlan_objmgr_pdev *pdev, uint8_t mod_id);
 };
-#endif
+#endif /* DIRECT_BUF_RX_ENABLE */
 
 #ifdef FEATURE_WLAN_TDLS
 /* fwd declarations for tdls tx ops */