Jelajahi Sumber

qca-wifi: Enhanced channel capture UCFG framework

Framework to accumulate RCC configurations until user issues commit
command. Once commit command is issued, all the gathered configurations
are sent to FW through WMI fixed and variable TLVs.

Change-Id: I84fec42d22a3b4eceb710b72d89a7c3047fed1f6
CRs-Fixed: 2582833
Adwait Nayak 5 tahun lalu
induk
melakukan
1a4ad8923f

+ 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