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