Răsfoiți Sursa

Merge "qca-wifi: Enhanced channel capture UCFG framework"

Linux Build Service Account 5 ani în urmă
părinte
comite
6012551d92

+ 3 - 0
target_if/cfr/inc/target_if_cfr.h

@@ -25,6 +25,9 @@
 #include <wlan_objmgr_vdev_obj.h>
 #include <wlan_objmgr_peer_obj.h>
 
+#include "wmi_unified_cfr_api.h"
+#include "wmi_unified_param.h"
+#include "wmi_unified_cfr_param.h"
 #define PEER_CFR_CAPTURE_ENABLE   1
 #define PEER_CFR_CAPTURE_DISABLE  0
 

+ 94 - 0
target_if/cfr/src/target_if_cfr.c

@@ -228,6 +228,99 @@ int target_if_cfr_deinit_pdev(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NOSUPPORT;
 }
 
+#ifdef WLAN_ENH_CFR_ENABLE
+QDF_STATUS target_if_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
+				    struct cfr_rcc_param *rcc_info)
+{
+	QDF_STATUS status;
+	struct wmi_unified *pdev_wmi_handle = NULL;
+
+	pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev);
+	if (!pdev_wmi_handle) {
+		cfr_err("pdev_wmi_handle is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	rcc_info->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+	rcc_info->num_grp_tlvs =
+		count_set_bits(rcc_info->modified_in_curr_session);
+
+	status = wmi_unified_send_cfr_rcc_cmd(pdev_wmi_handle, rcc_info);
+	return status;
+}
+
+void target_if_cfr_default_ta_ra_config(struct cfr_rcc_param *rcc_info,
+					bool allvalid, uint16_t reset_cfg)
+{
+	struct ta_ra_cfr_cfg *curr_cfg = NULL;
+	int grp_id;
+
+	uint8_t null_mac[QDF_MAC_ADDR_SIZE] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+	for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
+		if (qdf_test_bit(grp_id, (unsigned long *)&reset_cfg)) {
+			curr_cfg = &rcc_info->curr[grp_id];
+			qdf_mem_copy(curr_cfg->tx_addr,
+				     null_mac, QDF_MAC_ADDR_SIZE);
+			qdf_mem_copy(curr_cfg->tx_addr_mask,
+				     null_mac, QDF_MAC_ADDR_SIZE);
+			qdf_mem_copy(curr_cfg->rx_addr,
+				     null_mac, QDF_MAC_ADDR_SIZE);
+			qdf_mem_copy(curr_cfg->rx_addr_mask,
+				     null_mac, QDF_MAC_ADDR_SIZE);
+			curr_cfg->bw = 0xf;
+			curr_cfg->nss = 0xff;
+			curr_cfg->mgmt_subtype_filter = 0xffff;
+			curr_cfg->ctrl_subtype_filter = 0xffff;
+			curr_cfg->data_subtype_filter = 0xffff;
+			if (!allvalid) {
+				curr_cfg->valid_ta = 0;
+				curr_cfg->valid_ta_mask = 0;
+				curr_cfg->valid_ra = 0;
+				curr_cfg->valid_ra_mask = 0;
+				curr_cfg->valid_bw_mask = 0;
+				curr_cfg->valid_nss_mask = 0;
+				curr_cfg->valid_mgmt_subtype = 0;
+				curr_cfg->valid_ctrl_subtype = 0;
+				curr_cfg->valid_data_subtype = 0;
+			} else {
+				curr_cfg->valid_ta = 1;
+				curr_cfg->valid_ta_mask = 1;
+				curr_cfg->valid_ra = 1;
+				curr_cfg->valid_ra_mask = 1;
+				curr_cfg->valid_bw_mask = 1;
+				curr_cfg->valid_nss_mask = 1;
+				curr_cfg->valid_mgmt_subtype = 1;
+				curr_cfg->valid_ctrl_subtype = 1;
+				curr_cfg->valid_data_subtype = 1;
+			}
+		}
+	}
+}
+#endif
+
+#ifdef WLAN_ENH_CFR_ENABLE
+void target_if_enh_cfr_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	tx_ops->cfr_tx_ops.cfr_config_rcc =
+		target_if_cfr_config_rcc;
+	tx_ops->cfr_tx_ops.cfr_start_lut_timer =
+		target_if_cfr_start_lut_age_timer;
+	tx_ops->cfr_tx_ops.cfr_stop_lut_timer =
+		target_if_cfr_stop_lut_age_timer;
+	tx_ops->cfr_tx_ops.cfr_default_ta_ra_cfg =
+		target_if_cfr_default_ta_ra_config;
+	tx_ops->cfr_tx_ops.cfr_dump_lut_enh =
+		target_if_cfr_dump_lut_enh;
+	tx_ops->cfr_tx_ops.cfr_rx_tlv_process =
+		target_if_cfr_rx_tlv_process;
+}
+#else
+void target_if_enh_cfr_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+}
+#endif
+
 void target_if_cfr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
 {
 	tx_ops->cfr_tx_ops.cfr_init_pdev =
@@ -240,6 +333,7 @@ void target_if_cfr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
 		target_if_cfr_start_capture;
 	tx_ops->cfr_tx_ops.cfr_stop_capture =
 		target_if_cfr_stop_capture;
+	target_if_enh_cfr_tx_ops(tx_ops);
 }
 
 void target_if_cfr_set_cfr_support(struct wlan_objmgr_psoc *psoc,

+ 17 - 0
target_if/cfr/src/target_if_cfr_6018.c

@@ -1565,6 +1565,20 @@ QDF_STATUS cfr_6018_init_pdev(struct wlan_objmgr_psoc *psoc,
 		return status;
 	}
 
+	pcfr->rcc_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+	pcfr->rcc_param.modified_in_curr_session = MAX_RESET_CFG_ENTRY;
+	pcfr->rcc_param.num_grp_tlvs = MAX_TA_RA_ENTRIES;
+
+	target_if_cfr_default_ta_ra_config(&pcfr->rcc_param,
+					   true, MAX_RESET_CFG_ENTRY);
+
+	status = target_if_cfr_config_rcc(pdev, &pcfr->rcc_param);
+	if (status != QDF_STATUS_SUCCESS) {
+		cfr_err("Failed sending WMI to configure default values\n");
+		return status;
+	}
+	pcfr->rcc_param.modified_in_curr_session = 0;
+
 	pcfr->cfr_max_sta_count = MAX_CFR_ENABLED_CLIENTS;
 	pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_CYP;
 	pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_CYP;
@@ -1632,6 +1646,9 @@ QDF_STATUS cfr_6018_deinit_pdev(struct wlan_objmgr_psoc *psoc,
 		     sizeof(uint64_t) * NUM_CHAN_CAPTURE_STATUS);
 	qdf_mem_zero(&pcfr->bb_captured_reason_cnt,
 		     sizeof(uint64_t) * NUM_CHAN_CAPTURE_REASON);
+	qdf_mem_zero(&pcfr->rcc_param, sizeof(struct cfr_rcc_param));
+	qdf_mem_zero(&pcfr->global, (sizeof(struct ta_ra_cfr_cfg) *
+				     MAX_TA_RA_ENTRIES));
 
 #ifdef DIRECT_BUF_RX_ENABLE
 	status = target_if_unregister_to_dbr_enh(pdev);

+ 53 - 0
umac/cfr/dispatcher/inc/wlan_cfr_tgt_api.h

@@ -107,4 +107,57 @@ uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head,
 			   size_t hlen, void *data, size_t dlen, void *tail,
 			   size_t tlen);
 
+#ifdef WLAN_ENH_CFR_ENABLE
+/**
+ * tgt_cfr_config_rcc() - API to set RCC
+ * @pdev: pointer to pdev_object
+ * @rcc_param: rcc configurations
+ *
+ * Return: succcess / failure
+ */
+QDF_STATUS tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
+			      struct cfr_rcc_param *rcc_param);
+
+/**
+ * tgt_cfr_start_lut_age_timer() - API to start timer to flush aged out LUT
+ * entries
+ * @pdev: pointer to pdev_object
+ *
+ * Return: succcess / failure
+ */
+QDF_STATUS tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * tgt_cfr_stop_lut_age_timer() - API to stop timer to flush aged out LUT
+ * entries
+ * @pdev: pointer to pdev_object
+ *
+ * Return: succcess / failure
+ */
+QDF_STATUS tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * tgt_cfr_default_ta_ra_cfg() - API to configure default values in TA_RA mode
+ * entries
+ * @pdev: pointer to pdev_object
+ *
+ * Return: none
+ */
+void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
+			       struct cfr_rcc_param *rcc_param,
+			       bool allvalid, uint16_t reset_cfg);
+
+/**
+ * tgt_cfr_dump_lut_enh() - Print all LUT entries
+ * @pdev: pointer to pdev_object
+ */
+void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * tgt_cfr_rx_tlv_process() - Process PPDU status TLVs
+ * @pdev_obj: pointer to pdev_object
+ * @nbuf: pointer to cdp_rx_indication_ppdu
+ */
+void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf);
+#endif
 #endif

+ 162 - 0
umac/cfr/dispatcher/inc/wlan_cfr_ucfg_api.h

@@ -21,6 +21,7 @@
 
 #include <wlan_objmgr_peer_obj.h>
 #include <wlan_objmgr_pdev_obj.h>
+#include <ieee80211_ioctl.h>
 
 #define MAX_CFR_PRD        (10*60*1000)        /* 10 minutes */
 
@@ -94,4 +95,165 @@ int ucfg_cfr_set_timer(struct wlan_objmgr_pdev *pdev, uint32_t value);
  * Return: value of cfr_timer_enable
  */
 int ucfg_cfr_get_timer(struct wlan_objmgr_pdev *pdev);
+
+#ifdef WLAN_ENH_CFR_ENABLE
+/* Channel capture recipe filters */
+enum capture_type {
+	RCC_DIRECTED_FTM_FILTER,
+	RCC_ALL_FTM_ACK_FILTER,
+	RCC_DIRECTED_NDPA_NDP_FILTER,
+	RCC_NDPA_NDP_ALL_FILTER,
+	RCC_TA_RA_FILTER,
+	RCC_ALL_PACKET_FILTER,
+	RCC_DIS_ALL_MODE,
+};
+
+/**
+ * ucfg_cfr_set_rcc_mode() - function to set RCC mode
+ * @vdev: pointer to vdev object
+ * @mode: capture type passed by user
+ * @value: Enable/Disable capture mode
+ *
+ * Return: status if the mode is set or not
+ */
+QDF_STATUS ucfg_cfr_set_rcc_mode(struct wlan_objmgr_vdev *vdev,
+				 enum capture_type mode, uint8_t value);
+
+/**
+ * ucfg_cfr_get_rcc_enabled() - function to get RCC mode
+ * @vdev: pointer to vdev object
+ *
+ * Return: if the rcc is enabled or not
+ */
+bool ucfg_cfr_get_rcc_enabled(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_cfr_set_tara_config() - function to configure TA/RA address and mask
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_set_tara_config(struct wlan_objmgr_vdev *vdev,
+				    struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_bw_nss() - function to configure nss and bandwidth
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_set_bw_nss(struct wlan_objmgr_vdev *vdev,
+			       struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_frame_type_subtype() - function to configure frame type/subtype
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS
+ucfg_cfr_set_frame_type_subtype(struct wlan_objmgr_vdev *vdev,
+				struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_capture_duration() - function to configure capture duration
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS
+ucfg_cfr_set_capture_duration(struct wlan_objmgr_vdev *vdev,
+			      struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_capture_interval() - function to configure capture interval
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS
+ucfg_cfr_set_capture_interval(struct wlan_objmgr_vdev *vdev,
+			      struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_en_bitmap() - function to configure 16-bit bitmap in TA_RA mode
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_set_en_bitmap(struct wlan_objmgr_vdev *vdev,
+				  struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_reset_bitmap() - function to clear all 9 params for all 16
+ * groups in TA_RA mode
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_set_reset_bitmap(struct wlan_objmgr_vdev *vdev,
+				     struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_ul_mu_user_mask() - function to configure UL MU user mask
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS
+ucfg_cfr_set_ul_mu_user_mask(struct wlan_objmgr_vdev *vdev,
+			     struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_set_freeze_tlv_delay_cnt() - function to configure freeze TLV delay
+ * count threshold
+ * @vdev: pointer to vdev object
+ * @params: user config
+ *
+ * Return: status
+ */
+QDF_STATUS
+ucfg_cfr_set_freeze_tlv_delay_cnt(struct wlan_objmgr_vdev *vdev,
+				  struct ieee80211_wlanconfig_cfr *params);
+
+/**
+ * ucfg_cfr_committed_rcc_config() - function to commit user config
+ * @vdev: pointer to vdev object
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_committed_rcc_config(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_cfr_get_cfg() - function to display user config
+ * @vdev: pointer to vdev object
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_get_cfg(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_cfr_rcc_dump_dbg_counters() - function to display PPDU counters
+ * @vdev: pointer to vdev object
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_rcc_dump_dbg_counters(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_cfr_rcc_dump_lut() - function to display lookup table
+ * @vdev: pointer to vdev object
+ *
+ * Return: status
+ */
+QDF_STATUS ucfg_cfr_rcc_dump_lut(struct wlan_objmgr_vdev *vdev);
+#endif
 #endif

+ 133 - 0
umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h

@@ -47,6 +47,8 @@
 #define MAX_CFR_MU_USERS 4
 #define NUM_CHAN_CAPTURE_STATUS 4
 #define NUM_CHAN_CAPTURE_REASON 6
+#define MAX_TA_RA_ENTRIES 16
+#define MAX_RESET_CFG_ENTRY 0xFFFF
 #endif
 
 enum cfrmetaversion {
@@ -326,6 +328,117 @@ struct unassoc_pool_entry {
 	bool is_valid;
 };
 
+#ifdef WLAN_ENH_CFR_ENABLE
+/**
+ * struct ta_ra_cfr_cfg - structure to store configuration of 16 groups in
+ * M_TA_RA mode
+ * filter_group_id: Filter group number for which the below filters needs to be
+ * applied
+ * bw: CFR capture will be done for packets matching the bandwidths specified
+ * within this bitmask
+ * nss: CFR capture will be done for packets matching the Nss specified within
+ * this bitmask
+ * valid_ta: Ta_addr is valid if set
+ * valid_ta_mask: Ta_addr_mask is valid if set
+ * valid_ra: Ra_addr is valid if set
+ * valid_ra_mask: Ra_addr_mask is valid if set
+ * valid_bw_mask: Bandwidth is valid if set
+ * valid_nss_mask: NSS is valid if set
+ * valid_mgmt_subtype: Mgmt_subtype is valid if set
+ * valid_ctrl_subtype: Ctrl_subtype is valid if set
+ * valid_data_subtype: Data_subtype is valid if set
+ * mgmt_subtype_filter: Managments Packets matching the subtype filter
+ * categories will be filtered in by MAC for CFR capture.
+ * ctrl_subtype_filter: Control Packets matching the subtype filter
+ * categories will be filtered in by MAC for CFR capture.
+ * data_subtype_filter: Data Packets matching the subtype filter
+ * categories will be filtered in by MAC for CFR capture.
+ * tx_addr: Packets whose transmitter address matches (tx_addr & tx_addr_mask)
+ * will be filtered in by MAC
+ * tx_addr_mask: Packets whose transmitter address matches (tx_addr &
+ * tx_addr_mask) will be filtered in by MAC
+ * rx_addr: Packets whose receiver address matches (rx_addr & rx_addr_mask)
+ * will be filtered in by MAC
+ * rx_addr_mask: Packets whose receiver address matches (rx_addr &
+ * rx_addr_mask) will be filtered in by MAC
+ */
+struct ta_ra_cfr_cfg {
+	uint8_t filter_group_id;
+	uint16_t bw                          :5,
+		 nss                         :8,
+		 rsvd0                       :3;
+	uint16_t valid_ta                    :1,
+		 valid_ta_mask               :1,
+		 valid_ra                    :1,
+		 valid_ra_mask               :1,
+		 valid_bw_mask               :1,
+		 valid_nss_mask              :1,
+		 valid_mgmt_subtype          :1,
+		 valid_ctrl_subtype          :1,
+		 valid_data_subtype          :1,
+		 rsvd1                       :7;
+	uint16_t mgmt_subtype_filter;
+	uint16_t ctrl_subtype_filter;
+	uint16_t data_subtype_filter;
+	uint8_t tx_addr[QDF_MAC_ADDR_SIZE];
+	uint8_t rx_addr[QDF_MAC_ADDR_SIZE];
+	uint8_t tx_addr_mask[QDF_MAC_ADDR_SIZE];
+	uint8_t rx_addr_mask[QDF_MAC_ADDR_SIZE];
+
+} qdf_packed;
+
+/**
+ * struct cfr_rcc_param - structure to store cfr config param
+ * pdev_id: pdev_id for identifying the MAC
+ * capture_duration: Capture Duration field for which CFR capture has to happen,
+ * in microsecond units
+ * capture_interval: Capture interval field which is time in between
+ * consecutive CFR capture, in microsecond units
+ * ul_mu_user_mask_lower: Bitfields indicates which of the users in the current
+ * UL MU tranmission are enabled for CFR capture.
+ * ul_mu_user_mask_upper: This is contiuation of the above lower mask.
+ * freeze_tlv_delay_cnt_en: Enable Freeze TLV delay counter in MAC
+ * freeze_tlv_delay_cnt_thr: Indicates the number of consecutive Rx packets to
+ * be skipped before CFR capture is enabled again.
+ * filter_group_bitmap: Bitfields set indicates which of the CFR group config is
+ * enabled
+ * m_directed_ftm: Filter Directed FTM ACK frames for CFR capture
+ * m_all_ftm_ack: Filter All FTM ACK frames for CFR capture
+ * m_ndpa_ndp_directed: Filter NDPA NDP Directed Frames for CFR capture
+ * m_ndpa_ndp_all: Filter all NDPA NDP for CFR capture
+ * m_ta_ra_filter: Filter Frames based on TA/RA/Subtype as provided in CFR Group
+ * config
+ * m_all_packet: Filter in All packets for CFR Capture
+ * num_grp_tlvs: Indicates the number of groups in M_TA_RA mode, that have
+ * changes in the current commit session, use to construct WMI group TLV(s)
+ * curr: Placeholder for M_TA_RA group config in current commit session
+ * modified_in_curr_session: Bitmap indicating number of groups in M_TA_RA mode
+ * that have changed in current commit session.
+ */
+struct cfr_rcc_param {
+	uint8_t pdev_id;
+	uint32_t capture_duration;
+	uint32_t capture_interval;
+	uint32_t ul_mu_user_mask_lower;
+	uint32_t ul_mu_user_mask_upper;
+	uint16_t freeze_tlv_delay_cnt_en  :1,
+		 freeze_tlv_delay_cnt_thr :8,
+		 rsvd0 :7;
+	uint16_t filter_group_bitmap;
+	uint8_t m_directed_ftm      : 1,
+		m_all_ftm_ack       : 1,
+		m_ndpa_ndp_directed : 1,
+		m_ndpa_ndp_all      : 1,
+		m_ta_ra_filter      : 1,
+		m_all_packet        : 1,
+		rsvd1               : 2;
+	uint8_t num_grp_tlvs;
+
+	struct ta_ra_cfr_cfg curr[MAX_TA_RA_ENTRIES];
+	uint16_t modified_in_curr_session;
+};
+#endif /* WLAN_ENH_CFR_ENABLE */
+
 /**
  * struct pdev_cfr - private pdev object for cfr
  * pdev_obj: pointer to pdev object
@@ -464,4 +577,24 @@ QDF_STATUS wlan_cfr_pdev_open(struct wlan_objmgr_pdev *pdev);
  * Return: status of pdev_close pass/fail
  */
 QDF_STATUS wlan_cfr_pdev_close(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * count_set_bits() - function to count set bits in a bitmap
+ * @value: input bitmap
+ *
+ * Return: No. of set bits
+ */
+uint8_t count_set_bits(uint32_t value);
+
+#ifdef WLAN_ENH_CFR_ENABLE
+/**
+ * wlan_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in
+ * lookup table
+ * @pdev_obj: PDEV object
+ * @nbuf: ppdu info
+ *
+ * Return: none
+ */
+void wlan_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf);
+#endif
 #endif

+ 94 - 0
umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c

@@ -180,3 +180,97 @@ tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer)
 
 	return status;
 }
+
+#ifdef WLAN_ENH_CFR_ENABLE
+QDF_STATUS
+tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
+		   struct cfr_rcc_param *rcc_param)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_config_rcc)
+		status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param);
+
+	if (status != QDF_STATUS_SUCCESS)
+		cfr_err("Error occurred with exit code %d\n", status);
+
+	return status;
+}
+
+QDF_STATUS
+tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_start_lut_timer)
+		status = cfr_tx_ops->cfr_start_lut_timer(pdev);
+
+	if (status != QDF_STATUS_SUCCESS)
+		cfr_err("Error occurred with exit code %d\n", status);
+
+	return status;
+}
+
+QDF_STATUS
+tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_stop_lut_timer)
+		status = cfr_tx_ops->cfr_stop_lut_timer(pdev);
+
+	if (status != QDF_STATUS_SUCCESS)
+		cfr_err("Error occurred with exit code %d\n", status);
+
+	return status;
+}
+
+void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
+			       struct cfr_rcc_param *rcc_param,
+			       bool allvalid, uint16_t reset_cfg)
+{
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_default_ta_ra_cfg)
+		cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param,
+						 allvalid, reset_cfg);
+}
+
+void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_dump_lut_enh)
+		cfr_tx_ops->cfr_dump_lut_enh(pdev);
+}
+
+void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
+{
+	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
+
+	if (cfr_tx_ops->cfr_rx_tlv_process)
+		cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf);
+}
+
+#endif

+ 819 - 0
umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c

@@ -22,6 +22,9 @@
 #include <wlan_cfr_tgt_api.h>
 #include <wlan_objmgr_peer_obj.h>
 #include <wlan_objmgr_pdev_obj.h>
+#ifdef WLAN_ENH_CFR_ENABLE
+#include "cdp_txrx_ctrl.h"
+#endif
 
 int ucfg_cfr_start_capture(struct wlan_objmgr_pdev *pdev,
 			   struct wlan_objmgr_peer *peer,
@@ -272,3 +275,819 @@ int ucfg_cfr_list_peers(struct wlan_objmgr_pdev *pdev)
 {
 	return 0;
 }
+
+#ifdef WLAN_ENH_CFR_ENABLE
+
+static inline
+QDF_STATUS dev_sanity_check(struct wlan_objmgr_vdev *vdev,
+			    struct wlan_objmgr_pdev **ppdev,
+			    struct pdev_cfr **ppcfr)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!vdev) {
+		cfr_err("vdev is NULL\n");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	*ppdev = wlan_vdev_get_pdev(vdev);
+
+	if (!*ppdev) {
+		cfr_err("pdev is NULL\n");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = wlan_objmgr_pdev_try_get_ref(*ppdev, WLAN_CFR_ID);
+	if (status != QDF_STATUS_SUCCESS) {
+		cfr_err("Failed to get pdev reference\n");
+		return status;
+	}
+
+	*ppcfr = wlan_objmgr_pdev_get_comp_private_obj(*ppdev,
+						     WLAN_UMAC_COMP_CFR);
+
+	if (!(*ppcfr)) {
+		cfr_err("pdev object for CFR is null");
+		wlan_objmgr_pdev_release_ref(*ppdev, WLAN_CFR_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!(*ppcfr)->is_cfr_capable) {
+		cfr_err("cfr is not supported on this chip\n");
+		wlan_objmgr_pdev_release_ref(*ppdev, WLAN_CFR_ID);
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
+	return status;
+}
+
+/*
+ * This is needed only in case of m_ta_ra_filter mode.
+ * If user wants to reset the group configurations to default values,
+ * then this handler will come into action.
+ *
+ * If user wants to reset the configurations of 0th, 1st and 3rd group,
+ * then the input should be :
+ *
+ *               wlanconfig ath0 cfr reset_cfg 0xb
+ *
+ */
+
+QDF_STATUS ucfg_cfr_set_reset_bitmap(struct wlan_objmgr_vdev *vdev,
+				     struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.modified_in_curr_session |= params->reset_cfg;
+	tgt_cfr_default_ta_ra_cfg(pdev, &pcfr->rcc_param,
+				  true, params->reset_cfg);
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * This is needed only in case of m_ta_ra_filter mode.
+ * After providing all the group configurations, user should provide
+ * the information about which groups need to be enabled.
+ * Based on that FW will enable the configurations for CFR groups.
+ * If user has to enable only 0th group, then input should be :
+ *
+ *               wlanconfig ath0 cfr en_cfg 0x1
+ *
+ * Enable the bitmap from user provided configuration into cfr_rcc_param.
+ */
+
+QDF_STATUS ucfg_cfr_set_en_bitmap(struct wlan_objmgr_vdev *vdev,
+				  struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.filter_group_bitmap = params->en_cfg;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Copy user provided input for ul_mu_user_mask into cfr_rcc_param.
+ */
+
+QDF_STATUS
+ucfg_cfr_set_ul_mu_user_mask(struct wlan_objmgr_vdev *vdev,
+			     struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.ul_mu_user_mask_lower = params->ul_mu_user_mask_lower;
+	pcfr->rcc_param.ul_mu_user_mask_upper = params->ul_mu_user_mask_upper;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * FREEZE_TLV_DELAY_CNT_* registers are used for FREEZE TLV timeout mechanism
+ * in MAC side. In case MAC send FREEZE TLV to PHY too late due to
+ * long AST delay, PHY ucode may not handle it well or it will impact
+ * next frame’s normal processing, then MAC needs to drop FREEZE TLV
+ * sending process after reaching the threshold.
+ *
+ * This handler will copy user provided input for freeze_tlv_delay_cnt
+ * into cfr_rcc_param.
+ */
+
+QDF_STATUS
+ucfg_cfr_set_freeze_tlv_delay_cnt(struct wlan_objmgr_vdev *vdev,
+				  struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.freeze_tlv_delay_cnt_en =
+		params->freeze_tlv_delay_cnt_en;
+
+	pcfr->rcc_param.freeze_tlv_delay_cnt_thr =
+		params->freeze_tlv_delay_cnt_thr;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Set capture interval from the provided configuration into cfr_rcc_param.
+ * All fixed parameters are needed to be stored into cfr_rcc_param.
+ */
+
+QDF_STATUS
+ucfg_cfr_set_capture_interval(struct wlan_objmgr_vdev *vdev,
+			      struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.capture_interval = params->cap_intvl;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Set capture duration from the provided configuration into cfr_rcc_param.
+ * All fixed parameters are needed to be stored into cfr_rcc_param.
+ */
+
+QDF_STATUS
+ucfg_cfr_set_capture_duration(struct wlan_objmgr_vdev *vdev,
+			      struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	pcfr->rcc_param.capture_duration = params->cap_dur;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Copy user provided group parameters( type/ subtype of mgmt, ctrl, data )
+ * into curr_cfg instance of ta_ra_cfr_cfg.
+ * Set valid mask for the provided configuration.
+ * Set modified_in_this_session for the particular group.
+ */
+
+QDF_STATUS
+ucfg_cfr_set_frame_type_subtype(struct wlan_objmgr_vdev *vdev,
+				struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct ta_ra_cfr_cfg *curr_cfg = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	/* Populating current config based on user's input */
+	curr_cfg = &pcfr->rcc_param.curr[params->grp_id];
+	curr_cfg->mgmt_subtype_filter = params->expected_mgmt_subtype;
+	curr_cfg->ctrl_subtype_filter = params->expected_ctrl_subtype;
+	curr_cfg->data_subtype_filter = params->expected_data_subtype;
+
+	curr_cfg->valid_mgmt_subtype = 1;
+	curr_cfg->valid_ctrl_subtype = 1;
+	curr_cfg->valid_data_subtype = 1;
+
+	qdf_set_bit(params->grp_id,
+		    (unsigned long *)
+		    &pcfr->rcc_param.modified_in_curr_session);
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Copy user provided group parameters( BW and NSS )
+ * into curr_cfg instance of ta_ra_cfr_cfg.
+ * Set valid mask for the provided configuration.
+ * Set modified_in_this_session for the particular group.
+ */
+
+QDF_STATUS ucfg_cfr_set_bw_nss(struct wlan_objmgr_vdev *vdev,
+			       struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct ta_ra_cfr_cfg *curr_cfg = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	/* Populating current config based on user's input */
+	curr_cfg = &pcfr->rcc_param.curr[params->grp_id];
+	curr_cfg->bw = params->bw;
+	curr_cfg->nss = params->nss;
+
+	curr_cfg->valid_bw_mask = 1;
+	curr_cfg->valid_nss_mask = 1;
+
+	qdf_set_bit(params->grp_id,
+		    (unsigned long *)&pcfr->rcc_param.modified_in_curr_session);
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * Copy user provided group parameters( TA, RA, TA_MASK, RA_MASK )
+ * into curr_cfg instance of ta_ra_cfr_cfg.
+ * Set valid mask for the provided configuration.
+ * Set modified_in_this_session for the particular group.
+ */
+
+QDF_STATUS ucfg_cfr_set_tara_config(struct wlan_objmgr_vdev *vdev,
+				    struct ieee80211_wlanconfig_cfr *params)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct ta_ra_cfr_cfg *curr_cfg = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	curr_cfg = &pcfr->rcc_param.curr[params->grp_id];
+	qdf_mem_copy(curr_cfg->tx_addr, params->ta, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(curr_cfg->rx_addr, params->ra, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(curr_cfg->tx_addr_mask,
+		     params->ta_mask, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(curr_cfg->rx_addr_mask,
+		     params->ra_mask, QDF_MAC_ADDR_SIZE);
+
+	curr_cfg->valid_ta = 1;
+	curr_cfg->valid_ta_mask = 1;
+	curr_cfg->valid_ra = 1;
+	curr_cfg->valid_ra_mask = 1;
+
+	qdf_set_bit(params->grp_id,
+		    (unsigned long *)
+		    &pcfr->rcc_param.modified_in_curr_session);
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+void cfr_update_global_cfg(struct pdev_cfr *pdev_cfrobj)
+{
+	int grp_id;
+	struct ta_ra_cfr_cfg *curr_cfg = NULL;
+	struct ta_ra_cfr_cfg *glbl_cfg = NULL;
+	unsigned long *modified_in_this_session =
+	 (unsigned long *)&pdev_cfrobj->rcc_param.modified_in_curr_session;
+
+	for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
+		if (qdf_test_bit(grp_id, modified_in_this_session)) {
+			/* Populating global config based on user's input */
+			glbl_cfg = &pdev_cfrobj->global[grp_id];
+			curr_cfg = &pdev_cfrobj->rcc_param.curr[grp_id];
+
+			if (curr_cfg->valid_ta)
+				qdf_mem_copy(glbl_cfg->tx_addr,
+					     curr_cfg->tx_addr,
+					     QDF_MAC_ADDR_SIZE);
+
+			if (curr_cfg->valid_ra)
+				qdf_mem_copy(glbl_cfg->rx_addr,
+					     curr_cfg->rx_addr,
+					     QDF_MAC_ADDR_SIZE);
+
+			if (curr_cfg->valid_ta_mask)
+				qdf_mem_copy(glbl_cfg->tx_addr_mask,
+					     curr_cfg->tx_addr_mask,
+					     QDF_MAC_ADDR_SIZE);
+
+			if (curr_cfg->valid_ra_mask)
+				qdf_mem_copy(glbl_cfg->rx_addr_mask,
+					     curr_cfg->rx_addr_mask,
+					     QDF_MAC_ADDR_SIZE);
+
+			if (curr_cfg->valid_bw_mask)
+				glbl_cfg->bw = curr_cfg->bw;
+
+			if (curr_cfg->valid_nss_mask)
+				glbl_cfg->nss = curr_cfg->nss;
+
+			if (curr_cfg->valid_mgmt_subtype)
+				glbl_cfg->mgmt_subtype_filter =
+					curr_cfg->mgmt_subtype_filter;
+
+			if (curr_cfg->valid_ctrl_subtype)
+				glbl_cfg->ctrl_subtype_filter =
+					curr_cfg->ctrl_subtype_filter;
+
+			if (curr_cfg->valid_data_subtype)
+				glbl_cfg->data_subtype_filter =
+					curr_cfg->data_subtype_filter;
+		}
+	}
+}
+
+QDF_STATUS ucfg_cfr_get_cfg(struct wlan_objmgr_vdev *vdev)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct ta_ra_cfr_cfg *glbl_cfg = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t grp_id;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	cfr_info("CAPTURE MODE:\n");
+
+	cfr_info("m_directed_ftm is : %s\n",
+		 pcfr->rcc_param.m_directed_ftm ?
+		 "enabled" : "disabled");
+	cfr_info("m_all_ftm_ack is : %s\n",
+		 pcfr->rcc_param.m_all_ftm_ack ?
+		 "enabled" : "disabled");
+	cfr_info("m_ndpa_ndp_directed is: %s\n",
+		 pcfr->rcc_param.m_ndpa_ndp_directed ?
+		 "enabled" : "disabled");
+	cfr_info("m_ndpa_ndp_all is : %s\n",
+		 pcfr->rcc_param.m_ndpa_ndp_all ?
+		 "enabled" : "disabled");
+	cfr_info("m_ta_ra_filter is : %s\n",
+		 pcfr->rcc_param.m_ta_ra_filter ?
+		 "enabled" : "disabled");
+	cfr_info("m_all_packet is : %s\n",
+		 pcfr->rcc_param.m_all_packet ?
+		 "enabled" : "disabled");
+
+	cfr_info("capture duration : %u usec\n",
+		 pcfr->rcc_param.capture_duration);
+	cfr_info("capture interval : %u usec\n",
+		 pcfr->rcc_param.capture_interval);
+	cfr_info("UL MU User mask lower : %u\n",
+		 pcfr->rcc_param.ul_mu_user_mask_lower);
+	cfr_info("UL MU User mask upper : %u\n",
+		 pcfr->rcc_param.ul_mu_user_mask_upper);
+	cfr_info("Freeze TLV delay count is : %s\n",
+		 pcfr->rcc_param.freeze_tlv_delay_cnt_en ?
+		 "enabled" : "disabled");
+	cfr_info("Freeze TLV delay count threshold : %u\n",
+		 pcfr->rcc_param.freeze_tlv_delay_cnt_thr);
+	cfr_info("Enabled CFG id bitmap : 0x%x\n",
+		 pcfr->rcc_param.filter_group_bitmap);
+	cfr_info(" Modified cfg id bitmap : 0x%x\n",
+		 pcfr->rcc_param.modified_in_curr_session);
+
+	cfr_info("TARA_CONFIG details:\n");
+
+	for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
+		glbl_cfg = &pcfr->global[grp_id];
+
+		cfr_info("Config ID: %d\n", grp_id);
+		cfr_info("Bandwidth :0x%x\n", glbl_cfg->bw);
+		cfr_info("NSS : 0x%x\n", glbl_cfg->nss);
+		cfr_info("valid_ta: %d\n", glbl_cfg->valid_ta);
+		cfr_info("valid_ta_mask: %d\n", glbl_cfg->valid_ta_mask);
+		cfr_info("valid_ra: %d\n", glbl_cfg->valid_ra);
+		cfr_info("valid_ra_mask: %d\n", glbl_cfg->valid_ra_mask);
+		cfr_info("valid_bw_mask: %d\n", glbl_cfg->valid_bw_mask);
+		cfr_info("valid_nss_mask: %d\n", glbl_cfg->valid_nss_mask);
+		cfr_info("valid_mgmt_subtype: %d\n",
+			 glbl_cfg->valid_mgmt_subtype);
+		cfr_info("valid_ctrl_subtype: %d\n",
+			 glbl_cfg->valid_ctrl_subtype);
+		cfr_info("valid_data_subtype: %d\n",
+			 glbl_cfg->valid_data_subtype);
+		cfr_info("Mgmt subtype : 0x%x\n",
+			 glbl_cfg->mgmt_subtype_filter);
+		cfr_info("CTRL subtype : 0x%x\n",
+			 glbl_cfg->ctrl_subtype_filter);
+		cfr_info("Data subtype : 0x%x\n",
+			 glbl_cfg->data_subtype_filter);
+		cfr_info("TX Addr : %s\n",
+			 ether_sprintf(glbl_cfg->tx_addr));
+		cfr_info("TX Addr Mask : %s\n",
+			 ether_sprintf(glbl_cfg->tx_addr_mask));
+		cfr_info("RX Addr : %s\n",
+			 ether_sprintf(glbl_cfg->rx_addr));
+		cfr_info("RX Addr Mask: %s\n",
+			 ether_sprintf(glbl_cfg->rx_addr_mask));
+	}
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+static const char *chan_capture_status_to_str(enum chan_capture_status type)
+{
+	switch (type) {
+	case CAPTURE_IDLE:
+		return "CAPTURE_IDLE";
+	case CAPTURE_BUSY:
+		return "CAPTURE_BUSY";
+	case CAPTURE_ACTIVE:
+		return "CAPTURE_ACTIVE";
+	case CAPTURE_NO_BUFFER:
+		return "CAPTURE_NO_BUFFER";
+	default:
+		return "NONE";
+	}
+}
+
+static const
+char *mac_freeze_reason_to_str(enum mac_freeze_capture_reason type)
+{
+	switch (type) {
+	case FREEZE_REASON_TM:
+		return "FREEZE_REASON_TM";
+	case FREEZE_REASON_FTM:
+		return "FREEZE_REASON_FTM";
+	case FREEZE_REASON_ACK_RESP_TO_TM_FTM:
+		return "FREEZE_REASON_ACK_RESP_TO_TM_FTM";
+	case FREEZE_REASON_TA_RA_TYPE_FILTER:
+		return "FREEZE_REASON_TA_RA_TYPE_FILTER";
+	case FREEZE_REASON_NDPA_NDP:
+		return "FREEZE_REASON_NDPA_NDP";
+	case FREEZE_REASON_ALL_PACKET:
+		return "FREEZE_REASON_ALL_PACKET";
+	default:
+		return "NONE";
+	}
+}
+
+QDF_STATUS ucfg_cfr_rcc_dump_dbg_counters(struct wlan_objmgr_vdev *vdev)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	int counter;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	cfr_info("bb_captured_channel_cnt = %llu\n",
+		 pcfr->bb_captured_channel_cnt);
+	cfr_info("bb_captured_timeout_cnt = %llu\n",
+		 pcfr->bb_captured_timeout_cnt);
+	cfr_info("rx_loc_info_valid_cnt = %llu\n",
+		 pcfr->rx_loc_info_valid_cnt);
+	cfr_info("tx_evt_cnt = %llu\n",
+		 pcfr->tx_evt_cnt);
+	cfr_info("dbr_evt_cnt = %llu\n",
+		 pcfr->dbr_evt_cnt);
+	cfr_info("rx_tlv_evt_cnt = %llu\n",
+		 pcfr->rx_tlv_evt_cnt);
+	cfr_info("release_cnt = %llu\n",
+		 pcfr->release_cnt);
+	cfr_info("Error cnt:\n");
+	cfr_info("flush_dbr_cnt = %llu\n",
+		 pcfr->flush_dbr_cnt);
+	cfr_info("invalid_dma_length_cnt = %llu\n",
+		 pcfr->invalid_dma_length_cnt);
+	cfr_info("flush_all_dbr_cnt = %llu\n",
+		 pcfr->flush_all_dbr_cnt);
+	cfr_info("flush_all_txrx_cnt = %llu\n",
+		 pcfr->flush_all_txrx_cnt);
+	cfr_info("flush_timeout_dbr_cnt = %llu\n",
+		 pcfr->flush_timeout_dbr_cnt);
+	cfr_info("flush_timeout_txrx_cnt = %llu\n",
+		 pcfr->flush_timeout_txrx_cnt);
+	cfr_info("PPDU id mismatch for same cookie:\n");
+	cfr_info("clear_dbr_event = %llu\n",
+		 pcfr->clear_dbr_event);
+	cfr_info("clear_txrx_event = %llu\n",
+		 pcfr->clear_txrx_event);
+
+	cfr_info("Channel capture status:\n");
+	for (counter = 0; counter < CAPTURE_MAX; counter++) {
+		cfr_info("%s = %llu\n",
+			 chan_capture_status_to_str(counter),
+			 pcfr->chan_capture_status[counter]);
+	}
+
+	cfr_info("Freeze reason:\n");
+	for (counter = 0; counter < FREEZE_REASON_MAX; counter++) {
+		cfr_info("%s = %llu\n",
+			 mac_freeze_reason_to_str(counter),
+			 pcfr->bb_captured_reason_cnt[counter]);
+	}
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+QDF_STATUS ucfg_cfr_rcc_dump_lut(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!vdev) {
+		cfr_err("vdev is NULL\n");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		cfr_err("pdev is NULL\n");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID) !=
+	    QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_INVAL;
+	}
+
+	cfr_info("LUT table:\n");
+	tgt_cfr_dump_lut_enh(pdev);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+void cfr_set_filter(struct wlan_objmgr_pdev *pdev,
+		    bool enable, struct cdp_monitor_filter *filter_val)
+{
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+
+	cfr_info("pdev_id=%d\n", wlan_objmgr_pdev_get_pdev_id(pdev));
+
+	cdp_cfr_filter(wlan_psoc_get_dp_handle(psoc),
+		       wlan_pdev_get_dp_handle(pdev),
+		       enable, filter_val);
+}
+
+static bool cfr_is_filter_enabled(struct cfr_rcc_param *rcc_param)
+{
+	if (rcc_param->m_directed_ftm ||
+	    rcc_param->m_all_ftm_ack ||
+	    rcc_param->m_ndpa_ndp_directed ||
+	    rcc_param->m_ndpa_ndp_all ||
+	    rcc_param->m_ta_ra_filter ||
+	    rcc_param->m_all_packet)
+		return true;
+	else
+		return false;
+}
+
+/*
+ * With the initiation of commit command, this handler will be triggered.
+ *
+ * Starts the procedure of forming the TLVs.
+ * If Host succeeds to send WMI command to FW, after TLV processing, then it
+ * will save the previous CFR configurations into one instance ta_ra_cfr_cfg,
+ * called glbl_cfg and update the current config to default state for the
+ * next commit session.
+ *
+ * Finally, reset the counter (modified_in_this_session) to 0 before moving to
+ * next commit session.
+ *
+ */
+
+QDF_STATUS ucfg_cfr_committed_rcc_config(struct wlan_objmgr_vdev *vdev)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct cdp_monitor_filter filter_val = {0};
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	/*
+	 * If capture mode is valid, then Host:
+	 * Subscribes for PPDU status TLVs in monitor status ring.
+	 * Sets filter type to either FP or MO, based on the capture mode.
+	 * Starts the LUT_AGE_TIMER of 1sec.
+	 *
+	 * If capture mode is disabled, then Host:
+	 * unsubscribes for PPDU status TLVs in monitor status ring.
+	 * Sets filter type to 0.
+	 * Stops the LUT_AGE_TIMER.
+	 *
+	 */
+
+	if (cfr_is_filter_enabled(&pcfr->rcc_param)) {
+		if (pcfr->rcc_param.m_all_ftm_ack) {
+			filter_val.mode |= MON_FILTER_PASS |
+					   MON_FILTER_OTHER;
+			filter_val.fp_mgmt |= FILTER_MGMT_ACTION;
+			filter_val.mo_mgmt |= FILTER_MGMT_ACTION;
+		}
+
+		if (pcfr->rcc_param.m_ndpa_ndp_all) {
+			filter_val.mode |= MON_FILTER_PASS |
+					   MON_FILTER_OTHER;
+			filter_val.fp_ctrl |= FILTER_CTRL_VHT_NDP;
+			filter_val.mo_ctrl |= FILTER_CTRL_VHT_NDP;
+		}
+
+		if (pcfr->rcc_param.m_all_packet) {
+			filter_val.mode |= MON_FILTER_PASS |
+					   MON_FILTER_OTHER;
+			filter_val.fp_mgmt |= FILTER_MGMT_ALL;
+			filter_val.mo_mgmt |= FILTER_MGMT_ALL;
+			filter_val.fp_ctrl |= FILTER_CTRL_ALL;
+			filter_val.mo_ctrl |= FILTER_CTRL_ALL;
+			filter_val.fp_data |= FILTER_DATA_ALL;
+			filter_val.mo_data |= FILTER_DATA_ALL;
+		}
+
+		/*
+		 * M_TA_RA in monitor other is as intensive as M_ALL pkt
+		 * Support only FP in M_TA_RA mode
+		 */
+		if (pcfr->rcc_param.m_ta_ra_filter) {
+			filter_val.mode |= MON_FILTER_PASS |
+					   MON_FILTER_OTHER;
+			filter_val.fp_mgmt |= FILTER_MGMT_ALL;
+			filter_val.mo_mgmt |= FILTER_MGMT_ALL;
+			filter_val.fp_ctrl |= FILTER_CTRL_ALL;
+			filter_val.mo_ctrl |= FILTER_CTRL_ALL;
+			filter_val.fp_data |= FILTER_DATA_ALL;
+			filter_val.mo_data |= FILTER_DATA_ALL;
+		}
+
+		if (pcfr->rcc_param.m_directed_ftm) {
+			filter_val.mode |= MON_FILTER_PASS;
+			filter_val.fp_mgmt |= FILTER_MGMT_ACTION;
+		}
+
+		if (pcfr->rcc_param.m_ndpa_ndp_directed) {
+			filter_val.mode |= MON_FILTER_PASS;
+			filter_val.fp_ctrl |= FILTER_CTRL_VHT_NDP;
+		}
+
+		cfr_set_filter(pdev, 1, &filter_val);
+		tgt_cfr_start_lut_age_timer(pdev);
+	} else {
+		cfr_set_filter(pdev, 0, &filter_val);
+		tgt_cfr_stop_lut_age_timer(pdev);
+	}
+
+	/* Trigger wmi to start the TLV processing. */
+	status = tgt_cfr_config_rcc(pdev, &pcfr->rcc_param);
+	if (status == QDF_STATUS_SUCCESS) {
+		cfr_info("CFR commit done\n");
+		/* Update glbl cfg */
+		cfr_update_global_cfg(pcfr);
+
+		/* Bring curr_cfg to default state for next commit session */
+		tgt_cfr_default_ta_ra_cfg(pdev, &pcfr->rcc_param,
+					  false, MAX_RESET_CFG_ENTRY);
+	} else {
+		cfr_err("CFR commit failed\n");
+	}
+
+	pcfr->rcc_param.num_grp_tlvs = 0;
+	pcfr->rcc_param.modified_in_curr_session = 0;
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+/*
+ * This handler is used to enable / disable the capture mode.
+ *
+ */
+QDF_STATUS ucfg_cfr_set_rcc_mode(struct wlan_objmgr_vdev *vdev,
+				 enum capture_type mode, uint8_t value)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return status;
+
+	switch (mode) {
+	case RCC_DIRECTED_FTM_FILTER:
+		pcfr->rcc_param.m_directed_ftm = value;
+		break;
+	case RCC_ALL_FTM_ACK_FILTER:
+		pcfr->rcc_param.m_all_ftm_ack = value;
+		break;
+	case RCC_DIRECTED_NDPA_NDP_FILTER:
+		pcfr->rcc_param.m_ndpa_ndp_directed = value;
+		break;
+	case RCC_NDPA_NDP_ALL_FILTER:
+		pcfr->rcc_param.m_ndpa_ndp_all = value;
+		break;
+	case RCC_TA_RA_FILTER:
+		pcfr->rcc_param.m_ta_ra_filter = value;
+		break;
+	case RCC_ALL_PACKET_FILTER:
+		pcfr->rcc_param.m_all_packet = value;
+		break;
+	case RCC_DIS_ALL_MODE:
+		pcfr->rcc_param.m_directed_ftm = value;
+		pcfr->rcc_param.m_all_ftm_ack = value;
+		pcfr->rcc_param.m_ndpa_ndp_directed = value;
+		pcfr->rcc_param.m_ndpa_ndp_all = value;
+		pcfr->rcc_param.m_ta_ra_filter = value;
+		pcfr->rcc_param.m_all_packet = value;
+		break;
+
+	default:
+		break;
+	}
+
+	cfr_debug("<CFR_UMAC> Capture mode set by user: 0x%x\n", value);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return status;
+}
+
+bool ucfg_cfr_get_rcc_enabled(struct wlan_objmgr_vdev *vdev)
+{
+	struct pdev_cfr *pcfr = NULL;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool rcc_enabled = false;
+
+	status = dev_sanity_check(vdev, &pdev, &pcfr);
+	if (status != QDF_STATUS_SUCCESS)
+		return false;
+
+	rcc_enabled = cfr_is_filter_enabled(&pcfr->rcc_param);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
+
+	return rcc_enabled;
+}
+#endif

+ 23 - 0
umac/cfr/dispatcher/src/wlan_cfr_utils_api.c

@@ -159,3 +159,26 @@ QDF_STATUS cfr_deinitialize_pdev(struct wlan_objmgr_pdev *pdev)
 	return status;
 }
 qdf_export_symbol(cfr_deinitialize_pdev);
+
+uint8_t count_set_bits(uint32_t value)
+{
+	uint8_t count = 0;
+
+	while (value) {
+		value &= (value - 1);
+		count++;
+	}
+
+	return count;
+}
+
+qdf_export_symbol(count_set_bits);
+
+#ifdef WLAN_ENH_CFR_ENABLE
+void wlan_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
+{
+	tgt_cfr_rx_tlv_process(pdev, nbuf);
+}
+
+qdf_export_symbol(wlan_cfr_rx_tlv_process);
+#endif