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