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(wifi_pos_get_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 wifi_pos_tx_ops->wifi_pos_convert_pdev_id_host_to_target = 320 target_if_wifi_pos_convert_pdev_id_host_to_target; 321 wifi_pos_tx_ops->wifi_pos_convert_pdev_id_target_to_host = 322 target_if_wifi_pos_convert_pdev_id_target_to_host; 323 324 } 325 326 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( 327 struct wlan_objmgr_psoc *psoc) 328 { 329 struct wlan_lmac_if_rx_ops *rx_ops; 330 331 if (!psoc) { 332 target_if_err("passed psoc is NULL"); 333 return NULL; 334 } 335 336 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 337 if (!rx_ops) { 338 target_if_err("rx_ops is NULL"); 339 return NULL; 340 } 341 342 return &rx_ops->wifi_pos_rx_ops; 343 } 344 345 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) 346 { 347 int ret; 348 349 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 350 target_if_err("psoc or psoc->tgt_if_handle is null"); 351 return QDF_STATUS_E_INVAL; 352 } 353 354 /* wmi_oem_response_event_id is not defined for legacy targets. 355 * So do not check for error for this event. 356 */ 357 wmi_unified_register_event_handler( 358 get_wmi_unified_hdl_from_psoc(psoc), 359 wmi_oem_response_event_id, 360 target_if_wifi_pos_oem_rsp_ev_handler, 361 WMI_RX_WORK_CTX); 362 363 ret = wmi_unified_register_event_handler( 364 get_wmi_unified_hdl_from_psoc(psoc), 365 wmi_oem_cap_event_id, 366 wifi_pos_oem_cap_ev_handler, 367 WMI_RX_WORK_CTX); 368 if (ret) { 369 target_if_err("register_event_handler failed: err %d", ret); 370 return QDF_STATUS_E_INVAL; 371 } 372 373 ret = wmi_unified_register_event_handler( 374 get_wmi_unified_hdl_from_psoc(psoc), 375 wmi_oem_meas_report_event_id, 376 wifi_pos_oem_meas_rpt_ev_handler, 377 WMI_RX_WORK_CTX); 378 if (ret) { 379 target_if_err("register_event_handler failed: err %d", ret); 380 return QDF_STATUS_E_INVAL; 381 } 382 383 ret = wmi_unified_register_event_handler( 384 get_wmi_unified_hdl_from_psoc(psoc), 385 wmi_oem_report_event_id, 386 wifi_pos_oem_err_rpt_ev_handler, 387 WMI_RX_WORK_CTX); 388 if (ret) { 389 target_if_err("register_event_handler failed: err %d", ret); 390 return QDF_STATUS_E_INVAL; 391 } 392 393 return QDF_STATUS_SUCCESS; 394 } 395 396 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) 397 { 398 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 399 target_if_err("psoc or psoc->tgt_if_handle is null"); 400 return QDF_STATUS_E_INVAL; 401 } 402 403 wmi_unified_unregister_event_handler( 404 get_wmi_unified_hdl_from_psoc(psoc), 405 wmi_oem_response_event_id); 406 wmi_unified_unregister_event_handler( 407 get_wmi_unified_hdl_from_psoc(psoc), 408 wmi_oem_cap_event_id); 409 wmi_unified_unregister_event_handler( 410 get_wmi_unified_hdl_from_psoc(psoc), 411 wmi_oem_meas_report_event_id); 412 wmi_unified_unregister_event_handler( 413 get_wmi_unified_hdl_from_psoc(psoc), 414 wmi_oem_report_event_id); 415 416 return QDF_STATUS_SUCCESS; 417 } 418 419 #ifndef CNSS_GENL 420 QDF_STATUS target_if_wifi_pos_convert_pdev_id_host_to_target( 421 struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id, 422 uint32_t *target_pdev_id) 423 { 424 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 425 426 if (!wmi_hdl) { 427 target_if_err("null wmi_hdl"); 428 return QDF_STATUS_E_NULL_VALUE; 429 } 430 431 return wmi_convert_pdev_id_host_to_target(wmi_hdl, host_pdev_id, 432 target_pdev_id); 433 } 434 435 QDF_STATUS target_if_wifi_pos_convert_pdev_id_target_to_host( 436 struct wlan_objmgr_psoc *psoc, uint32_t target_pdev_id, 437 uint32_t *host_pdev_id) 438 { 439 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 440 441 if (!wmi_hdl) { 442 target_if_err("null wmi_hdl"); 443 return QDF_STATUS_E_NULL_VALUE; 444 } 445 446 return wmi_convert_pdev_id_target_to_host(wmi_hdl, target_pdev_id, 447 host_pdev_id); 448 } 449 #endif /* CNSS_GENL */ 450 451 #ifdef WLAN_FEATURE_CIF_CFR 452 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, 453 struct hal_srng *srng, 454 struct wifi_pos_psoc_priv_obj *priv) 455 { 456 uint32_t i; 457 void *buf, *buf_aligned; 458 459 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 460 buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size + 461 priv->dma_cap[ring_idx].min_buf_align - 1); 462 if (!buf) 463 return QDF_STATUS_E_NOMEM; 464 465 priv->dma_buf_pool[ring_idx][i].vaddr = buf; 466 buf_aligned = (void *)qdf_roundup((uint64_t)buf, 467 priv->dma_cap[ring_idx].min_buf_align); 468 priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf; 469 priv->dma_buf_pool[ring_idx][i].cookie = i; 470 target_if_wifi_pos_replenish_ring(priv, ring_idx, 471 buf_aligned, i); 472 } 473 474 return QDF_STATUS_SUCCESS; 475 } 476 477 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx, 478 struct wifi_pos_psoc_priv_obj *priv) 479 { 480 uint32_t i; 481 482 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 483 qdf_mem_unmap_nbytes_single(NULL, 484 (qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr, 485 QDF_DMA_FROM_DEVICE, 486 priv->dma_cap[ring_idx].min_buf_size); 487 qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr); 488 } 489 490 return QDF_STATUS_SUCCESS; 491 } 492 493 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx, 494 struct wifi_pos_psoc_priv_obj *priv) 495 { 496 void *srng; 497 uint32_t num_entries; 498 qdf_dma_addr_t paddr; 499 uint32_t ring_alloc_size; 500 void *hal_soc = priv->hal_soc; 501 struct hal_srng_params ring_params = {0}; 502 uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC); 503 uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC); 504 505 num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ? 506 max_entries : priv->dma_cap[ring_idx].min_num_ptr; 507 priv->dma_cfg[ring_idx].num_ptr = num_entries; 508 priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries * 509 sizeof(struct wifi_pos_dma_buf_info)); 510 if (!priv->dma_buf_pool[ring_idx]) 511 return QDF_STATUS_E_NOMEM; 512 513 ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1; 514 priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size; 515 priv->dma_cfg[ring_idx].base_vaddr_unaligned = 516 qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr); 517 priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr; 518 if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) { 519 target_if_err("malloc failed"); 520 return QDF_STATUS_E_NOMEM; 521 } 522 523 priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup( 524 (uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned, 525 RING_BASE_ALIGN); 526 ring_params.ring_base_vaddr = 527 priv->dma_cfg[ring_idx].base_vaddr_aligned; 528 priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup( 529 (uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 530 RING_BASE_ALIGN); 531 ring_params.ring_base_paddr = 532 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned; 533 ring_params.num_entries = num_entries; 534 srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0, 535 priv->dma_cap[ring_idx].pdev_id, &ring_params); 536 if (!srng) { 537 target_if_err("srng setup failed"); 538 return QDF_STATUS_E_FAILURE; 539 } 540 priv->dma_cfg[ring_idx].srng = srng; 541 priv->dma_cfg[ring_idx].tail_idx_addr = 542 (void *)hal_srng_get_tp_addr(hal_soc, srng); 543 priv->dma_cfg[ring_idx].head_idx_addr = 544 (void *)hal_srng_get_tp_addr(hal_soc, srng); 545 546 return target_if_wifi_pos_fill_ring(ring_idx, srng, priv); 547 } 548 549 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx, 550 struct wifi_pos_psoc_priv_obj *priv) 551 { 552 target_if_wifi_pos_empty_ring(ring_idx, priv); 553 priv->dma_buf_pool[ring_idx] = NULL; 554 hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng); 555 qdf_mem_free_consistent(NULL, NULL, 556 priv->dma_cfg[ring_idx].ring_alloc_size, 557 priv->dma_cfg[ring_idx].base_vaddr_unaligned, 558 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 559 0); 560 qdf_mem_free(priv->dma_buf_pool[ring_idx]); 561 562 return QDF_STATUS_SUCCESS; 563 } 564 565 static QDF_STATUS target_if_wifi_pos_init_srngs( 566 struct wifi_pos_psoc_priv_obj *priv) 567 { 568 uint8_t i; 569 QDF_STATUS status; 570 571 /* allocate memory for num_rings pointers */ 572 priv->dma_cfg = qdf_mem_malloc(priv->num_rings * 573 sizeof(struct wifi_pos_dma_rings_cap)); 574 if (!priv->dma_cfg) 575 return QDF_STATUS_E_NOMEM; 576 577 priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings * 578 sizeof(struct wifi_pos_dma_buf_info *)); 579 if (!priv->dma_buf_pool) 580 return QDF_STATUS_E_NOMEM; 581 582 for (i = 0; i < priv->num_rings; i++) { 583 status = target_if_wifi_pos_init_ring(i, priv); 584 if (QDF_IS_STATUS_ERROR(status)) { 585 target_if_err("init for ring[%d] failed", i); 586 return status; 587 } 588 } 589 590 return QDF_STATUS_SUCCESS; 591 } 592 593 static QDF_STATUS target_if_wifi_pos_deinit_srngs( 594 struct wifi_pos_psoc_priv_obj *priv) 595 { 596 uint8_t i; 597 598 for (i = 0; i < priv->num_rings; i++) 599 target_if_wifi_pos_deinit_ring(i, priv); 600 601 qdf_mem_free(priv->dma_buf_pool); 602 priv->dma_buf_pool = NULL; 603 604 return QDF_STATUS_SUCCESS; 605 } 606 607 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, 608 struct wifi_pos_psoc_priv_obj *priv) 609 { 610 uint8_t i; 611 QDF_STATUS status; 612 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 613 wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; 614 615 if (!wmi_hdl) { 616 target_if_err("WMA closed, can't send oem data req cmd"); 617 return QDF_STATUS_E_INVAL; 618 } 619 620 target_if_debug("Sending oem dma ring cfg to target"); 621 622 for (i = 0; i < priv->num_rings; i++) { 623 cfg.pdev_id = priv->dma_cfg[i].pdev_id; 624 cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 625 & 0xFFFFFFFF; 626 cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 627 & 0xFFFFFFFF00000000; 628 cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr 629 & 0xFFFFFFFF; 630 cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr 631 & 0xFFFFFFFF00000000; 632 cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr 633 & 0xFFFFFFFF; 634 cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr 635 & 0xFFFFFFFF00000000; 636 cfg.num_ptr = priv->dma_cfg[i].num_ptr; 637 status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg); 638 if (!QDF_IS_STATUS_SUCCESS(status)) { 639 target_if_err("wmi cmd send failed"); 640 return status; 641 } 642 } 643 644 return status; 645 } 646 647 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc) 648 { 649 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 650 651 target_if_wifi_pos_deinit_srngs(priv); 652 qdf_mem_free(priv->dma_cap); 653 priv->dma_cap = NULL; 654 655 return QDF_STATUS_SUCCESS; 656 } 657 658 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, 659 void *hal_soc, uint8_t num_mac, 660 void *buf) 661 { 662 uint8_t i; 663 QDF_STATUS status = QDF_STATUS_SUCCESS; 664 WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf; 665 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 666 667 if (!priv) { 668 target_if_err("unable to get wifi_pos psoc obj"); 669 return QDF_STATUS_E_NULL_VALUE; 670 } 671 672 priv->hal_soc = hal_soc; 673 priv->num_rings = num_mac; 674 priv->dma_cap = qdf_mem_malloc(priv->num_rings * 675 sizeof(struct wifi_pos_dma_rings_cap)); 676 if (!priv->dma_cap) 677 return QDF_STATUS_E_NOMEM; 678 679 for (i = 0; i < num_mac; i++) { 680 priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id; 681 priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; 682 priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; 683 priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; 684 } 685 686 /* initialize DMA rings now */ 687 status = target_if_wifi_pos_init_srngs(priv); 688 if (QDF_IS_STATUS_ERROR(status)) { 689 target_if_err("dma init failed: %d", status); 690 goto dma_init_failed; 691 } 692 693 /* send cfg req cmd to firmware */ 694 status = target_if_wifi_pos_cfg_fw(psoc, priv); 695 if (QDF_IS_STATUS_ERROR(status)) { 696 target_if_err("configure to FW failed: %d", status); 697 goto dma_init_failed; 698 } 699 700 return QDF_STATUS_SUCCESS; 701 702 dma_init_failed: 703 target_if_wifi_pos_deinit_dma_rings(psoc); 704 return status; 705 } 706 707 #endif 708