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