1 /* 2 * Copyright (c) 2013-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: 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 struct wmi_host_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 struct wmi_host_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 struct wmi_host_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; 158 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; 159 struct wmi_oem_response_param oem_resp_param = {0}; 160 wmi_unified_t wmi_handle; 161 162 psoc = target_if_get_psoc_from_scn_hdl(scn); 163 if (!psoc) { 164 target_if_err("psoc is null"); 165 return QDF_STATUS_NOT_INITIALIZED; 166 } 167 168 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 169 170 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 171 if (!wmi_handle) { 172 target_if_err("wmi_handle is null"); 173 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 174 return QDF_STATUS_NOT_INITIALIZED; 175 } 176 177 priv_obj = wifi_pos_get_psoc_priv_obj(psoc); 178 if (!priv_obj) { 179 target_if_err("priv_obj is null"); 180 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 181 return QDF_STATUS_NOT_INITIALIZED; 182 } 183 184 wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); 185 if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { 186 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 187 target_if_err("lmac callbacks not registered"); 188 return QDF_STATUS_NOT_INITIALIZED; 189 } 190 191 ret = wmi_extract_oem_response_param(wmi_handle, 192 data_buf, 193 &oem_resp_param); 194 195 oem_rsp.rsp_len_1 = oem_resp_param.num_data1; 196 oem_rsp.data_1 = oem_resp_param.data_1; 197 198 if (oem_resp_param.num_data2) { 199 oem_rsp.rsp_len_2 = oem_resp_param.num_data2; 200 oem_rsp.data_2 = oem_resp_param.data_2; 201 } 202 203 indirect = &oem_resp_param.indirect_data; 204 status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, 205 &oem_rsp, &cookie); 206 if (QDF_IS_STATUS_ERROR(status)) { 207 target_if_err("get indirect data failed status: %d", status); 208 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 209 return QDF_STATUS_E_INVAL; 210 } 211 212 ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp); 213 if (indirect) 214 ring_idx = indirect->pdev_id - 1; 215 status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx, 216 oem_rsp.vaddr, cookie); 217 if (QDF_IS_STATUS_ERROR(status)) { 218 target_if_err("replenish failed status: %d", status); 219 ret = QDF_STATUS_E_FAILURE; 220 } 221 222 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 223 224 return ret; 225 } 226 227 /** 228 * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id 229 * @scn: scn handle 230 * @buf: event buffer 231 * @len: event buffer length 232 * 233 * Return: status of operation 234 */ 235 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len) 236 { 237 /* TBD */ 238 return 0; 239 } 240 241 /** 242 * wifi_pos_oem_meas_rpt_ev_handler: handler registered with 243 * wmi_oem_meas_report_event_id 244 * @scn: scn handle 245 * @buf: event buffer 246 * @len: event buffer length 247 * 248 * Return: status of operation 249 */ 250 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 251 uint32_t len) 252 { 253 /* TBD */ 254 return 0; 255 } 256 257 /** 258 * wifi_pos_oem_err_rpt_ev_handler: handler registered with 259 * wmi_oem_err_report_event_id 260 * @scn: scn handle 261 * @buf: event buffer 262 * @len: event buffer length 263 * 264 * Return: status of operation 265 */ 266 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 267 uint32_t len) 268 { 269 /* TBD */ 270 return 0; 271 } 272 273 /** 274 * target_if_wifi_pos_oem_data_req() - start OEM data request to target 275 * @psoc: pointer to psoc object mgr 276 * @req: start request params 277 * 278 * Return: QDF_STATUS 279 */ 280 static QDF_STATUS 281 target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev, 282 struct oem_data_req *req) 283 { 284 QDF_STATUS status; 285 wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev); 286 287 target_if_debug("Send oem data req to target"); 288 289 if (!req || !req->data) { 290 target_if_err("oem_data_req is null"); 291 return QDF_STATUS_E_INVAL; 292 } 293 294 if (!wmi_hdl) { 295 target_if_err("WMA closed, can't send oem data req cmd"); 296 return QDF_STATUS_E_INVAL; 297 } 298 299 status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len, 300 req->data); 301 302 if (!QDF_IS_STATUS_SUCCESS(status)) 303 target_if_err("wmi cmd send failed"); 304 305 return status; 306 } 307 308 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 309 { 310 struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops; 311 wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops; 312 wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req; 313 wifi_pos_tx_ops->wifi_pos_register_events = 314 target_if_wifi_pos_register_events; 315 wifi_pos_tx_ops->wifi_pos_deregister_events = 316 target_if_wifi_pos_deregister_events; 317 } 318 319 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( 320 struct wlan_objmgr_psoc *psoc) 321 { 322 if (!psoc) { 323 target_if_err("passed psoc is NULL"); 324 return NULL; 325 } 326 327 return &psoc->soc_cb.rx_ops.wifi_pos_rx_ops; 328 } 329 330 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) 331 { 332 int ret; 333 334 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 335 target_if_err("psoc or psoc->tgt_if_handle is null"); 336 return QDF_STATUS_E_INVAL; 337 } 338 339 /* wmi_oem_response_event_id is not defined for legacy targets. 340 * So do not check for error for this event. 341 */ 342 wmi_unified_register_event_handler( 343 get_wmi_unified_hdl_from_psoc(psoc), 344 wmi_oem_response_event_id, 345 target_if_wifi_pos_oem_rsp_ev_handler, 346 WMI_RX_WORK_CTX); 347 348 ret = wmi_unified_register_event_handler( 349 get_wmi_unified_hdl_from_psoc(psoc), 350 wmi_oem_cap_event_id, 351 wifi_pos_oem_cap_ev_handler, 352 WMI_RX_WORK_CTX); 353 if (ret) { 354 target_if_err("register_event_handler failed: err %d", ret); 355 return QDF_STATUS_E_INVAL; 356 } 357 358 ret = wmi_unified_register_event_handler( 359 get_wmi_unified_hdl_from_psoc(psoc), 360 wmi_oem_meas_report_event_id, 361 wifi_pos_oem_meas_rpt_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_report_event_id, 371 wifi_pos_oem_err_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 return QDF_STATUS_SUCCESS; 379 } 380 381 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) 382 { 383 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 384 target_if_err("psoc or psoc->tgt_if_handle is null"); 385 return QDF_STATUS_E_INVAL; 386 } 387 388 wmi_unified_unregister_event_handler( 389 get_wmi_unified_hdl_from_psoc(psoc), 390 wmi_oem_response_event_id); 391 wmi_unified_unregister_event_handler( 392 get_wmi_unified_hdl_from_psoc(psoc), 393 wmi_oem_cap_event_id); 394 wmi_unified_unregister_event_handler( 395 get_wmi_unified_hdl_from_psoc(psoc), 396 wmi_oem_meas_report_event_id); 397 wmi_unified_unregister_event_handler( 398 get_wmi_unified_hdl_from_psoc(psoc), 399 wmi_oem_report_event_id); 400 401 return QDF_STATUS_SUCCESS; 402 } 403 404 #ifdef WLAN_FEATURE_CIF_CFR 405 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, 406 struct hal_srng *srng, 407 struct wifi_pos_psoc_priv_obj *priv) 408 { 409 uint32_t i; 410 void *buf, *buf_aligned; 411 412 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 413 buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size + 414 priv->dma_cap[ring_idx].min_buf_align - 1); 415 if (!buf) 416 return QDF_STATUS_E_NOMEM; 417 418 priv->dma_buf_pool[ring_idx][i].vaddr = buf; 419 buf_aligned = (void *)qdf_roundup((uint64_t)buf, 420 priv->dma_cap[ring_idx].min_buf_align); 421 priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf; 422 priv->dma_buf_pool[ring_idx][i].cookie = i; 423 target_if_wifi_pos_replenish_ring(priv, ring_idx, 424 buf_aligned, i); 425 } 426 427 return QDF_STATUS_SUCCESS; 428 } 429 430 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx, 431 struct wifi_pos_psoc_priv_obj *priv) 432 { 433 uint32_t i; 434 435 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 436 qdf_mem_unmap_nbytes_single(NULL, 437 (qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr, 438 QDF_DMA_FROM_DEVICE, 439 priv->dma_cap[ring_idx].min_buf_size); 440 qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr); 441 } 442 443 return QDF_STATUS_SUCCESS; 444 } 445 446 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx, 447 struct wifi_pos_psoc_priv_obj *priv) 448 { 449 void *srng; 450 uint32_t num_entries; 451 qdf_dma_addr_t paddr; 452 uint32_t ring_alloc_size; 453 void *hal_soc = priv->hal_soc; 454 struct hal_srng_params ring_params = {0}; 455 uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC); 456 uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC); 457 458 num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ? 459 max_entries : priv->dma_cap[ring_idx].min_num_ptr; 460 priv->dma_cfg[ring_idx].num_ptr = num_entries; 461 priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries * 462 sizeof(struct wifi_pos_dma_buf_info)); 463 if (!priv->dma_buf_pool[ring_idx]) 464 return QDF_STATUS_E_NOMEM; 465 466 ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1; 467 priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size; 468 priv->dma_cfg[ring_idx].base_vaddr_unaligned = 469 qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr); 470 priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr; 471 if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) { 472 target_if_err("malloc failed"); 473 return QDF_STATUS_E_NOMEM; 474 } 475 476 priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup( 477 (uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned, 478 RING_BASE_ALIGN); 479 ring_params.ring_base_vaddr = 480 priv->dma_cfg[ring_idx].base_vaddr_aligned; 481 priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup( 482 (uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 483 RING_BASE_ALIGN); 484 ring_params.ring_base_paddr = 485 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned; 486 ring_params.num_entries = num_entries; 487 srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0, 488 priv->dma_cap[ring_idx].pdev_id, &ring_params); 489 if (!srng) { 490 target_if_err("srng setup failed"); 491 return QDF_STATUS_E_FAILURE; 492 } 493 priv->dma_cfg[ring_idx].srng = srng; 494 priv->dma_cfg[ring_idx].tail_idx_addr = 495 (void *)hal_srng_get_tp_addr(hal_soc, srng); 496 priv->dma_cfg[ring_idx].head_idx_addr = 497 (void *)hal_srng_get_tp_addr(hal_soc, srng); 498 499 return target_if_wifi_pos_fill_ring(ring_idx, srng, priv); 500 } 501 502 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx, 503 struct wifi_pos_psoc_priv_obj *priv) 504 { 505 target_if_wifi_pos_empty_ring(ring_idx, priv); 506 priv->dma_buf_pool[ring_idx] = NULL; 507 hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng); 508 qdf_mem_free_consistent(NULL, NULL, 509 priv->dma_cfg[ring_idx].ring_alloc_size, 510 priv->dma_cfg[ring_idx].base_vaddr_unaligned, 511 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 512 0); 513 qdf_mem_free(priv->dma_buf_pool[ring_idx]); 514 515 return QDF_STATUS_SUCCESS; 516 } 517 518 static QDF_STATUS target_if_wifi_pos_init_srngs( 519 struct wifi_pos_psoc_priv_obj *priv) 520 { 521 uint8_t i; 522 QDF_STATUS status; 523 524 /* allocate memory for num_rings pointers */ 525 priv->dma_cfg = qdf_mem_malloc(priv->num_rings * 526 sizeof(struct wifi_pos_dma_rings_cap)); 527 if (!priv->dma_cfg) 528 return QDF_STATUS_E_NOMEM; 529 530 priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings * 531 sizeof(struct wifi_pos_dma_buf_info *)); 532 if (!priv->dma_buf_pool) 533 return QDF_STATUS_E_NOMEM; 534 535 for (i = 0; i < priv->num_rings; i++) { 536 status = target_if_wifi_pos_init_ring(i, priv); 537 if (QDF_IS_STATUS_ERROR(status)) { 538 target_if_err("init for ring[%d] failed", i); 539 return status; 540 } 541 } 542 543 return QDF_STATUS_SUCCESS; 544 } 545 546 static QDF_STATUS target_if_wifi_pos_deinit_srngs( 547 struct wifi_pos_psoc_priv_obj *priv) 548 { 549 uint8_t i; 550 551 for (i = 0; i < priv->num_rings; i++) 552 target_if_wifi_pos_deinit_ring(i, priv); 553 554 qdf_mem_free(priv->dma_buf_pool); 555 priv->dma_buf_pool = NULL; 556 557 return QDF_STATUS_SUCCESS; 558 } 559 560 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, 561 struct wifi_pos_psoc_priv_obj *priv) 562 { 563 uint8_t i; 564 QDF_STATUS status; 565 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 566 wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; 567 568 if (!wmi_hdl) { 569 target_if_err("WMA closed, can't send oem data req cmd"); 570 return QDF_STATUS_E_INVAL; 571 } 572 573 target_if_debug("Sending oem dma ring cfg to target"); 574 575 for (i = 0; i < priv->num_rings; i++) { 576 cfg.pdev_id = priv->dma_cfg[i].pdev_id; 577 cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 578 & 0xFFFFFFFF; 579 cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 580 & 0xFFFFFFFF00000000; 581 cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr 582 & 0xFFFFFFFF; 583 cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr 584 & 0xFFFFFFFF00000000; 585 cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr 586 & 0xFFFFFFFF; 587 cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr 588 & 0xFFFFFFFF00000000; 589 cfg.num_ptr = priv->dma_cfg[i].num_ptr; 590 status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg); 591 if (!QDF_IS_STATUS_SUCCESS(status)) { 592 target_if_err("wmi cmd send failed"); 593 return status; 594 } 595 } 596 597 return status; 598 } 599 600 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc) 601 { 602 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 603 604 target_if_wifi_pos_deinit_srngs(priv); 605 qdf_mem_free(priv->dma_cap); 606 priv->dma_cap = NULL; 607 608 return QDF_STATUS_SUCCESS; 609 } 610 611 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, 612 void *hal_soc, uint8_t num_mac, 613 void *buf) 614 { 615 uint8_t i; 616 QDF_STATUS status = QDF_STATUS_SUCCESS; 617 WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf; 618 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 619 620 if (!priv) { 621 target_if_err("unable to get wifi_pos psoc obj"); 622 return QDF_STATUS_E_NULL_VALUE; 623 } 624 625 priv->hal_soc = hal_soc; 626 priv->num_rings = num_mac; 627 priv->dma_cap = qdf_mem_malloc(priv->num_rings * 628 sizeof(struct wifi_pos_dma_rings_cap)); 629 if (!priv->dma_cap) 630 return QDF_STATUS_E_NOMEM; 631 632 for (i = 0; i < num_mac; i++) { 633 priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id; 634 priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; 635 priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; 636 priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; 637 } 638 639 /* initialize DMA rings now */ 640 status = target_if_wifi_pos_init_srngs(priv); 641 if (QDF_IS_STATUS_ERROR(status)) { 642 target_if_err("dma init failed: %d", status); 643 goto dma_init_failed; 644 } 645 646 /* send cfg req cmd to firmware */ 647 status = target_if_wifi_pos_cfg_fw(psoc, priv); 648 if (QDF_IS_STATUS_ERROR(status)) { 649 target_if_err("configure to FW failed: %d", status); 650 goto dma_init_failed; 651 } 652 653 return QDF_STATUS_SUCCESS; 654 655 dma_init_failed: 656 target_if_wifi_pos_deinit_dma_rings(psoc); 657 return status; 658 } 659 660 #endif 661