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 */ 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 * 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 */ 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 * 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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