xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_cfr_tlv.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <osdep.h>
18 #include "wmi.h"
19 #include "wmi_unified_priv.h"
20 #include "wmi_unified_cfr_param.h"
21 #include "wmi_unified_cfr_api.h"
22 
23 #ifdef WLAN_CFR_ENABLE
24 static QDF_STATUS
25 extract_cfr_peer_tx_event_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
26 				    wmi_cfr_peer_tx_event_param *peer_tx_event)
27 {
28 	int idx;
29 	WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *param_buf;
30 	wmi_peer_cfr_capture_event_fixed_param *peer_tx_event_ev;
31 	wmi_peer_cfr_capture_event_phase_fixed_param *chain_phase_ev;
32 
33 	param_buf = (WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *)evt_buf;
34 	if (!param_buf) {
35 		wmi_err("Invalid cfr capture buffer");
36 		return QDF_STATUS_E_INVAL;
37 	}
38 
39 	peer_tx_event_ev = param_buf->fixed_param;
40 	if (!peer_tx_event_ev) {
41 		wmi_err("peer cfr capture buffer is null");
42 		return QDF_STATUS_E_NULL_VALUE;
43 	}
44 
45 	peer_tx_event->capture_method = peer_tx_event_ev->capture_method;
46 	peer_tx_event->vdev_id = peer_tx_event_ev->vdev_id;
47 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_tx_event_ev->mac_addr,
48 				   &peer_tx_event->peer_mac_addr.bytes[0]);
49 	peer_tx_event->primary_20mhz_chan =
50 		peer_tx_event_ev->chan_mhz;
51 	peer_tx_event->bandwidth = peer_tx_event_ev->bandwidth;
52 	peer_tx_event->phy_mode = peer_tx_event_ev->phy_mode;
53 	peer_tx_event->band_center_freq1 = peer_tx_event_ev->band_center_freq1;
54 	peer_tx_event->band_center_freq2 = peer_tx_event_ev->band_center_freq2;
55 	peer_tx_event->spatial_streams = peer_tx_event_ev->sts_count;
56 	peer_tx_event->correlation_info_1 =
57 		peer_tx_event_ev->correlation_info_1;
58 	peer_tx_event->correlation_info_2 =
59 		peer_tx_event_ev->correlation_info_2;
60 	peer_tx_event->status = peer_tx_event_ev->status;
61 	peer_tx_event->timestamp_us = peer_tx_event_ev->timestamp_us;
62 	peer_tx_event->counter = peer_tx_event_ev->counter;
63 	qdf_mem_copy(peer_tx_event->chain_rssi, peer_tx_event_ev->chain_rssi,
64 		     sizeof(peer_tx_event->chain_rssi));
65 	if (peer_tx_event_ev->cfo_measurement_valid)
66 		peer_tx_event->cfo_measurement =
67 			peer_tx_event_ev->cfo_measurement;
68 	else
69 		peer_tx_event->cfo_measurement = 0;
70 
71 	peer_tx_event->rx_start_ts = peer_tx_event_ev->rx_start_ts;
72 	peer_tx_event->rx_ts_reset = peer_tx_event_ev->rx_ts_reset;
73 	peer_tx_event->mcs_rate =
74 		WMI_CFR_MCS_GET(peer_tx_event_ev->mcs_gi_info);
75 	peer_tx_event->gi_type =
76 		WMI_CFR_GI_TYPE_GET(peer_tx_event_ev->mcs_gi_info);
77 
78 	chain_phase_ev = param_buf->phase_param;
79 	if (chain_phase_ev) {
80 		for (idx = 0; idx < WMI_HOST_MAX_CHAINS; idx++) {
81 			/* Due to FW's alignment rules, phase information being
82 			 * passed is 32-bit, out of which only 16 bits is valid.
83 			 * Remaining bits are all zeroed. So direct mem copy
84 			 * will not work as it will copy extra zeroes into host
85 			 * structures.
86 			 */
87 			peer_tx_event->chain_phase[idx] =
88 				(0xffff & chain_phase_ev->chain_phase[idx]);
89 			peer_tx_event->agc_gain[idx] =
90 				WMI_UNIFIED_AGC_GAIN_GET(chain_phase_ev, idx);
91 			peer_tx_event->agc_gain_tbl_index[idx] =
92 				WMI_UNIFIED_AGC_GAIN_TBL_IDX_GET(chain_phase_ev,
93 								 idx);
94 		}
95 	}
96 
97 	return QDF_STATUS_SUCCESS;
98 }
99 
100 #ifdef WLAN_ENH_CFR_ENABLE
101 static void populate_wmi_cfr_param(uint8_t grp_id, struct cfr_rcc_param *rcc,
102 				   wmi_cfr_filter_group_config *param)
103 {
104 	struct ta_ra_cfr_cfg *tgt_cfg = NULL;
105 
106 	WMITLV_SET_HDR(&param->tlv_header,
107 		       WMITLV_TAG_STRUC_wmi_cfr_filter_group_config,
108 		       WMITLV_GET_STRUCT_TLVLEN
109 		       (wmi_cfr_filter_group_config));
110 	tgt_cfg  = &rcc->curr[grp_id];
111 
112 	param->filter_group_id = grp_id;
113 	WMI_CFR_GROUP_TA_ADDR_VALID_SET(param->filter_set_valid_mask,
114 					tgt_cfg->valid_ta);
115 	WMI_CFR_GROUP_TA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
116 					     tgt_cfg->valid_ta_mask);
117 	WMI_CFR_GROUP_RA_ADDR_VALID_SET(param->filter_set_valid_mask,
118 					tgt_cfg->valid_ra);
119 	WMI_CFR_GROUP_RA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
120 					     tgt_cfg->valid_ra_mask);
121 	WMI_CFR_GROUP_BW_VALID_SET(param->filter_set_valid_mask,
122 				   tgt_cfg->valid_bw_mask);
123 	WMI_CFR_GROUP_NSS_VALID_SET(param->filter_set_valid_mask,
124 				    tgt_cfg->valid_nss_mask);
125 	WMI_CFR_GROUP_MGMT_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
126 					     tgt_cfg->valid_mgmt_subtype);
127 	WMI_CFR_GROUP_CTRL_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
128 					     tgt_cfg->valid_ctrl_subtype);
129 	WMI_CFR_GROUP_DATA_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
130 					     tgt_cfg->valid_data_subtype);
131 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr,
132 				   &param->ta_addr);
133 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr_mask,
134 				   &param->ta_addr_mask);
135 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr,
136 				   &param->ra_addr);
137 	WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr_mask,
138 				   &param->ra_addr_mask);
139 	WMI_CFR_GROUP_BW_SET(param->bw_nss_filter,
140 			     tgt_cfg->bw);
141 	WMI_CFR_GROUP_NSS_SET(param->bw_nss_filter,
142 			      tgt_cfg->nss);
143 	param->mgmt_subtype_filter = tgt_cfg->mgmt_subtype_filter;
144 	param->ctrl_subtype_filter = tgt_cfg->ctrl_subtype_filter;
145 	param->data_subtype_filter = tgt_cfg->data_subtype_filter;
146 }
147 
148 static QDF_STATUS send_cfr_rcc_cmd_tlv(wmi_unified_t wmi_handle,
149 				       struct cfr_rcc_param *rcc)
150 {
151 	wmi_cfr_capture_filter_cmd_fixed_param *cmd;
152 	wmi_cfr_filter_group_config *param;
153 	uint8_t *buf_ptr, grp_id;
154 	wmi_buf_t buf;
155 	uint32_t len;
156 	QDF_STATUS status = QDF_STATUS_SUCCESS;
157 	struct wmi_ops *ops = wmi_handle->ops;
158 
159 	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
160 	len += rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config);
161 	buf = wmi_buf_alloc(wmi_handle, len);
162 
163 	if (!buf) {
164 		wmi_err("wmi_buf_alloc failed");
165 		return QDF_STATUS_E_NOMEM;
166 	}
167 
168 	buf_ptr = wmi_buf_data(buf);
169 	cmd = (wmi_cfr_capture_filter_cmd_fixed_param *)buf_ptr;
170 
171 	WMITLV_SET_HDR(&cmd->tlv_header,
172 		       WMITLV_TAG_STRUC_wmi_cfr_capture_filter_cmd_fixed_param,
173 		       WMITLV_GET_STRUCT_TLVLEN
174 		       (wmi_cfr_capture_filter_cmd_fixed_param));
175 	cmd->pdev_id = ops->convert_host_pdev_id_to_target(wmi_handle,
176 							   rcc->pdev_id);
177 	WMI_CFR_CAPTURE_INTERVAL_SET(cmd->capture_interval,
178 				     rcc->capture_interval);
179 	WMI_CFR_CAPTURE_DURATION_SET(cmd->capture_duration,
180 				     rcc->capture_duration);
181 	WMI_CFR_CAPTURE_COUNT_SET(cmd->capture_count, rcc->capture_count);
182 	WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_SET(cmd->capture_count,
183 					      rcc->capture_intval_mode_sel);
184 	WMI_CFR_FILTER_GROUP_BITMAP_SET(cmd->filter_group_bitmap,
185 					rcc->filter_group_bitmap);
186 	WMI_CFR_UL_MU_USER_UPPER_SET(cmd->ul_mu_user_mask_upper,
187 				     rcc->ul_mu_user_mask_upper);
188 	cmd->ul_mu_user_mask_lower = rcc->ul_mu_user_mask_lower;
189 	WMI_CFR_FREEZE_DELAY_CNT_EN_SET(cmd->freeze_tlv_delay_cnt,
190 					rcc->freeze_tlv_delay_cnt_en);
191 	WMI_CFR_FREEZE_DELAY_CNT_THR_SET(cmd->freeze_tlv_delay_cnt,
192 					 rcc->freeze_tlv_delay_cnt_thr);
193 	WMI_CFR_DIRECTED_FTM_ACK_EN_SET(cmd->filter_type,
194 					rcc->m_directed_ftm);
195 	WMI_CFR_ALL_FTM_ACK_EN_SET(cmd->filter_type,
196 				   rcc->m_all_ftm_ack);
197 	WMI_CFR_NDPA_NDP_DIRECTED_EN_SET(cmd->filter_type,
198 					 rcc->m_ndpa_ndp_directed);
199 	WMI_CFR_NDPA_NDP_ALL_EN_SET(cmd->filter_type,
200 				    rcc->m_ndpa_ndp_all);
201 	WMI_CFR_TA_RA_TYPE_FILTER_EN_SET(cmd->filter_type,
202 					 rcc->m_ta_ra_filter);
203 	WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_SET(cmd->filter_type,
204 					       rcc->en_ta_ra_filter_in_as_fp);
205 	WMI_CFR_ALL_PACKET_EN_SET(cmd->filter_type,
206 				  rcc->m_all_packet);
207 
208 	/* TLV indicating array of structures to follow */
209 	buf_ptr += sizeof(wmi_cfr_capture_filter_cmd_fixed_param);
210 
211 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
212 		       rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config));
213 
214 	if (rcc->num_grp_tlvs) {
215 		buf_ptr += WMI_TLV_HDR_SIZE;
216 		param = (wmi_cfr_filter_group_config *)buf_ptr;
217 
218 		for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
219 			if (qdf_test_bit(grp_id,
220 					 &rcc->modified_in_curr_session)) {
221 				populate_wmi_cfr_param(grp_id, rcc, param);
222 				param++;
223 			}
224 		}
225 	}
226 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
227 				      WMI_CFR_CAPTURE_FILTER_CMDID);
228 	if (status)
229 		wmi_buf_free(buf);
230 
231 	return status;
232 }
233 
234 static QDF_STATUS
235 extract_cfr_phase_param_tlv(wmi_unified_t wmi_handle,
236 			    void *evt_buf,
237 			    struct wmi_cfr_phase_delta_param *param)
238 {
239 	WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *param_buf;
240 	wmi_pdev_aoa_phasedelta_evt_fixed_param *phase_event;
241 
242 	param_buf = (WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *)evt_buf;
243 	if (!param_buf) {
244 		wmi_err("Invalid cfr aoa phase delta buffer");
245 		return QDF_STATUS_E_INVAL;
246 	}
247 
248 	phase_event = param_buf->fixed_param;
249 	if (!phase_event) {
250 		wmi_err("CFR phase AoA delta buffer is NULL");
251 		return QDF_STATUS_E_NULL_VALUE;
252 	}
253 
254 	param->freq = phase_event->freq;
255 	param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host
256 				(wmi_handle, phase_event->pdev_id);
257 
258 	param->max_chains = phase_event->chainInfo & 0xFFFF;
259 
260 	param->chain_phase_mask = (phase_event->chainInfo >> 16) & 0xFFFF;
261 
262 	if ((sizeof(param->ibf_cal_val)) <
263 	    (sizeof(phase_event->perChainIbfCalVal))) {
264 		wmi_err("ibf_cal_val can not hold all values from event data");
265 		return QDF_STATUS_E_RANGE;
266 	}
267 
268 	if ((sizeof(param->phase_delta)) <
269 	    (sizeof(phase_event->phasedelta))) {
270 		wmi_err("phase_delta can not hold all values from event data");
271 		return QDF_STATUS_E_RANGE;
272 	}
273 
274 	qdf_mem_copy(param->ibf_cal_val,
275 		     phase_event->perChainIbfCalVal,
276 		     sizeof(param->ibf_cal_val));
277 
278 	qdf_mem_copy(param->phase_delta,
279 		     phase_event->phasedelta,
280 		     sizeof(param->phase_delta));
281 
282 	return QDF_STATUS_SUCCESS;
283 }
284 #endif
285 
286 static QDF_STATUS send_peer_cfr_capture_cmd_tlv(wmi_unified_t wmi_handle,
287 						struct peer_cfr_params *param)
288 {
289 	wmi_peer_cfr_capture_cmd_fixed_param *cmd;
290 	wmi_buf_t buf;
291 	int len = sizeof(*cmd);
292 	int ret;
293 
294 	buf = wmi_buf_alloc(wmi_handle, len);
295 	if (!buf) {
296 		qdf_print("%s:wmi_buf_alloc failed\n", __func__);
297 		return QDF_STATUS_E_NOMEM;
298 	}
299 
300 	cmd = (wmi_peer_cfr_capture_cmd_fixed_param *)wmi_buf_data(buf);
301 	WMITLV_SET_HDR(&cmd->tlv_header,
302 		       WMITLV_TAG_STRUC_wmi_peer_cfr_capture_cmd_fixed_param,
303 		       WMITLV_GET_STRUCT_TLVLEN
304 		       (wmi_peer_cfr_capture_cmd_fixed_param));
305 
306 	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->macaddr, &cmd->mac_addr);
307 	cmd->request = param->request;
308 	cmd->vdev_id = param->vdev_id;
309 	cmd->periodicity = param->periodicity;
310 	cmd->bandwidth = param->bandwidth;
311 	cmd->capture_method = param->capture_method;
312 
313 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
314 				   WMI_PEER_CFR_CAPTURE_CMDID);
315 	if (QDF_IS_STATUS_ERROR(ret)) {
316 		wmi_err("Failed to send WMI_PEER_CFR_CAPTURE_CMDID");
317 		wmi_buf_free(buf);
318 	}
319 
320 	return ret;
321 }
322 
323 #ifdef WLAN_ENH_CFR_ENABLE
324 static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
325 {
326 	struct wmi_ops *ops = wmi_handle->ops;
327 
328 	ops->send_cfr_rcc_cmd = send_cfr_rcc_cmd_tlv;
329 }
330 #else
331 static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
332 {
333 }
334 #endif
335 
336 void wmi_cfr_attach_tlv(wmi_unified_t wmi_handle)
337 {
338 	struct wmi_ops *ops = wmi_handle->ops;
339 
340 	ops->send_peer_cfr_capture_cmd = send_peer_cfr_capture_cmd_tlv;
341 	ops->extract_cfr_peer_tx_event_param =
342 		extract_cfr_peer_tx_event_param_tlv;
343 	ops->extract_cfr_phase_param = extract_cfr_phase_param_tlv;
344 	wmi_enh_cfr_attach_tlv(wmi_handle);
345 }
346 #endif /* WLAN_CFR_ENABLE */
347