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 dbr_pdev_obj->dbr_mod_param[mod_id].dbr_rsp_handler = 698 dbr_rsp_handler; 699 700 status = target_if_init_dbr_ring(pdev, dbr_pdev_obj, 701 (enum DBR_MODULE)mod_id); 702 703 return status; 704 } 705 706 static void *target_if_dbr_vaddr_lookup( 707 struct direct_buf_rx_module_param *mod_param, 708 qdf_dma_addr_t paddr, uint32_t cookie) 709 { 710 struct direct_buf_rx_buf_info *dbr_buf_pool; 711 712 dbr_buf_pool = mod_param->dbr_buf_pool; 713 714 if (dbr_buf_pool[cookie].paddr == paddr) { 715 return dbr_buf_pool[cookie].vaddr + 716 dbr_buf_pool[cookie].offset; 717 } 718 719 direct_buf_rx_err("Incorrect paddr found on cookie slot"); 720 return NULL; 721 } 722 723 static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, 724 struct direct_buf_rx_module_param *mod_param, 725 struct direct_buf_rx_rsp *dbr_rsp, 726 struct direct_buf_rx_data *dbr_data, 727 uint8_t idx, uint32_t *cookie) 728 { 729 qdf_dma_addr_t paddr = 0; 730 uint32_t addr_hi; 731 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 732 struct direct_buf_rx_ring_cap *dbr_ring_cap; 733 struct wlan_objmgr_psoc *psoc; 734 735 psoc = wlan_pdev_get_psoc(pdev); 736 if (!psoc) { 737 direct_buf_rx_err("psoc is null"); 738 return QDF_STATUS_E_FAILURE; 739 } 740 741 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 742 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 743 744 if (dbr_psoc_obj == NULL) { 745 direct_buf_rx_err("dir buf rx psoc object is null"); 746 return QDF_STATUS_E_FAILURE; 747 } 748 749 dbr_ring_cap = mod_param->dbr_ring_cap; 750 addr_hi = (uint64_t)WMI_HOST_DBR_DATA_ADDR_HI_GET( 751 dbr_rsp->dbr_entries[idx].paddr_hi); 752 paddr = (qdf_dma_addr_t)((uint64_t)addr_hi << 32 | 753 dbr_rsp->dbr_entries[idx].paddr_lo); 754 *cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET( 755 dbr_rsp->dbr_entries[idx].paddr_hi); 756 direct_buf_rx_info("Cookie = %d", *cookie); 757 dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie); 758 direct_buf_rx_info("Vaddr look up = %x", dbr_data->vaddr); 759 dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len; 760 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr, 761 QDF_DMA_FROM_DEVICE, 762 dbr_ring_cap->min_buf_size); 763 764 return QDF_STATUS_SUCCESS; 765 } 766 767 static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, 768 uint8_t *data_buf, 769 uint32_t data_len) 770 { 771 int ret = 0; 772 uint8_t i = 0; 773 QDF_STATUS status; 774 uint32_t cookie = 0; 775 struct direct_buf_rx_rsp dbr_rsp = {0}; 776 struct direct_buf_rx_data dbr_data = {0}; 777 struct wlan_objmgr_psoc *psoc; 778 struct wlan_objmgr_pdev *pdev; 779 struct direct_buf_rx_buf_info *dbr_buf_pool; 780 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 781 struct direct_buf_rx_module_param *mod_param; 782 783 direct_buf_rx_enter(); 784 785 psoc = target_if_get_psoc_from_scn_hdl(scn); 786 if (!psoc) { 787 direct_buf_rx_err("psoc is null"); 788 return QDF_STATUS_E_FAILURE; 789 } 790 791 if (wmi_extract_dbr_buf_release_fixed(GET_WMI_HDL_FROM_PSOC(psoc), 792 data_buf, &dbr_rsp) != QDF_STATUS_SUCCESS) { 793 direct_buf_rx_err("unable to extract DBR rsp fixed param"); 794 return QDF_STATUS_E_FAILURE; 795 } 796 797 direct_buf_rx_info("Num buf release entry = %d", 798 dbr_rsp.num_buf_release_entry); 799 800 pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id, 801 WLAN_DIRECT_BUF_RX_ID); 802 if (!pdev) { 803 direct_buf_rx_err("pdev is null"); 804 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 805 return QDF_STATUS_E_INVAL; 806 } 807 808 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 809 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 810 811 if (dbr_pdev_obj == NULL) { 812 direct_buf_rx_err("dir buf rx object is null"); 813 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 814 return QDF_STATUS_E_FAILURE; 815 } 816 817 mod_param = &(dbr_pdev_obj->dbr_mod_param[dbr_rsp.mod_id]); 818 819 if (!mod_param) { 820 direct_buf_rx_err("dir buf rx module param is null"); 821 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 822 return QDF_STATUS_E_FAILURE; 823 } 824 825 dbr_buf_pool = mod_param->dbr_buf_pool; 826 dbr_rsp.dbr_entries = qdf_mem_malloc(dbr_rsp.num_buf_release_entry * 827 sizeof(struct direct_buf_rx_entry)); 828 829 for (i = 0; i < dbr_rsp.num_buf_release_entry; i++) { 830 if (wmi_extract_dbr_buf_release_entry( 831 GET_WMI_HDL_FROM_PSOC(psoc), data_buf, i, 832 &dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) { 833 direct_buf_rx_err("Unable to extract DBR buf entry %d", 834 i+1); 835 wlan_objmgr_pdev_release_ref(pdev, 836 WLAN_DIRECT_BUF_RX_ID); 837 return QDF_STATUS_E_FAILURE; 838 } 839 status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp, 840 &dbr_data, i, &cookie); 841 842 if (QDF_IS_STATUS_ERROR(status)) { 843 direct_buf_rx_err("DBR data get failed"); 844 wlan_objmgr_pdev_release_ref(pdev, 845 WLAN_DIRECT_BUF_RX_ID); 846 return QDF_STATUS_E_FAILURE; 847 } 848 ret = mod_param->dbr_rsp_handler(pdev, &dbr_data); 849 status = target_if_dbr_replenish_ring(pdev, mod_param, 850 dbr_data.vaddr, cookie); 851 if (QDF_IS_STATUS_ERROR(status)) { 852 direct_buf_rx_err("dir buf rx ring replenish failed"); 853 wlan_objmgr_pdev_release_ref(pdev, 854 WLAN_DIRECT_BUF_RX_ID); 855 return QDF_STATUS_E_FAILURE; 856 } 857 } 858 859 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 860 861 return ret; 862 } 863 864 static QDF_STATUS target_if_dbr_empty_ring(struct wlan_objmgr_pdev *pdev, 865 struct direct_buf_rx_psoc_obj *dbr_psoc_obj, 866 struct direct_buf_rx_module_param *mod_param) 867 { 868 uint8_t idx; 869 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 870 struct direct_buf_rx_ring_cap *dbr_ring_cap; 871 struct direct_buf_rx_buf_info *dbr_buf_pool; 872 873 direct_buf_rx_enter(); 874 dbr_ring_cfg = mod_param->dbr_ring_cfg; 875 dbr_ring_cap = mod_param->dbr_ring_cap; 876 dbr_buf_pool = mod_param->dbr_buf_pool; 877 878 direct_buf_rx_info("dbr_ring_cfg %pK, dbr_ring_cap %pK dbr_buf_pool %pK", 879 dbr_ring_cfg, dbr_ring_cap, dbr_buf_pool); 880 881 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { 882 direct_buf_rx_info("dbr buf pool unmap and free for ptr %d", 883 idx); 884 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, 885 (qdf_dma_addr_t)dbr_buf_pool[idx].paddr, 886 QDF_DMA_FROM_DEVICE, 887 dbr_ring_cap->min_buf_size); 888 qdf_mem_free(dbr_buf_pool[idx].vaddr); 889 } 890 891 return QDF_STATUS_SUCCESS; 892 } 893 894 static QDF_STATUS target_if_dbr_deinit_ring(struct wlan_objmgr_pdev *pdev, 895 struct direct_buf_rx_module_param *mod_param) 896 { 897 struct wlan_objmgr_psoc *psoc; 898 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 899 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 900 901 direct_buf_rx_enter(); 902 psoc = wlan_pdev_get_psoc(pdev); 903 if (!psoc) { 904 direct_buf_rx_err("psoc is null"); 905 return QDF_STATUS_E_FAILURE; 906 } 907 908 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 909 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 910 911 if (dbr_psoc_obj == NULL) { 912 direct_buf_rx_err("dir buf rx psoc object is null"); 913 return QDF_STATUS_E_FAILURE; 914 } 915 direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj); 916 917 dbr_ring_cfg = mod_param->dbr_ring_cfg; 918 if (dbr_ring_cfg) { 919 target_if_dbr_empty_ring(pdev, dbr_psoc_obj, mod_param); 920 hal_srng_cleanup(dbr_psoc_obj->hal_soc, dbr_ring_cfg->srng); 921 qdf_mem_free_consistent(dbr_psoc_obj->osdev, 922 dbr_psoc_obj->osdev->dev, 923 dbr_ring_cfg->ring_alloc_size, 924 dbr_ring_cfg->base_vaddr_unaligned, 925 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0); 926 } 927 928 return QDF_STATUS_SUCCESS; 929 } 930 931 static QDF_STATUS target_if_dbr_deinit_srng( 932 struct wlan_objmgr_pdev *pdev, 933 struct direct_buf_rx_module_param *mod_param) 934 { 935 struct direct_buf_rx_buf_info *dbr_buf_pool; 936 937 direct_buf_rx_enter(); 938 dbr_buf_pool = mod_param->dbr_buf_pool; 939 direct_buf_rx_info("dbr buf pool %pK", dbr_buf_pool); 940 target_if_dbr_deinit_ring(pdev, mod_param); 941 qdf_mem_free(dbr_buf_pool); 942 dbr_buf_pool = NULL; 943 944 return QDF_STATUS_SUCCESS; 945 } 946 947 QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev, 948 struct direct_buf_rx_pdev_obj *dbr_pdev_obj, 949 enum DBR_MODULE mod_id) 950 { 951 struct direct_buf_rx_module_param *mod_param; 952 struct direct_buf_rx_ring_cap *dbr_ring_cap; 953 954 direct_buf_rx_enter(); 955 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]); 956 957 if (!mod_param) { 958 direct_buf_rx_err("dir buf rx module param is null"); 959 return QDF_STATUS_E_FAILURE; 960 } 961 direct_buf_rx_info("mod_param %pK", mod_param); 962 963 dbr_ring_cap = mod_param->dbr_ring_cap; 964 direct_buf_rx_info("dbr_ring_cap %pK", dbr_ring_cap); 965 target_if_dbr_deinit_srng(pdev, mod_param); 966 qdf_mem_free(dbr_ring_cap); 967 dbr_ring_cap = NULL; 968 qdf_mem_free(mod_param); 969 mod_param = NULL; 970 971 return QDF_STATUS_SUCCESS; 972 } 973 974 QDF_STATUS target_if_direct_buf_rx_register_events( 975 struct wlan_objmgr_psoc *psoc) 976 { 977 int ret; 978 979 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 980 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 981 return QDF_STATUS_E_INVAL; 982 } 983 984 ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 985 wmi_dma_buf_release_event_id, 986 target_if_direct_buf_rx_rsp_event_handler, 987 WMI_RX_UMAC_CTX); 988 989 if (ret) 990 direct_buf_rx_info("event handler not supported", ret); 991 992 return QDF_STATUS_SUCCESS; 993 } 994 995 QDF_STATUS target_if_direct_buf_rx_unregister_events( 996 struct wlan_objmgr_psoc *psoc) 997 { 998 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 999 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 1000 return QDF_STATUS_E_INVAL; 1001 } 1002 1003 wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 1004 wmi_dma_buf_release_event_id); 1005 1006 return QDF_STATUS_SUCCESS; 1007 } 1008