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