1 /* 2 * Copyright (c) 2013-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: target_if_wifi_pos.c 21 * This file defines the functions pertinent to wifi positioning component's 22 * target if layer. 23 */ 24 #include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h" 25 #include "wifi_pos_utils_pub.h" 26 27 #include "wmi_unified_api.h" 28 #include "wlan_lmac_if_def.h" 29 #include "target_if_wifi_pos.h" 30 #include "../../../../umac/wifi_pos/src/wifi_pos_main_i.h" 31 #include "target_if.h" 32 #ifdef WLAN_FEATURE_CIF_CFR 33 #include "hal_api.h" 34 35 #define RING_BASE_ALIGN 8 36 37 static void *target_if_wifi_pos_vaddr_lookup( 38 struct wifi_pos_psoc_priv_obj *priv, 39 void *paddr, uint8_t ring_num, uint32_t cookie) 40 { 41 if (priv->dma_buf_pool[ring_num][cookie].paddr == paddr) { 42 return priv->dma_buf_pool[ring_num][cookie].vaddr + 43 priv->dma_buf_pool[ring_num][cookie].offset; 44 } else { 45 target_if_err("incorrect paddr found on cookie slot"); 46 return NULL; 47 } 48 } 49 50 static QDF_STATUS target_if_wifi_pos_replenish_ring( 51 struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx, 52 void *alinged_vaddr, uint32_t cookie) 53 { 54 uint64_t *ring_entry; 55 uint32_t dw_lo, dw_hi = 0, map_status; 56 void *hal_soc = priv->hal_soc; 57 void *srng = priv->dma_cfg[ring_idx].srng; 58 void *paddr; 59 60 if (!alinged_vaddr) { 61 target_if_debug("NULL alinged_vaddr provided"); 62 return QDF_STATUS_SUCCESS; 63 } 64 65 map_status = qdf_mem_map_nbytes_single(NULL, alinged_vaddr, 66 QDF_DMA_FROM_DEVICE, 67 priv->dma_cap[ring_idx].min_buf_size, 68 (qdf_dma_addr_t *)&paddr); 69 if (map_status) { 70 target_if_err("mem map failed status: %d", map_status); 71 return QDF_STATUS_E_FAILURE; 72 } 73 QDF_ASSERT(!((uint64_t)paddr % priv->dma_cap[ring_idx].min_buf_align)); 74 priv->dma_buf_pool[ring_idx][cookie].paddr = paddr; 75 76 hal_srng_access_start(hal_soc, srng); 77 ring_entry = hal_srng_src_get_next(hal_soc, srng); 78 dw_lo = (uint64_t)paddr & 0xFFFFFFFF; 79 WMI_OEM_DMA_DATA_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32); 80 WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie); 81 *ring_entry = (uint64_t)dw_hi << 32 | dw_lo; 82 hal_srng_access_end(hal_soc, srng); 83 84 return QDF_STATUS_SUCCESS; 85 } 86 87 static QDF_STATUS target_if_wifi_pos_get_indirect_data( 88 struct wifi_pos_psoc_priv_obj *priv_obj, 89 struct wmi_host_oem_indirect_data *indirect, 90 struct oem_data_rsp *rsp, uint32_t *cookie) 91 { 92 void *paddr = NULL; 93 uint32_t addr_hi; 94 uint8_t ring_idx = 0, num_rings; 95 96 if (!indirect) { 97 target_if_debug("no indirect data. regular event received"); 98 return QDF_STATUS_SUCCESS; 99 } 100 101 ring_idx = indirect->pdev_id - 1; 102 num_rings = priv_obj->num_rings; 103 if (ring_idx >= num_rings) { 104 target_if_err("incorrect pdev_id: %d", indirect->pdev_id); 105 return QDF_STATUS_E_INVAL; 106 } 107 addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET( 108 indirect->addr_hi); 109 paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo); 110 *cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET( 111 indirect->addr_hi); 112 rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj, 113 paddr, ring_idx, *cookie); 114 rsp->dma_len = indirect->len; 115 qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr, 116 QDF_DMA_FROM_DEVICE, 117 priv_obj->dma_cap[ring_idx].min_buf_size); 118 119 return QDF_STATUS_SUCCESS; 120 } 121 122 #else 123 static QDF_STATUS target_if_wifi_pos_replenish_ring( 124 struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx, 125 void *vaddr, uint32_t cookie) 126 { 127 return QDF_STATUS_SUCCESS; 128 } 129 130 static QDF_STATUS target_if_wifi_pos_get_indirect_data( 131 struct wifi_pos_psoc_priv_obj *priv_obj, 132 struct wmi_host_oem_indirect_data *indirect, 133 struct oem_data_rsp *rsp, uint32_t *cookie) 134 { 135 return QDF_STATUS_SUCCESS; 136 } 137 #endif 138 139 /** 140 * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with 141 * WMI_OEM_RESPONSE_EVENTID 142 * @scn: scn handle 143 * @data_buf: event buffer 144 * @data_len: event buffer length 145 * 146 * Return: status of operation 147 */ 148 static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, 149 uint8_t *data_buf, 150 uint32_t data_len) 151 { 152 int ret; 153 uint8_t ring_idx = 0; 154 QDF_STATUS status; 155 uint32_t cookie = 0; 156 struct wmi_host_oem_indirect_data *indirect; 157 struct oem_data_rsp oem_rsp = {0}; 158 struct wifi_pos_psoc_priv_obj *priv_obj; 159 struct wlan_objmgr_psoc *psoc; 160 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; 161 struct wmi_oem_response_param oem_resp_param = {0}; 162 wmi_unified_t wmi_handle; 163 164 psoc = target_if_get_psoc_from_scn_hdl(scn); 165 if (!psoc) { 166 target_if_err("psoc is null"); 167 return QDF_STATUS_NOT_INITIALIZED; 168 } 169 170 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 171 172 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 173 if (!wmi_handle) { 174 target_if_err("wmi_handle is null"); 175 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 176 return QDF_STATUS_NOT_INITIALIZED; 177 } 178 179 priv_obj = wifi_pos_get_psoc_priv_obj(psoc); 180 if (!priv_obj) { 181 target_if_err("priv_obj is null"); 182 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 183 return QDF_STATUS_NOT_INITIALIZED; 184 } 185 186 wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); 187 if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { 188 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 189 target_if_err("lmac callbacks not registered"); 190 return QDF_STATUS_NOT_INITIALIZED; 191 } 192 193 ret = wmi_extract_oem_response_param(wmi_handle, 194 data_buf, 195 &oem_resp_param); 196 197 oem_rsp.rsp_len_1 = oem_resp_param.num_data1; 198 oem_rsp.data_1 = oem_resp_param.data_1; 199 200 if (oem_resp_param.num_data2) { 201 oem_rsp.rsp_len_2 = oem_resp_param.num_data2; 202 oem_rsp.data_2 = oem_resp_param.data_2; 203 } 204 205 indirect = &oem_resp_param.indirect_data; 206 status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, 207 &oem_rsp, &cookie); 208 if (QDF_IS_STATUS_ERROR(status)) { 209 target_if_err("get indirect data failed status: %d", status); 210 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 211 return QDF_STATUS_E_INVAL; 212 } 213 214 ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp); 215 if (indirect) 216 ring_idx = indirect->pdev_id - 1; 217 status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx, 218 oem_rsp.vaddr, cookie); 219 if (QDF_IS_STATUS_ERROR(status)) { 220 target_if_err("replenish failed status: %d", status); 221 ret = QDF_STATUS_E_FAILURE; 222 } 223 224 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 225 226 return ret; 227 } 228 229 /** 230 * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id 231 * @scn: scn handle 232 * @buf: event buffer 233 * @len: event buffer length 234 * 235 * Return: status of operation 236 */ 237 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len) 238 { 239 /* TBD */ 240 return 0; 241 } 242 243 /** 244 * wifi_pos_oem_meas_rpt_ev_handler: handler registered with 245 * wmi_oem_meas_report_event_id 246 * @scn: scn handle 247 * @buf: event buffer 248 * @len: event buffer length 249 * 250 * Return: status of operation 251 */ 252 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 253 uint32_t len) 254 { 255 /* TBD */ 256 return 0; 257 } 258 259 /** 260 * wifi_pos_oem_err_rpt_ev_handler: handler registered with 261 * wmi_oem_err_report_event_id 262 * @scn: scn handle 263 * @buf: event buffer 264 * @len: event buffer length 265 * 266 * Return: status of operation 267 */ 268 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 269 uint32_t len) 270 { 271 /* TBD */ 272 return 0; 273 } 274 275 /** 276 * target_if_wifi_pos_oem_data_req() - start OEM data request to target 277 * @psoc: pointer to psoc object mgr 278 * @req: start request params 279 * 280 * Return: QDF_STATUS 281 */ 282 static QDF_STATUS 283 target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev, 284 struct oem_data_req *req) 285 { 286 QDF_STATUS status; 287 wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev); 288 289 target_if_debug("Send oem data req to target"); 290 291 if (!req || !req->data) { 292 target_if_err("oem_data_req is null"); 293 return QDF_STATUS_E_INVAL; 294 } 295 296 if (!wmi_hdl) { 297 target_if_err("WMA closed, can't send oem data req cmd"); 298 return QDF_STATUS_E_INVAL; 299 } 300 301 status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len, 302 req->data); 303 304 if (!QDF_IS_STATUS_SUCCESS(status)) 305 target_if_err("wmi cmd send failed"); 306 307 return status; 308 } 309 310 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 311 { 312 struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops; 313 wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops; 314 wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req; 315 wifi_pos_tx_ops->wifi_pos_register_events = 316 target_if_wifi_pos_register_events; 317 wifi_pos_tx_ops->wifi_pos_deregister_events = 318 target_if_wifi_pos_deregister_events; 319 } 320 321 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( 322 struct wlan_objmgr_psoc *psoc) 323 { 324 struct wlan_lmac_if_rx_ops *rx_ops; 325 326 if (!psoc) { 327 target_if_err("passed psoc is NULL"); 328 return NULL; 329 } 330 331 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 332 if (!rx_ops) { 333 target_if_err("rx_ops is NULL"); 334 return NULL; 335 } 336 337 return &rx_ops->wifi_pos_rx_ops; 338 } 339 340 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) 341 { 342 int ret; 343 344 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 345 target_if_err("psoc or psoc->tgt_if_handle is null"); 346 return QDF_STATUS_E_INVAL; 347 } 348 349 /* wmi_oem_response_event_id is not defined for legacy targets. 350 * So do not check for error for this event. 351 */ 352 wmi_unified_register_event_handler( 353 get_wmi_unified_hdl_from_psoc(psoc), 354 wmi_oem_response_event_id, 355 target_if_wifi_pos_oem_rsp_ev_handler, 356 WMI_RX_WORK_CTX); 357 358 ret = wmi_unified_register_event_handler( 359 get_wmi_unified_hdl_from_psoc(psoc), 360 wmi_oem_cap_event_id, 361 wifi_pos_oem_cap_ev_handler, 362 WMI_RX_WORK_CTX); 363 if (ret) { 364 target_if_err("register_event_handler failed: err %d", ret); 365 return QDF_STATUS_E_INVAL; 366 } 367 368 ret = wmi_unified_register_event_handler( 369 get_wmi_unified_hdl_from_psoc(psoc), 370 wmi_oem_meas_report_event_id, 371 wifi_pos_oem_meas_rpt_ev_handler, 372 WMI_RX_WORK_CTX); 373 if (ret) { 374 target_if_err("register_event_handler failed: err %d", ret); 375 return QDF_STATUS_E_INVAL; 376 } 377 378 ret = wmi_unified_register_event_handler( 379 get_wmi_unified_hdl_from_psoc(psoc), 380 wmi_oem_report_event_id, 381 wifi_pos_oem_err_rpt_ev_handler, 382 WMI_RX_WORK_CTX); 383 if (ret) { 384 target_if_err("register_event_handler failed: err %d", ret); 385 return QDF_STATUS_E_INVAL; 386 } 387 388 return QDF_STATUS_SUCCESS; 389 } 390 391 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) 392 { 393 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 394 target_if_err("psoc or psoc->tgt_if_handle is null"); 395 return QDF_STATUS_E_INVAL; 396 } 397 398 wmi_unified_unregister_event_handler( 399 get_wmi_unified_hdl_from_psoc(psoc), 400 wmi_oem_response_event_id); 401 wmi_unified_unregister_event_handler( 402 get_wmi_unified_hdl_from_psoc(psoc), 403 wmi_oem_cap_event_id); 404 wmi_unified_unregister_event_handler( 405 get_wmi_unified_hdl_from_psoc(psoc), 406 wmi_oem_meas_report_event_id); 407 wmi_unified_unregister_event_handler( 408 get_wmi_unified_hdl_from_psoc(psoc), 409 wmi_oem_report_event_id); 410 411 return QDF_STATUS_SUCCESS; 412 } 413 414 #ifdef WLAN_FEATURE_CIF_CFR 415 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, 416 struct hal_srng *srng, 417 struct wifi_pos_psoc_priv_obj *priv) 418 { 419 uint32_t i; 420 void *buf, *buf_aligned; 421 422 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 423 buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size + 424 priv->dma_cap[ring_idx].min_buf_align - 1); 425 if (!buf) 426 return QDF_STATUS_E_NOMEM; 427 428 priv->dma_buf_pool[ring_idx][i].vaddr = buf; 429 buf_aligned = (void *)qdf_roundup((uint64_t)buf, 430 priv->dma_cap[ring_idx].min_buf_align); 431 priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf; 432 priv->dma_buf_pool[ring_idx][i].cookie = i; 433 target_if_wifi_pos_replenish_ring(priv, ring_idx, 434 buf_aligned, i); 435 } 436 437 return QDF_STATUS_SUCCESS; 438 } 439 440 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx, 441 struct wifi_pos_psoc_priv_obj *priv) 442 { 443 uint32_t i; 444 445 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 446 qdf_mem_unmap_nbytes_single(NULL, 447 (qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr, 448 QDF_DMA_FROM_DEVICE, 449 priv->dma_cap[ring_idx].min_buf_size); 450 qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr); 451 } 452 453 return QDF_STATUS_SUCCESS; 454 } 455 456 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx, 457 struct wifi_pos_psoc_priv_obj *priv) 458 { 459 void *srng; 460 uint32_t num_entries; 461 qdf_dma_addr_t paddr; 462 uint32_t ring_alloc_size; 463 void *hal_soc = priv->hal_soc; 464 struct hal_srng_params ring_params = {0}; 465 uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC); 466 uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC); 467 468 num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ? 469 max_entries : priv->dma_cap[ring_idx].min_num_ptr; 470 priv->dma_cfg[ring_idx].num_ptr = num_entries; 471 priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries * 472 sizeof(struct wifi_pos_dma_buf_info)); 473 if (!priv->dma_buf_pool[ring_idx]) 474 return QDF_STATUS_E_NOMEM; 475 476 ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1; 477 priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size; 478 priv->dma_cfg[ring_idx].base_vaddr_unaligned = 479 qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr); 480 priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr; 481 if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) { 482 target_if_err("malloc failed"); 483 return QDF_STATUS_E_NOMEM; 484 } 485 486 priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup( 487 (uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned, 488 RING_BASE_ALIGN); 489 ring_params.ring_base_vaddr = 490 priv->dma_cfg[ring_idx].base_vaddr_aligned; 491 priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup( 492 (uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 493 RING_BASE_ALIGN); 494 ring_params.ring_base_paddr = 495 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned; 496 ring_params.num_entries = num_entries; 497 srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0, 498 priv->dma_cap[ring_idx].pdev_id, &ring_params); 499 if (!srng) { 500 target_if_err("srng setup failed"); 501 return QDF_STATUS_E_FAILURE; 502 } 503 priv->dma_cfg[ring_idx].srng = srng; 504 priv->dma_cfg[ring_idx].tail_idx_addr = 505 (void *)hal_srng_get_tp_addr(hal_soc, srng); 506 priv->dma_cfg[ring_idx].head_idx_addr = 507 (void *)hal_srng_get_tp_addr(hal_soc, srng); 508 509 return target_if_wifi_pos_fill_ring(ring_idx, srng, priv); 510 } 511 512 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx, 513 struct wifi_pos_psoc_priv_obj *priv) 514 { 515 target_if_wifi_pos_empty_ring(ring_idx, priv); 516 priv->dma_buf_pool[ring_idx] = NULL; 517 hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng); 518 qdf_mem_free_consistent(NULL, NULL, 519 priv->dma_cfg[ring_idx].ring_alloc_size, 520 priv->dma_cfg[ring_idx].base_vaddr_unaligned, 521 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 522 0); 523 qdf_mem_free(priv->dma_buf_pool[ring_idx]); 524 525 return QDF_STATUS_SUCCESS; 526 } 527 528 static QDF_STATUS target_if_wifi_pos_init_srngs( 529 struct wifi_pos_psoc_priv_obj *priv) 530 { 531 uint8_t i; 532 QDF_STATUS status; 533 534 /* allocate memory for num_rings pointers */ 535 priv->dma_cfg = qdf_mem_malloc(priv->num_rings * 536 sizeof(struct wifi_pos_dma_rings_cap)); 537 if (!priv->dma_cfg) 538 return QDF_STATUS_E_NOMEM; 539 540 priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings * 541 sizeof(struct wifi_pos_dma_buf_info *)); 542 if (!priv->dma_buf_pool) 543 return QDF_STATUS_E_NOMEM; 544 545 for (i = 0; i < priv->num_rings; i++) { 546 status = target_if_wifi_pos_init_ring(i, priv); 547 if (QDF_IS_STATUS_ERROR(status)) { 548 target_if_err("init for ring[%d] failed", i); 549 return status; 550 } 551 } 552 553 return QDF_STATUS_SUCCESS; 554 } 555 556 static QDF_STATUS target_if_wifi_pos_deinit_srngs( 557 struct wifi_pos_psoc_priv_obj *priv) 558 { 559 uint8_t i; 560 561 for (i = 0; i < priv->num_rings; i++) 562 target_if_wifi_pos_deinit_ring(i, priv); 563 564 qdf_mem_free(priv->dma_buf_pool); 565 priv->dma_buf_pool = NULL; 566 567 return QDF_STATUS_SUCCESS; 568 } 569 570 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, 571 struct wifi_pos_psoc_priv_obj *priv) 572 { 573 uint8_t i; 574 QDF_STATUS status; 575 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 576 wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; 577 578 if (!wmi_hdl) { 579 target_if_err("WMA closed, can't send oem data req cmd"); 580 return QDF_STATUS_E_INVAL; 581 } 582 583 target_if_debug("Sending oem dma ring cfg to target"); 584 585 for (i = 0; i < priv->num_rings; i++) { 586 cfg.pdev_id = priv->dma_cfg[i].pdev_id; 587 cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 588 & 0xFFFFFFFF; 589 cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 590 & 0xFFFFFFFF00000000; 591 cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr 592 & 0xFFFFFFFF; 593 cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr 594 & 0xFFFFFFFF00000000; 595 cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr 596 & 0xFFFFFFFF; 597 cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr 598 & 0xFFFFFFFF00000000; 599 cfg.num_ptr = priv->dma_cfg[i].num_ptr; 600 status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg); 601 if (!QDF_IS_STATUS_SUCCESS(status)) { 602 target_if_err("wmi cmd send failed"); 603 return status; 604 } 605 } 606 607 return status; 608 } 609 610 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc) 611 { 612 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 613 614 target_if_wifi_pos_deinit_srngs(priv); 615 qdf_mem_free(priv->dma_cap); 616 priv->dma_cap = NULL; 617 618 return QDF_STATUS_SUCCESS; 619 } 620 621 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, 622 void *hal_soc, uint8_t num_mac, 623 void *buf) 624 { 625 uint8_t i; 626 QDF_STATUS status = QDF_STATUS_SUCCESS; 627 WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf; 628 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 629 630 if (!priv) { 631 target_if_err("unable to get wifi_pos psoc obj"); 632 return QDF_STATUS_E_NULL_VALUE; 633 } 634 635 priv->hal_soc = hal_soc; 636 priv->num_rings = num_mac; 637 priv->dma_cap = qdf_mem_malloc(priv->num_rings * 638 sizeof(struct wifi_pos_dma_rings_cap)); 639 if (!priv->dma_cap) 640 return QDF_STATUS_E_NOMEM; 641 642 for (i = 0; i < num_mac; i++) { 643 priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id; 644 priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; 645 priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; 646 priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; 647 } 648 649 /* initialize DMA rings now */ 650 status = target_if_wifi_pos_init_srngs(priv); 651 if (QDF_IS_STATUS_ERROR(status)) { 652 target_if_err("dma init failed: %d", status); 653 goto dma_init_failed; 654 } 655 656 /* send cfg req cmd to firmware */ 657 status = target_if_wifi_pos_cfg_fw(psoc, priv); 658 if (QDF_IS_STATUS_ERROR(status)) { 659 target_if_err("configure to FW failed: %d", status); 660 goto dma_init_failed; 661 } 662 663 return QDF_STATUS_SUCCESS; 664 665 dma_init_failed: 666 target_if_wifi_pos_deinit_dma_rings(psoc); 667 return status; 668 } 669 670 #endif 671