xref: /wlan-driver/qca-wifi-host-cmn/wmi/src/wmi_unified_cfr_tlv.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
6*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
7*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*5113495bSYour Name  */
17*5113495bSYour Name 
18*5113495bSYour Name #include <osdep.h>
19*5113495bSYour Name #include "wmi.h"
20*5113495bSYour Name #include "wmi_unified_priv.h"
21*5113495bSYour Name #include "wmi_unified_cfr_param.h"
22*5113495bSYour Name #include "wmi_unified_cfr_api.h"
23*5113495bSYour Name 
24*5113495bSYour Name #ifdef WLAN_CFR_ENABLE
25*5113495bSYour Name static QDF_STATUS
extract_cfr_peer_tx_event_param_tlv(wmi_unified_t wmi_handle,void * evt_buf,wmi_cfr_peer_tx_event_param * peer_tx_event)26*5113495bSYour Name extract_cfr_peer_tx_event_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
27*5113495bSYour Name 				    wmi_cfr_peer_tx_event_param *peer_tx_event)
28*5113495bSYour Name {
29*5113495bSYour Name 	int idx;
30*5113495bSYour Name 	WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *param_buf;
31*5113495bSYour Name 	wmi_peer_cfr_capture_event_fixed_param *peer_tx_event_ev;
32*5113495bSYour Name 	wmi_peer_cfr_capture_event_phase_fixed_param *chain_phase_ev;
33*5113495bSYour Name 
34*5113495bSYour Name 	param_buf = (WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *)evt_buf;
35*5113495bSYour Name 	if (!param_buf) {
36*5113495bSYour Name 		wmi_err("Invalid cfr capture buffer");
37*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
38*5113495bSYour Name 	}
39*5113495bSYour Name 
40*5113495bSYour Name 	peer_tx_event_ev = param_buf->fixed_param;
41*5113495bSYour Name 	if (!peer_tx_event_ev) {
42*5113495bSYour Name 		wmi_err("peer cfr capture buffer is null");
43*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
44*5113495bSYour Name 	}
45*5113495bSYour Name 
46*5113495bSYour Name 	peer_tx_event->capture_method = peer_tx_event_ev->capture_method;
47*5113495bSYour Name 	peer_tx_event->vdev_id = peer_tx_event_ev->vdev_id;
48*5113495bSYour Name 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_tx_event_ev->mac_addr,
49*5113495bSYour Name 				   &peer_tx_event->peer_mac_addr.bytes[0]);
50*5113495bSYour Name 	peer_tx_event->primary_20mhz_chan =
51*5113495bSYour Name 		peer_tx_event_ev->chan_mhz;
52*5113495bSYour Name 	peer_tx_event->bandwidth = peer_tx_event_ev->bandwidth;
53*5113495bSYour Name 	peer_tx_event->phy_mode = peer_tx_event_ev->phy_mode;
54*5113495bSYour Name 	peer_tx_event->band_center_freq1 = peer_tx_event_ev->band_center_freq1;
55*5113495bSYour Name 	peer_tx_event->band_center_freq2 = peer_tx_event_ev->band_center_freq2;
56*5113495bSYour Name 	peer_tx_event->spatial_streams = peer_tx_event_ev->sts_count;
57*5113495bSYour Name 	peer_tx_event->correlation_info_1 =
58*5113495bSYour Name 		peer_tx_event_ev->correlation_info_1;
59*5113495bSYour Name 	peer_tx_event->correlation_info_2 =
60*5113495bSYour Name 		peer_tx_event_ev->correlation_info_2;
61*5113495bSYour Name 	peer_tx_event->status = peer_tx_event_ev->status;
62*5113495bSYour Name 	peer_tx_event->timestamp_us = peer_tx_event_ev->timestamp_us;
63*5113495bSYour Name 	peer_tx_event->counter = peer_tx_event_ev->counter;
64*5113495bSYour Name 	qdf_mem_copy(peer_tx_event->chain_rssi, peer_tx_event_ev->chain_rssi,
65*5113495bSYour Name 		     sizeof(peer_tx_event->chain_rssi));
66*5113495bSYour Name 	if (peer_tx_event_ev->cfo_measurement_valid)
67*5113495bSYour Name 		peer_tx_event->cfo_measurement =
68*5113495bSYour Name 			peer_tx_event_ev->cfo_measurement;
69*5113495bSYour Name 	else
70*5113495bSYour Name 		peer_tx_event->cfo_measurement = 0;
71*5113495bSYour Name 
72*5113495bSYour Name 	peer_tx_event->rx_start_ts = peer_tx_event_ev->rx_start_ts;
73*5113495bSYour Name 	peer_tx_event->rx_ts_reset = peer_tx_event_ev->rx_ts_reset;
74*5113495bSYour Name 	peer_tx_event->mcs_rate =
75*5113495bSYour Name 		WMI_CFR_MCS_GET(peer_tx_event_ev->mcs_gi_info);
76*5113495bSYour Name 	peer_tx_event->gi_type =
77*5113495bSYour Name 		WMI_CFR_GI_TYPE_GET(peer_tx_event_ev->mcs_gi_info);
78*5113495bSYour Name 
79*5113495bSYour Name 	chain_phase_ev = param_buf->phase_param;
80*5113495bSYour Name 	if (chain_phase_ev) {
81*5113495bSYour Name 		for (idx = 0; idx < WMI_HOST_MAX_CHAINS; idx++) {
82*5113495bSYour Name 			/* Due to FW's alignment rules, phase information being
83*5113495bSYour Name 			 * passed is 32-bit, out of which only 16 bits is valid.
84*5113495bSYour Name 			 * Remaining bits are all zeroed. So direct mem copy
85*5113495bSYour Name 			 * will not work as it will copy extra zeroes into host
86*5113495bSYour Name 			 * structures.
87*5113495bSYour Name 			 */
88*5113495bSYour Name 			peer_tx_event->chain_phase[idx] =
89*5113495bSYour Name 				(0xffff & chain_phase_ev->chain_phase[idx]);
90*5113495bSYour Name 			peer_tx_event->agc_gain[idx] =
91*5113495bSYour Name 				WMI_UNIFIED_AGC_GAIN_GET(chain_phase_ev, idx);
92*5113495bSYour Name 			peer_tx_event->agc_gain_tbl_index[idx] =
93*5113495bSYour Name 				WMI_UNIFIED_AGC_GAIN_TBL_IDX_GET(chain_phase_ev,
94*5113495bSYour Name 								 idx);
95*5113495bSYour Name 		}
96*5113495bSYour Name 	}
97*5113495bSYour Name 
98*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
99*5113495bSYour Name }
100*5113495bSYour Name 
101*5113495bSYour Name #ifdef WLAN_ENH_CFR_ENABLE
populate_wmi_cfr_param(uint8_t grp_id,struct cfr_rcc_param * rcc,wmi_cfr_filter_group_config * param)102*5113495bSYour Name static void populate_wmi_cfr_param(uint8_t grp_id, struct cfr_rcc_param *rcc,
103*5113495bSYour Name 				   wmi_cfr_filter_group_config *param)
104*5113495bSYour Name {
105*5113495bSYour Name 	struct ta_ra_cfr_cfg *tgt_cfg = NULL;
106*5113495bSYour Name 
107*5113495bSYour Name 	WMITLV_SET_HDR(&param->tlv_header,
108*5113495bSYour Name 		       WMITLV_TAG_STRUC_wmi_cfr_filter_group_config,
109*5113495bSYour Name 		       WMITLV_GET_STRUCT_TLVLEN
110*5113495bSYour Name 		       (wmi_cfr_filter_group_config));
111*5113495bSYour Name 	tgt_cfg  = &rcc->curr[grp_id];
112*5113495bSYour Name 
113*5113495bSYour Name 	param->filter_group_id = grp_id;
114*5113495bSYour Name 	WMI_CFR_GROUP_TA_ADDR_VALID_SET(param->filter_set_valid_mask,
115*5113495bSYour Name 					tgt_cfg->valid_ta);
116*5113495bSYour Name 	WMI_CFR_GROUP_TA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
117*5113495bSYour Name 					     tgt_cfg->valid_ta_mask);
118*5113495bSYour Name 	WMI_CFR_GROUP_RA_ADDR_VALID_SET(param->filter_set_valid_mask,
119*5113495bSYour Name 					tgt_cfg->valid_ra);
120*5113495bSYour Name 	WMI_CFR_GROUP_RA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
121*5113495bSYour Name 					     tgt_cfg->valid_ra_mask);
122*5113495bSYour Name 	WMI_CFR_GROUP_BW_VALID_SET(param->filter_set_valid_mask,
123*5113495bSYour Name 				   tgt_cfg->valid_bw_mask);
124*5113495bSYour Name 	WMI_CFR_GROUP_NSS_VALID_SET(param->filter_set_valid_mask,
125*5113495bSYour Name 				    tgt_cfg->valid_nss_mask);
126*5113495bSYour Name 	WMI_CFR_GROUP_MGMT_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
127*5113495bSYour Name 					     tgt_cfg->valid_mgmt_subtype);
128*5113495bSYour Name 	WMI_CFR_GROUP_CTRL_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
129*5113495bSYour Name 					     tgt_cfg->valid_ctrl_subtype);
130*5113495bSYour Name 	WMI_CFR_GROUP_DATA_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
131*5113495bSYour Name 					     tgt_cfg->valid_data_subtype);
132*5113495bSYour Name 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr,
133*5113495bSYour Name 				   &param->ta_addr);
134*5113495bSYour Name 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr_mask,
135*5113495bSYour Name 				   &param->ta_addr_mask);
136*5113495bSYour Name 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr,
137*5113495bSYour Name 				   &param->ra_addr);
138*5113495bSYour Name 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr_mask,
139*5113495bSYour Name 				   &param->ra_addr_mask);
140*5113495bSYour Name 	WMI_CFR_GROUP_BW_SET(param->bw_nss_filter,
141*5113495bSYour Name 			     tgt_cfg->bw);
142*5113495bSYour Name 	WMI_CFR_GROUP_NSS_SET(param->bw_nss_filter,
143*5113495bSYour Name 			      tgt_cfg->nss);
144*5113495bSYour Name 	param->mgmt_subtype_filter = tgt_cfg->mgmt_subtype_filter;
145*5113495bSYour Name 	param->ctrl_subtype_filter = tgt_cfg->ctrl_subtype_filter;
146*5113495bSYour Name 	param->data_subtype_filter = tgt_cfg->data_subtype_filter;
147*5113495bSYour Name }
148*5113495bSYour Name 
send_cfr_rcc_cmd_tlv(wmi_unified_t wmi_handle,struct cfr_rcc_param * rcc)149*5113495bSYour Name static QDF_STATUS send_cfr_rcc_cmd_tlv(wmi_unified_t wmi_handle,
150*5113495bSYour Name 				       struct cfr_rcc_param *rcc)
151*5113495bSYour Name {
152*5113495bSYour Name 	wmi_cfr_capture_filter_cmd_fixed_param *cmd;
153*5113495bSYour Name 	wmi_cfr_filter_group_config *param;
154*5113495bSYour Name 	uint8_t *buf_ptr, grp_id;
155*5113495bSYour Name 	wmi_buf_t buf;
156*5113495bSYour Name 	uint32_t len;
157*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
158*5113495bSYour Name 	struct wmi_ops *ops = wmi_handle->ops;
159*5113495bSYour Name 
160*5113495bSYour Name 	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
161*5113495bSYour Name 	len += rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config);
162*5113495bSYour Name 	buf = wmi_buf_alloc(wmi_handle, len);
163*5113495bSYour Name 
164*5113495bSYour Name 	if (!buf) {
165*5113495bSYour Name 		wmi_err("wmi_buf_alloc failed");
166*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
167*5113495bSYour Name 	}
168*5113495bSYour Name 
169*5113495bSYour Name 	buf_ptr = wmi_buf_data(buf);
170*5113495bSYour Name 	cmd = (wmi_cfr_capture_filter_cmd_fixed_param *)buf_ptr;
171*5113495bSYour Name 
172*5113495bSYour Name 	WMITLV_SET_HDR(&cmd->tlv_header,
173*5113495bSYour Name 		       WMITLV_TAG_STRUC_wmi_cfr_capture_filter_cmd_fixed_param,
174*5113495bSYour Name 		       WMITLV_GET_STRUCT_TLVLEN
175*5113495bSYour Name 		       (wmi_cfr_capture_filter_cmd_fixed_param));
176*5113495bSYour Name 	cmd->pdev_id = ops->convert_host_pdev_id_to_target(wmi_handle,
177*5113495bSYour Name 							   rcc->pdev_id);
178*5113495bSYour Name 	WMI_CFR_CAPTURE_INTERVAL_SET(cmd->capture_interval,
179*5113495bSYour Name 				     rcc->capture_interval);
180*5113495bSYour Name 	WMI_CFR_CAPTURE_DURATION_SET(cmd->capture_duration,
181*5113495bSYour Name 				     rcc->capture_duration);
182*5113495bSYour Name 	WMI_CFR_CAPTURE_COUNT_SET(cmd->capture_count, rcc->capture_count);
183*5113495bSYour Name 	WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_SET(cmd->capture_count,
184*5113495bSYour Name 					      rcc->capture_intval_mode_sel);
185*5113495bSYour Name 	WMI_CFR_FILTER_GROUP_BITMAP_SET(cmd->filter_group_bitmap,
186*5113495bSYour Name 					rcc->filter_group_bitmap);
187*5113495bSYour Name 	WMI_CFR_UL_MU_USER_UPPER_SET(cmd->ul_mu_user_mask_upper,
188*5113495bSYour Name 				     rcc->ul_mu_user_mask_upper);
189*5113495bSYour Name 	cmd->ul_mu_user_mask_lower = rcc->ul_mu_user_mask_lower;
190*5113495bSYour Name 	WMI_CFR_FREEZE_DELAY_CNT_EN_SET(cmd->freeze_tlv_delay_cnt,
191*5113495bSYour Name 					rcc->freeze_tlv_delay_cnt_en);
192*5113495bSYour Name 	WMI_CFR_FREEZE_DELAY_CNT_THR_SET(cmd->freeze_tlv_delay_cnt,
193*5113495bSYour Name 					 rcc->freeze_tlv_delay_cnt_thr);
194*5113495bSYour Name 	WMI_CFR_DIRECTED_FTM_ACK_EN_SET(cmd->filter_type,
195*5113495bSYour Name 					rcc->m_directed_ftm);
196*5113495bSYour Name 	WMI_CFR_ALL_FTM_ACK_EN_SET(cmd->filter_type,
197*5113495bSYour Name 				   rcc->m_all_ftm_ack);
198*5113495bSYour Name 	WMI_CFR_NDPA_NDP_DIRECTED_EN_SET(cmd->filter_type,
199*5113495bSYour Name 					 rcc->m_ndpa_ndp_directed);
200*5113495bSYour Name 	WMI_CFR_NDPA_NDP_ALL_EN_SET(cmd->filter_type,
201*5113495bSYour Name 				    rcc->m_ndpa_ndp_all);
202*5113495bSYour Name 	WMI_CFR_TA_RA_TYPE_FILTER_EN_SET(cmd->filter_type,
203*5113495bSYour Name 					 rcc->m_ta_ra_filter);
204*5113495bSYour Name 	WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_SET(cmd->filter_type,
205*5113495bSYour Name 					       rcc->en_ta_ra_filter_in_as_fp);
206*5113495bSYour Name 	WMI_CFR_ALL_PACKET_EN_SET(cmd->filter_type,
207*5113495bSYour Name 				  rcc->m_all_packet);
208*5113495bSYour Name 
209*5113495bSYour Name 	/* TLV indicating array of structures to follow */
210*5113495bSYour Name 	buf_ptr += sizeof(wmi_cfr_capture_filter_cmd_fixed_param);
211*5113495bSYour Name 
212*5113495bSYour Name 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
213*5113495bSYour Name 		       rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config));
214*5113495bSYour Name 
215*5113495bSYour Name 	if (rcc->num_grp_tlvs) {
216*5113495bSYour Name 		buf_ptr += WMI_TLV_HDR_SIZE;
217*5113495bSYour Name 		param = (wmi_cfr_filter_group_config *)buf_ptr;
218*5113495bSYour Name 
219*5113495bSYour Name 		for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
220*5113495bSYour Name 			if (qdf_test_bit(grp_id,
221*5113495bSYour Name 					 &rcc->modified_in_curr_session)) {
222*5113495bSYour Name 				populate_wmi_cfr_param(grp_id, rcc, param);
223*5113495bSYour Name 				param++;
224*5113495bSYour Name 			}
225*5113495bSYour Name 		}
226*5113495bSYour Name 	}
227*5113495bSYour Name 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
228*5113495bSYour Name 				      WMI_CFR_CAPTURE_FILTER_CMDID);
229*5113495bSYour Name 	if (status)
230*5113495bSYour Name 		wmi_buf_free(buf);
231*5113495bSYour Name 
232*5113495bSYour Name 	return status;
233*5113495bSYour Name }
234*5113495bSYour Name 
235*5113495bSYour Name static QDF_STATUS
extract_cfr_phase_param_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wmi_cfr_phase_delta_param * param)236*5113495bSYour Name extract_cfr_phase_param_tlv(wmi_unified_t wmi_handle,
237*5113495bSYour Name 			    void *evt_buf,
238*5113495bSYour Name 			    struct wmi_cfr_phase_delta_param *param)
239*5113495bSYour Name {
240*5113495bSYour Name 	WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *param_buf;
241*5113495bSYour Name 	wmi_pdev_aoa_phasedelta_evt_fixed_param *phase_event;
242*5113495bSYour Name 
243*5113495bSYour Name 	param_buf = (WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *)evt_buf;
244*5113495bSYour Name 	if (!param_buf) {
245*5113495bSYour Name 		wmi_err("Invalid cfr aoa phase delta buffer");
246*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
247*5113495bSYour Name 	}
248*5113495bSYour Name 
249*5113495bSYour Name 	phase_event = param_buf->fixed_param;
250*5113495bSYour Name 	if (!phase_event) {
251*5113495bSYour Name 		wmi_err("CFR phase AoA delta buffer is NULL");
252*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
253*5113495bSYour Name 	}
254*5113495bSYour Name 
255*5113495bSYour Name 	param->freq = phase_event->freq;
256*5113495bSYour Name 	param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host
257*5113495bSYour Name 				(wmi_handle, phase_event->pdev_id);
258*5113495bSYour Name 
259*5113495bSYour Name 	param->max_chains = phase_event->chainInfo & 0xFFFF;
260*5113495bSYour Name 
261*5113495bSYour Name 	param->chain_phase_mask = (phase_event->chainInfo >> 16) & 0xFFFF;
262*5113495bSYour Name 
263*5113495bSYour Name 	if ((sizeof(param->ibf_cal_val)) <
264*5113495bSYour Name 	    (sizeof(phase_event->perChainIbfCalVal))) {
265*5113495bSYour Name 		wmi_err("ibf_cal_val can not hold all values from event data");
266*5113495bSYour Name 		return QDF_STATUS_E_RANGE;
267*5113495bSYour Name 	}
268*5113495bSYour Name 
269*5113495bSYour Name 	if ((sizeof(param->phase_delta)) <
270*5113495bSYour Name 	    (sizeof(phase_event->phasedelta))) {
271*5113495bSYour Name 		wmi_err("phase_delta can not hold all values from event data");
272*5113495bSYour Name 		return QDF_STATUS_E_RANGE;
273*5113495bSYour Name 	}
274*5113495bSYour Name 
275*5113495bSYour Name 	qdf_mem_copy(param->ibf_cal_val,
276*5113495bSYour Name 		     phase_event->perChainIbfCalVal,
277*5113495bSYour Name 		     sizeof(param->ibf_cal_val));
278*5113495bSYour Name 
279*5113495bSYour Name 	qdf_mem_copy(param->phase_delta,
280*5113495bSYour Name 		     phase_event->phasedelta,
281*5113495bSYour Name 		     sizeof(param->phase_delta));
282*5113495bSYour Name 
283*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
284*5113495bSYour Name }
285*5113495bSYour Name 
286*5113495bSYour Name #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT
287*5113495bSYour Name static QDF_STATUS
extract_cfr_enh_phase_fixed_param_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wmi_cfr_enh_phase_delta_param * param)288*5113495bSYour Name extract_cfr_enh_phase_fixed_param_tlv
289*5113495bSYour Name 		(wmi_unified_t wmi_handle,
290*5113495bSYour Name 		 void *evt_buf,
291*5113495bSYour Name 		 struct wmi_cfr_enh_phase_delta_param *param)
292*5113495bSYour Name {
293*5113495bSYour Name 	WMI_PDEV_ENHANCED_AOA_PHASEDELTA_EVENTID_param_tlvs *ev_buf;
294*5113495bSYour Name 	wmi_pdev_enhanced_aoa_phasedelta_evt_fixed_param *fixed_param;
295*5113495bSYour Name 
296*5113495bSYour Name 	ev_buf = (WMI_PDEV_ENHANCED_AOA_PHASEDELTA_EVENTID_param_tlvs *)evt_buf;
297*5113495bSYour Name 	if (!ev_buf) {
298*5113495bSYour Name 		wmi_err("Invalid cfr enh aoa phase delta event buffer");
299*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
300*5113495bSYour Name 	}
301*5113495bSYour Name 
302*5113495bSYour Name 	fixed_param = ev_buf->fixed_param;
303*5113495bSYour Name 	if (!fixed_param) {
304*5113495bSYour Name 		wmi_err("cfr enh aoa event fixed_param is NULL");
305*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
306*5113495bSYour Name 	}
307*5113495bSYour Name 
308*5113495bSYour Name 	param->freq = fixed_param->freq;
309*5113495bSYour Name 	param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host
310*5113495bSYour Name 				(wmi_handle, fixed_param->pdev_id);
311*5113495bSYour Name 
312*5113495bSYour Name 	param->max_chains =
313*5113495bSYour Name 		WMI_AOA_MAX_SUPPORTED_CHAINS_GET(fixed_param->chain_info);
314*5113495bSYour Name 	param->data_for_chainmask =
315*5113495bSYour Name 		WMI_AOA_SUPPORTED_CHAINMASK_GET(fixed_param->chain_info);
316*5113495bSYour Name 	param->xbar_config = fixed_param->xbar_config;
317*5113495bSYour Name 
318*5113495bSYour Name 	if (sizeof(param->ibf_cal_val) <
319*5113495bSYour Name 			sizeof(fixed_param->per_chain_ibf_cal_val)) {
320*5113495bSYour Name 		wmi_err("ibf_cal_val can not hold all values from event data");
321*5113495bSYour Name 		return QDF_STATUS_E_RANGE;
322*5113495bSYour Name 	}
323*5113495bSYour Name 
324*5113495bSYour Name 	qdf_mem_copy(param->ibf_cal_val, fixed_param->per_chain_ibf_cal_val,
325*5113495bSYour Name 		     QDF_MIN(sizeof(param->ibf_cal_val),
326*5113495bSYour Name 			     sizeof(fixed_param->per_chain_ibf_cal_val)));
327*5113495bSYour Name 
328*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
329*5113495bSYour Name }
330*5113495bSYour Name 
331*5113495bSYour Name static QDF_STATUS
populate_enhanced_aoa_data(uint32_t * dst_array,uint32_t * src_array,wmi_enhanced_aoa_gain_phase_data_hdr * data_hdr,uint32_t offset,uint32_t dst_size)332*5113495bSYour Name populate_enhanced_aoa_data(uint32_t *dst_array, uint32_t *src_array,
333*5113495bSYour Name 			   wmi_enhanced_aoa_gain_phase_data_hdr *data_hdr,
334*5113495bSYour Name 			   uint32_t offset, uint32_t dst_size)
335*5113495bSYour Name {
336*5113495bSYour Name 	uint32_t src_size = WMI_AOA_NUM_ENTIRES_GET(data_hdr->data_info) *
337*5113495bSYour Name 				sizeof(uint32_t);
338*5113495bSYour Name 
339*5113495bSYour Name 	if (src_size > dst_size) {
340*5113495bSYour Name 		wmi_err("the amount of data can not fit in the host array");
341*5113495bSYour Name 		return QDF_STATUS_E_RANGE;
342*5113495bSYour Name 	}
343*5113495bSYour Name 
344*5113495bSYour Name 	qdf_mem_copy(dst_array, src_array + offset, src_size);
345*5113495bSYour Name 
346*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
347*5113495bSYour Name }
348*5113495bSYour Name 
349*5113495bSYour Name static QDF_STATUS
extract_cfr_enh_phase_data_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wmi_cfr_enh_phase_delta_param * param)350*5113495bSYour Name extract_cfr_enh_phase_data_tlv(wmi_unified_t wmi_handle,
351*5113495bSYour Name 			       void *evt_buf,
352*5113495bSYour Name 			       struct wmi_cfr_enh_phase_delta_param *param)
353*5113495bSYour Name {
354*5113495bSYour Name 	WMI_PDEV_ENHANCED_AOA_PHASEDELTA_EVENTID_param_tlvs *ev_buf;
355*5113495bSYour Name 	wmi_enhanced_aoa_gain_phase_data_hdr *data_hdr;
356*5113495bSYour Name 	QDF_STATUS status;
357*5113495bSYour Name 	uint32_t *dst_array = NULL;
358*5113495bSYour Name 	uint32_t i, offset = 0;
359*5113495bSYour Name 	uint8_t data_type;
360*5113495bSYour Name 
361*5113495bSYour Name 	ev_buf = (WMI_PDEV_ENHANCED_AOA_PHASEDELTA_EVENTID_param_tlvs *)evt_buf;
362*5113495bSYour Name 
363*5113495bSYour Name 	if (!ev_buf) {
364*5113495bSYour Name 		wmi_err("Invalid cfr enh aoa phase delta event buffer");
365*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
366*5113495bSYour Name 	}
367*5113495bSYour Name 
368*5113495bSYour Name 	if (!ev_buf->aoa_data_hdr) {
369*5113495bSYour Name 		wmi_err("data headers NULL.. investigate");
370*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
371*5113495bSYour Name 	}
372*5113495bSYour Name 
373*5113495bSYour Name 	if (!ev_buf->aoa_data_buf) {
374*5113495bSYour Name 		wmi_err("data bufs NULL.. investigate");
375*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
376*5113495bSYour Name 	}
377*5113495bSYour Name 
378*5113495bSYour Name 	for (i = 0; i < ev_buf->num_aoa_data_hdr; i++) {
379*5113495bSYour Name 		data_hdr = &ev_buf->aoa_data_hdr[i];
380*5113495bSYour Name 		data_type = WMI_AOA_DATA_TYPE_GET(data_hdr->data_info);
381*5113495bSYour Name 
382*5113495bSYour Name 		if (data_type == WMI_PHASE_DELTA_ARRAY) {
383*5113495bSYour Name 			dst_array = param->enh_phase_delta_array;
384*5113495bSYour Name 		} else if (data_type == WMI_GAIN_GROUP_STOP_ARRAY) {
385*5113495bSYour Name 			dst_array = param->gain_stop_index_array;
386*5113495bSYour Name 		} else {
387*5113495bSYour Name 			wmi_err("invalid aoa data type received");
388*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
389*5113495bSYour Name 		}
390*5113495bSYour Name 
391*5113495bSYour Name 		status = populate_enhanced_aoa_data
392*5113495bSYour Name 				(dst_array, ev_buf->aoa_data_buf,
393*5113495bSYour Name 				 data_hdr, offset, param->array_size);
394*5113495bSYour Name 		if (status) {
395*5113495bSYour Name 			wmi_err("error in populating aoa data");
396*5113495bSYour Name 			return status;
397*5113495bSYour Name 		}
398*5113495bSYour Name 
399*5113495bSYour Name 		offset += WMI_AOA_NUM_ENTIRES_GET(data_hdr->data_info);
400*5113495bSYour Name 	}
401*5113495bSYour Name 
402*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
403*5113495bSYour Name }
404*5113495bSYour Name #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */
405*5113495bSYour Name #endif /* WLAN_ENH_CFR_ENABLE */
406*5113495bSYour Name 
send_peer_cfr_capture_cmd_tlv(wmi_unified_t wmi_handle,struct peer_cfr_params * param)407*5113495bSYour Name static QDF_STATUS send_peer_cfr_capture_cmd_tlv(wmi_unified_t wmi_handle,
408*5113495bSYour Name 						struct peer_cfr_params *param)
409*5113495bSYour Name {
410*5113495bSYour Name 	wmi_peer_cfr_capture_cmd_fixed_param *cmd;
411*5113495bSYour Name 	wmi_buf_t buf;
412*5113495bSYour Name 	int len = sizeof(*cmd);
413*5113495bSYour Name 	int ret;
414*5113495bSYour Name 
415*5113495bSYour Name 	buf = wmi_buf_alloc(wmi_handle, len);
416*5113495bSYour Name 	if (!buf) {
417*5113495bSYour Name 		qdf_print("%s:wmi_buf_alloc failed\n", __func__);
418*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
419*5113495bSYour Name 	}
420*5113495bSYour Name 
421*5113495bSYour Name 	cmd = (wmi_peer_cfr_capture_cmd_fixed_param *)wmi_buf_data(buf);
422*5113495bSYour Name 	WMITLV_SET_HDR(&cmd->tlv_header,
423*5113495bSYour Name 		       WMITLV_TAG_STRUC_wmi_peer_cfr_capture_cmd_fixed_param,
424*5113495bSYour Name 		       WMITLV_GET_STRUCT_TLVLEN
425*5113495bSYour Name 		       (wmi_peer_cfr_capture_cmd_fixed_param));
426*5113495bSYour Name 
427*5113495bSYour Name 	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->macaddr, &cmd->mac_addr);
428*5113495bSYour Name 	cmd->request = param->request;
429*5113495bSYour Name 	cmd->vdev_id = param->vdev_id;
430*5113495bSYour Name 	cmd->periodicity = param->periodicity;
431*5113495bSYour Name 	cmd->bandwidth = param->bandwidth;
432*5113495bSYour Name 	cmd->capture_method = param->capture_method;
433*5113495bSYour Name 
434*5113495bSYour Name 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
435*5113495bSYour Name 				   WMI_PEER_CFR_CAPTURE_CMDID);
436*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
437*5113495bSYour Name 		wmi_err("Failed to send WMI_PEER_CFR_CAPTURE_CMDID");
438*5113495bSYour Name 		wmi_buf_free(buf);
439*5113495bSYour Name 	}
440*5113495bSYour Name 
441*5113495bSYour Name 	return ret;
442*5113495bSYour Name }
443*5113495bSYour Name 
444*5113495bSYour Name #ifdef WLAN_ENH_CFR_ENABLE
wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)445*5113495bSYour Name static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
446*5113495bSYour Name {
447*5113495bSYour Name 	struct wmi_ops *ops = wmi_handle->ops;
448*5113495bSYour Name 
449*5113495bSYour Name 	ops->send_cfr_rcc_cmd = send_cfr_rcc_cmd_tlv;
450*5113495bSYour Name }
451*5113495bSYour Name #else
wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)452*5113495bSYour Name static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
453*5113495bSYour Name {
454*5113495bSYour Name }
455*5113495bSYour Name #endif
456*5113495bSYour Name 
457*5113495bSYour Name #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT
wmi_cfr_attach_enh_aoa_tlv(struct wmi_ops * ops)458*5113495bSYour Name static void wmi_cfr_attach_enh_aoa_tlv(struct wmi_ops *ops)
459*5113495bSYour Name {
460*5113495bSYour Name 	ops->extract_cfr_enh_phase_data = extract_cfr_enh_phase_data_tlv;
461*5113495bSYour Name 	ops->extract_cfr_enh_phase_fixed_param =
462*5113495bSYour Name 		extract_cfr_enh_phase_fixed_param_tlv;
463*5113495bSYour Name }
464*5113495bSYour Name #else
wmi_cfr_attach_enh_aoa_tlv(struct wmi_ops * ops)465*5113495bSYour Name static void wmi_cfr_attach_enh_aoa_tlv(struct wmi_ops *ops)
466*5113495bSYour Name {
467*5113495bSYour Name }
468*5113495bSYour Name #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */
469*5113495bSYour Name 
wmi_cfr_attach_tlv(wmi_unified_t wmi_handle)470*5113495bSYour Name void wmi_cfr_attach_tlv(wmi_unified_t wmi_handle)
471*5113495bSYour Name {
472*5113495bSYour Name 	struct wmi_ops *ops = wmi_handle->ops;
473*5113495bSYour Name 
474*5113495bSYour Name 	ops->send_peer_cfr_capture_cmd = send_peer_cfr_capture_cmd_tlv;
475*5113495bSYour Name 	ops->extract_cfr_peer_tx_event_param =
476*5113495bSYour Name 		extract_cfr_peer_tx_event_param_tlv;
477*5113495bSYour Name 	ops->extract_cfr_phase_param = extract_cfr_phase_param_tlv;
478*5113495bSYour Name 	wmi_cfr_attach_enh_aoa_tlv(ops);
479*5113495bSYour Name 	wmi_enh_cfr_attach_tlv(wmi_handle);
480*5113495bSYour Name }
481*5113495bSYour Name #endif /* WLAN_CFR_ENABLE */
482