xref: /wlan-dirver/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c (revision 93830f424d9ddc2ed54b338975b4f4fb38ca46e6)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wifi_pos_main.c
22  * This file defines the important functions pertinent to
23  * wifi positioning to initialize and de-initialize the component.
24  */
25 #include <wlan_lmac_if_def.h>
26 #include "target_if_wifi_pos.h"
27 #include "wifi_pos_oem_interface_i.h"
28 #include "wifi_pos_utils_i.h"
29 #include "wifi_pos_api.h"
30 #include "wifi_pos_main_i.h"
31 #include "wifi_pos_ucfg_i.h"
32 #include "wlan_objmgr_cmn.h"
33 #include "wlan_objmgr_global_obj.h"
34 #include "wlan_objmgr_psoc_obj.h"
35 #include "wlan_objmgr_pdev_obj.h"
36 #include "wlan_objmgr_vdev_obj.h"
37 #include "wlan_ptt_sock_svc.h"
38 #include "target_if.h"
39 #include "wlan_objmgr_peer_obj.h"
40 
41 #ifndef CNSS_GENL
42 #include <wlan_objmgr_global_obj_i.h>
43 #endif
44 
45 #include "wlan_reg_services_api.h"
46 /* forward declaration */
47 struct regulatory_channel;
48 
49 #define REG_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \
50 	reg_info_1 &= 0xff00ffff;           \
51 	reg_info_1 |= ((val & 0xff) << 16); \
52 } while (0)
53 
54 /* max tx power is in 1 dBm units */
55 #define REG_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \
56 	reg_info_2 &= 0xffff00ff;              \
57 	reg_info_2 |= ((val & 0xff) << 8);     \
58 } while (0)
59 
60 /* channel info consists of 6 bits of channel mode */
61 
62 #define REG_SET_CHANNEL_MODE(reg_channel, val) do { \
63 	(reg_channel)->info &= 0xffffffc0;            \
64 	(reg_channel)->info |= (val);                 \
65 } while (0)
66 
67 /*
68  * obj mgr api to iterate over vdevs does not provide a direct array or vdevs,
69  * rather takes a callback that is called for every vdev. wifi pos needs to
70  * store device mode and vdev id of all active vdevs and provide this info to
71  * user space as part of APP registration response. due to this, vdev_idx is
72  * used to identify how many vdevs have been populated by obj manager API.
73  */
74 static uint32_t vdev_idx;
75 
76 /**
77  * wifi_pos_get_tlv_support() - indicates if firmware supports TLV wifi pos msg
78  * @psoc: psoc object
79  *
80  * Return: status of operation
81  */
82 static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
83 {
84 	/* this is TBD */
85 	return true;
86 }
87 
88 #ifdef CNSS_GENL
89 static uint8_t *
90 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
91 			  struct app_reg_rsp_vdev_info *vdevs_info)
92 {
93 	uint32_t *nl_sign;
94 	uint8_t *resp_buf;
95 	struct wifi_app_reg_rsp *app_reg_rsp;
96 
97 	/*
98 	 * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp
99 	 * to indicate NLA type response is supported for OEM request
100 	 * commands.
101 	 */
102 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
103 			+ sizeof(uint8_t) + ENHNC_FLAGS_LEN;
104 	resp_buf = qdf_mem_malloc(*rsp_len);
105 	if (!resp_buf)
106 		return NULL;
107 
108 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
109 	app_reg_rsp->num_inf = vdev_idx;
110 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
111 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
112 
113 	nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx];
114 	*nl_sign |= NL_ENABLE_OEM_REQ_RSP;
115 
116 	return resp_buf;
117 }
118 
119 /**
120  * wifi_pos_get_host_pdev_id() - Get host pdev_id
121  * @psoc: Pointer to psoc object
122  * @tgt_pdev_id: target_pdev_id
123  * @host_pdev_id: host pdev_id
124  *
125  * Return: QDF_STATUS_SUCCESS in case of success, error codes in case of failure
126  */
127 static QDF_STATUS wifi_pos_get_host_pdev_id(
128 		struct wlan_objmgr_psoc *psoc, uint32_t tgt_pdev_id,
129 		uint32_t *host_pdev_id)
130 {
131 	/* pdev_id in FW starts from 1. So convert it to
132 	 * host id by decrementing it.
133 	 * zero has special meaning due to backward
134 	 * compatibility. Dont change it.
135 	 */
136 	if (tgt_pdev_id)
137 		*host_pdev_id = tgt_pdev_id - 1;
138 	else
139 		*host_pdev_id = tgt_pdev_id;
140 
141 	return QDF_STATUS_SUCCESS;
142 }
143 #else
144 static uint8_t *
145 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
146 			  struct app_reg_rsp_vdev_info *vdevs_info)
147 {
148 	uint8_t *resp_buf;
149 	struct wifi_app_reg_rsp *app_reg_rsp;
150 
151 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
152 			+ sizeof(uint8_t);
153 	resp_buf = qdf_mem_malloc(*rsp_len);
154 	if (!resp_buf)
155 		return NULL;
156 
157 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
158 	app_reg_rsp->num_inf = vdev_idx;
159 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
160 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
161 
162 	return resp_buf;
163 }
164 
165 static QDF_STATUS wifi_pos_get_host_pdev_id(
166 		struct wlan_objmgr_psoc *psoc, uint32_t tgt_pdev_id,
167 		uint32_t *host_pdev_id)
168 {
169 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
170 
171 	tx_ops = wifi_pos_get_tx_ops(psoc);
172 	if (!tx_ops) {
173 		qdf_print("tx ops null");
174 		return QDF_STATUS_E_NULL_VALUE;
175 	}
176 
177 	if (!tx_ops->wifi_pos_convert_pdev_id_target_to_host) {
178 		wifi_pos_err("wifi_pos_convert_pdev_id_target_to_host is null");
179 		return QDF_STATUS_E_NULL_VALUE;
180 	}
181 
182 	return tx_ops->wifi_pos_convert_pdev_id_target_to_host(
183 			psoc, tgt_pdev_id, host_pdev_id);
184 }
185 #endif
186 
187 static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
188 					struct wifi_pos_req_msg *req)
189 {
190 	uint8_t idx;
191 	uint32_t sub_type = 0;
192 	uint32_t channel_mhz = 0;
193 	uint32_t host_pdev_id = 0, tgt_pdev_id = 0;
194 	uint32_t offset;
195 	struct oem_data_req data_req;
196 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
197 	struct wlan_objmgr_pdev *pdev;
198 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
199 				wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
200 	QDF_STATUS status;
201 	uint8_t err;
202 
203 
204 	if (!wifi_pos_obj) {
205 		wifi_pos_err("wifi_pos priv obj is null");
206 		return QDF_STATUS_E_INVAL;
207 	}
208 
209 	wifi_pos_debug("Received data req pid(%d), len(%d)",
210 			req->pid, req->buf_len);
211 
212 	/* look for fields */
213 	if (req->field_info_buf)
214 		for (idx = 0; idx < req->field_info_buf->count; idx++) {
215 			offset = req->field_info_buf->fields[idx].offset;
216 			/*
217 			 * replace following reads with read_api based on
218 			 * length
219 			 */
220 			if (req->field_info_buf->fields[idx].id ==
221 					META_DATA_SUB_TYPE) {
222 				sub_type = *((uint32_t *)&req->buf[offset]);
223 				continue;
224 			}
225 
226 			if (req->field_info_buf->fields[idx].id ==
227 					META_DATA_CHANNEL_MHZ) {
228 				channel_mhz = *((uint32_t *)&req->buf[offset]);
229 				continue;
230 			}
231 
232 			if (req->field_info_buf->fields[idx].id ==
233 					META_DATA_PDEV) {
234 				tgt_pdev_id = *((uint32_t *)&req->buf[offset]);
235 				status = wifi_pos_get_host_pdev_id(
236 						psoc, tgt_pdev_id,
237 						&host_pdev_id);
238 				if (QDF_IS_STATUS_ERROR(status)) {
239 					wifi_pos_err("failed to get host pdev_id, tgt_pdev_id = %d",
240 						     tgt_pdev_id);
241 					return QDF_STATUS_E_INVAL;
242 				}
243 				continue;
244 			}
245 		}
246 
247 	switch (sub_type) {
248 	case TARGET_OEM_CAPABILITY_REQ:
249 		/* TBD */
250 		break;
251 	case TARGET_OEM_CONFIGURE_LCR:
252 		/* TBD */
253 		break;
254 	case TARGET_OEM_CONFIGURE_LCI:
255 		/* TBD */
256 		break;
257 	case TARGET_OEM_MEASUREMENT_REQ:
258 		/* TBD */
259 		break;
260 	case TARGET_OEM_CONFIGURE_FTMRR:
261 		wifi_pos_debug("FTMRR request");
262 		if (wifi_pos_obj->wifi_pos_send_action)
263 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
264 							   req->buf,
265 							   req->buf_len);
266 		break;
267 	case TARGET_OEM_CONFIGURE_WRU:
268 		wifi_pos_debug("WRU request");
269 		if (wifi_pos_obj->wifi_pos_send_action)
270 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
271 							   req->buf,
272 							   req->buf_len);
273 		break;
274 	default:
275 		wifi_pos_debug("invalid sub type or not passed");
276 
277 		tx_ops = wifi_pos_get_tx_ops(psoc);
278 		if (!tx_ops) {
279 			wifi_pos_err("tx ops null");
280 			return QDF_STATUS_E_INVAL;
281 		}
282 
283 		pdev = wlan_objmgr_get_pdev_by_id(psoc, host_pdev_id,
284 						  WLAN_WIFI_POS_CORE_ID);
285 		if (!pdev) {
286 			wifi_pos_err("pdev null");
287 			return QDF_STATUS_E_INVAL;
288 		}
289 
290 		status = ucfg_wifi_pos_measurement_request_notification(
291 				pdev, req);
292 		if (QDF_IS_STATUS_ERROR(status)) {
293 			err = OEM_ERR_REQUEST_REJECTED;
294 			wifi_pos_obj->wifi_pos_send_rsp(
295 					psoc, wifi_pos_get_app_pid(psoc),
296 					WIFI_POS_CMD_ERROR, sizeof(err), &err);
297 			wlan_objmgr_pdev_release_ref(pdev,
298 						     WLAN_WIFI_POS_CORE_ID);
299 			return QDF_STATUS_E_INVAL;
300 		}
301 
302 		data_req.data_len = req->buf_len;
303 		data_req.data = req->buf;
304 		tx_ops->data_req_tx(pdev, &data_req);
305 		wlan_objmgr_pdev_release_ref(pdev,
306 					     WLAN_WIFI_POS_CORE_ID);
307 		break;
308 	}
309 
310 	return QDF_STATUS_SUCCESS;
311 }
312 
313 static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
314 					struct wifi_pos_req_msg *req)
315 {
316 	int error_code;
317 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
318 				wifi_pos_get_psoc_priv_obj(psoc);
319 	struct wifi_pos_user_defined_caps *caps =
320 				(struct wifi_pos_user_defined_caps *)req->buf;
321 
322 	if (!wifi_pos_obj) {
323 		wifi_pos_err("wifi_pos priv obj is null");
324 		return QDF_STATUS_E_INVAL;
325 	}
326 
327 	wifi_pos_debug("Received set cap req pid(%d), len(%d)",
328 			req->pid, req->buf_len);
329 
330 	wifi_pos_obj->ftm_rr = caps->ftm_rr;
331 	wifi_pos_obj->lci_capability = caps->lci_capability;
332 	error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
333 	wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
334 					WIFI_POS_CMD_SET_CAPS,
335 					sizeof(error_code),
336 					(uint8_t *)&error_code);
337 
338 	return QDF_STATUS_SUCCESS;
339 }
340 
341 static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
342 					struct wifi_pos_req_msg *req)
343 {
344 	struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
345 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
346 					wifi_pos_get_psoc_priv_obj(psoc);
347 
348 	if (!wifi_pos_obj) {
349 		wifi_pos_err("wifi_pos priv obj is null");
350 		return QDF_STATUS_E_INVAL;
351 	}
352 
353 	wifi_pos_debug("Received get cap req pid(%d), len(%d)",
354 		       req->pid, req->buf_len);
355 
356 	wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
357 	cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
358 	cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
359 
360 	wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
361 					WIFI_POS_CMD_GET_CAPS,
362 					sizeof(cap_rsp),
363 					(uint8_t *)&cap_rsp);
364 
365 	return QDF_STATUS_SUCCESS;
366 }
367 
368 QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
369 				     int req_id, uint8_t *dest_mac,
370 				     int err_code)
371 {
372 	struct wifi_pos_err_msg_report err_report = {0};
373 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
374 					wifi_pos_get_psoc_priv_obj(psoc);
375 
376 	if (!wifi_pos_obj) {
377 		wifi_pos_err("wifi_pos priv obj is null");
378 		return QDF_STATUS_E_INVAL;
379 	}
380 
381 	err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
382 	err_report.msg_tag_len |= (sizeof(err_report) -
383 				   sizeof(err_report.err_rpt)) & 0x0000FFFF;
384 	err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
385 	err_report.req_id = req_id & 0xFFFF;
386 	err_report.req_id |= ((err_code & 0xFF) << 16);
387 	err_report.req_id |= (0x1 << 24);
388 	err_report.time_left = 0xFFFFFFFF;
389 	err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
390 	err_report.err_rpt.tag_len |=
391 				(sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
392 	memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
393 
394 	wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
395 			WIFI_POS_CMD_OEM_DATA,
396 			sizeof(err_report),
397 			(uint8_t *)&err_report);
398 
399 	return QDF_STATUS_SUCCESS;
400 }
401 
402 static QDF_STATUS wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc,
403 					    enum phy_ch_width *ch_width)
404 {
405 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
406 
407 	tx_ops = wifi_pos_get_tx_ops(psoc);
408 	if (!tx_ops) {
409 		qdf_print("tx ops null");
410 		return QDF_STATUS_E_NULL_VALUE;
411 	}
412 
413 	if (!tx_ops->wifi_pos_get_vht_ch_width) {
414 		wifi_pos_err("wifi pos get vht ch width is null");
415 		return QDF_STATUS_E_NULL_VALUE;
416 	}
417 
418 	return tx_ops->wifi_pos_get_vht_ch_width(
419 			psoc, ch_width);
420 }
421 
422 static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
423 					struct wlan_objmgr_pdev *pdev,
424 					uint16_t freq,
425 					struct wifi_pos_channel_power *chan)
426 {
427 	struct ch_params ch_params = {0};
428 	uint16_t sec_ch_2g = 0;
429 	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
430 		wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
431 	uint32_t phy_mode;
432 	QDF_STATUS status;
433 
434 	if (!wifi_pos_psoc) {
435 		wifi_pos_err("wifi_pos priv obj is null");
436 		return;
437 	}
438 
439 	status = wifi_pos_get_vht_ch_width(psoc, &ch_params.ch_width);
440 
441 	if (QDF_IS_STATUS_ERROR(status)) {
442 		wifi_pos_err("can not get vht ch width");
443 		return;
444 	}
445 
446 	wlan_reg_set_channel_params_for_pwrmode(pdev, freq, sec_ch_2g,
447 						&ch_params,
448 						REG_CURRENT_PWR_MODE);
449 	chan->band_center_freq1 = ch_params.mhz_freq_seg0;
450 
451 	if (wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq) {
452 		wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq(
453 				freq, ch_params.ch_width, &phy_mode);
454 		chan->phy_mode = phy_mode;
455 	}
456 }
457 
458 /**
459  * wifi_pos_get_valid_channels() - Get the list of valid channels from the
460  *                                 given channel list
461  * @chan_freqs: Channel frequencies to be validated
462  * @num_ch: NUmber of channels in the channel list to be validated
463  * @valid_channel_list: Pointer to valid channel list
464  *
465  * Return: Number of valid channels in the given list
466  */
467 static uint32_t wifi_pos_get_valid_channels(qdf_freq_t *chan_freqs,
468 					    uint32_t num_ch,
469 					    qdf_freq_t *valid_channel_list)
470 {
471 	uint32_t i, num_valid_channels = 0;
472 
473 	for (i = 0; i < num_ch; i++) {
474 		enum channel_enum ch_enum;
475 
476 		ch_enum = wlan_reg_get_chan_enum_for_freq(chan_freqs[i]);
477 		if (reg_is_chan_enum_invalid(ch_enum))
478 			continue;
479 		valid_channel_list[num_valid_channels++] = chan_freqs[i];
480 	}
481 	return num_valid_channels;
482 }
483 
484 static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
485 				   void *obj, void *arg)
486 {
487 	QDF_STATUS status;
488 	uint8_t num_channels;
489 	struct wlan_objmgr_pdev *pdev = obj;
490 	struct wifi_pos_channel_list *chan_list = arg;
491 	struct channel_power *ch_info = NULL;
492 	struct wifi_pos_channel_power *wifi_pos_ch;
493 	int i;
494 	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
495 		wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
496 
497 	if (!wifi_pos_psoc) {
498 		wifi_pos_err("wifi_pos priv obj is null");
499 		return;
500 	}
501 
502 	if (!chan_list) {
503 		wifi_pos_err("wifi_pos priv arg is null");
504 		return;
505 	}
506 
507 	wifi_pos_ch = &chan_list->chan_info[chan_list->num_channels];
508 
509 	ch_info = (struct channel_power *)qdf_mem_malloc(
510 			sizeof(*ch_info) * WIFI_POS_MAX_NUM_CHANNELS);
511 	if (!ch_info) {
512 		wifi_pos_err("ch_info is null");
513 		return;
514 	}
515 
516 	status = wlan_reg_get_channel_list_with_power_for_freq(pdev, ch_info,
517 							       &num_channels);
518 
519 	if (QDF_IS_STATUS_ERROR(status)) {
520 		wifi_pos_err("Failed to get valid channel list");
521 		qdf_mem_free(ch_info);
522 		return;
523 	}
524 
525 	if ((chan_list->num_channels + num_channels) >
526 			WIFI_POS_MAX_NUM_CHANNELS) {
527 		wifi_pos_err("Invalid number of channels");
528 		qdf_mem_free(ch_info);
529 		return;
530 	}
531 
532 	for (i = 0; i < num_channels; i++) {
533 		wifi_pos_ch[i].ch_power.center_freq = ch_info[i].center_freq;
534 		wifi_pos_ch[i].ch_power.chan_num = ch_info[i].chan_num;
535 		wifi_pos_ch[i].ch_power.tx_power = ch_info[i].tx_power;
536 		wifi_pos_ch[i].is_dfs_chan =
537 			wlan_reg_is_dfs_for_freq(pdev, ch_info[i].center_freq);
538 		wifi_update_channel_bw_info(
539 				psoc, pdev,
540 				ch_info[i].center_freq, &wifi_pos_ch[i]);
541 	}
542 
543 	if (wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels) {
544 		status = wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels(
545 				pdev, wifi_pos_ch, num_channels);
546 		if (QDF_IS_STATUS_ERROR(status)) {
547 			wifi_pos_err("Failed to get phymode");
548 			qdf_mem_free(ch_info);
549 			return;
550 		}
551 	}
552 
553 	chan_list->num_channels += num_channels;
554 	qdf_mem_free(ch_info);
555 }
556 
557 #ifdef CNSS_GENL
558 static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
559 {
560 	return (rsp_version == WIFI_POS_RSP_V2_NL) ? true : false;
561 }
562 
563 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
564 				 struct wifi_pos_channel_list *chan_list)
565 {
566 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
567 				     wifi_pos_pdev_iterator,
568 				     chan_list, true, WLAN_WIFI_POS_CORE_ID);
569 	wifi_pos_debug("num channels: %d", chan_list->num_channels);
570 }
571 
572 #else
573 static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
574 {
575 	return ((rsp_version == WIFI_POS_RSP_V2_NL) ||
576 		(rsp_version == WIFI_POS_RSP_V1_FLAT_MEMORY)) ?
577 		true : false;
578 }
579 
580 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
581 				 struct wifi_pos_channel_list *chan_list)
582 {
583 	uint8_t index;
584 
585 	for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
586 		if (g_umac_glb_obj->psoc[index]) {
587 			wlan_objmgr_iterate_obj_list(
588 					g_umac_glb_obj->psoc[index],
589 					WLAN_PDEV_OP, wifi_pos_pdev_iterator,
590 					chan_list, true, WLAN_WIFI_POS_CORE_ID);
591 		}
592 	}
593 
594 	wifi_pos_notice("num channels: %d", chan_list->num_channels);
595 }
596 #endif
597 
598 #ifdef CNSS_GENL
599 static bool wifi_pos_is_duplicate_freq(struct wifi_pos_ch_info_rsp *ch_info,
600 				       int num_chans, qdf_freq_t freq)
601 {
602 	return false;
603 }
604 #else
605 static bool wifi_pos_is_duplicate_freq(struct wifi_pos_ch_info_rsp *ch_info,
606 				       int num_chans, qdf_freq_t freq)
607 {
608 	int k;
609 
610 	for (k = 0; k < num_chans; k++) {
611 		if (freq == ch_info[k].mhz)
612 			return true;
613 	}
614 
615 	return false;
616 }
617 #endif
618 
619 static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
620 					struct wifi_pos_req_msg *req)
621 {
622 	uint8_t idx;
623 	uint8_t *buf = NULL;
624 	uint32_t len, i, freq;
625 	qdf_freq_t *chan_freqs = NULL;
626 	bool oem_6g_support_disable;
627 	uint8_t *channels = req->buf;
628 	struct wlan_objmgr_pdev *pdev;
629 	uint32_t num_ch = req->buf_len;
630 	qdf_freq_t valid_channel_list[WIFI_POS_MAX_NUM_CHANNELS];
631 	uint32_t num_valid_channels = 0;
632 	struct wifi_pos_ch_info_rsp *ch_info;
633 	struct wifi_pos_channel_list *ch_list = NULL;
634 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
635 					wifi_pos_get_psoc_priv_obj(psoc);
636 	QDF_STATUS ret_val;
637 	struct wifi_pos_channel_power *ch;
638 	bool dup_freq = false;
639 
640 	if (!wifi_pos_obj) {
641 		wifi_pos_err("wifi_pos priv obj is null");
642 		return QDF_STATUS_E_INVAL;
643 	}
644 
645 	wifi_pos_debug("Received ch info req pid(%d), len(%d)",
646 			req->pid, req->buf_len);
647 
648 	/* get first pdev since we need that only for freq and dfs state */
649 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
650 	if (!pdev) {
651 		wifi_pos_err("pdev get API failed");
652 		return QDF_STATUS_E_INVAL;
653 	}
654 	if (num_ch > WIFI_POS_MAX_NUM_CHANNELS) {
655 		wifi_pos_err("Invalid number of channels");
656 		ret_val = QDF_STATUS_E_INVAL;
657 		goto cleanup;
658 	}
659 
660 	chan_freqs = qdf_mem_malloc(WIFI_POS_MAX_NUM_CHANNELS *
661 				    (sizeof(*chan_freqs)));
662 	if (!chan_freqs) {
663 		ret_val = QDF_STATUS_E_NOMEM;
664 		goto cleanup;
665 	}
666 
667 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
668 	if (!ch_list) {
669 		ret_val = QDF_STATUS_E_NOMEM;
670 		goto cleanup;
671 	}
672 
673 	ch = ch_list->chan_info;
674 
675 	if ((num_ch == 0) &&
676 	    wifi_pos_is_resp_version_valid(req->rsp_version)) {
677 		wifi_pos_get_ch_info(psoc, ch_list);
678 		qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
679 		oem_6g_support_disable = wifi_pos_obj->oem_6g_support_disable;
680 		qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
681 
682 		/* ch_list has the frequencies in order of 2.4g, 5g & 6g */
683 		for (i = 0; i < ch_list->num_channels; i++) {
684 			freq = ch[i].ch_power.center_freq;
685 			if (oem_6g_support_disable &&
686 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
687 				continue;
688 			num_valid_channels++;
689 		}
690 	} else {
691 		for (i = 0; i < WIFI_POS_MAX_NUM_CHANNELS; i++)
692 			chan_freqs[i] =
693 			    wlan_reg_chan_band_to_freq(pdev, channels[i],
694 						       BIT(REG_BAND_5G) |
695 						       BIT(REG_BAND_2G));
696 		/* v1 has ch_list with frequencies in order of 2.4g, 5g only */
697 		num_valid_channels = wifi_pos_get_valid_channels(
698 							chan_freqs, num_ch,
699 							 valid_channel_list);
700 		for (i = 0; i < num_valid_channels; i++) {
701 			ch[i].ch_power.center_freq = valid_channel_list[i];
702 			ch[i].ch_power.chan_num = wlan_reg_freq_to_chan(
703 					pdev, ch[i].ch_power.center_freq);
704 			ch[i].ch_power.tx_power =
705 				wlan_reg_get_channel_reg_power_for_freq(
706 						pdev,
707 						ch[i].ch_power.center_freq);
708 			ch[i].is_dfs_chan = wlan_reg_is_dfs_for_freq(
709 						pdev,
710 						ch[i].ch_power.center_freq);
711 
712 			wifi_update_channel_bw_info(psoc, pdev,
713 						    ch[i].ch_power.center_freq,
714 						    &ch[i]);
715 		}
716 	}
717 
718 	len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
719 			num_valid_channels;
720 	buf = qdf_mem_malloc(len);
721 	if (!buf) {
722 		ret_val = QDF_STATUS_E_NOMEM;
723 		goto cleanup;
724 	}
725 
726 	/* First byte of message body will have num of channels */
727 	ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
728 	for (idx = 0, i = 0; idx < num_valid_channels; idx++) {
729 		dup_freq = wifi_pos_is_duplicate_freq(
730 				ch_info, i, ch[idx].ch_power.center_freq);
731 		if (dup_freq)
732 			continue;
733 
734 		ch_info[i].reserved0 = 0;
735 		ch_info[i].chan_id = ch[idx].ch_power.chan_num;
736 		ch_info[i].mhz = ch[idx].ch_power.center_freq;
737 		ch_info[i].band_center_freq1 = ch[idx].band_center_freq1;
738 		ch_info[i].band_center_freq2 = 0;
739 		ch_info[i].info = 0;
740 
741 		REG_SET_CHANNEL_REG_POWER(ch_info[i].reg_info_1,
742 					  ch[idx].ch_power.tx_power);
743 		REG_SET_CHANNEL_MAX_TX_POWER(ch_info[i].reg_info_2,
744 					     ch[idx].ch_power.tx_power);
745 
746 		if (ch[idx].is_dfs_chan)
747 			WIFI_POS_SET_DFS(ch_info[i].info);
748 
749 		if (ch[idx].phy_mode)
750 			REG_SET_CHANNEL_MODE(&ch_info[i], ch[idx].phy_mode);
751 		wifi_pos_debug("i:%d chan_id:%d freq:%d cfreq1:%d reg_info_1:%x reg_info_2:%x is_dfs_chan:%d phymode:%d",
752 			       i, ch_info[i].chan_id, ch_info[i].mhz,
753 			       ch_info[i].band_center_freq1,
754 			       ch_info[i].reg_info_1, ch_info[i].reg_info_2,
755 			       ch[idx].is_dfs_chan, ch[idx].phy_mode);
756 		i++;
757 	}
758 
759 	buf[0] = i;
760 
761 	wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
762 					WIFI_POS_CMD_GET_CH_INFO,
763 					len, buf);
764 	ret_val = QDF_STATUS_SUCCESS;
765 
766 cleanup:
767 	qdf_mem_free(buf);
768 	qdf_mem_free(ch_list);
769 	qdf_mem_free(chan_freqs);
770 	wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
771 
772 	return ret_val;
773 }
774 
775 static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
776 				   void *vdev, void *arg)
777 {
778 	struct app_reg_rsp_vdev_info *vdev_info = arg;
779 
780 	vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
781 	vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
782 	vdev_idx++;
783 }
784 
785 #ifdef CNSS_GENL
786 static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
787 				   struct app_reg_rsp_vdev_info *vdevs_info)
788 {
789 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
790 				     wifi_pos_vdev_iterator,
791 				     vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
792 }
793 
794 static uint32_t wifi_pos_get_vdev_count(struct wlan_objmgr_psoc *psoc)
795 {
796 	return psoc->soc_objmgr.max_vdev_count;
797 }
798 
799 #else
800 /* For WIN, WIFI POS command registration is called only for the first
801  * PSOC. Hence, iterate through all the PSOCs and send the vdev list
802  * to LOWI.
803  */
804 static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
805 				   struct app_reg_rsp_vdev_info *vdevs_info)
806 {
807 	uint8_t index;
808 
809 	for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
810 		if (g_umac_glb_obj->psoc[index]) {
811 			wlan_objmgr_iterate_obj_list(
812 					g_umac_glb_obj->psoc[index],
813 					WLAN_VDEV_OP, wifi_pos_vdev_iterator,
814 					vdevs_info, true,
815 					WLAN_WIFI_POS_CORE_ID);
816 		}
817 	}
818 }
819 
820 static uint32_t wifi_pos_get_vdev_count(struct wlan_objmgr_psoc *tpsoc)
821 {
822 	struct wlan_objmgr_psoc *psoc = NULL;
823 	uint8_t index;
824 	uint32_t vdev_count = 0;
825 
826 	for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
827 		if (g_umac_glb_obj->psoc[index]) {
828 			psoc = g_umac_glb_obj->psoc[index];
829 			vdev_count += psoc->soc_objmgr.max_vdev_count;
830 		}
831 	}
832 
833 	return vdev_count;
834 }
835 #endif
836 
837 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
838 					struct wifi_pos_req_msg *req)
839 {
840 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
841 	uint8_t err = 0, *app_reg_rsp;
842 	uint32_t rsp_len;
843 	uint32_t vdev_count;
844 	char *sign_str = NULL;
845 	struct app_reg_rsp_vdev_info *vdevs_info = NULL;
846 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
847 			wifi_pos_get_psoc_priv_obj(psoc);
848 
849 	if (!wifi_pos_obj) {
850 		wifi_pos_err("wifi_pos priv obj is null");
851 		return QDF_STATUS_E_INVAL;
852 	}
853 
854 	wifi_pos_debug("Received App Req Req pid(%d), len(%d)",
855 			req->pid, req->buf_len);
856 
857 	sign_str = (char *)req->buf;
858 	/* Registration request is only allowed for QTI Application */
859 	if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
860 		(strncmp(sign_str, OEM_APP_SIGNATURE_STR,
861 			 OEM_APP_SIGNATURE_LEN))) {
862 		wifi_pos_err("Invalid signature pid(%d)", req->pid);
863 		ret = QDF_STATUS_E_PERM;
864 		err = OEM_ERR_INVALID_SIGNATURE;
865 		goto app_reg_failed;
866 	}
867 
868 	wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
869 	qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
870 	wifi_pos_obj->is_app_registered = true;
871 	wifi_pos_obj->app_pid = req->pid;
872 	qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
873 
874 	vdev_idx = 0;
875 	vdev_count = wifi_pos_get_vdev_count(psoc);
876 
877 	if (!vdev_count || vdev_count > (WLAN_OBJMGR_MAX_DEVICES
878 	    * WLAN_UMAC_PSOC_MAX_VDEVS)) {
879 		wifi_pos_err("App Reg failed as Vdev count is %d (zero or greater than max)",
880 			     vdev_count);
881 		ret = QDF_STATUS_E_INVAL;
882 		err = OEM_ERR_NULL_CONTEXT;
883 		goto app_reg_failed;
884 	}
885 
886 	vdevs_info = (struct app_reg_rsp_vdev_info *)
887 			qdf_mem_malloc(sizeof(struct app_reg_rsp_vdev_info) *
888 				       vdev_count);
889 	if (!vdevs_info) {
890 		wifi_pos_err("App Reg failed as Vdevs info allocation failed");
891 		ret = QDF_STATUS_E_NOMEM;
892 		err = OEM_ERR_NULL_CONTEXT;
893 		goto app_reg_failed;
894 	}
895 
896 	wifi_pos_get_vdev_list(psoc, vdevs_info);
897 
898 	app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
899 	if (!app_reg_rsp) {
900 		ret = QDF_STATUS_E_NOMEM;
901 		err = OEM_ERR_NULL_CONTEXT;
902 		qdf_mem_free(vdevs_info);
903 		goto app_reg_failed;
904 	}
905 
906 	if (!vdev_idx)
907 		wifi_pos_debug("no active vdev");
908 
909 	vdev_idx = 0;
910 	wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid,
911 					WIFI_POS_CMD_REGISTRATION,
912 					rsp_len, (uint8_t *)app_reg_rsp);
913 
914 	qdf_mem_free(app_reg_rsp);
915 	qdf_mem_free(vdevs_info);
916 	return ret;
917 
918 app_reg_failed:
919 
920 	wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid, WIFI_POS_CMD_ERROR,
921 					sizeof(err), &err);
922 	return ret;
923 }
924 
925 /**
926  * wifi_pos_tlv_callback() - wifi pos msg handler registered for TLV type req
927  * @psoc: psoc object
928  * @req: wifi positioning request msg
929  *
930  * Return: status of operation
931  */
932 static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
933 					struct wifi_pos_req_msg *req)
934 {
935 	wifi_pos_debug("enter: msg_type: %d", req->msg_type);
936 	switch (req->msg_type) {
937 	case WIFI_POS_CMD_REGISTRATION:
938 		return wifi_pos_process_app_reg_req(psoc, req);
939 	case WIFI_POS_CMD_OEM_DATA:
940 		return wifi_pos_process_data_req(psoc, req);
941 	case WIFI_POS_CMD_GET_CH_INFO:
942 		return wifi_pos_process_ch_info_req(psoc, req);
943 	case WIFI_POS_CMD_SET_CAPS:
944 		return wifi_pos_process_set_cap_req(psoc, req);
945 	case WIFI_POS_CMD_GET_CAPS:
946 		return wifi_pos_process_get_cap_req(psoc, req);
947 	default:
948 		wifi_pos_err("invalid request type");
949 		break;
950 	}
951 	return 0;
952 }
953 
954 /**
955  * wifi_pos_non_tlv_callback() - wifi pos msg handler registered for non-TLV
956  *                               type req
957  * @psoc: psoc object
958  * @req: wifi positioning request msg
959  *
960  * Return: status of operation
961  */
962 static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
963 					    struct wifi_pos_req_msg *req)
964 {
965 	return QDF_STATUS_SUCCESS;
966 }
967 
968 QDF_STATUS wifi_pos_convert_host_pdev_id_to_target(
969 		struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id,
970 		uint32_t *target_pdev_id)
971 {
972 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
973 
974 	tx_ops = wifi_pos_get_tx_ops(psoc);
975 	if (!tx_ops) {
976 		wifi_pos_err("tx_ops is null");
977 		return QDF_STATUS_E_NULL_VALUE;
978 	}
979 
980 	if (!tx_ops->wifi_pos_convert_pdev_id_host_to_target) {
981 		wifi_pos_err("wifi_pos_convert_pdev_id_host_to_target is null");
982 		return QDF_STATUS_E_NULL_VALUE;
983 	}
984 
985 	return tx_ops->wifi_pos_convert_pdev_id_host_to_target(
986 			psoc, host_pdev_id, target_pdev_id);
987 }
988 
989 QDF_STATUS wifi_pos_psoc_obj_created_notification(
990 		struct wlan_objmgr_psoc *psoc, void *arg_list)
991 {
992 	QDF_STATUS status;
993 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
994 
995 	/*
996 	 * this is for WIN, if they have multiple psoc, we dont want to create
997 	 * multiple priv object. Since there is just one LOWI app registered to
998 	 * one driver, avoid 2nd private object with another psoc.
999 	 */
1000 	if (wifi_pos_get_psoc()) {
1001 		wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
1002 		return QDF_STATUS_SUCCESS;
1003 	} else {
1004 		wifi_pos_debug("setting global pos object");
1005 		wifi_pos_set_psoc(psoc);
1006 	}
1007 
1008 	/* initialize wifi-pos psoc priv object */
1009 	wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
1010 	if (!wifi_pos_obj) {
1011 		wifi_pos_clear_psoc();
1012 		return QDF_STATUS_E_NOMEM;
1013 	}
1014 
1015 	qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
1016 	/* Register TLV or non-TLV callbacks depending on target fw version */
1017 	if (wifi_pos_get_tlv_support(psoc))
1018 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
1019 	else
1020 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
1021 
1022 	/*
1023 	 * MGMT Rx is not handled in this phase since wifi pos only uses few
1024 	 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
1025 	 * used for 80211k. That part is not yet converged and still follows
1026 	 * legacy MGMT Rx to work. Action frame in new TXRX can be registered
1027 	 * at per ACTION Frame type granularity only.
1028 	 */
1029 
1030 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
1031 						WLAN_UMAC_COMP_WIFI_POS,
1032 						wifi_pos_obj,
1033 						QDF_STATUS_SUCCESS);
1034 
1035 	if (QDF_IS_STATUS_ERROR(status)) {
1036 		wifi_pos_err("obj attach with psoc failed with status: %d",
1037 				status);
1038 		qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
1039 		qdf_mem_free(wifi_pos_obj);
1040 		wifi_pos_clear_psoc();
1041 	}
1042 
1043 	return status;
1044 }
1045 
1046 QDF_STATUS  wifi_pos_psoc_obj_destroyed_notification(
1047 		struct wlan_objmgr_psoc *psoc, void *arg_list)
1048 {
1049 	QDF_STATUS status;
1050 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
1051 
1052 	if (wifi_pos_get_psoc() == psoc) {
1053 		wifi_pos_debug("deregistering wifi_pos_psoc object");
1054 		wifi_pos_clear_psoc();
1055 	} else {
1056 		wifi_pos_warn("un-related PSOC closed. do nothing");
1057 		return QDF_STATUS_SUCCESS;
1058 	}
1059 
1060 	wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
1061 	if (!wifi_pos_obj) {
1062 		wifi_pos_err("wifi_pos_obj is NULL");
1063 		return QDF_STATUS_E_FAULT;
1064 	}
1065 
1066 	target_if_wifi_pos_deinit_dma_rings(psoc);
1067 
1068 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
1069 						WLAN_UMAC_COMP_WIFI_POS,
1070 						wifi_pos_obj);
1071 	if (status != QDF_STATUS_SUCCESS)
1072 		wifi_pos_err("wifi_pos_obj detach failed");
1073 
1074 	wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
1075 	qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
1076 	qdf_mem_free(wifi_pos_obj);
1077 
1078 	return status;
1079 }
1080 
1081 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
1082 void
1083 wifi_pos_init_11az_context(struct wifi_pos_vdev_priv_obj *vdev_pos_obj)
1084 {
1085 	struct wifi_pos_11az_context *pasn_context;
1086 	uint8_t i;
1087 
1088 	pasn_context = &vdev_pos_obj->pasn_context;
1089 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
1090 		qdf_set_macaddr_broadcast(
1091 				&pasn_context->secure_peer_list[i].peer_mac);
1092 		qdf_set_macaddr_broadcast(
1093 				&pasn_context->secure_peer_list[i].self_mac);
1094 		pasn_context->secure_peer_list[i].force_self_mac_usage = false;
1095 		pasn_context->secure_peer_list[i].control_flags = 0;
1096 		qdf_set_macaddr_broadcast(
1097 				&pasn_context->unsecure_peer_list[i].peer_mac);
1098 		qdf_set_macaddr_broadcast(&pasn_context->failed_peer_list[i]);
1099 	}
1100 
1101 	pasn_context->num_secure_peers = 0;
1102 	pasn_context->num_unsecure_peers = 0;
1103 	pasn_context->num_failed_peers = 0;
1104 }
1105 #endif
1106 
1107 QDF_STATUS
1108 wifi_pos_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
1109 				   void *arg_list)
1110 {
1111 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
1112 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1113 
1114 	vdev_pos_obj = qdf_mem_malloc(sizeof(*vdev_pos_obj));
1115 	if (!vdev_pos_obj)
1116 		return QDF_STATUS_E_NOMEM;
1117 
1118 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
1119 						       WLAN_UMAC_COMP_WIFI_POS,
1120 						       vdev_pos_obj,
1121 						       QDF_STATUS_SUCCESS);
1122 	if (QDF_IS_STATUS_ERROR(status)) {
1123 		qdf_mem_free(vdev_pos_obj);
1124 		wifi_pos_err("Wifi pos vdev attach failed");
1125 		return status;
1126 	}
1127 
1128 	wifi_pos_init_11az_context(vdev_pos_obj);
1129 
1130 	return status;
1131 }
1132 
1133 QDF_STATUS
1134 wifi_pos_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
1135 				     void *arg_list)
1136 {
1137 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
1138 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1139 
1140 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
1141 	if (!vdev_pos_obj) {
1142 		wifi_pos_err("Wifi pos vdev priv obj is null");
1143 		return QDF_STATUS_E_FAILURE;
1144 	}
1145 
1146 	status = wlan_objmgr_vdev_component_obj_detach(vdev,
1147 						       WLAN_UMAC_COMP_WIFI_POS,
1148 						       vdev_pos_obj);
1149 	if (QDF_IS_STATUS_ERROR(status))
1150 		wifi_pos_err("Detach vdev private obj failed");
1151 
1152 	qdf_mem_free(vdev_pos_obj);
1153 
1154 	return status;
1155 }
1156 
1157 QDF_STATUS
1158 wifi_pos_peer_object_created_notification(struct wlan_objmgr_peer *peer,
1159 					  void *arg)
1160 {
1161 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
1162 	QDF_STATUS status;
1163 
1164 	if (!peer) {
1165 		wifi_pos_err("Peer is NULL");
1166 		return QDF_STATUS_E_NULL_VALUE;
1167 	}
1168 
1169 	peer_priv = qdf_mem_malloc(sizeof(*peer_priv));
1170 	if (!peer_priv)
1171 		return QDF_STATUS_E_NOMEM;
1172 
1173 	status = wlan_objmgr_peer_component_obj_attach(peer,
1174 						       WLAN_UMAC_COMP_WIFI_POS,
1175 						       (void *)peer_priv,
1176 						       QDF_STATUS_SUCCESS);
1177 	if (QDF_IS_STATUS_ERROR(status)) {
1178 		wifi_pos_err("unable to attach peer_priv obj to peer obj");
1179 		qdf_mem_free(peer_priv);
1180 	}
1181 
1182 	return status;
1183 }
1184 
1185 QDF_STATUS
1186 wifi_pos_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
1187 					    void *arg)
1188 {
1189 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
1190 	QDF_STATUS status;
1191 
1192 	if (!peer) {
1193 		wifi_pos_err("Peer is NULL");
1194 		return QDF_STATUS_E_NULL_VALUE;
1195 	}
1196 
1197 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1198 							  WLAN_UMAC_COMP_WIFI_POS);
1199 	if (!peer_priv) {
1200 		wifi_pos_err("peer MLME component object is NULL");
1201 		return QDF_STATUS_E_FAILURE;
1202 	}
1203 
1204 	status = wlan_objmgr_peer_component_obj_detach(peer,
1205 						       WLAN_UMAC_COMP_WIFI_POS,
1206 						       (void *)peer_priv);
1207 	if (QDF_IS_STATUS_ERROR(status))
1208 		wifi_pos_err("unable to detach peer_priv obj to peer obj");
1209 
1210 	qdf_mem_free(peer_priv);
1211 
1212 	return status;
1213 }
1214 
1215 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
1216 			     struct oem_data_rsp *oem_rsp)
1217 {
1218 	uint32_t len;
1219 	uint8_t *data;
1220 	uint32_t app_pid;
1221 	struct wifi_pos_psoc_priv_obj *priv;
1222 	wifi_pos_send_rsp_handler wifi_pos_send_rsp;
1223 
1224 	priv = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
1225 	if (!priv) {
1226 		wifi_pos_err("private object is NULL");
1227 		return -EINVAL;
1228 	}
1229 
1230 	qdf_spin_lock_bh(&priv->wifi_pos_lock);
1231 	app_pid = priv->app_pid;
1232 	wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
1233 	qdf_spin_unlock_bh(&priv->wifi_pos_lock);
1234 
1235 	len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
1236 	if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
1237 			oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
1238 		wifi_pos_err("invalid length of Oem Data response");
1239 		return -EINVAL;
1240 	}
1241 
1242 	if (!wifi_pos_send_rsp) {
1243 		wifi_pos_err("invalid response handler");
1244 		return -EINVAL;
1245 	}
1246 
1247 	wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
1248 
1249 	if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
1250 		/* stitch together the msg data_1 + CIR/CFR + data_2 */
1251 		data = qdf_mem_malloc(len);
1252 		if (!data)
1253 			return -ENOMEM;
1254 
1255 		qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
1256 		qdf_mem_copy(&data[oem_rsp->rsp_len_1],
1257 			     oem_rsp->vaddr, oem_rsp->dma_len);
1258 		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
1259 			     oem_rsp->data_2, oem_rsp->rsp_len_2);
1260 
1261 		wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA, len,
1262 				  data);
1263 		qdf_mem_free(data);
1264 	} else {
1265 		wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA,
1266 				  oem_rsp->rsp_len_1, oem_rsp->data_1);
1267 	}
1268 
1269 	return 0;
1270 }
1271 
1272 void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
1273 {
1274 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
1275 
1276 	wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
1277 	wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
1278 	wifi_pos_rx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb =
1279 			wifi_pos_vdev_delete_all_ranging_peers;
1280 }
1281 
1282 QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
1283 			   struct wifi_pos_driver_caps *caps)
1284 {
1285 	uint16_t i, count = 0;
1286 	uint32_t freq;
1287 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
1288 					wifi_pos_get_psoc_priv_obj(psoc);
1289 	struct wifi_pos_channel_list *ch_list = NULL;
1290 
1291 	wifi_pos_debug("Enter");
1292 	if (!wifi_pos_obj) {
1293 		wifi_pos_err("wifi_pos_obj is null");
1294 		return QDF_STATUS_E_NULL_VALUE;
1295 	}
1296 
1297 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
1298 	if (!ch_list)
1299 		return QDF_STATUS_E_NOMEM;
1300 
1301 	strlcpy(caps->oem_target_signature,
1302 		OEM_TARGET_SIGNATURE,
1303 		OEM_TARGET_SIGNATURE_LEN);
1304 	caps->oem_target_type = wifi_pos_obj->oem_target_type;
1305 	caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
1306 	caps->driver_version.major = wifi_pos_obj->driver_version.major;
1307 	caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
1308 	caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
1309 	caps->driver_version.build = wifi_pos_obj->driver_version.build;
1310 	caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
1311 	caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
1312 	caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
1313 	caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
1314 	caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
1315 	wifi_pos_get_ch_info(psoc, ch_list);
1316 
1317 	/* copy valid channels list to caps */
1318 	for (i = 0; i < ch_list->num_channels; i++) {
1319 		freq = ch_list->chan_info[i].ch_power.center_freq;
1320 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
1321 			continue;
1322 		caps->channel_list[count++] =
1323 			ch_list->chan_info[i].ch_power.chan_num;
1324 	}
1325 	caps->num_channels = count;
1326 	qdf_mem_free(ch_list);
1327 	return QDF_STATUS_SUCCESS;
1328 }
1329