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 QDF_STATUS status; 305 306 direct_buf_rx_enter(); 307 308 dbr_ring_cfg = mod_param->dbr_ring_cfg; 309 dbr_ring_cap = mod_param->dbr_ring_cap; 310 dbr_buf_pool = mod_param->dbr_buf_pool; 311 312 psoc = wlan_pdev_get_psoc(pdev); 313 314 if (!psoc) { 315 direct_buf_rx_err("psoc is null"); 316 return QDF_STATUS_E_FAILURE; 317 } 318 319 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 320 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 321 322 if (dbr_psoc_obj == NULL) { 323 direct_buf_rx_err("dir buf rx psoc object is null"); 324 return QDF_STATUS_E_FAILURE; 325 } 326 327 hal_soc = dbr_psoc_obj->hal_soc; 328 srng = dbr_ring_cfg->srng; 329 if (!aligned_vaddr) { 330 direct_buf_rx_err("aligned vaddr is null"); 331 return QDF_STATUS_SUCCESS; 332 } 333 334 map_status = qdf_mem_map_nbytes_single(dbr_psoc_obj->osdev, 335 aligned_vaddr, 336 QDF_DMA_FROM_DEVICE, 337 dbr_ring_cap->min_buf_size, 338 &paddr); 339 if (map_status) { 340 direct_buf_rx_err("mem map failed status = %d", status); 341 return QDF_STATUS_E_FAILURE; 342 } 343 344 QDF_ASSERT(!((uint64_t)paddr & dbr_ring_cap->min_buf_align)); 345 dbr_buf_pool[cookie].paddr = paddr; 346 347 hal_srng_access_start(hal_soc, srng); 348 ring_entry = hal_srng_src_get_next(hal_soc, srng); 349 QDF_ASSERT(ring_entry != NULL); 350 dw_lo = (uint64_t)paddr & 0xFFFFFFFF; 351 WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32); 352 WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie); 353 direct_buf_rx_info("Cookie = %d", cookie); 354 direct_buf_rx_info("dw_lo = %x dw_hi = %x", dw_lo, dw_hi); 355 *ring_entry = (uint64_t)dw_hi << 32 | dw_lo; 356 direct_buf_rx_info("Valid ring entry"); 357 hal_srng_access_end(hal_soc, srng); 358 359 return QDF_STATUS_SUCCESS; 360 } 361 362 static QDF_STATUS target_if_dbr_fill_ring(struct wlan_objmgr_pdev *pdev, 363 struct direct_buf_rx_module_param *mod_param) 364 { 365 uint8_t idx; 366 void *buf, *buf_aligned; 367 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 368 struct direct_buf_rx_ring_cap *dbr_ring_cap; 369 struct direct_buf_rx_buf_info *dbr_buf_pool; 370 QDF_STATUS status; 371 372 direct_buf_rx_enter(); 373 374 dbr_ring_cfg = mod_param->dbr_ring_cfg; 375 dbr_ring_cap = mod_param->dbr_ring_cap; 376 dbr_buf_pool = mod_param->dbr_buf_pool; 377 378 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { 379 buf = qdf_mem_malloc(dbr_ring_cap->min_buf_size + 380 dbr_ring_cap->min_buf_align - 1); 381 if (!buf) { 382 direct_buf_rx_err("dir buf rx ring buf alloc failed"); 383 return QDF_STATUS_E_NOMEM; 384 } 385 dbr_buf_pool[idx].vaddr = buf; 386 buf_aligned = (void *)(uintptr_t)qdf_roundup( 387 (uint64_t)(uintptr_t)buf, DBR_RING_BASE_ALIGN); 388 dbr_buf_pool[idx].offset = buf_aligned - buf; 389 dbr_buf_pool[idx].cookie = idx; 390 status = target_if_dbr_replenish_ring(pdev, mod_param, 391 buf_aligned, idx); 392 if (QDF_IS_STATUS_ERROR(status)) { 393 direct_buf_rx_err("replenish failed with status : %d", 394 status); 395 qdf_mem_free(buf); 396 return QDF_STATUS_E_FAILURE; 397 } 398 } 399 400 return QDF_STATUS_SUCCESS; 401 } 402 403 static QDF_STATUS target_if_dbr_init_ring(struct wlan_objmgr_pdev *pdev, 404 struct direct_buf_rx_module_param *mod_param) 405 { 406 void *srng; 407 uint32_t num_entries, ring_alloc_size, max_entries, entry_size; 408 qdf_dma_addr_t paddr; 409 struct hal_srng_params ring_params = {0}; 410 struct wlan_objmgr_psoc *psoc; 411 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 412 struct direct_buf_rx_ring_cap *dbr_ring_cap; 413 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 414 QDF_STATUS status; 415 416 direct_buf_rx_enter(); 417 418 psoc = wlan_pdev_get_psoc(pdev); 419 420 if (!psoc) { 421 direct_buf_rx_err("psoc is null"); 422 return QDF_STATUS_E_FAILURE; 423 } 424 425 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 426 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 427 428 if (dbr_psoc_obj == NULL) { 429 direct_buf_rx_err("dir buf rx psoc object is null"); 430 return QDF_STATUS_E_FAILURE; 431 } 432 433 if (dbr_psoc_obj->hal_soc == NULL || 434 dbr_psoc_obj->osdev == NULL) { 435 direct_buf_rx_err("dir buf rx target attach failed"); 436 return QDF_STATUS_E_FAILURE; 437 } 438 439 max_entries = hal_srng_max_entries(dbr_psoc_obj->hal_soc, 440 DIR_BUF_RX_DMA_SRC); 441 entry_size = hal_srng_get_entrysize(dbr_psoc_obj->hal_soc, 442 DIR_BUF_RX_DMA_SRC); 443 direct_buf_rx_info("Max Entries = %d", max_entries); 444 direct_buf_rx_info("Entry Size = %d", entry_size); 445 446 status = populate_dbr_cap_mod_param(pdev, mod_param); 447 if (QDF_IS_STATUS_ERROR(status)) { 448 direct_buf_rx_err("Module cap population failed"); 449 return QDF_STATUS_E_FAILURE; 450 } 451 452 dbr_ring_cap = mod_param->dbr_ring_cap; 453 dbr_ring_cfg = mod_param->dbr_ring_cfg; 454 num_entries = dbr_ring_cap->ring_elems_min > max_entries ? 455 max_entries : dbr_ring_cap->ring_elems_min; 456 direct_buf_rx_info("Num entries = %d", num_entries); 457 dbr_ring_cfg->num_ptr = num_entries; 458 mod_param->dbr_buf_pool = qdf_mem_malloc(num_entries * sizeof( 459 struct direct_buf_rx_buf_info)); 460 if (!mod_param->dbr_buf_pool) { 461 direct_buf_rx_err("dir buf rx buf pool alloc failed"); 462 return QDF_STATUS_E_NOMEM; 463 } 464 465 ring_alloc_size = (num_entries * entry_size) + DBR_RING_BASE_ALIGN - 1; 466 dbr_ring_cfg->ring_alloc_size = ring_alloc_size; 467 direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj); 468 dbr_ring_cfg->base_vaddr_unaligned = qdf_mem_alloc_consistent( 469 dbr_psoc_obj->osdev, dbr_psoc_obj->osdev->dev, ring_alloc_size, 470 &paddr); 471 direct_buf_rx_info("vaddr aligned allocated"); 472 dbr_ring_cfg->base_paddr_unaligned = paddr; 473 if (!dbr_ring_cfg->base_vaddr_unaligned) { 474 direct_buf_rx_err("dir buf rx vaddr alloc failed"); 475 qdf_mem_free(mod_param->dbr_buf_pool); 476 return QDF_STATUS_E_NOMEM; 477 } 478 479 /* Alignment is defined to 8 for now. Will be advertised by FW */ 480 dbr_ring_cfg->base_vaddr_aligned = (void *)(uintptr_t)qdf_roundup( 481 (uint64_t)(uintptr_t)dbr_ring_cfg->base_vaddr_unaligned, 482 DBR_RING_BASE_ALIGN); 483 ring_params.ring_base_vaddr = dbr_ring_cfg->base_vaddr_aligned; 484 dbr_ring_cfg->base_paddr_aligned = qdf_roundup( 485 (uint64_t)dbr_ring_cfg->base_paddr_unaligned, 486 DBR_RING_BASE_ALIGN); 487 ring_params.ring_base_paddr = 488 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_aligned; 489 ring_params.num_entries = num_entries; 490 srng = hal_srng_setup(dbr_psoc_obj->hal_soc, DIR_BUF_RX_DMA_SRC, 0, 491 wlan_objmgr_pdev_get_pdev_id(pdev), &ring_params); 492 493 if (!srng) { 494 direct_buf_rx_err("srng setup failed"); 495 qdf_mem_free(mod_param->dbr_buf_pool); 496 qdf_mem_free_consistent(dbr_psoc_obj->osdev, 497 dbr_psoc_obj->osdev->dev, 498 ring_alloc_size, 499 dbr_ring_cfg->base_vaddr_unaligned, 500 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0); 501 return QDF_STATUS_E_FAILURE; 502 } 503 dbr_ring_cfg->srng = srng; 504 dbr_ring_cfg->tail_idx_addr = 505 hal_srng_get_tp_addr(dbr_psoc_obj->hal_soc, srng); 506 dbr_ring_cfg->head_idx_addr = 507 hal_srng_get_hp_addr(dbr_psoc_obj->hal_soc, srng); 508 dbr_ring_cfg->buf_size = dbr_ring_cap->min_buf_size; 509 510 return target_if_dbr_fill_ring(pdev, mod_param); 511 } 512 513 static QDF_STATUS target_if_dbr_init_srng(struct wlan_objmgr_pdev *pdev, 514 struct direct_buf_rx_module_param *mod_param) 515 { 516 QDF_STATUS status; 517 518 direct_buf_rx_info("Init DBR srng"); 519 520 if (!mod_param) { 521 direct_buf_rx_err("dir buf rx module param is null"); 522 return QDF_STATUS_E_INVAL; 523 } 524 525 mod_param->dbr_ring_cap = qdf_mem_malloc(sizeof( 526 struct direct_buf_rx_ring_cap)); 527 528 if (!mod_param->dbr_ring_cap) { 529 direct_buf_rx_err("Ring cap alloc failed"); 530 return QDF_STATUS_E_NOMEM; 531 } 532 533 /* Allocate memory for DBR Ring Config */ 534 mod_param->dbr_ring_cfg = qdf_mem_malloc(sizeof( 535 struct direct_buf_rx_ring_cfg)); 536 537 if (!mod_param->dbr_ring_cfg) { 538 direct_buf_rx_err("Ring config alloc failed"); 539 qdf_mem_free(mod_param->dbr_ring_cap); 540 return QDF_STATUS_E_NOMEM; 541 } 542 543 status = target_if_dbr_init_ring(pdev, mod_param); 544 545 if (QDF_IS_STATUS_ERROR(status)) { 546 direct_buf_rx_err("DBR ring init failed"); 547 qdf_mem_free(mod_param->dbr_ring_cfg); 548 qdf_mem_free(mod_param->dbr_ring_cap); 549 return QDF_STATUS_E_FAILURE; 550 } 551 552 return QDF_STATUS_SUCCESS; 553 } 554 555 static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev, 556 struct direct_buf_rx_module_param *mod_param) 557 { 558 QDF_STATUS status; 559 struct wlan_objmgr_psoc *psoc; 560 void *wmi_hdl; 561 struct direct_buf_rx_cfg_req dbr_cfg_req = {0}; 562 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 563 struct direct_buf_rx_ring_cap *dbr_ring_cap; 564 565 direct_buf_rx_enter(); 566 567 psoc = wlan_pdev_get_psoc(pdev); 568 if (!psoc) { 569 direct_buf_rx_err("psoc is null"); 570 return QDF_STATUS_E_FAILURE; 571 } 572 573 dbr_ring_cfg = mod_param->dbr_ring_cfg; 574 dbr_ring_cap = mod_param->dbr_ring_cap; 575 wmi_hdl = ucfg_get_pdev_wmi_handle(pdev); 576 if (!wmi_hdl) { 577 direct_buf_rx_err("WMI handle null. Can't send WMI CMD"); 578 return QDF_STATUS_E_INVAL; 579 } 580 581 direct_buf_rx_debug("Sending DBR Ring CFG to target"); 582 dbr_cfg_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 583 /* Module ID numbering starts from 1 in FW. need to fix it */ 584 dbr_cfg_req.mod_id = mod_param->mod_id; 585 dbr_cfg_req.base_paddr_lo = (uint64_t)dbr_ring_cfg->base_paddr_aligned 586 & 0xFFFFFFFF; 587 dbr_cfg_req.base_paddr_hi = (uint64_t)dbr_ring_cfg->base_paddr_aligned 588 & 0xFFFFFFFF00000000; 589 dbr_cfg_req.head_idx_paddr_lo = (uint64_t)dbr_ring_cfg->head_idx_addr 590 & 0xFFFFFFFF; 591 dbr_cfg_req.head_idx_paddr_hi = (uint64_t)dbr_ring_cfg->head_idx_addr 592 & 0xFFFFFFFF00000000; 593 dbr_cfg_req.tail_idx_paddr_lo = (uint64_t)dbr_ring_cfg->tail_idx_addr 594 & 0xFFFFFFFF; 595 dbr_cfg_req.tail_idx_paddr_hi = (uint64_t)dbr_ring_cfg->tail_idx_addr 596 & 0xFFFFFFFF00000000; 597 dbr_cfg_req.num_elems = dbr_ring_cap->ring_elems_min; 598 dbr_cfg_req.buf_size = dbr_ring_cap->min_buf_size; 599 dbr_cfg_req.num_resp_per_event = DBR_NUM_RESP_PER_EVENT; 600 dbr_cfg_req.event_timeout_ms = DBR_EVENT_TIMEOUT_IN_MS; 601 direct_buf_rx_info("pdev id %d mod id %d base addr lo %x\n" 602 "base addr hi %x head idx addr lo %x\n" 603 "head idx addr hi %x tail idx addr lo %x\n" 604 "tail idx addr hi %x num ptr %d\n" 605 "num resp %d event timeout %d\n", 606 dbr_cfg_req.pdev_id, dbr_cfg_req.mod_id, 607 dbr_cfg_req.base_paddr_lo, dbr_cfg_req.base_paddr_hi, 608 dbr_cfg_req.head_idx_paddr_lo, 609 dbr_cfg_req.head_idx_paddr_hi, 610 dbr_cfg_req.tail_idx_paddr_lo, 611 dbr_cfg_req.tail_idx_paddr_hi, 612 dbr_cfg_req.num_elems, 613 dbr_cfg_req.num_resp_per_event, 614 dbr_cfg_req.event_timeout_ms); 615 status = wmi_unified_dbr_ring_cfg(wmi_hdl, &dbr_cfg_req); 616 617 return status; 618 } 619 620 static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev, 621 struct direct_buf_rx_pdev_obj *dbr_pdev_obj, 622 enum DBR_MODULE mod_id) 623 { 624 QDF_STATUS status = QDF_STATUS_SUCCESS; 625 struct direct_buf_rx_module_param *mod_param; 626 627 direct_buf_rx_info("Init DBR ring for module %d", mod_id); 628 629 if (!dbr_pdev_obj) { 630 direct_buf_rx_err("dir buf rx object is null"); 631 return QDF_STATUS_E_INVAL; 632 } 633 634 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]); 635 636 if (!mod_param) { 637 direct_buf_rx_err("dir buf rx module param is null"); 638 return QDF_STATUS_E_FAILURE; 639 } 640 641 direct_buf_rx_info("mod_param %pK", mod_param); 642 643 mod_param->mod_id = mod_id; 644 645 /* Initialize DMA ring now */ 646 status = target_if_dbr_init_srng(pdev, mod_param); 647 if (QDF_IS_STATUS_ERROR(status)) { 648 direct_buf_rx_err("DBR ring init failed %d", status); 649 return status; 650 } 651 652 /* Send CFG request command to firmware */ 653 status = target_if_dbr_cfg_tgt(pdev, mod_param); 654 if (QDF_IS_STATUS_ERROR(status)) { 655 direct_buf_rx_err("DBR config to target failed %d", status); 656 goto dbr_srng_init_failed; 657 } 658 659 return QDF_STATUS_SUCCESS; 660 661 dbr_srng_init_failed: 662 target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_id); 663 return status; 664 } 665 666 QDF_STATUS target_if_direct_buf_rx_module_register( 667 struct wlan_objmgr_pdev *pdev, uint8_t mod_id, 668 int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, 669 struct direct_buf_rx_data *dbr_data)) 670 { 671 QDF_STATUS status; 672 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 673 674 if (pdev == NULL) { 675 direct_buf_rx_err("pdev context passed is null"); 676 return QDF_STATUS_E_INVAL; 677 } 678 679 if (dbr_rsp_handler == NULL) { 680 direct_buf_rx_err("Response handler is null"); 681 return QDF_STATUS_E_INVAL; 682 } 683 684 if (mod_id >= DBR_MODULE_MAX) { 685 direct_buf_rx_err("Invalid module id"); 686 return QDF_STATUS_E_INVAL; 687 } 688 689 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 690 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 691 692 if (dbr_pdev_obj == NULL) { 693 direct_buf_rx_err("dir buf rx object is null"); 694 return QDF_STATUS_E_FAILURE; 695 } 696 direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj); 697 698 dbr_pdev_obj->dbr_mod_param[mod_id].dbr_rsp_handler = 699 dbr_rsp_handler; 700 701 status = target_if_init_dbr_ring(pdev, dbr_pdev_obj, 702 (enum DBR_MODULE)mod_id); 703 704 return status; 705 } 706 707 static void *target_if_dbr_vaddr_lookup( 708 struct direct_buf_rx_module_param *mod_param, 709 qdf_dma_addr_t paddr, uint32_t cookie) 710 { 711 struct direct_buf_rx_buf_info *dbr_buf_pool; 712 713 dbr_buf_pool = mod_param->dbr_buf_pool; 714 715 if (dbr_buf_pool[cookie].paddr == paddr) { 716 return dbr_buf_pool[cookie].vaddr + 717 dbr_buf_pool[cookie].offset; 718 } 719 720 direct_buf_rx_err("Incorrect paddr found on cookie slot"); 721 return NULL; 722 } 723 724 static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, 725 struct direct_buf_rx_module_param *mod_param, 726 struct direct_buf_rx_rsp *dbr_rsp, 727 struct direct_buf_rx_data *dbr_data, 728 uint8_t idx, uint32_t *cookie) 729 { 730 qdf_dma_addr_t paddr = 0; 731 uint32_t addr_hi; 732 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 733 struct direct_buf_rx_ring_cap *dbr_ring_cap; 734 struct wlan_objmgr_psoc *psoc; 735 736 psoc = wlan_pdev_get_psoc(pdev); 737 if (!psoc) { 738 direct_buf_rx_err("psoc is null"); 739 return QDF_STATUS_E_FAILURE; 740 } 741 742 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 743 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 744 745 if (dbr_psoc_obj == NULL) { 746 direct_buf_rx_err("dir buf rx psoc object is null"); 747 return QDF_STATUS_E_FAILURE; 748 } 749 750 dbr_ring_cap = mod_param->dbr_ring_cap; 751 addr_hi = (uint64_t)WMI_HOST_DBR_DATA_ADDR_HI_GET( 752 dbr_rsp->dbr_entries[idx].paddr_hi); 753 paddr = (qdf_dma_addr_t)((uint64_t)addr_hi << 32 | 754 dbr_rsp->dbr_entries[idx].paddr_lo); 755 *cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET( 756 dbr_rsp->dbr_entries[idx].paddr_hi); 757 direct_buf_rx_info("Cookie = %d", *cookie); 758 dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie); 759 direct_buf_rx_info("Vaddr look up = %x", dbr_data->vaddr); 760 dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len; 761 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr, 762 QDF_DMA_FROM_DEVICE, 763 dbr_ring_cap->min_buf_size); 764 765 return QDF_STATUS_SUCCESS; 766 } 767 768 static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, 769 uint8_t *data_buf, 770 uint32_t data_len) 771 { 772 int ret; 773 uint8_t i = 0; 774 QDF_STATUS status; 775 uint32_t cookie = 0; 776 struct direct_buf_rx_rsp dbr_rsp = {0}; 777 struct direct_buf_rx_data dbr_data = {0}; 778 struct wlan_objmgr_psoc *psoc; 779 struct wlan_objmgr_pdev *pdev; 780 struct direct_buf_rx_buf_info *dbr_buf_pool; 781 struct direct_buf_rx_pdev_obj *dbr_pdev_obj; 782 struct direct_buf_rx_module_param *mod_param; 783 784 direct_buf_rx_enter(); 785 786 psoc = target_if_get_psoc_from_scn_hdl(scn); 787 if (!psoc) { 788 direct_buf_rx_err("psoc is null"); 789 return QDF_STATUS_E_FAILURE; 790 } 791 792 if (wmi_extract_dbr_buf_release_fixed(GET_WMI_HDL_FROM_PSOC(psoc), 793 data_buf, &dbr_rsp) != QDF_STATUS_SUCCESS) { 794 direct_buf_rx_err("unable to extract DBR rsp fixed param"); 795 return QDF_STATUS_E_FAILURE; 796 } 797 798 direct_buf_rx_info("Num buf release entry = %d", 799 dbr_rsp.num_buf_release_entry); 800 801 pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id, 802 WLAN_DIRECT_BUF_RX_ID); 803 if (!pdev) { 804 direct_buf_rx_err("pdev is null"); 805 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 806 return QDF_STATUS_E_INVAL; 807 } 808 809 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, 810 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 811 812 if (dbr_pdev_obj == NULL) { 813 direct_buf_rx_err("dir buf rx object is null"); 814 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 815 return QDF_STATUS_E_FAILURE; 816 } 817 818 mod_param = &(dbr_pdev_obj->dbr_mod_param[dbr_rsp.mod_id]); 819 820 if (!mod_param) { 821 direct_buf_rx_err("dir buf rx module param is null"); 822 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 823 return QDF_STATUS_E_FAILURE; 824 } 825 826 dbr_buf_pool = mod_param->dbr_buf_pool; 827 dbr_rsp.dbr_entries = qdf_mem_malloc(dbr_rsp.num_buf_release_entry * 828 sizeof(struct direct_buf_rx_entry)); 829 830 for (i = 0; i < dbr_rsp.num_buf_release_entry; i++) { 831 if (wmi_extract_dbr_buf_release_entry( 832 GET_WMI_HDL_FROM_PSOC(psoc), data_buf, i, 833 &dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) { 834 direct_buf_rx_err("Unable to extract DBR buf entry %d", 835 i+1); 836 wlan_objmgr_pdev_release_ref(pdev, 837 WLAN_DIRECT_BUF_RX_ID); 838 return QDF_STATUS_E_FAILURE; 839 } 840 status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp, 841 &dbr_data, i, &cookie); 842 843 if (QDF_IS_STATUS_ERROR(status)) { 844 direct_buf_rx_err("DBR data get failed"); 845 wlan_objmgr_pdev_release_ref(pdev, 846 WLAN_DIRECT_BUF_RX_ID); 847 return QDF_STATUS_E_FAILURE; 848 } 849 ret = mod_param->dbr_rsp_handler(pdev, &dbr_data); 850 status = target_if_dbr_replenish_ring(pdev, mod_param, 851 dbr_data.vaddr, cookie); 852 if (QDF_IS_STATUS_ERROR(status)) { 853 direct_buf_rx_err("dir buf rx ring replenish failed"); 854 wlan_objmgr_pdev_release_ref(pdev, 855 WLAN_DIRECT_BUF_RX_ID); 856 return QDF_STATUS_E_FAILURE; 857 } 858 } 859 860 wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); 861 862 return ret; 863 } 864 865 static QDF_STATUS target_if_dbr_empty_ring(struct wlan_objmgr_pdev *pdev, 866 struct direct_buf_rx_psoc_obj *dbr_psoc_obj, 867 struct direct_buf_rx_module_param *mod_param) 868 { 869 uint8_t idx; 870 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 871 struct direct_buf_rx_ring_cap *dbr_ring_cap; 872 struct direct_buf_rx_buf_info *dbr_buf_pool; 873 874 direct_buf_rx_enter(); 875 dbr_ring_cfg = mod_param->dbr_ring_cfg; 876 dbr_ring_cap = mod_param->dbr_ring_cap; 877 dbr_buf_pool = mod_param->dbr_buf_pool; 878 879 direct_buf_rx_info("dbr_ring_cfg %pK, dbr_ring_cap %pK dbr_buf_pool %pK", 880 dbr_ring_cfg, dbr_ring_cap, dbr_buf_pool); 881 882 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { 883 direct_buf_rx_info("dbr buf pool unmap and free for ptr %d", 884 idx); 885 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, 886 (qdf_dma_addr_t)dbr_buf_pool[idx].paddr, 887 QDF_DMA_FROM_DEVICE, 888 dbr_ring_cap->min_buf_size); 889 qdf_mem_free(dbr_buf_pool[idx].vaddr); 890 } 891 892 return QDF_STATUS_SUCCESS; 893 } 894 895 static QDF_STATUS target_if_dbr_deinit_ring(struct wlan_objmgr_pdev *pdev, 896 struct direct_buf_rx_module_param *mod_param) 897 { 898 struct wlan_objmgr_psoc *psoc; 899 struct direct_buf_rx_psoc_obj *dbr_psoc_obj; 900 struct direct_buf_rx_ring_cfg *dbr_ring_cfg; 901 902 direct_buf_rx_enter(); 903 psoc = wlan_pdev_get_psoc(pdev); 904 if (!psoc) { 905 direct_buf_rx_err("psoc is null"); 906 return QDF_STATUS_E_FAILURE; 907 } 908 909 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 910 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); 911 912 if (dbr_psoc_obj == NULL) { 913 direct_buf_rx_err("dir buf rx psoc object is null"); 914 return QDF_STATUS_E_FAILURE; 915 } 916 direct_buf_rx_info("dbr_psoc_obj %pK", dbr_psoc_obj); 917 918 dbr_ring_cfg = mod_param->dbr_ring_cfg; 919 if (dbr_ring_cfg) { 920 target_if_dbr_empty_ring(pdev, dbr_psoc_obj, mod_param); 921 hal_srng_cleanup(dbr_psoc_obj->hal_soc, dbr_ring_cfg->srng); 922 qdf_mem_free_consistent(dbr_psoc_obj->osdev, 923 dbr_psoc_obj->osdev->dev, 924 dbr_ring_cfg->ring_alloc_size, 925 dbr_ring_cfg->base_vaddr_unaligned, 926 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0); 927 } 928 929 return QDF_STATUS_SUCCESS; 930 } 931 932 static QDF_STATUS target_if_dbr_deinit_srng( 933 struct wlan_objmgr_pdev *pdev, 934 struct direct_buf_rx_module_param *mod_param) 935 { 936 struct direct_buf_rx_buf_info *dbr_buf_pool; 937 938 direct_buf_rx_enter(); 939 dbr_buf_pool = mod_param->dbr_buf_pool; 940 direct_buf_rx_info("dbr buf pool %pK", dbr_buf_pool); 941 target_if_dbr_deinit_ring(pdev, mod_param); 942 qdf_mem_free(dbr_buf_pool); 943 dbr_buf_pool = NULL; 944 945 return QDF_STATUS_SUCCESS; 946 } 947 948 QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev, 949 struct direct_buf_rx_pdev_obj *dbr_pdev_obj, 950 enum DBR_MODULE mod_id) 951 { 952 struct direct_buf_rx_module_param *mod_param; 953 struct direct_buf_rx_ring_cap *dbr_ring_cap; 954 QDF_STATUS status; 955 956 direct_buf_rx_enter(); 957 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id]); 958 959 if (!mod_param) { 960 direct_buf_rx_err("dir buf rx module param is null"); 961 return QDF_STATUS_E_FAILURE; 962 } 963 direct_buf_rx_info("mod_param %pK", mod_param); 964 965 dbr_ring_cap = mod_param->dbr_ring_cap; 966 direct_buf_rx_info("dbr_ring_cap %pK", dbr_ring_cap); 967 target_if_dbr_deinit_srng(pdev, mod_param); 968 qdf_mem_free(dbr_ring_cap); 969 dbr_ring_cap = NULL; 970 qdf_mem_free(mod_param); 971 mod_param = NULL; 972 973 return status; 974 } 975 976 QDF_STATUS target_if_direct_buf_rx_register_events( 977 struct wlan_objmgr_psoc *psoc) 978 { 979 int ret; 980 981 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 982 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 983 return QDF_STATUS_E_INVAL; 984 } 985 986 ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 987 wmi_dma_buf_release_event_id, 988 target_if_direct_buf_rx_rsp_event_handler, 989 WMI_RX_UMAC_CTX); 990 991 if (ret) 992 direct_buf_rx_info("event handler not supported", ret); 993 994 return QDF_STATUS_SUCCESS; 995 } 996 997 QDF_STATUS target_if_direct_buf_rx_unregister_events( 998 struct wlan_objmgr_psoc *psoc) 999 { 1000 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { 1001 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null"); 1002 return QDF_STATUS_E_INVAL; 1003 } 1004 1005 wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc), 1006 wmi_dma_buf_release_event_id); 1007 1008 return QDF_STATUS_SUCCESS; 1009 } 1010