xref: /wlan-dirver/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
1 /*
2  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: wifi_pos_main.c
21  * This file defines the important functions pertinent to
22  * wifi positioning to initialize and de-initialize the component.
23  */
24 #include "target_if_wifi_pos.h"
25 #include "wifi_pos_oem_interface_i.h"
26 #include "wifi_pos_utils_i.h"
27 #include "wifi_pos_api.h"
28 #include "wifi_pos_main_i.h"
29 #include "wifi_pos_ucfg_i.h"
30 #include "wlan_objmgr_cmn.h"
31 #include "wlan_objmgr_global_obj.h"
32 #include "wlan_objmgr_psoc_obj.h"
33 #include "wlan_objmgr_pdev_obj.h"
34 #include "wlan_objmgr_vdev_obj.h"
35 #include "wlan_ptt_sock_svc.h"
36 
37 #include "wlan_reg_services_api.h"
38 /* forward declartion */
39 struct regulatory_channel;
40 
41 #define REG_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \
42 	reg_info_1 &= 0xff00ffff;           \
43 	reg_info_1 |= ((val & 0xff) << 16); \
44 } while (0)
45 
46 /* max tx power is in 1 dBm units */
47 #define REG_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \
48 	reg_info_2 &= 0xffff00ff;              \
49 	reg_info_2 |= ((val & 0xff) << 8);     \
50 } while (0)
51 
52 /* channel info consists of 6 bits of channel mode */
53 
54 #define REG_SET_CHANNEL_MODE(reg_channel, val) do { \
55 	(reg_channel)->info &= 0xffffffc0;            \
56 	(reg_channel)->info |= (val);                 \
57 } while (0)
58 
59 /*
60  * obj mgr api to iterate over vdevs does not provide a direct array or vdevs,
61  * rather takes a callback that is called for every vdev. wifi pos needs to
62  * store device mode and vdev id of all active vdevs and provide this info to
63  * user space as part of APP registration response. due to this, vdev_idx is
64  * used to identify how many vdevs have been populated by obj manager API.
65  */
66 static uint32_t vdev_idx;
67 
68 /**
69  * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg
70  * @psoc: psoc object
71  *
72  * Return: status of operation
73  */
74 static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
75 {
76 	/* this is TBD */
77 	return true;
78 }
79 
80 struct wlan_lmac_if_wifi_pos_tx_ops *
81 	wifi_pos_get_tx_ops(struct wlan_objmgr_psoc *psoc)
82 {
83 	if (!psoc) {
84 		wifi_pos_err("psoc is null");
85 		return NULL;
86 	}
87 
88 	return &psoc->soc_cb.tx_ops.wifi_pos_tx_ops;
89 }
90 
91 static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
92 					struct wifi_pos_req_msg *req)
93 {
94 	uint8_t idx;
95 	uint32_t sub_type = 0;
96 	uint32_t channel_mhz = 0;
97 	uint32_t pdev_id = 0;
98 	uint32_t offset;
99 	struct oem_data_req data_req;
100 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
101 	struct wlan_objmgr_pdev *pdev;
102 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
103 				wifi_pos_get_psoc_priv_obj(psoc);
104 
105 	if (!wifi_pos_obj) {
106 		wifi_pos_err("wifi_pos priv obj is null");
107 		return QDF_STATUS_E_INVAL;
108 	}
109 
110 	wifi_pos_debug("Received data req pid(%d), len(%d)",
111 			req->pid, req->buf_len);
112 
113 	/* look for fields */
114 	if (req->field_info_buf)
115 		for (idx = 0; idx < req->field_info_buf->count; idx++) {
116 			offset = req->field_info_buf->fields[idx].offset;
117 			/*
118 			 * replace following reads with read_api based on
119 			 * length
120 			 */
121 			if (req->field_info_buf->fields[idx].id ==
122 					WMIRTT_FIELD_ID_oem_data_sub_type) {
123 				sub_type = *((uint32_t *)&req->buf[offset]);
124 				continue;
125 			}
126 
127 			if (req->field_info_buf->fields[idx].id ==
128 					WMIRTT_FIELD_ID_channel_mhz) {
129 				channel_mhz = *((uint32_t *)&req->buf[offset]);
130 				continue;
131 			}
132 
133 			if (req->field_info_buf->fields[idx].id ==
134 					WMIRTT_FIELD_ID_pdev) {
135 				pdev_id = *((uint32_t *)&req->buf[offset]);
136 				/* pdev_id in FW starts from 1. So convert it to
137 				 * host id by decrementing it.
138 				 * zero has special meaning due to backward
139 				 * compatibility. Dont change it.
140 				 */
141 				if (pdev_id)
142 					pdev_id -= 1;
143 				continue;
144 			}
145 		}
146 
147 	switch (sub_type) {
148 	case TARGET_OEM_CAPABILITY_REQ:
149 		/* TBD */
150 		break;
151 	case TARGET_OEM_CONFIGURE_LCR:
152 		/* TBD */
153 		break;
154 	case TARGET_OEM_CONFIGURE_LCI:
155 		/* TBD */
156 		break;
157 	case TARGET_OEM_MEASUREMENT_REQ:
158 		/* TBD */
159 		break;
160 	case TARGET_OEM_CONFIGURE_FTMRR:
161 		wifi_pos_debug("FTMRR request");
162 		if (wifi_pos_obj->wifi_pos_send_action)
163 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
164 							   req->buf,
165 							   req->buf_len);
166 		break;
167 	case TARGET_OEM_CONFIGURE_WRU:
168 		wifi_pos_debug("WRU request");
169 		if (wifi_pos_obj->wifi_pos_send_action)
170 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
171 							   req->buf,
172 							   req->buf_len);
173 		break;
174 	default:
175 		wifi_pos_debug("invalid sub type or not passed");
176 
177 		tx_ops = wifi_pos_get_tx_ops(psoc);
178 		if (!tx_ops) {
179 			wifi_pos_err("tx ops null");
180 			return QDF_STATUS_E_INVAL;
181 		}
182 
183 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
184 						  WLAN_WIFI_POS_CORE_ID);
185 		if (pdev) {
186 			data_req.data_len = req->buf_len;
187 			data_req.data = req->buf;
188 			tx_ops->data_req_tx(pdev, &data_req);
189 			wlan_objmgr_pdev_release_ref(pdev,
190 						     WLAN_WIFI_POS_CORE_ID);
191 		}
192 		break;
193 	}
194 
195 	return QDF_STATUS_SUCCESS;
196 }
197 
198 static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
199 					struct wifi_pos_req_msg *req)
200 {
201 	int error_code;
202 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
203 				wifi_pos_get_psoc_priv_obj(psoc);
204 	struct wifi_pos_user_defined_caps *caps =
205 				(struct wifi_pos_user_defined_caps *)req->buf;
206 
207 	if (!wifi_pos_obj) {
208 		wifi_pos_err("wifi_pos priv obj is null");
209 		return QDF_STATUS_E_INVAL;
210 	}
211 
212 	wifi_pos_debug("Received set cap req pid(%d), len(%d)",
213 			req->pid, req->buf_len);
214 
215 	wifi_pos_obj->ftm_rr = caps->ftm_rr;
216 	wifi_pos_obj->lci_capability = caps->lci_capability;
217 	error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
218 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
219 					ANI_MSG_SET_OEM_CAP_RSP,
220 					sizeof(error_code),
221 					(uint8_t *)&error_code);
222 
223 	return QDF_STATUS_SUCCESS;
224 }
225 
226 static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
227 					struct wifi_pos_req_msg *req)
228 {
229 	struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
230 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
231 					wifi_pos_get_psoc_priv_obj(psoc);
232 
233 	if (!wifi_pos_obj) {
234 		wifi_pos_err("wifi_pos priv obj is null");
235 		return QDF_STATUS_E_INVAL;
236 	}
237 
238 	wifi_pos_debug("Received get cap req pid(%d), len(%d)",
239 			req->pid, req->buf_len);
240 
241 	wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
242 	cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
243 	cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
244 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
245 					ANI_MSG_GET_OEM_CAP_RSP,
246 					sizeof(cap_rsp),
247 					(uint8_t *)&cap_rsp);
248 
249 	return QDF_STATUS_SUCCESS;
250 }
251 
252 QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
253 				     int req_id, uint8_t *dest_mac,
254 				     int err_code)
255 {
256 	struct wifi_pos_err_msg_report err_report = {0};
257 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
258 					wifi_pos_get_psoc_priv_obj(psoc);
259 
260 	if (!wifi_pos_obj) {
261 		wifi_pos_err("wifi_pos priv obj is null");
262 		return QDF_STATUS_E_INVAL;
263 	}
264 
265 	err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
266 	err_report.msg_tag_len |= (sizeof(err_report) -
267 				   sizeof(err_report.err_rpt)) & 0x0000FFFF;
268 	err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
269 	err_report.req_id = req_id & 0xFFFF;
270 	err_report.req_id |= ((err_code & 0xFF) << 16);
271 	err_report.req_id |= (0x1 << 24);
272 	err_report.time_left = 0xFFFFFFFF;
273 	err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
274 	err_report.err_rpt.tag_len |=
275 				(sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
276 	memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
277 
278 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
279 			ANI_MSG_OEM_DATA_RSP,
280 			sizeof(err_report),
281 			(uint8_t *)&err_report);
282 
283 	return QDF_STATUS_SUCCESS;
284 }
285 
286 static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
287 					struct wlan_objmgr_pdev *pdev,
288 					uint16_t chan,
289 					struct wifi_pos_ch_info_rsp *chan_info)
290 {
291 	struct ch_params ch_params = {0};
292 	uint16_t sec_ch_2g = 0;
293 	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
294 		wifi_pos_get_psoc_priv_obj(psoc);
295 	uint32_t phy_mode;
296 
297 	if (!wifi_pos_psoc) {
298 		wifi_pos_err("wifi_pos priv obj is null");
299 		return;
300 	}
301 
302 	/* Passing CH_WIDTH_MAX will give the max bandwidth supported */
303 	ch_params.ch_width = CH_WIDTH_MAX;
304 
305 	wlan_reg_set_channel_params(pdev, chan, sec_ch_2g, &ch_params);
306 	if (ch_params.center_freq_seg0)
307 		chan_info->band_center_freq1 =
308 			wlan_reg_legacy_chan_to_freq(
309 						pdev,
310 						ch_params.center_freq_seg0);
311 
312 	wifi_pos_psoc->wifi_pos_get_phy_mode(chan, ch_params.ch_width,
313 					     &phy_mode);
314 
315 	REG_SET_CHANNEL_MODE(chan_info, phy_mode);
316 }
317 
318 static void wifi_pos_get_reg_info(struct wlan_objmgr_pdev *pdev,
319 				  uint32_t chan_num, uint32_t *reg_info_1,
320 				  uint32_t *reg_info_2)
321 {
322 	uint32_t reg_power = wlan_reg_get_channel_reg_power(pdev, chan_num);
323 
324 	*reg_info_1 = 0;
325 	*reg_info_2 = 0;
326 
327 	REG_SET_CHANNEL_REG_POWER(*reg_info_1, reg_power);
328 	REG_SET_CHANNEL_MAX_TX_POWER(*reg_info_2, reg_power);
329 }
330 
331 /**
332  * wifi_pos_get_valid_channels: Get the list of valid channels from the
333  * given channel list
334  * @channels: Channel list to be validated
335  * @num_ch: NUmber of channels in the channel list to be validated
336  * @valid_channel_list: Pointer to valid channel list
337  *
338  * Return: Number of valid channels in the given list
339  */
340 
341 static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch,
342 					    uint8_t *valid_channel_list) {
343 	uint32_t i, num_valid_channels = 0;
344 
345 	for (i = 0; i < num_ch; i++) {
346 		if (wlan_reg_get_chan_enum(channels[i]) == INVALID_CHANNEL)
347 			continue;
348 		valid_channel_list[num_valid_channels++] = channels[i];
349 	}
350 	return num_valid_channels;
351 }
352 
353 static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
354 					struct wifi_pos_req_msg *req)
355 {
356 	uint8_t idx;
357 	uint8_t *buf;
358 	uint32_t len;
359 	uint32_t reg_info_1;
360 	uint32_t reg_info_2;
361 	uint8_t *channels = req->buf;
362 	struct wlan_objmgr_pdev *pdev;
363 	uint32_t num_ch = req->buf_len;
364 	uint8_t valid_channel_list[NUM_CHANNELS];
365 	uint32_t num_valid_channels;
366 	struct wifi_pos_ch_info_rsp *ch_info;
367 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
368 					wifi_pos_get_psoc_priv_obj(psoc);
369 
370 	if (!wifi_pos_obj) {
371 		wifi_pos_err("wifi_pos priv obj is null");
372 		return QDF_STATUS_E_INVAL;
373 	}
374 
375 	wifi_pos_debug("Received ch info req pid(%d), len(%d)",
376 			req->pid, req->buf_len);
377 
378 	/* get first pdev since we need that only for freq and dfs state */
379 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
380 	if (!pdev) {
381 		wifi_pos_err("pdev get API failed");
382 		return QDF_STATUS_E_INVAL;
383 	}
384 	if (num_ch > NUM_CHANNELS) {
385 		wifi_pos_err("Invalid number of channels");
386 		return QDF_STATUS_E_INVAL;
387 	}
388 	num_valid_channels = wifi_pos_get_valid_channels(channels, num_ch,
389 							 valid_channel_list);
390 
391 	len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
392 			num_valid_channels;
393 	buf = qdf_mem_malloc(len);
394 	if (!buf) {
395 		wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
396 		return QDF_STATUS_E_NOMEM;
397 	}
398 
399 	qdf_mem_zero(buf, len);
400 
401 	/* First byte of message body will have num of channels */
402 	buf[0] = num_valid_channels;
403 	ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
404 	for (idx = 0; idx < num_valid_channels; idx++) {
405 		ch_info[idx].chan_id = valid_channel_list[idx];
406 		wifi_pos_get_reg_info(pdev, ch_info[idx].chan_id,
407 				      &reg_info_1, &reg_info_2);
408 		ch_info[idx].reserved0 = 0;
409 		ch_info[idx].mhz = wlan_reg_get_channel_freq(
410 						pdev,
411 						valid_channel_list[idx]);
412 		ch_info[idx].band_center_freq1 = ch_info[idx].mhz;
413 		ch_info[idx].band_center_freq2 = 0;
414 		ch_info[idx].info = 0;
415 		if (wlan_reg_is_dfs_ch(pdev, valid_channel_list[idx]))
416 			WIFI_POS_SET_DFS(ch_info[idx].info);
417 
418 		wifi_update_channel_bw_info(psoc, pdev,
419 					    ch_info[idx].chan_id,
420 					    &ch_info[idx]);
421 
422 		ch_info[idx].reg_info_1 = reg_info_1;
423 		ch_info[idx].reg_info_2 = reg_info_2;
424 	}
425 
426 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
427 					ANI_MSG_CHANNEL_INFO_RSP,
428 					len, buf);
429 	qdf_mem_free(buf);
430 	wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
431 
432 	return QDF_STATUS_SUCCESS;
433 }
434 
435 static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
436 				   void *vdev, void *arg)
437 {
438 	struct app_reg_rsp_vdev_info *vdev_info = arg;
439 
440 	vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
441 	vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
442 	vdev_idx++;
443 }
444 
445 #ifdef CNSS_GENL
446 static uint8_t *
447 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
448 			  struct app_reg_rsp_vdev_info *vdevs_info)
449 {
450 	uint32_t *nl_sign;
451 	uint8_t *resp_buf;
452 	struct wifi_app_reg_rsp *app_reg_rsp;
453 
454 	/*
455 	 * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp
456 	 * to indicate NLA type resoponse is supported for OEM request
457 	 * commands.
458 	 */
459 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
460 			+ sizeof(uint8_t) + ENHNC_FLAGS_LEN;
461 	resp_buf = qdf_mem_malloc(*rsp_len);
462 	if (!resp_buf)
463 		return NULL;
464 
465 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
466 	app_reg_rsp->num_inf = vdev_idx;
467 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
468 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
469 
470 	nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx];
471 	*nl_sign |= NL_ENABLE_OEM_REQ_RSP;
472 
473 	return resp_buf;
474 }
475 #else
476 static uint8_t *
477 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
478 			  struct app_reg_rsp_vdev_info *vdevs_info)
479 {
480 	uint8_t *resp_buf;
481 	struct wifi_app_reg_rsp *app_reg_rsp;
482 
483 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
484 			+ sizeof(uint8_t);
485 	resp_buf = qdf_mem_malloc(*rsp_len);
486 	if (!resp_buf)
487 		return NULL;
488 
489 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
490 	app_reg_rsp->num_inf = vdev_idx;
491 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
492 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
493 
494 	return resp_buf;
495 }
496 #endif
497 
498 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
499 					struct wifi_pos_req_msg *req)
500 {
501 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
502 	uint8_t err = 0, *app_reg_rsp;
503 	uint32_t rsp_len;
504 	char *sign_str = NULL;
505 	struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
506 								= { { 0 } };
507 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
508 			wifi_pos_get_psoc_priv_obj(psoc);
509 
510 	if (!wifi_pos_obj) {
511 		wifi_pos_err("wifi_pos priv obj is null");
512 		return QDF_STATUS_E_INVAL;
513 	}
514 
515 	wifi_pos_err("Received App Req Req pid(%d), len(%d)",
516 			req->pid, req->buf_len);
517 
518 	sign_str = (char *)req->buf;
519 	/* Registration request is only allowed for QTI Application */
520 	if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
521 		(strncmp(sign_str, OEM_APP_SIGNATURE_STR,
522 			 OEM_APP_SIGNATURE_LEN))) {
523 		wifi_pos_err("Invalid signature pid(%d)", req->pid);
524 		ret = QDF_STATUS_E_PERM;
525 		err = OEM_ERR_INVALID_SIGNATURE;
526 		goto app_reg_failed;
527 	}
528 
529 	wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
530 	qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
531 	wifi_pos_obj->is_app_registered = true;
532 	wifi_pos_obj->app_pid = req->pid;
533 	qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
534 
535 	vdev_idx = 0;
536 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
537 				     wifi_pos_vdev_iterator,
538 				     vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
539 
540 	app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
541 	if (!app_reg_rsp) {
542 		ret = QDF_STATUS_E_NOMEM;
543 		err = OEM_ERR_NULL_CONTEXT;
544 		goto app_reg_failed;
545 	}
546 
547 	if (!vdev_idx)
548 		wifi_pos_debug("no active vdev");
549 
550 	vdev_idx = 0;
551 	wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP,
552 					rsp_len, (uint8_t *)app_reg_rsp);
553 
554 	qdf_mem_free(app_reg_rsp);
555 	return ret;
556 
557 app_reg_failed:
558 
559 	wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR,
560 					sizeof(err), &err);
561 	return ret;
562 }
563 
564 /**
565  * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
566  * @wmi_msg: wmi type request msg
567  *
568  * Return: status of operation
569  */
570 static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
571 					struct wifi_pos_req_msg *req)
572 {
573 	wifi_pos_debug("enter: msg_type: %d", req->msg_type);
574 	switch (req->msg_type) {
575 	case ANI_MSG_APP_REG_REQ:
576 		return wifi_pos_process_app_reg_req(psoc, req);
577 	case ANI_MSG_OEM_DATA_REQ:
578 		return wifi_pos_process_data_req(psoc, req);
579 	case ANI_MSG_CHANNEL_INFO_REQ:
580 		return wifi_pos_process_ch_info_req(psoc, req);
581 	case ANI_MSG_SET_OEM_CAP_REQ:
582 		return wifi_pos_process_set_cap_req(psoc, req);
583 	case ANI_MSG_GET_OEM_CAP_REQ:
584 		return wifi_pos_process_get_cap_req(psoc, req);
585 	default:
586 		wifi_pos_err("invalid request type");
587 		break;
588 	}
589 	return 0;
590 }
591 
592 /**
593  * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV
594  * type req
595  * @wmi_msg: wmi type request msg
596  *
597  * Return: status of operation
598  */
599 static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
600 					    struct wifi_pos_req_msg *req)
601 {
602 	return QDF_STATUS_SUCCESS;
603 }
604 
605 QDF_STATUS wifi_pos_psoc_obj_created_notification(
606 		struct wlan_objmgr_psoc *psoc, void *arg_list)
607 {
608 	QDF_STATUS status;
609 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
610 
611 	/*
612 	 * this is for WIN, if they have multiple psoc, we dont want to create
613 	 * multiple priv object. Since there is just one LOWI app registered to
614 	 * one driver, avoid 2nd private object with another psoc.
615 	 */
616 	if (wifi_pos_get_psoc()) {
617 		wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
618 		return QDF_STATUS_SUCCESS;
619 	} else {
620 		wifi_pos_debug("setting global pos object");
621 		wifi_pos_set_psoc(psoc);
622 	}
623 
624 	/* initialize wifi-pos psoc priv object */
625 	wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
626 	if (!wifi_pos_obj) {
627 		wifi_pos_clear_psoc();
628 		return QDF_STATUS_E_NOMEM;
629 	}
630 
631 	qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
632 	/* Register TLV or non-TLV callbacks depending on target fw version */
633 	if (wifi_pos_get_tlv_support(psoc))
634 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
635 	else
636 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
637 
638 	/*
639 	 * MGMT Rx is not handled in this phase since wifi pos only uses few
640 	 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
641 	 * used for 80211k. That part is not yet converged and still follows
642 	 * legacy MGMT Rx to work. Action frame in new TXRX can be registered
643 	 * at per ACTION Frame type granularity only.
644 	 */
645 
646 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
647 						WLAN_UMAC_COMP_WIFI_POS,
648 						wifi_pos_obj,
649 						QDF_STATUS_SUCCESS);
650 
651 	if (QDF_IS_STATUS_ERROR(status)) {
652 		wifi_pos_err("obj attach with psoc failed with status: %d",
653 				status);
654 		qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
655 		qdf_mem_free(wifi_pos_obj);
656 		wifi_pos_clear_psoc();
657 	}
658 
659 	return status;
660 }
661 
662 QDF_STATUS  wifi_pos_psoc_obj_destroyed_notification(
663 		struct wlan_objmgr_psoc *psoc, void *arg_list)
664 {
665 	QDF_STATUS status;
666 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
667 
668 	if (wifi_pos_get_psoc() == psoc) {
669 		wifi_pos_debug("deregistering wifi_pos_psoc object");
670 		wifi_pos_clear_psoc();
671 	} else {
672 		wifi_pos_warn("un-related PSOC closed. do nothing");
673 		return QDF_STATUS_SUCCESS;
674 	}
675 
676 	wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
677 	if (!wifi_pos_obj) {
678 		wifi_pos_err("wifi_pos_obj is NULL");
679 		return QDF_STATUS_E_FAULT;
680 	}
681 
682 	target_if_wifi_pos_deinit_dma_rings(psoc);
683 
684 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
685 						WLAN_UMAC_COMP_WIFI_POS,
686 						wifi_pos_obj);
687 	if (status != QDF_STATUS_SUCCESS)
688 		wifi_pos_err("wifi_pos_obj detach failed");
689 
690 	wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
691 	qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
692 	qdf_mem_free(wifi_pos_obj);
693 
694 	return status;
695 }
696 
697 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
698 			     struct oem_data_rsp *oem_rsp)
699 {
700 	uint32_t len;
701 	uint8_t *data;
702 	uint32_t app_pid;
703 	struct wifi_pos_psoc_priv_obj *priv =
704 					wifi_pos_get_psoc_priv_obj(psoc);
705 	void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
706 
707 	if (!priv) {
708 		wifi_pos_err("private object is NULL");
709 		return -EINVAL;
710 	}
711 
712 	qdf_spin_lock_bh(&priv->wifi_pos_lock);
713 	app_pid = priv->app_pid;
714 	wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
715 	qdf_spin_unlock_bh(&priv->wifi_pos_lock);
716 
717 	len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
718 	if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
719 			oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
720 		wifi_pos_err("invalid length of Oem Data response");
721 		return -EINVAL;
722 	}
723 
724 	if (!wifi_pos_send_rsp) {
725 		wifi_pos_err("invalid response handler");
726 		return -EINVAL;
727 	}
728 
729 	wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
730 
731 	if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
732 		/* stitch togther the msg data_1 + CIR/CFR + data_2 */
733 		data = qdf_mem_malloc(len);
734 		if (!data)
735 			return -ENOMEM;
736 
737 		qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
738 		qdf_mem_copy(&data[oem_rsp->rsp_len_1],
739 			     oem_rsp->vaddr, oem_rsp->dma_len);
740 		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
741 			     oem_rsp->data_2, oem_rsp->rsp_len_2);
742 
743 		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data);
744 		qdf_mem_free(data);
745 	} else {
746 		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP,
747 				  oem_rsp->rsp_len_1, oem_rsp->data_1);
748 	}
749 
750 	return 0;
751 }
752 
753 void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
754 {
755 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
756 
757 	wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
758 	wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
759 }
760 
761 static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
762 				   void *obj, void *arg)
763 {
764 	QDF_STATUS status;
765 	uint8_t i, num_channels, size;
766 	struct wlan_objmgr_pdev *pdev = obj;
767 	struct wifi_pos_driver_caps *caps = arg;
768 	struct channel_power *ch_list;
769 
770 	size = QDF_MAX(OEM_CAP_MAX_NUM_CHANNELS, NUM_CHANNELS);
771 	ch_list = qdf_mem_malloc(size * sizeof(*ch_list));
772 	if (!ch_list)
773 		return;
774 
775 	status = wlan_reg_get_channel_list_with_power(pdev, ch_list,
776 						      &num_channels);
777 
778 	if (QDF_IS_STATUS_ERROR(status)) {
779 		wifi_pos_err("Failed to get valid channel list");
780 		qdf_mem_free(ch_list);
781 		return;
782 	}
783 	if (num_channels > OEM_CAP_MAX_NUM_CHANNELS)
784 		num_channels = OEM_CAP_MAX_NUM_CHANNELS;
785 
786 	for (i = 0; i < num_channels; i++)
787 		caps->channel_list[i] = ch_list[i].chan_num;
788 	caps->num_channels = num_channels;
789 	qdf_mem_free(ch_list);
790 }
791 
792 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
793 				 struct wifi_pos_driver_caps *caps)
794 {
795 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
796 				     wifi_pos_pdev_iterator,
797 				      caps, true, WLAN_WIFI_POS_CORE_ID);
798 	wifi_pos_err("num channels: %d", caps->num_channels);
799 }
800 
801 QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
802 			   struct wifi_pos_driver_caps *caps)
803 {
804 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
805 					wifi_pos_get_psoc_priv_obj(psoc);
806 
807 	wifi_pos_debug("Enter");
808 	if (!wifi_pos_obj) {
809 		wifi_pos_err("wifi_pos_obj is null");
810 		return QDF_STATUS_E_NULL_VALUE;
811 	}
812 
813 	strlcpy(caps->oem_target_signature,
814 		OEM_TARGET_SIGNATURE,
815 		OEM_TARGET_SIGNATURE_LEN);
816 	caps->oem_target_type = wifi_pos_obj->oem_target_type;
817 	caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
818 	caps->driver_version.major = wifi_pos_obj->driver_version.major;
819 	caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
820 	caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
821 	caps->driver_version.build = wifi_pos_obj->driver_version.build;
822 	caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
823 	caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
824 	caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
825 	caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
826 	caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
827 	wifi_pos_get_ch_info(psoc, caps);
828 	return QDF_STATUS_SUCCESS;
829 }
830