xref: /wlan-dirver/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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 declartion */
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 		if (wlan_reg_get_chan_enum_for_freq(chan_freqs[i]) ==
475 		    INVALID_CHANNEL)
476 			continue;
477 		valid_channel_list[num_valid_channels++] = chan_freqs[i];
478 	}
479 	return num_valid_channels;
480 }
481 
482 static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
483 				   void *obj, void *arg)
484 {
485 	QDF_STATUS status;
486 	uint8_t num_channels;
487 	struct wlan_objmgr_pdev *pdev = obj;
488 	struct wifi_pos_channel_list *chan_list = arg;
489 	struct channel_power *ch_info = NULL;
490 	struct wifi_pos_channel_power *wifi_pos_ch;
491 	int i;
492 	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
493 		wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
494 
495 	if (!wifi_pos_psoc) {
496 		wifi_pos_err("wifi_pos priv obj is null");
497 		return;
498 	}
499 
500 	if (!chan_list) {
501 		wifi_pos_err("wifi_pos priv arg is null");
502 		return;
503 	}
504 
505 	wifi_pos_ch = &chan_list->chan_info[chan_list->num_channels];
506 
507 	ch_info = (struct channel_power *)qdf_mem_malloc(
508 			sizeof(*ch_info) * NUM_CHANNELS);
509 	if (!ch_info) {
510 		wifi_pos_err("ch_info is null");
511 		return;
512 	}
513 
514 	status = wlan_reg_get_channel_list_with_power_for_freq(pdev, ch_info,
515 							       &num_channels);
516 
517 	if (QDF_IS_STATUS_ERROR(status)) {
518 		wifi_pos_err("Failed to get valid channel list");
519 		qdf_mem_free(ch_info);
520 		return;
521 	}
522 
523 	if ((chan_list->num_channels + num_channels) > NUM_CHANNELS) {
524 		wifi_pos_err("Invalid number of channels");
525 		qdf_mem_free(ch_info);
526 		return;
527 	}
528 
529 	for (i = 0; i < num_channels; i++) {
530 		wifi_pos_ch[i].ch_power.center_freq = ch_info[i].center_freq;
531 		wifi_pos_ch[i].ch_power.chan_num = ch_info[i].chan_num;
532 		wifi_pos_ch[i].ch_power.tx_power = ch_info[i].tx_power;
533 		wifi_pos_ch[i].is_dfs_chan =
534 			wlan_reg_is_dfs_for_freq(pdev, ch_info[i].center_freq);
535 		wifi_update_channel_bw_info(
536 				psoc, pdev,
537 				ch_info[i].center_freq, &wifi_pos_ch[i]);
538 	}
539 
540 	if (wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels) {
541 		status = wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels(
542 				pdev, wifi_pos_ch, num_channels);
543 		if (QDF_IS_STATUS_ERROR(status)) {
544 			wifi_pos_err("Failed to get phymode");
545 			qdf_mem_free(ch_info);
546 			return;
547 		}
548 	}
549 
550 	chan_list->num_channels += num_channels;
551 	qdf_mem_free(ch_info);
552 }
553 
554 #ifdef CNSS_GENL
555 static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
556 {
557 	return (rsp_version == WIFI_POS_RSP_V2_NL) ? true : false;
558 }
559 
560 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
561 				 struct wifi_pos_channel_list *chan_list)
562 {
563 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
564 				     wifi_pos_pdev_iterator,
565 				     chan_list, true, WLAN_WIFI_POS_CORE_ID);
566 	wifi_pos_debug("num channels: %d", chan_list->num_channels);
567 }
568 
569 #else
570 static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
571 {
572 	return ((rsp_version == WIFI_POS_RSP_V2_NL) ||
573 		(rsp_version == WIFI_POS_RSP_V1_FLAT_MEMORY)) ?
574 		true : false;
575 }
576 
577 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
578 				 struct wifi_pos_channel_list *chan_list)
579 {
580 	uint8_t index;
581 
582 	for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
583 		if (g_umac_glb_obj->psoc[index]) {
584 			wlan_objmgr_iterate_obj_list(
585 					g_umac_glb_obj->psoc[index],
586 					WLAN_PDEV_OP, wifi_pos_pdev_iterator,
587 					chan_list, true, WLAN_WIFI_POS_CORE_ID);
588 		}
589 	}
590 
591 	wifi_pos_notice("num channels: %d", chan_list->num_channels);
592 }
593 #endif
594 
595 static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
596 					struct wifi_pos_req_msg *req)
597 {
598 	uint8_t idx;
599 	uint8_t *buf = NULL;
600 	uint32_t len, i, freq;
601 	qdf_freq_t *chan_freqs = NULL;
602 	bool oem_6g_support_disable;
603 	uint8_t *channels = req->buf;
604 	struct wlan_objmgr_pdev *pdev;
605 	uint32_t num_ch = req->buf_len;
606 	qdf_freq_t valid_channel_list[NUM_CHANNELS];
607 	uint32_t num_valid_channels = 0;
608 	struct wifi_pos_ch_info_rsp *ch_info;
609 	struct wifi_pos_channel_list *ch_list = NULL;
610 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
611 					wifi_pos_get_psoc_priv_obj(psoc);
612 	QDF_STATUS ret_val;
613 	struct wifi_pos_channel_power *ch;
614 
615 	if (!wifi_pos_obj) {
616 		wifi_pos_err("wifi_pos priv obj is null");
617 		return QDF_STATUS_E_INVAL;
618 	}
619 
620 	wifi_pos_debug("Received ch info req pid(%d), len(%d)",
621 			req->pid, req->buf_len);
622 
623 	/* get first pdev since we need that only for freq and dfs state */
624 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
625 	if (!pdev) {
626 		wifi_pos_err("pdev get API failed");
627 		return QDF_STATUS_E_INVAL;
628 	}
629 	if (num_ch > NUM_CHANNELS) {
630 		wifi_pos_err("Invalid number of channels");
631 		ret_val = QDF_STATUS_E_INVAL;
632 		goto cleanup;
633 	}
634 
635 	chan_freqs = qdf_mem_malloc(NUM_CHANNELS * (sizeof(*chan_freqs)));
636 	if (!chan_freqs) {
637 		ret_val = QDF_STATUS_E_NOMEM;
638 		goto cleanup;
639 	}
640 
641 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
642 	if (!ch_list) {
643 		ret_val = QDF_STATUS_E_NOMEM;
644 		goto cleanup;
645 	}
646 
647 	ch = ch_list->chan_info;
648 
649 	if ((num_ch == 0) &&
650 	    wifi_pos_is_resp_version_valid(req->rsp_version)) {
651 		wifi_pos_get_ch_info(psoc, ch_list);
652 		qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
653 		oem_6g_support_disable = wifi_pos_obj->oem_6g_support_disable;
654 		qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
655 
656 		/* ch_list has the frequencies in order of 2.4g, 5g & 6g */
657 		for (i = 0; i < ch_list->num_channels; i++) {
658 			freq = ch[i].ch_power.center_freq;
659 			if (oem_6g_support_disable &&
660 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
661 				continue;
662 			num_valid_channels++;
663 		}
664 	} else {
665 		for (i = 0; i < NUM_CHANNELS; i++)
666 			chan_freqs[i] =
667 			    wlan_reg_chan_band_to_freq(pdev, channels[i],
668 						       BIT(REG_BAND_5G) |
669 						       BIT(REG_BAND_2G));
670 		/* v1 has ch_list with frequencies in order of 2.4g, 5g only */
671 		num_valid_channels = wifi_pos_get_valid_channels(
672 							chan_freqs, num_ch,
673 							 valid_channel_list);
674 		for (i = 0; i < num_valid_channels; i++) {
675 			ch[i].ch_power.center_freq = valid_channel_list[i];
676 			ch[i].ch_power.chan_num = wlan_reg_freq_to_chan(
677 					pdev, ch[i].ch_power.center_freq);
678 			ch[i].ch_power.tx_power =
679 				wlan_reg_get_channel_reg_power_for_freq(
680 						pdev,
681 						ch[i].ch_power.center_freq);
682 			ch[i].is_dfs_chan = wlan_reg_is_dfs_for_freq(
683 						pdev,
684 						ch[i].ch_power.center_freq);
685 
686 			wifi_update_channel_bw_info(psoc, pdev,
687 						    ch[i].ch_power.center_freq,
688 						    &ch[i]);
689 		}
690 	}
691 
692 	len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
693 			num_valid_channels;
694 	buf = qdf_mem_malloc(len);
695 	if (!buf) {
696 		ret_val = QDF_STATUS_E_NOMEM;
697 		goto cleanup;
698 	}
699 
700 	/* First byte of message body will have num of channels */
701 	buf[0] = num_valid_channels;
702 	ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
703 	for (idx = 0; idx < num_valid_channels; idx++) {
704 		ch_info[idx].reserved0 = 0;
705 		ch_info[idx].chan_id = ch[idx].ch_power.chan_num;
706 		ch_info[idx].mhz = ch[idx].ch_power.center_freq;
707 		ch_info[idx].band_center_freq1 = ch[idx].band_center_freq1;
708 		ch_info[idx].band_center_freq2 = 0;
709 		ch_info[idx].info = 0;
710 
711 		REG_SET_CHANNEL_REG_POWER(ch_info[idx].reg_info_1,
712 					  ch[idx].ch_power.tx_power);
713 		REG_SET_CHANNEL_MAX_TX_POWER(ch_info[idx].reg_info_2,
714 					     ch[idx].ch_power.tx_power);
715 
716 		if (ch[idx].is_dfs_chan)
717 			WIFI_POS_SET_DFS(ch_info[idx].info);
718 
719 		if (ch[idx].phy_mode)
720 			REG_SET_CHANNEL_MODE(&ch_info[idx], ch[idx].phy_mode);
721 	}
722 
723 	wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
724 					WIFI_POS_CMD_GET_CH_INFO,
725 					len, buf);
726 	ret_val = QDF_STATUS_SUCCESS;
727 
728 cleanup:
729 	qdf_mem_free(buf);
730 	qdf_mem_free(ch_list);
731 	qdf_mem_free(chan_freqs);
732 	wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
733 
734 	return ret_val;
735 }
736 
737 static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
738 				   void *vdev, void *arg)
739 {
740 	struct app_reg_rsp_vdev_info *vdev_info = arg;
741 
742 	vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
743 	vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
744 	vdev_idx++;
745 }
746 
747 #ifdef CNSS_GENL
748 static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
749 				   struct app_reg_rsp_vdev_info *vdevs_info)
750 {
751 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
752 				     wifi_pos_vdev_iterator,
753 				     vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
754 }
755 #else
756 /* For WIN, WIFI POS command registration is called only for the first
757  * PSOC. Hence, iterate through all the PSOCs and send the vdev list
758  * to LOWI.
759  */
760 static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
761 				   struct app_reg_rsp_vdev_info *vdevs_info)
762 {
763 	uint8_t index;
764 
765 	for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
766 		if (g_umac_glb_obj->psoc[index]) {
767 			wlan_objmgr_iterate_obj_list(
768 					g_umac_glb_obj->psoc[index],
769 					WLAN_VDEV_OP, wifi_pos_vdev_iterator,
770 					vdevs_info, true,
771 					WLAN_WIFI_POS_CORE_ID);
772 		}
773 	}
774 }
775 #endif
776 
777 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
778 					struct wifi_pos_req_msg *req)
779 {
780 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
781 	uint8_t err = 0, *app_reg_rsp;
782 	uint32_t rsp_len;
783 	char *sign_str = NULL;
784 	struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
785 								= { { 0 } };
786 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
787 			wifi_pos_get_psoc_priv_obj(psoc);
788 
789 	if (!wifi_pos_obj) {
790 		wifi_pos_err("wifi_pos priv obj is null");
791 		return QDF_STATUS_E_INVAL;
792 	}
793 
794 	wifi_pos_debug("Received App Req Req pid(%d), len(%d)",
795 			req->pid, req->buf_len);
796 
797 	sign_str = (char *)req->buf;
798 	/* Registration request is only allowed for QTI Application */
799 	if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
800 		(strncmp(sign_str, OEM_APP_SIGNATURE_STR,
801 			 OEM_APP_SIGNATURE_LEN))) {
802 		wifi_pos_err("Invalid signature pid(%d)", req->pid);
803 		ret = QDF_STATUS_E_PERM;
804 		err = OEM_ERR_INVALID_SIGNATURE;
805 		goto app_reg_failed;
806 	}
807 
808 	wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
809 	qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
810 	wifi_pos_obj->is_app_registered = true;
811 	wifi_pos_obj->app_pid = req->pid;
812 	qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
813 
814 	vdev_idx = 0;
815 
816 	wifi_pos_get_vdev_list(psoc, vdevs_info);
817 
818 	app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
819 	if (!app_reg_rsp) {
820 		ret = QDF_STATUS_E_NOMEM;
821 		err = OEM_ERR_NULL_CONTEXT;
822 		goto app_reg_failed;
823 	}
824 
825 	if (!vdev_idx)
826 		wifi_pos_debug("no active vdev");
827 
828 	vdev_idx = 0;
829 	wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid,
830 					WIFI_POS_CMD_REGISTRATION,
831 					rsp_len, (uint8_t *)app_reg_rsp);
832 
833 	qdf_mem_free(app_reg_rsp);
834 	return ret;
835 
836 app_reg_failed:
837 
838 	wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid, WIFI_POS_CMD_ERROR,
839 					sizeof(err), &err);
840 	return ret;
841 }
842 
843 /**
844  * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
845  * @wmi_msg: wmi type request msg
846  *
847  * Return: status of operation
848  */
849 static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
850 					struct wifi_pos_req_msg *req)
851 {
852 	wifi_pos_debug("enter: msg_type: %d", req->msg_type);
853 	switch (req->msg_type) {
854 	case WIFI_POS_CMD_REGISTRATION:
855 		return wifi_pos_process_app_reg_req(psoc, req);
856 	case WIFI_POS_CMD_OEM_DATA:
857 		return wifi_pos_process_data_req(psoc, req);
858 	case WIFI_POS_CMD_GET_CH_INFO:
859 		return wifi_pos_process_ch_info_req(psoc, req);
860 	case WIFI_POS_CMD_SET_CAPS:
861 		return wifi_pos_process_set_cap_req(psoc, req);
862 	case WIFI_POS_CMD_GET_CAPS:
863 		return wifi_pos_process_get_cap_req(psoc, req);
864 	default:
865 		wifi_pos_err("invalid request type");
866 		break;
867 	}
868 	return 0;
869 }
870 
871 /**
872  * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV
873  * type req
874  * @wmi_msg: wmi type request msg
875  *
876  * Return: status of operation
877  */
878 static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
879 					    struct wifi_pos_req_msg *req)
880 {
881 	return QDF_STATUS_SUCCESS;
882 }
883 
884 QDF_STATUS wifi_pos_convert_host_pdev_id_to_target(
885 		struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id,
886 		uint32_t *target_pdev_id)
887 {
888 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
889 
890 	tx_ops = wifi_pos_get_tx_ops(psoc);
891 	if (!tx_ops) {
892 		wifi_pos_err("tx_ops is null");
893 		return QDF_STATUS_E_NULL_VALUE;
894 	}
895 
896 	if (!tx_ops->wifi_pos_convert_pdev_id_host_to_target) {
897 		wifi_pos_err("wifi_pos_convert_pdev_id_host_to_target is null");
898 		return QDF_STATUS_E_NULL_VALUE;
899 	}
900 
901 	return tx_ops->wifi_pos_convert_pdev_id_host_to_target(
902 			psoc, host_pdev_id, target_pdev_id);
903 }
904 
905 QDF_STATUS wifi_pos_psoc_obj_created_notification(
906 		struct wlan_objmgr_psoc *psoc, void *arg_list)
907 {
908 	QDF_STATUS status;
909 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
910 
911 	/*
912 	 * this is for WIN, if they have multiple psoc, we dont want to create
913 	 * multiple priv object. Since there is just one LOWI app registered to
914 	 * one driver, avoid 2nd private object with another psoc.
915 	 */
916 	if (wifi_pos_get_psoc()) {
917 		wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
918 		return QDF_STATUS_SUCCESS;
919 	} else {
920 		wifi_pos_debug("setting global pos object");
921 		wifi_pos_set_psoc(psoc);
922 	}
923 
924 	/* initialize wifi-pos psoc priv object */
925 	wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
926 	if (!wifi_pos_obj) {
927 		wifi_pos_clear_psoc();
928 		return QDF_STATUS_E_NOMEM;
929 	}
930 
931 	qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
932 	/* Register TLV or non-TLV callbacks depending on target fw version */
933 	if (wifi_pos_get_tlv_support(psoc))
934 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
935 	else
936 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
937 
938 	/*
939 	 * MGMT Rx is not handled in this phase since wifi pos only uses few
940 	 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
941 	 * used for 80211k. That part is not yet converged and still follows
942 	 * legacy MGMT Rx to work. Action frame in new TXRX can be registered
943 	 * at per ACTION Frame type granularity only.
944 	 */
945 
946 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
947 						WLAN_UMAC_COMP_WIFI_POS,
948 						wifi_pos_obj,
949 						QDF_STATUS_SUCCESS);
950 
951 	if (QDF_IS_STATUS_ERROR(status)) {
952 		wifi_pos_err("obj attach with psoc failed with status: %d",
953 				status);
954 		qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
955 		qdf_mem_free(wifi_pos_obj);
956 		wifi_pos_clear_psoc();
957 	}
958 
959 	return status;
960 }
961 
962 QDF_STATUS  wifi_pos_psoc_obj_destroyed_notification(
963 		struct wlan_objmgr_psoc *psoc, void *arg_list)
964 {
965 	QDF_STATUS status;
966 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
967 
968 	if (wifi_pos_get_psoc() == psoc) {
969 		wifi_pos_debug("deregistering wifi_pos_psoc object");
970 		wifi_pos_clear_psoc();
971 	} else {
972 		wifi_pos_warn("un-related PSOC closed. do nothing");
973 		return QDF_STATUS_SUCCESS;
974 	}
975 
976 	wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
977 	if (!wifi_pos_obj) {
978 		wifi_pos_err("wifi_pos_obj is NULL");
979 		return QDF_STATUS_E_FAULT;
980 	}
981 
982 	target_if_wifi_pos_deinit_dma_rings(psoc);
983 
984 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
985 						WLAN_UMAC_COMP_WIFI_POS,
986 						wifi_pos_obj);
987 	if (status != QDF_STATUS_SUCCESS)
988 		wifi_pos_err("wifi_pos_obj detach failed");
989 
990 	wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
991 	qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
992 	qdf_mem_free(wifi_pos_obj);
993 
994 	return status;
995 }
996 
997 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
998 void
999 wifi_pos_init_11az_context(struct wifi_pos_vdev_priv_obj *vdev_pos_obj)
1000 {
1001 	struct wifi_pos_11az_context *pasn_context;
1002 	uint8_t i;
1003 
1004 	pasn_context = &vdev_pos_obj->pasn_context;
1005 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
1006 		qdf_set_macaddr_broadcast(
1007 				&pasn_context->secure_peer_list[i].peer_mac);
1008 		qdf_set_macaddr_broadcast(
1009 				&pasn_context->secure_peer_list[i].self_mac);
1010 		pasn_context->secure_peer_list[i].force_self_mac_usage = false;
1011 		pasn_context->secure_peer_list[i].control_flags = 0;
1012 		qdf_set_macaddr_broadcast(
1013 				&pasn_context->unsecure_peer_list[i].peer_mac);
1014 		qdf_set_macaddr_broadcast(&pasn_context->failed_peer_list[i]);
1015 	}
1016 
1017 	pasn_context->num_secure_peers = 0;
1018 	pasn_context->num_unsecure_peers = 0;
1019 	pasn_context->num_failed_peers = 0;
1020 }
1021 #endif
1022 
1023 QDF_STATUS
1024 wifi_pos_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
1025 				   void *arg_list)
1026 {
1027 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
1028 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1029 
1030 	vdev_pos_obj = qdf_mem_malloc(sizeof(*vdev_pos_obj));
1031 	if (!vdev_pos_obj)
1032 		return QDF_STATUS_E_NOMEM;
1033 
1034 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
1035 						       WLAN_UMAC_COMP_WIFI_POS,
1036 						       vdev_pos_obj,
1037 						       QDF_STATUS_SUCCESS);
1038 	if (QDF_IS_STATUS_ERROR(status)) {
1039 		qdf_mem_free(vdev_pos_obj);
1040 		wifi_pos_err("Wifi pos vdev attach failed");
1041 		return status;
1042 	}
1043 
1044 	wifi_pos_init_11az_context(vdev_pos_obj);
1045 
1046 	return status;
1047 }
1048 
1049 QDF_STATUS
1050 wifi_pos_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
1051 				     void *arg_list)
1052 {
1053 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
1054 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1055 
1056 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
1057 	if (!vdev_pos_obj) {
1058 		wifi_pos_err("Wifi pos vdev priv obj is null");
1059 		return QDF_STATUS_E_FAILURE;
1060 	}
1061 
1062 	status = wlan_objmgr_vdev_component_obj_detach(vdev,
1063 						       WLAN_UMAC_COMP_WIFI_POS,
1064 						       vdev_pos_obj);
1065 	if (QDF_IS_STATUS_ERROR(status))
1066 		wifi_pos_err("Detach vdev private obj failed");
1067 
1068 	qdf_mem_free(vdev_pos_obj);
1069 
1070 	return status;
1071 }
1072 
1073 QDF_STATUS
1074 wifi_pos_peer_object_created_notification(struct wlan_objmgr_peer *peer,
1075 					  void *arg)
1076 {
1077 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
1078 	QDF_STATUS status;
1079 
1080 	if (!peer) {
1081 		wifi_pos_err("Peer is NULL");
1082 		return QDF_STATUS_E_NULL_VALUE;
1083 	}
1084 
1085 	peer_priv = qdf_mem_malloc(sizeof(*peer_priv));
1086 	if (!peer_priv)
1087 		return QDF_STATUS_E_NOMEM;
1088 
1089 	status = wlan_objmgr_peer_component_obj_attach(peer,
1090 						       WLAN_UMAC_COMP_WIFI_POS,
1091 						       (void *)peer_priv,
1092 						       QDF_STATUS_SUCCESS);
1093 	if (QDF_IS_STATUS_ERROR(status)) {
1094 		wifi_pos_err("unable to attach peer_priv obj to peer obj");
1095 		qdf_mem_free(peer_priv);
1096 	}
1097 
1098 	return status;
1099 }
1100 
1101 QDF_STATUS
1102 wifi_pos_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
1103 					    void *arg)
1104 {
1105 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
1106 	QDF_STATUS status;
1107 
1108 	if (!peer) {
1109 		wifi_pos_err("Peer is NULL");
1110 		return QDF_STATUS_E_NULL_VALUE;
1111 	}
1112 
1113 	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
1114 							  WLAN_UMAC_COMP_WIFI_POS);
1115 	if (!peer_priv) {
1116 		wifi_pos_err("peer MLME component object is NULL");
1117 		return QDF_STATUS_E_FAILURE;
1118 	}
1119 
1120 	status = wlan_objmgr_peer_component_obj_detach(peer,
1121 						       WLAN_UMAC_COMP_WIFI_POS,
1122 						       (void *)peer_priv);
1123 	if (QDF_IS_STATUS_ERROR(status))
1124 		wifi_pos_err("unable to dettach peer_priv obj to peer obj");
1125 
1126 	qdf_mem_free(peer_priv);
1127 
1128 	return status;
1129 }
1130 
1131 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
1132 			     struct oem_data_rsp *oem_rsp)
1133 {
1134 	uint32_t len;
1135 	uint8_t *data;
1136 	uint32_t app_pid;
1137 	struct wifi_pos_psoc_priv_obj *priv;
1138 	wifi_pos_send_rsp_handler wifi_pos_send_rsp;
1139 
1140 	priv = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
1141 	if (!priv) {
1142 		wifi_pos_err("private object is NULL");
1143 		return -EINVAL;
1144 	}
1145 
1146 	qdf_spin_lock_bh(&priv->wifi_pos_lock);
1147 	app_pid = priv->app_pid;
1148 	wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
1149 	qdf_spin_unlock_bh(&priv->wifi_pos_lock);
1150 
1151 	len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
1152 	if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
1153 			oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
1154 		wifi_pos_err("invalid length of Oem Data response");
1155 		return -EINVAL;
1156 	}
1157 
1158 	if (!wifi_pos_send_rsp) {
1159 		wifi_pos_err("invalid response handler");
1160 		return -EINVAL;
1161 	}
1162 
1163 	wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
1164 
1165 	if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
1166 		/* stitch togther the msg data_1 + CIR/CFR + data_2 */
1167 		data = qdf_mem_malloc(len);
1168 		if (!data)
1169 			return -ENOMEM;
1170 
1171 		qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
1172 		qdf_mem_copy(&data[oem_rsp->rsp_len_1],
1173 			     oem_rsp->vaddr, oem_rsp->dma_len);
1174 		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
1175 			     oem_rsp->data_2, oem_rsp->rsp_len_2);
1176 
1177 		wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA, len,
1178 				  data);
1179 		qdf_mem_free(data);
1180 	} else {
1181 		wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA,
1182 				  oem_rsp->rsp_len_1, oem_rsp->data_1);
1183 	}
1184 
1185 	return 0;
1186 }
1187 
1188 void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
1189 {
1190 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
1191 
1192 	wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
1193 	wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
1194 }
1195 
1196 QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
1197 			   struct wifi_pos_driver_caps *caps)
1198 {
1199 	uint16_t i, count = 0;
1200 	uint32_t freq;
1201 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
1202 					wifi_pos_get_psoc_priv_obj(psoc);
1203 	struct wifi_pos_channel_list *ch_list = NULL;
1204 
1205 	wifi_pos_debug("Enter");
1206 	if (!wifi_pos_obj) {
1207 		wifi_pos_err("wifi_pos_obj is null");
1208 		return QDF_STATUS_E_NULL_VALUE;
1209 	}
1210 
1211 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
1212 	if (!ch_list)
1213 		return QDF_STATUS_E_NOMEM;
1214 
1215 	strlcpy(caps->oem_target_signature,
1216 		OEM_TARGET_SIGNATURE,
1217 		OEM_TARGET_SIGNATURE_LEN);
1218 	caps->oem_target_type = wifi_pos_obj->oem_target_type;
1219 	caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
1220 	caps->driver_version.major = wifi_pos_obj->driver_version.major;
1221 	caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
1222 	caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
1223 	caps->driver_version.build = wifi_pos_obj->driver_version.build;
1224 	caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
1225 	caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
1226 	caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
1227 	caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
1228 	caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
1229 	wifi_pos_get_ch_info(psoc, ch_list);
1230 
1231 	/* copy valid channels list to caps */
1232 	for (i = 0; i < ch_list->num_channels; i++) {
1233 		freq = ch_list->chan_info[i].ch_power.center_freq;
1234 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
1235 			continue;
1236 		caps->channel_list[count++] =
1237 			ch_list->chan_info[i].ch_power.chan_num;
1238 	}
1239 	caps->num_channels = count;
1240 	qdf_mem_free(ch_list);
1241 	return QDF_STATUS_SUCCESS;
1242 }
1243