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