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