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