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