xref: /wlan-dirver/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c (revision a86b23ee68a2491aede2e03991f3fb37046f4e41)
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 	struct wlan_lmac_if_tx_ops *tx_ops;
84 
85 	if (!psoc) {
86 		wifi_pos_err("psoc is null");
87 		return NULL;
88 	}
89 
90 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
91 	if (!tx_ops) {
92 		wifi_pos_err("tx_ops is NULL");
93 		return NULL;
94 	}
95 
96 	return &tx_ops->wifi_pos_tx_ops;
97 }
98 
99 #ifdef CNSS_GENL
100 static uint8_t *
101 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
102 			  struct app_reg_rsp_vdev_info *vdevs_info)
103 {
104 	uint32_t *nl_sign;
105 	uint8_t *resp_buf;
106 	struct wifi_app_reg_rsp *app_reg_rsp;
107 
108 	/*
109 	 * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp
110 	 * to indicate NLA type response is supported for OEM request
111 	 * commands.
112 	 */
113 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
114 			+ sizeof(uint8_t) + ENHNC_FLAGS_LEN;
115 	resp_buf = qdf_mem_malloc(*rsp_len);
116 	if (!resp_buf)
117 		return NULL;
118 
119 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
120 	app_reg_rsp->num_inf = vdev_idx;
121 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
122 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
123 
124 	nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx];
125 	*nl_sign |= NL_ENABLE_OEM_REQ_RSP;
126 
127 	return resp_buf;
128 }
129 #else
130 static uint8_t *
131 wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
132 			  struct app_reg_rsp_vdev_info *vdevs_info)
133 {
134 	uint8_t *resp_buf;
135 	struct wifi_app_reg_rsp *app_reg_rsp;
136 
137 	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
138 			+ sizeof(uint8_t);
139 	resp_buf = qdf_mem_malloc(*rsp_len);
140 	if (!resp_buf)
141 		return NULL;
142 
143 	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
144 	app_reg_rsp->num_inf = vdev_idx;
145 	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
146 		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
147 
148 	return resp_buf;
149 }
150 #endif
151 
152 static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
153 					struct wifi_pos_req_msg *req)
154 {
155 	uint8_t idx;
156 	uint32_t sub_type = 0;
157 	uint32_t channel_mhz = 0;
158 	uint32_t pdev_id = 0;
159 	uint32_t offset;
160 	struct oem_data_req data_req;
161 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
162 	struct wlan_objmgr_pdev *pdev;
163 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
164 				wifi_pos_get_psoc_priv_obj(psoc);
165 
166 	if (!wifi_pos_obj) {
167 		wifi_pos_err("wifi_pos priv obj is null");
168 		return QDF_STATUS_E_INVAL;
169 	}
170 
171 	wifi_pos_debug("Received data req pid(%d), len(%d)",
172 			req->pid, req->buf_len);
173 
174 	/* look for fields */
175 	if (req->field_info_buf)
176 		for (idx = 0; idx < req->field_info_buf->count; idx++) {
177 			offset = req->field_info_buf->fields[idx].offset;
178 			/*
179 			 * replace following reads with read_api based on
180 			 * length
181 			 */
182 			if (req->field_info_buf->fields[idx].id ==
183 					WMIRTT_FIELD_ID_oem_data_sub_type) {
184 				sub_type = *((uint32_t *)&req->buf[offset]);
185 				continue;
186 			}
187 
188 			if (req->field_info_buf->fields[idx].id ==
189 					WMIRTT_FIELD_ID_channel_mhz) {
190 				channel_mhz = *((uint32_t *)&req->buf[offset]);
191 				continue;
192 			}
193 
194 			if (req->field_info_buf->fields[idx].id ==
195 					WMIRTT_FIELD_ID_pdev) {
196 				pdev_id = *((uint32_t *)&req->buf[offset]);
197 				/* pdev_id in FW starts from 1. So convert it to
198 				 * host id by decrementing it.
199 				 * zero has special meaning due to backward
200 				 * compatibility. Dont change it.
201 				 */
202 				if (pdev_id)
203 					pdev_id -= 1;
204 				continue;
205 			}
206 		}
207 
208 	switch (sub_type) {
209 	case TARGET_OEM_CAPABILITY_REQ:
210 		/* TBD */
211 		break;
212 	case TARGET_OEM_CONFIGURE_LCR:
213 		/* TBD */
214 		break;
215 	case TARGET_OEM_CONFIGURE_LCI:
216 		/* TBD */
217 		break;
218 	case TARGET_OEM_MEASUREMENT_REQ:
219 		/* TBD */
220 		break;
221 	case TARGET_OEM_CONFIGURE_FTMRR:
222 		wifi_pos_debug("FTMRR request");
223 		if (wifi_pos_obj->wifi_pos_send_action)
224 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
225 							   req->buf,
226 							   req->buf_len);
227 		break;
228 	case TARGET_OEM_CONFIGURE_WRU:
229 		wifi_pos_debug("WRU request");
230 		if (wifi_pos_obj->wifi_pos_send_action)
231 			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
232 							   req->buf,
233 							   req->buf_len);
234 		break;
235 	default:
236 		wifi_pos_debug("invalid sub type or not passed");
237 
238 		tx_ops = wifi_pos_get_tx_ops(psoc);
239 		if (!tx_ops) {
240 			wifi_pos_err("tx ops null");
241 			return QDF_STATUS_E_INVAL;
242 		}
243 
244 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
245 						  WLAN_WIFI_POS_CORE_ID);
246 		if (!pdev) {
247 			wifi_pos_err("pdev null");
248 			return QDF_STATUS_E_INVAL;
249 		}
250 		data_req.data_len = req->buf_len;
251 		data_req.data = req->buf;
252 		tx_ops->data_req_tx(pdev, &data_req);
253 		wlan_objmgr_pdev_release_ref(pdev,
254 					     WLAN_WIFI_POS_CORE_ID);
255 		break;
256 	}
257 
258 	return QDF_STATUS_SUCCESS;
259 }
260 
261 static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
262 					struct wifi_pos_req_msg *req)
263 {
264 	int error_code;
265 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
266 				wifi_pos_get_psoc_priv_obj(psoc);
267 	struct wifi_pos_user_defined_caps *caps =
268 				(struct wifi_pos_user_defined_caps *)req->buf;
269 
270 	if (!wifi_pos_obj) {
271 		wifi_pos_err("wifi_pos priv obj is null");
272 		return QDF_STATUS_E_INVAL;
273 	}
274 
275 	wifi_pos_debug("Received set cap req pid(%d), len(%d)",
276 			req->pid, req->buf_len);
277 
278 	wifi_pos_obj->ftm_rr = caps->ftm_rr;
279 	wifi_pos_obj->lci_capability = caps->lci_capability;
280 	error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
281 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
282 					WIFI_POS_CMD_SET_CAPS,
283 					sizeof(error_code),
284 					(uint8_t *)&error_code);
285 
286 	return QDF_STATUS_SUCCESS;
287 }
288 
289 static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
290 					struct wifi_pos_req_msg *req)
291 {
292 	struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
293 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
294 					wifi_pos_get_psoc_priv_obj(psoc);
295 
296 	if (!wifi_pos_obj) {
297 		wifi_pos_err("wifi_pos priv obj is null");
298 		return QDF_STATUS_E_INVAL;
299 	}
300 
301 	wifi_pos_debug("Received get cap req pid(%d), len(%d)",
302 		       req->pid, req->buf_len);
303 
304 	wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
305 	cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
306 	cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
307 
308 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
309 					WIFI_POS_CMD_GET_CAPS,
310 					sizeof(cap_rsp),
311 					(uint8_t *)&cap_rsp);
312 
313 	return QDF_STATUS_SUCCESS;
314 }
315 
316 QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
317 				     int req_id, uint8_t *dest_mac,
318 				     int err_code)
319 {
320 	struct wifi_pos_err_msg_report err_report = {0};
321 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
322 					wifi_pos_get_psoc_priv_obj(psoc);
323 
324 	if (!wifi_pos_obj) {
325 		wifi_pos_err("wifi_pos priv obj is null");
326 		return QDF_STATUS_E_INVAL;
327 	}
328 
329 	err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
330 	err_report.msg_tag_len |= (sizeof(err_report) -
331 				   sizeof(err_report.err_rpt)) & 0x0000FFFF;
332 	err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
333 	err_report.req_id = req_id & 0xFFFF;
334 	err_report.req_id |= ((err_code & 0xFF) << 16);
335 	err_report.req_id |= (0x1 << 24);
336 	err_report.time_left = 0xFFFFFFFF;
337 	err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
338 	err_report.err_rpt.tag_len |=
339 				(sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
340 	memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
341 
342 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
343 			WIFI_POS_CMD_OEM_DATA,
344 			sizeof(err_report),
345 			(uint8_t *)&err_report);
346 
347 	return QDF_STATUS_SUCCESS;
348 }
349 
350 static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
351 					struct wlan_objmgr_pdev *pdev,
352 					uint16_t freq,
353 					struct wifi_pos_ch_info_rsp *chan_info)
354 {
355 	struct ch_params ch_params = {0};
356 	uint16_t sec_ch_2g = 0;
357 	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
358 		wifi_pos_get_psoc_priv_obj(psoc);
359 	uint32_t phy_mode;
360 
361 	if (!wifi_pos_psoc) {
362 		wifi_pos_err("wifi_pos priv obj is null");
363 		return;
364 	}
365 
366 	/* Passing CH_WIDTH_MAX will give the max bandwidth supported */
367 	ch_params.ch_width = CH_WIDTH_MAX;
368 	wlan_reg_set_channel_params_for_freq(pdev, freq,
369 					     sec_ch_2g, &ch_params);
370 	chan_info->band_center_freq1 = ch_params.mhz_freq_seg0;
371 	wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq(freq,
372 						ch_params.ch_width,
373 						&phy_mode);
374 	REG_SET_CHANNEL_MODE(chan_info, phy_mode);
375 }
376 
377 static void wifi_pos_get_reg_info(struct wlan_objmgr_pdev *pdev,
378 				  uint16_t freq, uint32_t *reg_info_1,
379 				  uint32_t *reg_info_2)
380 {
381 	uint32_t reg_power = wlan_reg_get_channel_reg_power_for_freq(pdev,
382 								     freq);
383 
384 	*reg_info_1 = 0;
385 	*reg_info_2 = 0;
386 
387 	REG_SET_CHANNEL_REG_POWER(*reg_info_1, reg_power);
388 	REG_SET_CHANNEL_MAX_TX_POWER(*reg_info_2, reg_power);
389 }
390 
391 /**
392  * wifi_pos_get_valid_channels: Get the list of valid channels from the
393  * given channel list
394  * @channels: Channel list to be validated
395  * @num_ch: NUmber of channels in the channel list to be validated
396  * @valid_channel_list: Pointer to valid channel list
397  *
398  * Return: Number of valid channels in the given list
399  */
400 
401 static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch,
402 					    uint8_t *valid_channel_list) {
403 	uint32_t i, num_valid_channels = 0;
404 
405 	for (i = 0; i < num_ch; i++) {
406 		if (wlan_reg_get_chan_enum(channels[i]) == INVALID_CHANNEL)
407 			continue;
408 		valid_channel_list[num_valid_channels++] = channels[i];
409 	}
410 	return num_valid_channels;
411 }
412 
413 static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
414 				   void *obj, void *arg)
415 {
416 	QDF_STATUS status;
417 	uint8_t num_channels;
418 	struct wlan_objmgr_pdev *pdev = obj;
419 	struct wifi_pos_channel_list *chan_list = arg;
420 	struct channel_power *ch_info = NULL;
421 
422 	if (!chan_list) {
423 		wifi_pos_err("wifi_pos priv arg is null");
424 		return;
425 	}
426 	ch_info = (struct channel_power *)chan_list->chan_info;
427 	status = wlan_reg_get_channel_list_with_power(pdev, ch_info,
428 						      &num_channels);
429 
430 	if (QDF_IS_STATUS_ERROR(status)) {
431 		wifi_pos_err("Failed to get valid channel list");
432 		return;
433 	}
434 	chan_list->num_channels = num_channels;
435 }
436 
437 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
438 				 struct wifi_pos_channel_list *chan_list)
439 {
440 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
441 				     wifi_pos_pdev_iterator,
442 				     chan_list, true, WLAN_WIFI_POS_CORE_ID);
443 	wifi_pos_notice("num channels: %d", chan_list->num_channels);
444 }
445 
446 static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
447 					struct wifi_pos_req_msg *req)
448 {
449 	uint8_t idx, band_mask;
450 	uint8_t *buf;
451 	uint32_t len, i, freq;
452 	uint32_t reg_info_1;
453 	uint32_t reg_info_2;
454 	bool oem_6g_support_disable;
455 	uint8_t *channels = req->buf;
456 	struct wlan_objmgr_pdev *pdev;
457 	uint32_t num_ch = req->buf_len;
458 	uint8_t valid_channel_list[NUM_CHANNELS];
459 	uint32_t num_valid_channels = 0;
460 	struct wifi_pos_ch_info_rsp *ch_info;
461 	struct wifi_pos_channel_list *ch_list;
462 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
463 					wifi_pos_get_psoc_priv_obj(psoc);
464 
465 	if (!wifi_pos_obj) {
466 		wifi_pos_err("wifi_pos priv obj is null");
467 		return QDF_STATUS_E_INVAL;
468 	}
469 
470 	wifi_pos_debug("Received ch info req pid(%d), len(%d)",
471 			req->pid, req->buf_len);
472 
473 	/* get first pdev since we need that only for freq and dfs state */
474 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
475 	if (!pdev) {
476 		wifi_pos_err("pdev get API failed");
477 		return QDF_STATUS_E_INVAL;
478 	}
479 	if (num_ch > NUM_CHANNELS) {
480 		wifi_pos_err("Invalid number of channels");
481 		return QDF_STATUS_E_INVAL;
482 	}
483 
484 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
485 	if (!ch_list)
486 		return QDF_STATUS_E_NOMEM;
487 
488 	if (num_ch == 0 && req->rsp_version == WIFI_POS_RSP_V2_NL) {
489 		wifi_pos_get_ch_info(psoc, ch_list);
490 		qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
491 		oem_6g_support_disable = wifi_pos_obj->oem_6g_support_disable;
492 		qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
493 
494 		/* ch_list has the frequencies in order of 2.4g, 5g & 6g */
495 		for (i = 0; i < ch_list->num_channels; i++) {
496 			freq = ch_list->chan_info[i].center_freq;
497 			if (oem_6g_support_disable &&
498 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
499 				continue;
500 			num_valid_channels++;
501 		}
502 	} else {
503 		/* v1 has ch_list with frequencies in order of 2.4g, 5g only */
504 		num_valid_channels = wifi_pos_get_valid_channels(
505 							channels, num_ch,
506 							 valid_channel_list);
507 		band_mask = BIT(REG_BAND_5G) | BIT(REG_BAND_2G);
508 		for (i = 0; i < num_valid_channels; i++) {
509 			ch_list->chan_info[i].chan_num = valid_channel_list[i];
510 			ch_list->chan_info[i].center_freq =
511 				wlan_reg_chan_band_to_freq(
512 						pdev,
513 						ch_list->chan_info[i].chan_num,
514 						band_mask);
515 		}
516 	}
517 
518 	len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
519 			num_valid_channels;
520 	buf = qdf_mem_malloc(len);
521 	if (!buf) {
522 		wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
523 		qdf_mem_free(ch_list);
524 		return QDF_STATUS_E_NOMEM;
525 	}
526 
527 	/* First byte of message body will have num of channels */
528 	buf[0] = num_valid_channels;
529 	ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
530 	for (idx = 0; idx < num_valid_channels; idx++) {
531 		ch_info[idx].reserved0 = 0;
532 		ch_info[idx].chan_id = ch_list->chan_info[idx].chan_num;
533 		ch_info[idx].mhz = ch_list->chan_info[idx].center_freq;
534 		ch_info[idx].band_center_freq1 = ch_info[idx].mhz;
535 		ch_info[idx].band_center_freq2 = 0;
536 		ch_info[idx].info = 0;
537 		wifi_pos_get_reg_info(pdev, ch_info[idx].mhz,
538 				      &reg_info_1, &reg_info_2);
539 
540 		if (wlan_reg_is_dfs_for_freq(pdev, ch_info[idx].mhz))
541 			WIFI_POS_SET_DFS(ch_info[idx].info);
542 
543 		wifi_update_channel_bw_info(psoc, pdev,
544 					    ch_info[idx].mhz,
545 					    &ch_info[idx]);
546 
547 		ch_info[idx].reg_info_1 = reg_info_1;
548 		ch_info[idx].reg_info_2 = reg_info_2;
549 	}
550 
551 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
552 					WIFI_POS_CMD_GET_CH_INFO,
553 					len, buf);
554 
555 	qdf_mem_free(buf);
556 	qdf_mem_free(ch_list);
557 	wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
558 
559 	return QDF_STATUS_SUCCESS;
560 }
561 
562 static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
563 				   void *vdev, void *arg)
564 {
565 	struct app_reg_rsp_vdev_info *vdev_info = arg;
566 
567 	vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
568 	vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
569 	vdev_idx++;
570 }
571 
572 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
573 					struct wifi_pos_req_msg *req)
574 {
575 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
576 	uint8_t err = 0, *app_reg_rsp;
577 	uint32_t rsp_len;
578 	char *sign_str = NULL;
579 	struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
580 								= { { 0 } };
581 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
582 			wifi_pos_get_psoc_priv_obj(psoc);
583 
584 	if (!wifi_pos_obj) {
585 		wifi_pos_err("wifi_pos priv obj is null");
586 		return QDF_STATUS_E_INVAL;
587 	}
588 
589 	wifi_pos_err("Received App Req Req pid(%d), len(%d)",
590 			req->pid, req->buf_len);
591 
592 	sign_str = (char *)req->buf;
593 	/* Registration request is only allowed for QTI Application */
594 	if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
595 		(strncmp(sign_str, OEM_APP_SIGNATURE_STR,
596 			 OEM_APP_SIGNATURE_LEN))) {
597 		wifi_pos_err("Invalid signature pid(%d)", req->pid);
598 		ret = QDF_STATUS_E_PERM;
599 		err = OEM_ERR_INVALID_SIGNATURE;
600 		goto app_reg_failed;
601 	}
602 
603 	wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
604 	qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
605 	wifi_pos_obj->is_app_registered = true;
606 	wifi_pos_obj->app_pid = req->pid;
607 	qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
608 
609 	vdev_idx = 0;
610 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
611 				     wifi_pos_vdev_iterator,
612 				     vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
613 
614 	app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
615 	if (!app_reg_rsp) {
616 		ret = QDF_STATUS_E_NOMEM;
617 		err = OEM_ERR_NULL_CONTEXT;
618 		goto app_reg_failed;
619 	}
620 
621 	if (!vdev_idx)
622 		wifi_pos_debug("no active vdev");
623 
624 	vdev_idx = 0;
625 	wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_REGISTRATION,
626 					rsp_len, (uint8_t *)app_reg_rsp);
627 
628 	qdf_mem_free(app_reg_rsp);
629 	return ret;
630 
631 app_reg_failed:
632 
633 	wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_ERROR,
634 					sizeof(err), &err);
635 	return ret;
636 }
637 
638 /**
639  * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
640  * @wmi_msg: wmi type request msg
641  *
642  * Return: status of operation
643  */
644 static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
645 					struct wifi_pos_req_msg *req)
646 {
647 	wifi_pos_debug("enter: msg_type: %d", req->msg_type);
648 	switch (req->msg_type) {
649 	case WIFI_POS_CMD_REGISTRATION:
650 		return wifi_pos_process_app_reg_req(psoc, req);
651 	case WIFI_POS_CMD_OEM_DATA:
652 		return wifi_pos_process_data_req(psoc, req);
653 	case WIFI_POS_CMD_GET_CH_INFO:
654 		return wifi_pos_process_ch_info_req(psoc, req);
655 	case WIFI_POS_CMD_SET_CAPS:
656 		return wifi_pos_process_set_cap_req(psoc, req);
657 	case WIFI_POS_CMD_GET_CAPS:
658 		return wifi_pos_process_get_cap_req(psoc, req);
659 	default:
660 		wifi_pos_err("invalid request type");
661 		break;
662 	}
663 	return 0;
664 }
665 
666 /**
667  * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV
668  * type req
669  * @wmi_msg: wmi type request msg
670  *
671  * Return: status of operation
672  */
673 static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
674 					    struct wifi_pos_req_msg *req)
675 {
676 	return QDF_STATUS_SUCCESS;
677 }
678 
679 QDF_STATUS wifi_pos_psoc_obj_created_notification(
680 		struct wlan_objmgr_psoc *psoc, void *arg_list)
681 {
682 	QDF_STATUS status;
683 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
684 
685 	/*
686 	 * this is for WIN, if they have multiple psoc, we dont want to create
687 	 * multiple priv object. Since there is just one LOWI app registered to
688 	 * one driver, avoid 2nd private object with another psoc.
689 	 */
690 	if (wifi_pos_get_psoc()) {
691 		wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
692 		return QDF_STATUS_SUCCESS;
693 	} else {
694 		wifi_pos_debug("setting global pos object");
695 		wifi_pos_set_psoc(psoc);
696 	}
697 
698 	/* initialize wifi-pos psoc priv object */
699 	wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
700 	if (!wifi_pos_obj) {
701 		wifi_pos_clear_psoc();
702 		return QDF_STATUS_E_NOMEM;
703 	}
704 
705 	qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
706 	/* Register TLV or non-TLV callbacks depending on target fw version */
707 	if (wifi_pos_get_tlv_support(psoc))
708 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
709 	else
710 		wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
711 
712 	/*
713 	 * MGMT Rx is not handled in this phase since wifi pos only uses few
714 	 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
715 	 * used for 80211k. That part is not yet converged and still follows
716 	 * legacy MGMT Rx to work. Action frame in new TXRX can be registered
717 	 * at per ACTION Frame type granularity only.
718 	 */
719 
720 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
721 						WLAN_UMAC_COMP_WIFI_POS,
722 						wifi_pos_obj,
723 						QDF_STATUS_SUCCESS);
724 
725 	if (QDF_IS_STATUS_ERROR(status)) {
726 		wifi_pos_err("obj attach with psoc failed with status: %d",
727 				status);
728 		qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
729 		qdf_mem_free(wifi_pos_obj);
730 		wifi_pos_clear_psoc();
731 	}
732 
733 	return status;
734 }
735 
736 QDF_STATUS  wifi_pos_psoc_obj_destroyed_notification(
737 		struct wlan_objmgr_psoc *psoc, void *arg_list)
738 {
739 	QDF_STATUS status;
740 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
741 
742 	if (wifi_pos_get_psoc() == psoc) {
743 		wifi_pos_debug("deregistering wifi_pos_psoc object");
744 		wifi_pos_clear_psoc();
745 	} else {
746 		wifi_pos_warn("un-related PSOC closed. do nothing");
747 		return QDF_STATUS_SUCCESS;
748 	}
749 
750 	wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
751 	if (!wifi_pos_obj) {
752 		wifi_pos_err("wifi_pos_obj is NULL");
753 		return QDF_STATUS_E_FAULT;
754 	}
755 
756 	target_if_wifi_pos_deinit_dma_rings(psoc);
757 
758 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
759 						WLAN_UMAC_COMP_WIFI_POS,
760 						wifi_pos_obj);
761 	if (status != QDF_STATUS_SUCCESS)
762 		wifi_pos_err("wifi_pos_obj detach failed");
763 
764 	wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
765 	qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
766 	qdf_mem_free(wifi_pos_obj);
767 
768 	return status;
769 }
770 
771 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
772 			     struct oem_data_rsp *oem_rsp)
773 {
774 	uint32_t len;
775 	uint8_t *data;
776 	uint32_t app_pid;
777 	struct wifi_pos_psoc_priv_obj *priv =
778 					wifi_pos_get_psoc_priv_obj(psoc);
779 	wifi_pos_send_rsp_handler wifi_pos_send_rsp;
780 
781 	if (!priv) {
782 		wifi_pos_err("private object is NULL");
783 		return -EINVAL;
784 	}
785 
786 	qdf_spin_lock_bh(&priv->wifi_pos_lock);
787 	app_pid = priv->app_pid;
788 	wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
789 	qdf_spin_unlock_bh(&priv->wifi_pos_lock);
790 
791 	len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
792 	if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
793 			oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
794 		wifi_pos_err("invalid length of Oem Data response");
795 		return -EINVAL;
796 	}
797 
798 	if (!wifi_pos_send_rsp) {
799 		wifi_pos_err("invalid response handler");
800 		return -EINVAL;
801 	}
802 
803 	wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
804 
805 	if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
806 		/* stitch togther the msg data_1 + CIR/CFR + data_2 */
807 		data = qdf_mem_malloc(len);
808 		if (!data)
809 			return -ENOMEM;
810 
811 		qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
812 		qdf_mem_copy(&data[oem_rsp->rsp_len_1],
813 			     oem_rsp->vaddr, oem_rsp->dma_len);
814 		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
815 			     oem_rsp->data_2, oem_rsp->rsp_len_2);
816 
817 		wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA, len, data);
818 		qdf_mem_free(data);
819 	} else {
820 		wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA,
821 				  oem_rsp->rsp_len_1, oem_rsp->data_1);
822 	}
823 
824 	return 0;
825 }
826 
827 void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
828 {
829 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
830 
831 	wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
832 	wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
833 }
834 
835 QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
836 			   struct wifi_pos_driver_caps *caps)
837 {
838 	uint16_t i, count = 0;
839 	uint32_t freq;
840 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
841 					wifi_pos_get_psoc_priv_obj(psoc);
842 	struct wifi_pos_channel_list *ch_list = NULL;
843 
844 	wifi_pos_debug("Enter");
845 	if (!wifi_pos_obj) {
846 		wifi_pos_err("wifi_pos_obj is null");
847 		return QDF_STATUS_E_NULL_VALUE;
848 	}
849 
850 	ch_list = qdf_mem_malloc(sizeof(*ch_list));
851 	if (!ch_list)
852 		return QDF_STATUS_E_NOMEM;
853 
854 	strlcpy(caps->oem_target_signature,
855 		OEM_TARGET_SIGNATURE,
856 		OEM_TARGET_SIGNATURE_LEN);
857 	caps->oem_target_type = wifi_pos_obj->oem_target_type;
858 	caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
859 	caps->driver_version.major = wifi_pos_obj->driver_version.major;
860 	caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
861 	caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
862 	caps->driver_version.build = wifi_pos_obj->driver_version.build;
863 	caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
864 	caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
865 	caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
866 	caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
867 	caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
868 	wifi_pos_get_ch_info(psoc, ch_list);
869 
870 	/* copy valid channels list to caps */
871 	for (i = 0; i < ch_list->num_channels; i++) {
872 		freq = ch_list->chan_info[i].center_freq;
873 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
874 			continue;
875 		caps->channel_list[count++] = ch_list->chan_info[i].chan_num;
876 	}
877 	caps->num_channels = count;
878 	qdf_mem_free(ch_list);
879 	return QDF_STATUS_SUCCESS;
880 }
881