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