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