1 /* 2 * Copyright (c) 2013-2021 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 uint32_t allocated_len; 96 97 if (!indirect) { 98 target_if_debug("no indirect data. regular event received"); 99 return QDF_STATUS_SUCCESS; 100 } 101 102 ring_idx = indirect->pdev_id - 1; 103 num_rings = priv_obj->num_rings; 104 if (ring_idx >= num_rings) { 105 target_if_err("incorrect pdev_id: %d", indirect->pdev_id); 106 return QDF_STATUS_E_INVAL; 107 } 108 109 allocated_len = priv_obj->dma_cap[ring_idx].min_buf_size + 110 (priv_obj->dma_cap[ring_idx].min_buf_align - 1); 111 if (indirect->len > allocated_len || 112 indirect->len > OEM_DATA_DMA_BUFF_SIZE) { 113 target_if_err("Invalid indirect len: %d, allocated_len:%d", 114 indirect->len, allocated_len); 115 return QDF_STATUS_E_INVAL; 116 } 117 118 addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET( 119 indirect->addr_hi); 120 paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo); 121 *cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET( 122 indirect->addr_hi); 123 rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj, 124 paddr, ring_idx, *cookie); 125 rsp->dma_len = indirect->len; 126 qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr, 127 QDF_DMA_FROM_DEVICE, 128 priv_obj->dma_cap[ring_idx].min_buf_size); 129 130 return QDF_STATUS_SUCCESS; 131 } 132 133 #else 134 static QDF_STATUS target_if_wifi_pos_replenish_ring( 135 struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx, 136 void *vaddr, uint32_t cookie) 137 { 138 return QDF_STATUS_SUCCESS; 139 } 140 141 static QDF_STATUS target_if_wifi_pos_get_indirect_data( 142 struct wifi_pos_psoc_priv_obj *priv_obj, 143 struct wmi_host_oem_indirect_data *indirect, 144 struct oem_data_rsp *rsp, uint32_t *cookie) 145 { 146 return QDF_STATUS_SUCCESS; 147 } 148 #endif 149 150 /** 151 * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with 152 * WMI_OEM_RESPONSE_EVENTID 153 * @scn: scn handle 154 * @data_buf: event buffer 155 * @data_len: event buffer length 156 * 157 * Return: status of operation 158 */ 159 static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, 160 uint8_t *data_buf, 161 uint32_t data_len) 162 { 163 int ret; 164 uint8_t ring_idx = 0; 165 QDF_STATUS status; 166 uint32_t cookie = 0; 167 struct wmi_host_oem_indirect_data *indirect; 168 struct oem_data_rsp oem_rsp = {0}; 169 struct wifi_pos_psoc_priv_obj *priv_obj; 170 struct wlan_objmgr_psoc *psoc; 171 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; 172 struct wmi_oem_response_param oem_resp_param = {0}; 173 wmi_unified_t wmi_handle; 174 175 psoc = target_if_get_psoc_from_scn_hdl(scn); 176 if (!psoc) { 177 target_if_err("psoc is null"); 178 return QDF_STATUS_NOT_INITIALIZED; 179 } 180 181 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 182 183 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 184 if (!wmi_handle) { 185 target_if_err("wmi_handle is null"); 186 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 187 return QDF_STATUS_NOT_INITIALIZED; 188 } 189 190 priv_obj = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc()); 191 if (!priv_obj) { 192 target_if_err("priv_obj is null"); 193 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 194 return QDF_STATUS_NOT_INITIALIZED; 195 } 196 197 wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); 198 if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { 199 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 200 target_if_err("lmac callbacks not registered"); 201 return QDF_STATUS_NOT_INITIALIZED; 202 } 203 204 ret = wmi_extract_oem_response_param(wmi_handle, 205 data_buf, 206 &oem_resp_param); 207 208 oem_rsp.rsp_len_1 = oem_resp_param.num_data1; 209 oem_rsp.data_1 = oem_resp_param.data_1; 210 211 if (oem_resp_param.num_data2) { 212 oem_rsp.rsp_len_2 = oem_resp_param.num_data2; 213 oem_rsp.data_2 = oem_resp_param.data_2; 214 } 215 216 indirect = &oem_resp_param.indirect_data; 217 status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, 218 &oem_rsp, &cookie); 219 if (QDF_IS_STATUS_ERROR(status)) { 220 target_if_err("get indirect data failed status: %d", status); 221 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 222 return QDF_STATUS_E_INVAL; 223 } 224 225 ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp); 226 if (indirect) 227 ring_idx = indirect->pdev_id - 1; 228 status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx, 229 oem_rsp.vaddr, cookie); 230 if (QDF_IS_STATUS_ERROR(status)) { 231 target_if_err("replenish failed status: %d", status); 232 ret = QDF_STATUS_E_FAILURE; 233 } 234 235 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 236 237 return ret; 238 } 239 240 /** 241 * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id 242 * @scn: scn handle 243 * @buf: event buffer 244 * @len: event buffer length 245 * 246 * Return: status of operation 247 */ 248 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len) 249 { 250 /* TBD */ 251 return 0; 252 } 253 254 /** 255 * wifi_pos_oem_meas_rpt_ev_handler: handler registered with 256 * wmi_oem_meas_report_event_id 257 * @scn: scn handle 258 * @buf: event buffer 259 * @len: event buffer length 260 * 261 * Return: status of operation 262 */ 263 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 264 uint32_t len) 265 { 266 /* TBD */ 267 return 0; 268 } 269 270 /** 271 * wifi_pos_oem_err_rpt_ev_handler: handler registered with 272 * wmi_oem_err_report_event_id 273 * @scn: scn handle 274 * @buf: event buffer 275 * @len: event buffer length 276 * 277 * Return: status of operation 278 */ 279 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 280 uint32_t len) 281 { 282 /* TBD */ 283 return 0; 284 } 285 286 /** 287 * target_if_wifi_pos_oem_data_req() - start OEM data request to target 288 * @psoc: pointer to psoc object mgr 289 * @req: start request params 290 * 291 * Return: QDF_STATUS 292 */ 293 static QDF_STATUS 294 target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev, 295 struct oem_data_req *req) 296 { 297 QDF_STATUS status; 298 wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev); 299 300 target_if_debug("Send oem data req to target"); 301 302 if (!req || !req->data) { 303 target_if_err("oem_data_req is null"); 304 return QDF_STATUS_E_INVAL; 305 } 306 307 if (!wmi_hdl) { 308 target_if_err("WMA closed, can't send oem data req cmd"); 309 return QDF_STATUS_E_INVAL; 310 } 311 312 status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len, 313 req->data); 314 315 if (!QDF_IS_STATUS_SUCCESS(status)) 316 target_if_err("wmi cmd send failed"); 317 318 return status; 319 } 320 321 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 322 { 323 struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops; 324 wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops; 325 wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req; 326 wifi_pos_tx_ops->wifi_pos_register_events = 327 target_if_wifi_pos_register_events; 328 wifi_pos_tx_ops->wifi_pos_deregister_events = 329 target_if_wifi_pos_deregister_events; 330 wifi_pos_tx_ops->wifi_pos_convert_pdev_id_host_to_target = 331 target_if_wifi_pos_convert_pdev_id_host_to_target; 332 wifi_pos_tx_ops->wifi_pos_convert_pdev_id_target_to_host = 333 target_if_wifi_pos_convert_pdev_id_target_to_host; 334 wifi_pos_tx_ops->wifi_pos_get_vht_ch_width = 335 target_if_wifi_pos_get_vht_ch_width; 336 337 } 338 339 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( 340 struct wlan_objmgr_psoc *psoc) 341 { 342 struct wlan_lmac_if_rx_ops *rx_ops; 343 344 if (!psoc) { 345 target_if_err("passed psoc is NULL"); 346 return NULL; 347 } 348 349 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 350 if (!rx_ops) { 351 target_if_err("rx_ops is NULL"); 352 return NULL; 353 } 354 355 return &rx_ops->wifi_pos_rx_ops; 356 } 357 358 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) 359 { 360 QDF_STATUS ret; 361 362 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 363 target_if_err("psoc or psoc->tgt_if_handle is null"); 364 return QDF_STATUS_E_INVAL; 365 } 366 367 /* wmi_oem_response_event_id is not defined for legacy targets. 368 * So do not check for error for this event. 369 */ 370 wmi_unified_register_event_handler( 371 get_wmi_unified_hdl_from_psoc(psoc), 372 wmi_oem_response_event_id, 373 target_if_wifi_pos_oem_rsp_ev_handler, 374 WMI_RX_WORK_CTX); 375 376 ret = wmi_unified_register_event_handler( 377 get_wmi_unified_hdl_from_psoc(psoc), 378 wmi_oem_cap_event_id, 379 wifi_pos_oem_cap_ev_handler, 380 WMI_RX_WORK_CTX); 381 if (QDF_IS_STATUS_ERROR(ret)) { 382 target_if_err("register_event_handler failed: err %d", ret); 383 return QDF_STATUS_E_INVAL; 384 } 385 386 ret = wmi_unified_register_event_handler( 387 get_wmi_unified_hdl_from_psoc(psoc), 388 wmi_oem_meas_report_event_id, 389 wifi_pos_oem_meas_rpt_ev_handler, 390 WMI_RX_WORK_CTX); 391 if (QDF_IS_STATUS_ERROR(ret)) { 392 target_if_err("register_event_handler failed: err %d", ret); 393 return QDF_STATUS_E_INVAL; 394 } 395 396 ret = wmi_unified_register_event_handler( 397 get_wmi_unified_hdl_from_psoc(psoc), 398 wmi_oem_report_event_id, 399 wifi_pos_oem_err_rpt_ev_handler, 400 WMI_RX_WORK_CTX); 401 if (QDF_IS_STATUS_ERROR(ret)) { 402 target_if_err("register_event_handler failed: err %d", ret); 403 return QDF_STATUS_E_INVAL; 404 } 405 406 return QDF_STATUS_SUCCESS; 407 } 408 409 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) 410 { 411 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 412 target_if_err("psoc or psoc->tgt_if_handle is null"); 413 return QDF_STATUS_E_INVAL; 414 } 415 416 wmi_unified_unregister_event_handler( 417 get_wmi_unified_hdl_from_psoc(psoc), 418 wmi_oem_response_event_id); 419 wmi_unified_unregister_event_handler( 420 get_wmi_unified_hdl_from_psoc(psoc), 421 wmi_oem_cap_event_id); 422 wmi_unified_unregister_event_handler( 423 get_wmi_unified_hdl_from_psoc(psoc), 424 wmi_oem_meas_report_event_id); 425 wmi_unified_unregister_event_handler( 426 get_wmi_unified_hdl_from_psoc(psoc), 427 wmi_oem_report_event_id); 428 429 return QDF_STATUS_SUCCESS; 430 } 431 432 QDF_STATUS target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc, 433 enum phy_ch_width *ch_width) 434 { 435 struct target_psoc_info *tgt_hdl; 436 int vht_cap_info; 437 438 *ch_width = CH_WIDTH_INVALID; 439 440 if (!psoc) 441 return QDF_STATUS_E_INVAL; 442 443 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 444 if (!tgt_hdl) 445 return QDF_STATUS_E_INVAL; 446 447 *ch_width = CH_WIDTH_80MHZ; 448 449 vht_cap_info = target_if_get_vht_cap_info(tgt_hdl); 450 451 if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) 452 *ch_width = CH_WIDTH_80P80MHZ; 453 else if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) 454 *ch_width = CH_WIDTH_160MHZ; 455 456 return QDF_STATUS_SUCCESS; 457 } 458 459 #ifndef CNSS_GENL 460 QDF_STATUS target_if_wifi_pos_convert_pdev_id_host_to_target( 461 struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id, 462 uint32_t *target_pdev_id) 463 { 464 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 465 466 if (!wmi_hdl) { 467 target_if_err("null wmi_hdl"); 468 return QDF_STATUS_E_NULL_VALUE; 469 } 470 471 return wmi_convert_pdev_id_host_to_target(wmi_hdl, host_pdev_id, 472 target_pdev_id); 473 } 474 475 QDF_STATUS target_if_wifi_pos_convert_pdev_id_target_to_host( 476 struct wlan_objmgr_psoc *psoc, uint32_t target_pdev_id, 477 uint32_t *host_pdev_id) 478 { 479 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 480 481 if (!wmi_hdl) { 482 target_if_err("null wmi_hdl"); 483 return QDF_STATUS_E_NULL_VALUE; 484 } 485 486 return wmi_convert_pdev_id_target_to_host(wmi_hdl, target_pdev_id, 487 host_pdev_id); 488 } 489 #endif /* CNSS_GENL */ 490 491 #ifdef WLAN_FEATURE_CIF_CFR 492 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, 493 struct hal_srng *srng, 494 struct wifi_pos_psoc_priv_obj *priv) 495 { 496 uint32_t i; 497 void *buf, *buf_aligned; 498 499 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 500 buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size + 501 priv->dma_cap[ring_idx].min_buf_align - 1); 502 if (!buf) 503 return QDF_STATUS_E_NOMEM; 504 505 priv->dma_buf_pool[ring_idx][i].vaddr = buf; 506 buf_aligned = (void *)qdf_roundup((uint64_t)buf, 507 priv->dma_cap[ring_idx].min_buf_align); 508 priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf; 509 priv->dma_buf_pool[ring_idx][i].cookie = i; 510 target_if_wifi_pos_replenish_ring(priv, ring_idx, 511 buf_aligned, i); 512 } 513 514 return QDF_STATUS_SUCCESS; 515 } 516 517 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx, 518 struct wifi_pos_psoc_priv_obj *priv) 519 { 520 uint32_t i; 521 522 for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { 523 qdf_mem_unmap_nbytes_single(NULL, 524 (qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr, 525 QDF_DMA_FROM_DEVICE, 526 priv->dma_cap[ring_idx].min_buf_size); 527 qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr); 528 } 529 530 return QDF_STATUS_SUCCESS; 531 } 532 533 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx, 534 struct wifi_pos_psoc_priv_obj *priv) 535 { 536 void *srng; 537 uint32_t num_entries; 538 qdf_dma_addr_t paddr; 539 uint32_t ring_alloc_size; 540 void *hal_soc = priv->hal_soc; 541 struct hal_srng_params ring_params = {0}; 542 uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC); 543 uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC); 544 545 num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ? 546 max_entries : priv->dma_cap[ring_idx].min_num_ptr; 547 priv->dma_cfg[ring_idx].num_ptr = num_entries; 548 priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries * 549 sizeof(struct wifi_pos_dma_buf_info)); 550 if (!priv->dma_buf_pool[ring_idx]) 551 return QDF_STATUS_E_NOMEM; 552 553 ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1; 554 priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size; 555 priv->dma_cfg[ring_idx].base_vaddr_unaligned = 556 qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr); 557 priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr; 558 if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) { 559 target_if_err("malloc failed"); 560 return QDF_STATUS_E_NOMEM; 561 } 562 563 priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup( 564 (uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned, 565 RING_BASE_ALIGN); 566 ring_params.ring_base_vaddr = 567 priv->dma_cfg[ring_idx].base_vaddr_aligned; 568 priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup( 569 (uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 570 RING_BASE_ALIGN); 571 ring_params.ring_base_paddr = 572 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned; 573 ring_params.num_entries = num_entries; 574 srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0, 575 priv->dma_cap[ring_idx].pdev_id, &ring_params); 576 if (!srng) { 577 target_if_err("srng setup failed"); 578 return QDF_STATUS_E_FAILURE; 579 } 580 priv->dma_cfg[ring_idx].srng = srng; 581 priv->dma_cfg[ring_idx].tail_idx_addr = 582 (void *)hal_srng_get_tp_addr(hal_soc, srng); 583 priv->dma_cfg[ring_idx].head_idx_addr = 584 (void *)hal_srng_get_tp_addr(hal_soc, srng); 585 586 return target_if_wifi_pos_fill_ring(ring_idx, srng, priv); 587 } 588 589 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx, 590 struct wifi_pos_psoc_priv_obj *priv) 591 { 592 target_if_wifi_pos_empty_ring(ring_idx, priv); 593 priv->dma_buf_pool[ring_idx] = NULL; 594 hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng); 595 qdf_mem_free_consistent(NULL, NULL, 596 priv->dma_cfg[ring_idx].ring_alloc_size, 597 priv->dma_cfg[ring_idx].base_vaddr_unaligned, 598 (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, 599 0); 600 qdf_mem_free(priv->dma_buf_pool[ring_idx]); 601 602 return QDF_STATUS_SUCCESS; 603 } 604 605 static QDF_STATUS target_if_wifi_pos_init_srngs( 606 struct wifi_pos_psoc_priv_obj *priv) 607 { 608 uint8_t i; 609 QDF_STATUS status; 610 611 /* allocate memory for num_rings pointers */ 612 priv->dma_cfg = qdf_mem_malloc(priv->num_rings * 613 sizeof(struct wifi_pos_dma_rings_cap)); 614 if (!priv->dma_cfg) 615 return QDF_STATUS_E_NOMEM; 616 617 priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings * 618 sizeof(struct wifi_pos_dma_buf_info *)); 619 if (!priv->dma_buf_pool) 620 return QDF_STATUS_E_NOMEM; 621 622 for (i = 0; i < priv->num_rings; i++) { 623 status = target_if_wifi_pos_init_ring(i, priv); 624 if (QDF_IS_STATUS_ERROR(status)) { 625 target_if_err("init for ring[%d] failed", i); 626 return status; 627 } 628 } 629 630 return QDF_STATUS_SUCCESS; 631 } 632 633 static QDF_STATUS target_if_wifi_pos_deinit_srngs( 634 struct wifi_pos_psoc_priv_obj *priv) 635 { 636 uint8_t i; 637 638 for (i = 0; i < priv->num_rings; i++) 639 target_if_wifi_pos_deinit_ring(i, priv); 640 641 qdf_mem_free(priv->dma_buf_pool); 642 priv->dma_buf_pool = NULL; 643 644 return QDF_STATUS_SUCCESS; 645 } 646 647 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, 648 struct wifi_pos_psoc_priv_obj *priv) 649 { 650 uint8_t i; 651 QDF_STATUS status; 652 wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); 653 wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; 654 655 if (!wmi_hdl) { 656 target_if_err("WMA closed, can't send oem data req cmd"); 657 return QDF_STATUS_E_INVAL; 658 } 659 660 target_if_debug("Sending oem dma ring cfg to target"); 661 662 for (i = 0; i < priv->num_rings; i++) { 663 cfg.pdev_id = priv->dma_cfg[i].pdev_id; 664 cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 665 & 0xFFFFFFFF; 666 cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned 667 & 0xFFFFFFFF00000000; 668 cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr 669 & 0xFFFFFFFF; 670 cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr 671 & 0xFFFFFFFF00000000; 672 cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr 673 & 0xFFFFFFFF; 674 cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr 675 & 0xFFFFFFFF00000000; 676 cfg.num_ptr = priv->dma_cfg[i].num_ptr; 677 status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg); 678 if (!QDF_IS_STATUS_SUCCESS(status)) { 679 target_if_err("wmi cmd send failed"); 680 return status; 681 } 682 } 683 684 return status; 685 } 686 687 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc) 688 { 689 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 690 691 target_if_wifi_pos_deinit_srngs(priv); 692 qdf_mem_free(priv->dma_cap); 693 priv->dma_cap = NULL; 694 695 return QDF_STATUS_SUCCESS; 696 } 697 698 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, 699 void *hal_soc, uint8_t num_mac, 700 void *buf) 701 { 702 uint8_t i; 703 QDF_STATUS status = QDF_STATUS_SUCCESS; 704 WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf; 705 struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); 706 707 if (!priv) { 708 target_if_err("unable to get wifi_pos psoc obj"); 709 return QDF_STATUS_E_NULL_VALUE; 710 } 711 712 priv->hal_soc = hal_soc; 713 priv->num_rings = num_mac; 714 priv->dma_cap = qdf_mem_malloc(priv->num_rings * 715 sizeof(struct wifi_pos_dma_rings_cap)); 716 if (!priv->dma_cap) 717 return QDF_STATUS_E_NOMEM; 718 719 for (i = 0; i < num_mac; i++) { 720 priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id; 721 priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; 722 priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; 723 priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; 724 } 725 726 /* initialize DMA rings now */ 727 status = target_if_wifi_pos_init_srngs(priv); 728 if (QDF_IS_STATUS_ERROR(status)) { 729 target_if_err("dma init failed: %d", status); 730 goto dma_init_failed; 731 } 732 733 /* send cfg req cmd to firmware */ 734 status = target_if_wifi_pos_cfg_fw(psoc, priv); 735 if (QDF_IS_STATUS_ERROR(status)) { 736 target_if_err("configure to FW failed: %d", status); 737 goto dma_init_failed; 738 } 739 740 return QDF_STATUS_SUCCESS; 741 742 dma_init_failed: 743 target_if_wifi_pos_deinit_dma_rings(psoc); 744 return status; 745 } 746 747 #endif 748