1 /* 2 * Copyright (c) 2017-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 #include "target_if.h" 20 #include "wmi_unified_api.h" 21 #include "wlan_lmac_if_def.h" 22 #include "target_if_direct_buf_rx_main.h" 23 #include <target_if_direct_buf_rx_api.h> 24 #include "hal_api.h" 25 #include <service_ready_util.h> 26 #include <init_deinit_ucfg.h> 27 28 static uint8_t get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev *pdev) 29 { 30 struct wlan_objmgr_psoc *psoc; 31 struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap; 32 uint8_t num_dbr_ring_caps, cap_idx, pdev_id, num_modules; 33 struct target_psoc_info *tgt_psoc_info; 34 struct wlan_psoc_host_service_ext_param *ext_svc_param; 35 36 psoc = wlan_pdev_get_psoc(pdev); 37 38 if (psoc == NULL) { 39 direct_buf_rx_err("psoc is null"); 40 return 0; 41 } 42 43 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 44 if (tgt_psoc_info == NULL) { 45 direct_buf_rx_err("target_psoc_info is null"); 46 return 0; 47 } 48 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 49 num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps; 50 dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info); 51 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 52 num_modules = 0; 53 54 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 55 if (dbr_ring_cap[cap_idx].pdev_id == pdev_id) 56 num_modules++; 57 } 58 59 return num_modules; 60 } 61 62 static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev, 63 struct direct_buf_rx_module_param *mod_param) 64 { 65 struct wlan_objmgr_psoc *psoc; 66 struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap; 67 uint8_t cap_idx; 68 bool cap_found = false; 69 enum DBR_MODULE mod_id = mod_param->mod_id; 70 uint32_t num_dbr_ring_caps, pdev_id; 71 struct target_psoc_info *tgt_psoc_info; 72 struct wlan_psoc_host_service_ext_param *ext_svc_param; 73 74 psoc = wlan_pdev_get_psoc(pdev); 75 76 if (psoc == NULL) { 77 direct_buf_rx_err("psoc is null"); 78 return QDF_STATUS_E_INVAL; 79 } 80 81 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 82 if (tgt_psoc_info == NULL) { 83 direct_buf_rx_err("target_psoc_info is null"); 84 return QDF_STATUS_E_INVAL; 85 } 86 87 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 88 num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps; 89 dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info); 90 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 91 92 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 93 if (dbr_ring_cap[cap_idx].pdev_id == pdev_id) { 94 if (dbr_ring_cap[cap_idx].mod_id == mod_id) { 95 mod_param->dbr_ring_cap->ring_elems_min = 96 dbr_ring_cap[cap_idx].ring_elems_min; 97 mod_param->dbr_ring_cap->min_buf_size = 98 dbr_ring_cap[cap_idx].min_buf_size; 99 mod_param->dbr_ring_cap->min_buf_align = 100 dbr_ring_cap[cap_idx].min_buf_align; 101 cap_found = true; 102 } 103 } 104 } 105 106 if (!cap_found) { 107 direct_buf_rx_err("No cap found for module %d in pdev %d", 108 mod_id, pdev_id); 109 return QDF_STATUS_E_FAILURE; 110 } 111 112 return QDF_STATUS_SUCCESS; 113 } 114 115 QDF_STATUS target_if_direct_buf_rx_pdev_create_handler( 116 struct wlan_objmgr_pdev *pdev, void *data) 117 { 118 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 119 struct wlan_objmgr_psoc *psoc; 120 uint8_t num_modules; 121 QDF_STATUS status; 122 123 direct_buf_rx_enter(); 124 125 if (pdev == NULL) { 126 direct_buf_rx_err("pdev context passed is null"); 127 return QDF_STATUS_E_INVAL; 128 } 129 130 psoc = wlan_pdev_get_psoc(pdev); 131 132 if (psoc == NULL) { 133 direct_buf_rx_err("psoc is null"); 134 return QDF_STATUS_E_INVAL; 135 } 136 137 dbr_pdev_obj = qdf_mem_malloc(sizeof(*dbr_pdev_obj)); 138 139 if (dbr_pdev_obj == NULL) { 140 direct_buf_rx_err("Failed to allocate dir buf rx pdev obj"); 141 return QDF_STATUS_E_NOMEM; 142 } 143 144 direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj); 145 146 status = wlan_objmgr_pdev_component_obj_attach(pdev, 147 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, 148 dbr_pdev_obj, QDF_STATUS_SUCCESS); 149 150 if (status != QDF_STATUS_SUCCESS) { 151 direct_buf_rx_err("Failed to attach dir buf rx component %d", 152 status); 153 qdf_mem_free(dbr_pdev_obj); 154 return status; 155 } 156 157 num_modules = get_num_dbr_modules_per_pdev(pdev); 158 direct_buf_rx_info("Number of modules = %d pdev %d", num_modules, 159 wlan_objmgr_pdev_get_pdev_id(pdev)); 160 dbr_pdev_obj->num_modules = num_modules; 161 162 if (!dbr_pdev_obj->num_modules) { 163 direct_buf_rx_info("Number of modules = %d", num_modules); 164 return QDF_STATUS_SUCCESS; 165 } 166 167 dbr_pdev_obj->dbr_mod_param = qdf_mem_malloc(num_modules * 168 sizeof(struct direct_buf_rx_module_param)); 169 170 if (dbr_pdev_obj->dbr_mod_param == NULL) { 171 direct_buf_rx_err("Failed to allocate dir buf rx mod param"); 172 wlan_objmgr_pdev_component_obj_detach(pdev, 173 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, 174 dbr_pdev_obj); 175 qdf_mem_free(dbr_pdev_obj); 176 return QDF_STATUS_E_NOMEM; 177 } 178 179 180 return QDF_STATUS_SUCCESS; 181 } 182 183 QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler( 184 struct wlan_objmgr_pdev *pdev, void *data) 185 { 186 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 187 QDF_STATUS status; 188 uint8_t num_modules, mod_idx; 189 190 if (pdev == NULL) { 191 direct_buf_rx_err("pdev context passed is null"); 192 return QDF_STATUS_E_INVAL; 193 } 194 195 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 196 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 197 198 if (dbr_pdev_obj == NULL) { 199 direct_buf_rx_err("dir buf rx object is null"); 200 return QDF_STATUS_E_FAILURE; 201 } 202 203 num_modules = dbr_pdev_obj->num_modules; 204 for (mod_idx = 0; mod_idx < num_modules; mod_idx++) 205 target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_idx); 206 207 status = wlan_objmgr_pdev_component_obj_detach(pdev, 208 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, 209 dbr_pdev_obj); 210 211 if (status != QDF_STATUS_SUCCESS) { 212 direct_buf_rx_err("failed to detach dir buf rx component %d", 213 status); 214 } 215 216 qdf_mem_free(dbr_pdev_obj); 217 218 return status; 219 } 220 221 QDF_STATUS target_if_direct_buf_rx_psoc_create_handler( 222 struct wlan_objmgr_psoc *psoc, void *data) 223 { 224 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 225 QDF_STATUS status; 226 227 direct_buf_rx_enter(); 228 229 if (psoc == NULL) { 230 direct_buf_rx_err("psoc context passed is null"); 231 return QDF_STATUS_E_INVAL; 232 } 233 234 dbr_psoc_obj = qdf_mem_malloc(sizeof(*dbr_psoc_obj)); 235 236 if (!dbr_psoc_obj) { 237 direct_buf_rx_err("failed to alloc dir buf rx psoc obj"); 238 return QDF_STATUS_E_NOMEM; 239 } 240 241 direct_buf_rx_info("Dbr psoc obj %pK", dbr_psoc_obj); 242 243 status = wlan_objmgr_psoc_component_obj_attach(psoc, 244 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, dbr_psoc_obj, 245 QDF_STATUS_SUCCESS); 246 247 if (status != QDF_STATUS_SUCCESS) { 248 direct_buf_rx_err("Failed to attach dir buf rx component %d", 249 status); 250 goto attach_error; 251 } 252 253 return status; 254 255 attach_error: 256 qdf_mem_free(dbr_psoc_obj); 257 258 return status; 259 } 260 261 QDF_STATUS target_if_direct_buf_rx_psoc_destroy_handler( 262 struct wlan_objmgr_psoc *psoc, void *data) 263 { 264 QDF_STATUS status; 265 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 266 267 direct_buf_rx_enter(); 268 269 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 270 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 271 272 if (!dbr_psoc_obj) { 273 direct_buf_rx_err("dir buf rx psoc obj is null"); 274 return QDF_STATUS_E_FAILURE; 275 } 276 277 status = wlan_objmgr_psoc_component_obj_detach(psoc, 278 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, 279 dbr_psoc_obj); 280 281 if (status != QDF_STATUS_SUCCESS) { 282 direct_buf_rx_err("failed to detach dir buf rx component %d", 283 status); 284 } 285 286 qdf_mem_free(dbr_psoc_obj); 287 288 return status; 289 } 290 291 static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev, 292 struct direct_buf_rx_module_param *mod_param, 293 void *aligned_vaddr, uint8_t cookie) 294 { 295 uint64_t *ring_entry; 296 uint32_t dw_lo, dw_hi = 0, map_status; 297 void *hal_soc, *srng; 298 qdf_dma_addr_t paddr; 299 struct wlan_objmgr_psoc *psoc; 300 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 301 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 302 struct direct_buf_rx_ring_cap *dbr_ring_cap; 303 struct direct_buf_rx_buf_info *dbr_buf_pool; 304 305 direct_buf_rx_enter(); 306 307 dbr_ring_cfg = mod_param->dbr_ring_cfg; 308 dbr_ring_cap = mod_param->dbr_ring_cap; 309 dbr_buf_pool = mod_param->dbr_buf_pool; 310 311 psoc = wlan_pdev_get_psoc(pdev); 312 313 if (!psoc) { 314 direct_buf_rx_err("psoc is null"); 315 return QDF_STATUS_E_FAILURE; 316 } 317 318 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 319 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 320 321 if (dbr_psoc_obj == NULL) { 322 direct_buf_rx_err("dir buf rx psoc object is null"); 323 return QDF_STATUS_E_FAILURE; 324 } 325 326 hal_soc = dbr_psoc_obj->hal_soc; 327 srng = dbr_ring_cfg->srng; 328 if (!aligned_vaddr) { 329 direct_buf_rx_err("aligned vaddr is null"); 330 return QDF_STATUS_SUCCESS; 331 } 332 333 map_status = qdf_mem_map_nbytes_single(dbr_psoc_obj->osdev, 334 aligned_vaddr, 335 QDF_DMA_FROM_DEVICE, 336 dbr_ring_cap->min_buf_size, 337 &paddr); 338 if (map_status) { 339 direct_buf_rx_err("mem map failed status = %d", map_status); 340 return QDF_STATUS_E_FAILURE; 341 } 342 343 QDF_ASSERT(!((uint64_t)paddr & dbr_ring_cap->min_buf_align)); 344 dbr_buf_pool[cookie].paddr = paddr; 345 346 hal_srng_access_start(hal_soc, srng); 347 ring_entry = hal_srng_src_get_next(hal_soc, srng); 348 QDF_ASSERT(ring_entry != NULL); 349 dw_lo = (uint64_t)paddr & 0xFFFFFFFF; 350 WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32); 351 WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie); 352 direct_buf_rx_info("Cookie = %d", cookie); 353 direct_buf_rx_info("dw_lo = %x dw_hi = %x", dw_lo, dw_hi); 354 *ring_entry = (uint64_t)dw_hi << 32 | dw_lo; 355 direct_buf_rx_info("Valid ring entry"); 356 hal_srng_access_end(hal_soc, srng); 357 358 return QDF_STATUS_SUCCESS; 359 } 360 361 static QDF_STATUS target_if_dbr_fill_ring(struct wlan_objmgr_pdev *pdev, 362 struct direct_buf_rx_module_param *mod_param) 363 { 364 uint8_t idx; 365 void *buf, *buf_aligned; 366 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 367 struct direct_buf_rx_ring_cap *dbr_ring_cap; 368 struct direct_buf_rx_buf_info *dbr_buf_pool; 369 QDF_STATUS status; 370 371 direct_buf_rx_enter(); 372 373 dbr_ring_cfg = mod_param->dbr_ring_cfg; 374 dbr_ring_cap = mod_param->dbr_ring_cap; 375 dbr_buf_pool = mod_param->dbr_buf_pool; 376 377 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { 378 buf = qdf_mem_malloc(dbr_ring_cap->min_buf_size + 379 dbr_ring_cap->min_buf_align - 1); 380 if (!buf) { 381 direct_buf_rx_err("dir buf rx ring buf alloc failed"); 382 return QDF_STATUS_E_NOMEM; 383 } 384 dbr_buf_pool[idx].vaddr = buf; 385 buf_aligned = (void *)(uintptr_t)qdf_roundup( 386 (uint64_t)(uintptr_t)buf, DBR_RING_BASE_ALIGN); 387 dbr_buf_pool[idx].offset = buf_aligned - buf; 388 dbr_buf_pool[idx].cookie = idx; 389 status = target_if_dbr_replenish_ring(pdev, mod_param, 390 buf_aligned, idx); 391 if (QDF_IS_STATUS_ERROR(status)) { 392 direct_buf_rx_err("replenish failed with status : %d", 393 status); 394 qdf_mem_free(buf); 395 return QDF_STATUS_E_FAILURE; 396 } 397 } 398 399 return QDF_STATUS_SUCCESS; 400 } 401 402 static QDF_STATUS target_if_dbr_init_ring(struct wlan_objmgr_pdev *pdev, 403 struct direct_buf_rx_module_param *mod_param) 404 { 405 void *srng; 406 uint32_t num_entries, ring_alloc_size, max_entries, entry_size; 407 qdf_dma_addr_t paddr; 408 struct hal_srng_params ring_params = {0}; 409 struct wlan_objmgr_psoc *psoc; 410 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 411 struct direct_buf_rx_ring_cap *dbr_ring_cap; 412 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 413 QDF_STATUS status; 414 415 direct_buf_rx_enter(); 416 417 psoc = wlan_pdev_get_psoc(pdev); 418 419 if (!psoc) { 420 direct_buf_rx_err("psoc is null"); 421 return QDF_STATUS_E_FAILURE; 422 } 423 424 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 425 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 426 427 if (dbr_psoc_obj == NULL) { 428 direct_buf_rx_err("dir buf rx psoc object is null"); 429 return QDF_STATUS_E_FAILURE; 430 } 431 432 if (dbr_psoc_obj->hal_soc == NULL || 433 dbr_psoc_obj->osdev == NULL) { 434 direct_buf_rx_err("dir buf rx target attach failed"); 435 return QDF_STATUS_E_FAILURE; 436 } 437 438 max_entries = hal_srng_max_entries(dbr_psoc_obj->hal_soc, 439 DIR_BUF_RX_DMA_SRC); 440 entry_size = hal_srng_get_entrysize(dbr_psoc_obj->hal_soc, 441 DIR_BUF_RX_DMA_SRC); 442 direct_buf_rx_info("Max Entries = %d", max_entries); 443 direct_buf_rx_info("Entry Size = %d", entry_size); 444 445 status = populate_dbr_cap_mod_param(pdev, mod_param); 446 if (QDF_IS_STATUS_ERROR(status)) { 447 direct_buf_rx_err("Module cap population failed"); 448 return QDF_STATUS_E_FAILURE; 449 } 450 451 dbr_ring_cap = mod_param->dbr_ring_cap; 452 dbr_ring_cfg = mod_param->dbr_ring_cfg; 453 num_entries = dbr_ring_cap->ring_elems_min > max_entries ? 454 max_entries : dbr_ring_cap->ring_elems_min; 455 direct_buf_rx_info("Num entries = %d", num_entries); 456 dbr_ring_cfg->num_ptr = num_entries; 457 mod_param->dbr_buf_pool = qdf_mem_malloc(num_entries * sizeof( 458 struct direct_buf_rx_buf_info)); 459 if (!mod_param->dbr_buf_pool) { 460 direct_buf_rx_err("dir buf rx buf pool alloc failed"); 461 return QDF_STATUS_E_NOMEM; 462 } 463 464 ring_alloc_size = (num_entries * entry_size) + DBR_RING_BASE_ALIGN - 1; 465 dbr_ring_cfg->ring_alloc_size = ring_alloc_size; 466 direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj); 467 dbr_ring_cfg->base_vaddr_unaligned = qdf_mem_alloc_consistent( 468 dbr_psoc_obj->osdev, dbr_psoc_obj->osdev->dev, ring_alloc_size, 469 &paddr); 470 direct_buf_rx_info("vaddr aligned allocated"); 471 dbr_ring_cfg->base_paddr_unaligned = paddr; 472 if (!dbr_ring_cfg->base_vaddr_unaligned) { 473 direct_buf_rx_err("dir buf rx vaddr alloc failed"); 474 qdf_mem_free(mod_param->dbr_buf_pool); 475 return QDF_STATUS_E_NOMEM; 476 } 477 478 /* Alignment is defined to 8 for now. Will be advertised by FW */ 479 dbr_ring_cfg->base_vaddr_aligned = (void *)(uintptr_t)qdf_roundup( 480 (uint64_t)(uintptr_t)dbr_ring_cfg->base_vaddr_unaligned, 481 DBR_RING_BASE_ALIGN); 482 ring_params.ring_base_vaddr = dbr_ring_cfg->base_vaddr_aligned; 483 dbr_ring_cfg->base_paddr_aligned = qdf_roundup( 484 (uint64_t)dbr_ring_cfg->base_paddr_unaligned, 485 DBR_RING_BASE_ALIGN); 486 ring_params.ring_base_paddr = 487 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_aligned; 488 ring_params.num_entries = num_entries; 489 srng = hal_srng_setup(dbr_psoc_obj->hal_soc, DIR_BUF_RX_DMA_SRC, 0, 490 wlan_objmgr_pdev_get_pdev_id(pdev), &ring_params); 491 492 if (!srng) { 493 direct_buf_rx_err("srng setup failed"); 494 qdf_mem_free(mod_param->dbr_buf_pool); 495 qdf_mem_free_consistent(dbr_psoc_obj->osdev, 496 dbr_psoc_obj->osdev->dev, 497 ring_alloc_size, 498 dbr_ring_cfg->base_vaddr_unaligned, 499 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0); 500 return QDF_STATUS_E_FAILURE; 501 } 502 dbr_ring_cfg->srng = srng; 503 dbr_ring_cfg->tail_idx_addr = 504 hal_srng_get_tp_addr(dbr_psoc_obj->hal_soc, srng); 505 dbr_ring_cfg->head_idx_addr = 506 hal_srng_get_hp_addr(dbr_psoc_obj->hal_soc, srng); 507 dbr_ring_cfg->buf_size = dbr_ring_cap->min_buf_size; 508 509 return target_if_dbr_fill_ring(pdev, mod_param); 510 } 511 512 static QDF_STATUS target_if_dbr_init_srng(struct wlan_objmgr_pdev *pdev, 513 struct direct_buf_rx_module_param *mod_param) 514 { 515 QDF_STATUS status; 516 517 direct_buf_rx_info("Init DBR srng"); 518 519 if (!mod_param) { 520 direct_buf_rx_err("dir buf rx module param is null"); 521 return QDF_STATUS_E_INVAL; 522 } 523 524 mod_param->dbr_ring_cap = qdf_mem_malloc(sizeof( 525 struct direct_buf_rx_ring_cap)); 526 527 if (!mod_param->dbr_ring_cap) { 528 direct_buf_rx_err("Ring cap alloc failed"); 529 return QDF_STATUS_E_NOMEM; 530 } 531 532 /* Allocate memory for DBR Ring Config */ 533 mod_param->dbr_ring_cfg = qdf_mem_malloc(sizeof( 534 struct direct_buf_rx_ring_cfg)); 535 536 if (!mod_param->dbr_ring_cfg) { 537 direct_buf_rx_err("Ring config alloc failed"); 538 qdf_mem_free(mod_param->dbr_ring_cap); 539 return QDF_STATUS_E_NOMEM; 540 } 541 542 status = target_if_dbr_init_ring(pdev, mod_param); 543 544 if (QDF_IS_STATUS_ERROR(status)) { 545 direct_buf_rx_err("DBR ring init failed"); 546 qdf_mem_free(mod_param->dbr_ring_cfg); 547 qdf_mem_free(mod_param->dbr_ring_cap); 548 return QDF_STATUS_E_FAILURE; 549 } 550 551 return QDF_STATUS_SUCCESS; 552 } 553 554 static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev, 555 struct direct_buf_rx_module_param *mod_param) 556 { 557 QDF_STATUS status; 558 struct wlan_objmgr_psoc *psoc; 559 void *wmi_hdl; 560 struct direct_buf_rx_cfg_req dbr_cfg_req = {0}; 561 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 562 struct direct_buf_rx_ring_cap *dbr_ring_cap; 563 564 direct_buf_rx_enter(); 565 566 psoc = wlan_pdev_get_psoc(pdev); 567 if (!psoc) { 568 direct_buf_rx_err("psoc is null"); 569 return QDF_STATUS_E_FAILURE; 570 } 571 572 dbr_ring_cfg = mod_param->dbr_ring_cfg; 573 dbr_ring_cap = mod_param->dbr_ring_cap; 574 wmi_hdl = ucfg_get_pdev_wmi_handle(pdev); 575 if (!wmi_hdl) { 576 direct_buf_rx_err("WMI handle null. Can't send WMI CMD"); 577 return QDF_STATUS_E_INVAL; 578 } 579 580 direct_buf_rx_debug("Sending DBR Ring CFG to target"); 581 dbr_cfg_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 582 /* Module ID numbering starts from 1 in FW. need to fix it */ 583 dbr_cfg_req.mod_id = mod_param->mod_id; 584 dbr_cfg_req.base_paddr_lo = (uint64_t)dbr_ring_cfg->base_paddr_aligned 585 & 0xFFFFFFFF; 586 dbr_cfg_req.base_paddr_hi = (uint64_t)dbr_ring_cfg->base_paddr_aligned 587 & 0xFFFFFFFF00000000; 588 dbr_cfg_req.head_idx_paddr_lo = (uint64_t)dbr_ring_cfg->head_idx_addr 589 & 0xFFFFFFFF; 590 dbr_cfg_req.head_idx_paddr_hi = (uint64_t)dbr_ring_cfg->head_idx_addr 591 & 0xFFFFFFFF00000000; 592 dbr_cfg_req.tail_idx_paddr_lo = (uint64_t)dbr_ring_cfg->tail_idx_addr 593 & 0xFFFFFFFF; 594 dbr_cfg_req.tail_idx_paddr_hi = (uint64_t)dbr_ring_cfg->tail_idx_addr 595 & 0xFFFFFFFF00000000; 596 dbr_cfg_req.num_elems = dbr_ring_cap->ring_elems_min; 597 dbr_cfg_req.buf_size = dbr_ring_cap->min_buf_size; 598 dbr_cfg_req.num_resp_per_event = DBR_NUM_RESP_PER_EVENT; 599 dbr_cfg_req.event_timeout_ms = DBR_EVENT_TIMEOUT_IN_MS; 600 direct_buf_rx_info("pdev id %d mod id %d base addr lo %x\n" 601 "base addr hi %x head idx addr lo %x\n" 602 "head idx addr hi %x tail idx addr lo %x\n" 603 "tail idx addr hi %x num ptr %d\n" 604 "num resp %d event timeout %d\n", 605 dbr_cfg_req.pdev_id, dbr_cfg_req.mod_id, 606 dbr_cfg_req.base_paddr_lo, dbr_cfg_req.base_paddr_hi, 607 dbr_cfg_req.head_idx_paddr_lo, 608 dbr_cfg_req.head_idx_paddr_hi, 609 dbr_cfg_req.tail_idx_paddr_lo, 610 dbr_cfg_req.tail_idx_paddr_hi, 611 dbr_cfg_req.num_elems, 612 dbr_cfg_req.num_resp_per_event, 613 dbr_cfg_req.event_timeout_ms); 614 status = wmi_unified_dbr_ring_cfg(wmi_hdl, &dbr_cfg_req); 615 616 return status; 617 } 618 619 static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev, 620 struct direct_buf_rx_pdev_obj *dbr_pdev_obj, 621 enum DBR_MODULE mod_id) 622 { 623 QDF_STATUS status = QDF_STATUS_SUCCESS; 624 struct direct_buf_rx_module_param *mod_param; 625 626 direct_buf_rx_info("Init DBR ring for module %d", mod_id); 627 628 if (!dbr_pdev_obj) { 629 direct_buf_rx_err("dir buf rx object is null"); 630 return QDF_STATUS_E_INVAL; 631 } 632 633 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]); 634 635 if (!mod_param) { 636 direct_buf_rx_err("dir buf rx module param is null"); 637 return QDF_STATUS_E_FAILURE; 638 } 639 640 direct_buf_rx_info("mod_param %pK", mod_param); 641 642 mod_param->mod_id = mod_id; 643 644 /* Initialize DMA ring now */ 645 status = target_if_dbr_init_srng(pdev, mod_param); 646 if (QDF_IS_STATUS_ERROR(status)) { 647 direct_buf_rx_err("DBR ring init failed %d", status); 648 return status; 649 } 650 651 /* Send CFG request command to firmware */ 652 status = target_if_dbr_cfg_tgt(pdev, mod_param); 653 if (QDF_IS_STATUS_ERROR(status)) { 654 direct_buf_rx_err("DBR config to target failed %d", status); 655 goto dbr_srng_init_failed; 656 } 657 658 return QDF_STATUS_SUCCESS; 659 660 dbr_srng_init_failed: 661 target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_id); 662 return status; 663 } 664 665 QDF_STATUS target_if_direct_buf_rx_module_register( 666 struct wlan_objmgr_pdev *pdev, uint8_t mod_id, 667 int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, 668 struct direct_buf_rx_data *dbr_data)) 669 { 670 QDF_STATUS status; 671 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 672 673 if (pdev == NULL) { 674 direct_buf_rx_err("pdev context passed is null"); 675 return QDF_STATUS_E_INVAL; 676 } 677 678 if (dbr_rsp_handler == NULL) { 679 direct_buf_rx_err("Response handler is null"); 680 return QDF_STATUS_E_INVAL; 681 } 682 683 if (mod_id >= DBR_MODULE_MAX) { 684 direct_buf_rx_err("Invalid module id"); 685 return QDF_STATUS_E_INVAL; 686 } 687 688 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 689 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 690 691 if (dbr_pdev_obj == NULL) { 692 direct_buf_rx_err("dir buf rx object is null"); 693 return QDF_STATUS_E_FAILURE; 694 } 695 direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj); 696 697 if (!dbr_pdev_obj->dbr_mod_param && 698 (mod_id >= dbr_pdev_obj->num_modules)) { 699 direct_buf_rx_err("Module %d not supported in target", mod_id); 700 return QDF_STATUS_E_FAILURE; 701 } 702 703 dbr_pdev_obj->dbr_mod_param[mod_id].dbr_rsp_handler = 704 dbr_rsp_handler; 705 706 status = target_if_init_dbr_ring(pdev, dbr_pdev_obj, 707 (enum DBR_MODULE)mod_id); 708 709 return status; 710 } 711 712 static void *target_if_dbr_vaddr_lookup( 713 struct direct_buf_rx_module_param *mod_param, 714 qdf_dma_addr_t paddr, uint32_t cookie) 715 { 716 struct direct_buf_rx_buf_info *dbr_buf_pool; 717 718 dbr_buf_pool = mod_param->dbr_buf_pool; 719 720 if (dbr_buf_pool[cookie].paddr == paddr) { 721 return dbr_buf_pool[cookie].vaddr + 722 dbr_buf_pool[cookie].offset; 723 } 724 725 direct_buf_rx_err("Incorrect paddr found on cookie slot"); 726 return NULL; 727 } 728 729 static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, 730 struct direct_buf_rx_module_param *mod_param, 731 struct direct_buf_rx_rsp *dbr_rsp, 732 struct direct_buf_rx_data *dbr_data, 733 uint8_t idx, uint32_t *cookie) 734 { 735 qdf_dma_addr_t paddr = 0; 736 uint32_t addr_hi; 737 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 738 struct direct_buf_rx_ring_cap *dbr_ring_cap; 739 struct wlan_objmgr_psoc *psoc; 740 741 psoc = wlan_pdev_get_psoc(pdev); 742 if (!psoc) { 743 direct_buf_rx_err("psoc is null"); 744 return QDF_STATUS_E_FAILURE; 745 } 746 747 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 748 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 749 750 if (dbr_psoc_obj == NULL) { 751 direct_buf_rx_err("dir buf rx psoc object is null"); 752 return QDF_STATUS_E_FAILURE; 753 } 754 755 dbr_ring_cap = mod_param->dbr_ring_cap; 756 addr_hi = (uint64_t)WMI_HOST_DBR_DATA_ADDR_HI_GET( 757 dbr_rsp->dbr_entries[idx].paddr_hi); 758 paddr = (qdf_dma_addr_t)((uint64_t)addr_hi << 32 | 759 dbr_rsp->dbr_entries[idx].paddr_lo); 760 *cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET( 761 dbr_rsp->dbr_entries[idx].paddr_hi); 762 direct_buf_rx_info("Cookie = %d", *cookie); 763 dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie); 764 direct_buf_rx_info("Vaddr look up = %x", dbr_data->vaddr); 765 dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len; 766 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr, 767 QDF_DMA_FROM_DEVICE, 768 dbr_ring_cap->min_buf_size); 769 770 return QDF_STATUS_SUCCESS; 771 } 772 773 static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, 774 uint8_t *data_buf, 775 uint32_t data_len) 776 { 777 int ret = 0; 778 uint8_t i = 0; 779 QDF_STATUS status; 780 uint32_t cookie = 0; 781 struct direct_buf_rx_rsp dbr_rsp = {0}; 782 struct direct_buf_rx_data dbr_data = {0}; 783 struct wlan_objmgr_psoc *psoc; 784 struct wlan_objmgr_pdev *pdev; 785 struct direct_buf_rx_buf_info *dbr_buf_pool; 786 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 787 struct direct_buf_rx_module_param *mod_param; 788 789 direct_buf_rx_enter(); 790 791 psoc = target_if_get_psoc_from_scn_hdl(scn); 792 if (!psoc) { 793 direct_buf_rx_err("psoc is null"); 794 return QDF_STATUS_E_FAILURE; 795 } 796 797 if (wmi_extract_dbr_buf_release_fixed(GET_WMI_HDL_FROM_PSOC(psoc), 798 data_buf, &dbr_rsp) != QDF_STATUS_SUCCESS) { 799 direct_buf_rx_err("unable to extract DBR rsp fixed param"); 800 return QDF_STATUS_E_FAILURE; 801 } 802 803 direct_buf_rx_info("Num buf release entry = %d", 804 dbr_rsp.num_buf_release_entry); 805 806 pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id, 807 WLAN_DIRECT_BUF_RX_ID); 808 if (!pdev) { 809 direct_buf_rx_err("pdev is null"); 810 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 811 return QDF_STATUS_E_INVAL; 812 } 813 814 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 815 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 816 817 if (dbr_pdev_obj == NULL) { 818 direct_buf_rx_err("dir buf rx object is null"); 819 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 820 return QDF_STATUS_E_FAILURE; 821 } 822 823 mod_param = &(dbr_pdev_obj->dbr_mod_param[dbr_rsp.mod_id]); 824 825 if (!mod_param) { 826 direct_buf_rx_err("dir buf rx module param is null"); 827 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 828 return QDF_STATUS_E_FAILURE; 829 } 830 831 dbr_buf_pool = mod_param->dbr_buf_pool; 832 dbr_rsp.dbr_entries = qdf_mem_malloc(dbr_rsp.num_buf_release_entry * 833 sizeof(struct direct_buf_rx_entry)); 834 835 for (i = 0; i < dbr_rsp.num_buf_release_entry; i++) { 836 if (wmi_extract_dbr_buf_release_entry( 837 GET_WMI_HDL_FROM_PSOC(psoc), data_buf, i, 838 &dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) { 839 direct_buf_rx_err("Unable to extract DBR buf entry %d", 840 i+1); 841 wlan_objmgr_pdev_release_ref(pdev, 842 WLAN_DIRECT_BUF_RX_ID); 843 return QDF_STATUS_E_FAILURE; 844 } 845 status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp, 846 &dbr_data, i, &cookie); 847 848 if (QDF_IS_STATUS_ERROR(status)) { 849 direct_buf_rx_err("DBR data get failed"); 850 wlan_objmgr_pdev_release_ref(pdev, 851 WLAN_DIRECT_BUF_RX_ID); 852 return QDF_STATUS_E_FAILURE; 853 } 854 ret = mod_param->dbr_rsp_handler(pdev, &dbr_data); 855 status = target_if_dbr_replenish_ring(pdev, mod_param, 856 dbr_data.vaddr, cookie); 857 if (QDF_IS_STATUS_ERROR(status)) { 858 direct_buf_rx_err("dir buf rx ring replenish failed"); 859 wlan_objmgr_pdev_release_ref(pdev, 860 WLAN_DIRECT_BUF_RX_ID); 861 return QDF_STATUS_E_FAILURE; 862 } 863 } 864 865 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 866 867 return ret; 868 } 869 870 static QDF_STATUS target_if_dbr_empty_ring(struct wlan_objmgr_pdev *pdev, 871 struct direct_buf_rx_psoc_obj *dbr_psoc_obj, 872 struct direct_buf_rx_module_param *mod_param) 873 { 874 uint8_t idx; 875 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 876 struct direct_buf_rx_ring_cap *dbr_ring_cap; 877 struct direct_buf_rx_buf_info *dbr_buf_pool; 878 879 direct_buf_rx_enter(); 880 dbr_ring_cfg = mod_param->dbr_ring_cfg; 881 dbr_ring_cap = mod_param->dbr_ring_cap; 882 dbr_buf_pool = mod_param->dbr_buf_pool; 883 884 direct_buf_rx_info("dbr_ring_cfg %pK, dbr_ring_cap %pK dbr_buf_pool %pK", 885 dbr_ring_cfg, dbr_ring_cap, dbr_buf_pool); 886 887 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { 888 direct_buf_rx_info("dbr buf pool unmap and free for ptr %d", 889 idx); 890 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, 891 (qdf_dma_addr_t)dbr_buf_pool[idx].paddr, 892 QDF_DMA_FROM_DEVICE, 893 dbr_ring_cap->min_buf_size); 894 qdf_mem_free(dbr_buf_pool[idx].vaddr); 895 } 896 897 return QDF_STATUS_SUCCESS; 898 } 899 900 static QDF_STATUS target_if_dbr_deinit_ring(struct wlan_objmgr_pdev *pdev, 901 struct direct_buf_rx_module_param *mod_param) 902 { 903 struct wlan_objmgr_psoc *psoc; 904 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 905 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 906 907 direct_buf_rx_enter(); 908 psoc = wlan_pdev_get_psoc(pdev); 909 if (!psoc) { 910 direct_buf_rx_err("psoc is null"); 911 return QDF_STATUS_E_FAILURE; 912 } 913 914 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 915 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 916 917 if (dbr_psoc_obj == NULL) { 918 direct_buf_rx_err("dir buf rx psoc object is null"); 919 return QDF_STATUS_E_FAILURE; 920 } 921 direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj); 922 923 dbr_ring_cfg = mod_param->dbr_ring_cfg; 924 if (dbr_ring_cfg) { 925 target_if_dbr_empty_ring(pdev, dbr_psoc_obj, mod_param); 926 hal_srng_cleanup(dbr_psoc_obj->hal_soc, dbr_ring_cfg->srng); 927 qdf_mem_free_consistent(dbr_psoc_obj->osdev, 928 dbr_psoc_obj->osdev->dev, 929 dbr_ring_cfg->ring_alloc_size, 930 dbr_ring_cfg->base_vaddr_unaligned, 931 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0); 932 } 933 934 return QDF_STATUS_SUCCESS; 935 } 936 937 static QDF_STATUS target_if_dbr_deinit_srng( 938 struct wlan_objmgr_pdev *pdev, 939 struct direct_buf_rx_module_param *mod_param) 940 { 941 struct direct_buf_rx_buf_info *dbr_buf_pool; 942 943 direct_buf_rx_enter(); 944 dbr_buf_pool = mod_param->dbr_buf_pool; 945 direct_buf_rx_info("dbr buf pool %pK", dbr_buf_pool); 946 target_if_dbr_deinit_ring(pdev, mod_param); 947 qdf_mem_free(dbr_buf_pool); 948 dbr_buf_pool = NULL; 949 950 return QDF_STATUS_SUCCESS; 951 } 952 953 QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev, 954 struct direct_buf_rx_pdev_obj *dbr_pdev_obj, 955 enum DBR_MODULE mod_id) 956 { 957 struct direct_buf_rx_module_param *mod_param; 958 struct direct_buf_rx_ring_cap *dbr_ring_cap; 959 960 direct_buf_rx_enter(); 961 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]); 962 963 if (!mod_param) { 964 direct_buf_rx_err("dir buf rx module param is null"); 965 return QDF_STATUS_E_FAILURE; 966 } 967 direct_buf_rx_info("mod_param %pK", mod_param); 968 969 dbr_ring_cap = mod_param->dbr_ring_cap; 970 direct_buf_rx_info("dbr_ring_cap %pK", dbr_ring_cap); 971 target_if_dbr_deinit_srng(pdev, mod_param); 972 qdf_mem_free(dbr_ring_cap); 973 dbr_ring_cap = NULL; 974 qdf_mem_free(mod_param); 975 mod_param = NULL; 976 977 return QDF_STATUS_SUCCESS; 978 } 979 980 QDF_STATUS target_if_direct_buf_rx_register_events( 981 struct wlan_objmgr_psoc *psoc) 982 { 983 int ret; 984 985 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 986 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 987 return QDF_STATUS_E_INVAL; 988 } 989 990 ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 991 wmi_dma_buf_release_event_id, 992 target_if_direct_buf_rx_rsp_event_handler, 993 WMI_RX_UMAC_CTX); 994 995 if (ret) 996 direct_buf_rx_info("event handler not supported", ret); 997 998 return QDF_STATUS_SUCCESS; 999 } 1000 1001 QDF_STATUS target_if_direct_buf_rx_unregister_events( 1002 struct wlan_objmgr_psoc *psoc) 1003 { 1004 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 1005 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 1006 return QDF_STATUS_E_INVAL; 1007 } 1008 1009 wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 1010 wmi_dma_buf_release_event_id); 1011 1012 return QDF_STATUS_SUCCESS; 1013 } 1014