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