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