1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "target_if.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 /**
29 * struct module_name : Module name information structure
30 * @module_name_str : Module name subscribing to DBR
31 */
32 struct module_name {
33 unsigned char module_name_str[QDF_MAX_NAME_SIZE];
34 };
35
36 static const struct module_name g_dbr_module_name[DBR_MODULE_MAX] = {
37 [DBR_MODULE_SPECTRAL] = {"SPECTRAL"},
38 [DBR_MODULE_CFR] = {"CFR"},
39 [DBR_MODULE_CBF] = {"CBF"},
40 };
41
get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev * pdev)42 static uint8_t get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev *pdev)
43 {
44 struct wlan_objmgr_psoc *psoc;
45 struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap;
46 uint8_t num_dbr_ring_caps, cap_idx, pdev_id, num_modules;
47 struct target_psoc_info *tgt_psoc_info;
48
49 psoc = wlan_pdev_get_psoc(pdev);
50
51 if (!psoc) {
52 direct_buf_rx_err("psoc is null");
53 return 0;
54 }
55
56 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
57 if (!tgt_psoc_info) {
58 direct_buf_rx_err("target_psoc_info is null");
59 return 0;
60 }
61 num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info);
62 dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info);
63 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
64 num_modules = 0;
65
66 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
67 if (dbr_ring_cap[cap_idx].pdev_id == pdev_id)
68 num_modules++;
69 }
70
71 return num_modules;
72 }
73
populate_dbr_cap_mod_param(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)74 static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev,
75 struct direct_buf_rx_module_param *mod_param)
76 {
77 struct wlan_objmgr_psoc *psoc;
78 struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap;
79 uint8_t cap_idx;
80 bool cap_found = false;
81 enum DBR_MODULE mod_id = mod_param->mod_id;
82 uint32_t num_dbr_ring_caps, pdev_id;
83 struct target_psoc_info *tgt_psoc_info;
84
85 psoc = wlan_pdev_get_psoc(pdev);
86
87 if (!psoc) {
88 direct_buf_rx_err("psoc is null");
89 return QDF_STATUS_E_INVAL;
90 }
91
92 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
93 if (!tgt_psoc_info) {
94 direct_buf_rx_err("target_psoc_info is null");
95 return QDF_STATUS_E_INVAL;
96 }
97
98 num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info);
99 dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info);
100 pdev_id = mod_param->pdev_id;
101
102 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
103 if (dbr_ring_cap[cap_idx].pdev_id == pdev_id) {
104 if (dbr_ring_cap[cap_idx].mod_id == mod_id) {
105 mod_param->dbr_ring_cap->ring_elems_min =
106 dbr_ring_cap[cap_idx].ring_elems_min;
107 mod_param->dbr_ring_cap->min_buf_size =
108 dbr_ring_cap[cap_idx].min_buf_size;
109 mod_param->dbr_ring_cap->min_buf_align =
110 dbr_ring_cap[cap_idx].min_buf_align;
111 cap_found = true;
112 }
113 }
114 }
115
116 if (!cap_found) {
117 direct_buf_rx_err("No cap found for module %d in pdev %d",
118 mod_id, pdev_id);
119 return QDF_STATUS_E_FAILURE;
120 }
121
122 return QDF_STATUS_SUCCESS;
123 }
124 #ifdef DIRECT_BUF_RX_DEBUG
125 static inline struct direct_buf_rx_module_debug *
target_if_get_dbr_mod_debug_from_dbr_pdev_obj(struct direct_buf_rx_pdev_obj * dbr_pdev_obj,uint8_t mod_id)126 target_if_get_dbr_mod_debug_from_dbr_pdev_obj(
127 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
128 uint8_t mod_id)
129 {
130 if (!dbr_pdev_obj) {
131 direct_buf_rx_err("dir buf rx object is null");
132 return NULL;
133 }
134
135 if (mod_id >= DBR_MODULE_MAX) {
136 direct_buf_rx_err("Invalid module id");
137 return NULL;
138 }
139
140 if (!dbr_pdev_obj->dbr_mod_debug) {
141 direct_buf_rx_err("dbr_pdev_obj->dbr_mod_debug is NULL");
142 return NULL;
143 }
144
145 if (mod_id >= dbr_pdev_obj->num_modules) {
146 direct_buf_rx_err("Module %d not supported in target", mod_id);
147 return NULL;
148 }
149 return &dbr_pdev_obj->dbr_mod_debug[mod_id];
150 }
151
152 static inline struct direct_buf_rx_module_debug *
target_if_get_dbr_mod_debug_from_pdev(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)153 target_if_get_dbr_mod_debug_from_pdev(
154 struct wlan_objmgr_pdev *pdev,
155 uint8_t mod_id)
156 {
157 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
158
159 if (!pdev) {
160 direct_buf_rx_err("pdev is null");
161 return NULL;
162 }
163
164 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
165 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
166
167 return target_if_get_dbr_mod_debug_from_dbr_pdev_obj(
168 dbr_pdev_obj, mod_id);
169 }
170 #endif
171
172 #ifdef DIRECT_BUF_RX_DEBUG
173 #define RING_DEBUG_EVENT_NAME_SIZE 12
174 static const unsigned char
175 g_dbr_ring_debug_event[DBR_RING_DEBUG_EVENT_MAX][RING_DEBUG_EVENT_NAME_SIZE] = {
176 [DBR_RING_DEBUG_EVENT_RX] = "Rx",
177 [DBR_RING_DEBUG_EVENT_REPLENISH_RING] = "Replenish",
178 };
179
180 /**
181 * target_if_dbr_print_ring_debug_entries() - Print ring debug entries
182 * @print: The print adapter function
183 * @print_priv: The private data to be consumed by @print
184 * @dbr_pdev_obj: Pdev object of the DBR module
185 * @mod_id: Module ID
186 * @srng_id: ring id
187 *
188 * Print ring debug entries of the ring identified by @dbr_pdev_obj and @mod_id
189 * using the given print adapter function
190 *
191 * Return: QDF_STATUS of operation
192 */
target_if_dbr_print_ring_debug_entries(qdf_abstract_print print,void * print_priv,struct direct_buf_rx_pdev_obj * dbr_pdev_obj,uint8_t mod_id,uint8_t srng_id)193 static QDF_STATUS target_if_dbr_print_ring_debug_entries(
194 qdf_abstract_print print, void *print_priv,
195 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
196 uint8_t mod_id, uint8_t srng_id)
197 {
198 struct direct_buf_rx_module_debug *mod_debug;
199 struct direct_buf_rx_ring_debug *ring_debug;
200 int idx;
201
202 mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
203 mod_id);
204 if (!mod_debug)
205 return QDF_STATUS_E_INVAL;
206
207 mod_debug = &dbr_pdev_obj->dbr_mod_debug[mod_id];
208 ring_debug = &mod_debug->dbr_ring_debug[srng_id];
209
210 if (ring_debug->entries) {
211 print(print_priv, "Current debug entry is %d",
212 ring_debug->ring_debug_idx);
213 print(print_priv, "---------------------------------------------------------");
214 print(print_priv, "| Number | Head Idx | Tail Idx | Timestamp | event |");
215 print(print_priv, "---------------------------------------------------------");
216 for (idx = 0; idx < ring_debug->num_ring_debug_entries; ++idx) {
217 print(print_priv, "|%8u|%10u|%10u|%11llu|%12s|", idx,
218 ring_debug->entries[idx].head_idx,
219 ring_debug->entries[idx].tail_idx,
220 ring_debug->entries[idx].timestamp,
221 g_dbr_ring_debug_event[
222 ring_debug->entries[idx].event]);
223 }
224 print(print_priv, "---------------------------------------------------------");
225 }
226
227 return QDF_STATUS_SUCCESS;
228 }
229
230 /**
231 * target_if_dbr_qdf_err_printer() - QDF error level printer for DBR module
232 * @priv: The private data
233 * @fmt: Format string
234 *
235 * This function should be passed in place of the 'print' argument to
236 * target_if_dbr_print_ring_debug_entries function for the logs that should be
237 * printed via QDF trace
238 *
239 * Return: QDF_STATUS of operation
240 */
target_if_dbr_qdf_err_printer(void * priv,const char * fmt,...)241 static int target_if_dbr_qdf_err_printer(void *priv, const char *fmt, ...)
242 {
243 va_list args;
244
245 va_start(args, fmt);
246 QDF_VTRACE(QDF_MODULE_ID_DIRECT_BUF_RX, QDF_TRACE_LEVEL_ERROR,
247 (char *)fmt, args);
248 va_end(args);
249
250 return 0;
251 }
252
target_if_direct_buf_rx_free_mod_debug(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)253 static inline void target_if_direct_buf_rx_free_mod_debug(
254 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
255 {
256 if (!dbr_pdev_obj) {
257 direct_buf_rx_err("dir buf rx object is null");
258 return;
259 }
260 /* Free the debug data structures of all modules */
261 if (dbr_pdev_obj->dbr_mod_debug) {
262 qdf_mem_free(dbr_pdev_obj->dbr_mod_debug);
263 dbr_pdev_obj->dbr_mod_debug = NULL;
264 }
265 }
266
target_if_direct_buf_rx_alloc_mod_debug(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)267 static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug(
268 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
269 {
270 if (!dbr_pdev_obj) {
271 direct_buf_rx_err("dir buf rx object is null");
272 return QDF_STATUS_E_FAILURE;
273 }
274 /* Allocate the debug data structure for each module */
275 dbr_pdev_obj->dbr_mod_debug = qdf_mem_malloc(
276 dbr_pdev_obj->num_modules *
277 sizeof(struct direct_buf_rx_module_debug));
278
279 if (!dbr_pdev_obj->dbr_mod_debug)
280 return QDF_STATUS_E_NOMEM;
281
282 return QDF_STATUS_SUCCESS;
283 }
284 #else
target_if_direct_buf_rx_alloc_mod_debug(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)285 static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug(
286 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
287 {
288 return QDF_STATUS_SUCCESS;
289 }
290
target_if_direct_buf_rx_free_mod_debug(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)291 static inline void target_if_direct_buf_rx_free_mod_debug(
292 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
293 {
294 }
295 #endif
296
297 #if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
target_if_direct_buf_pdev_debugfs_init(struct wlan_objmgr_pdev * pdev)298 static inline void target_if_direct_buf_pdev_debugfs_init(
299 struct wlan_objmgr_pdev *pdev)
300 {
301 char dir_name[32];
302 struct wlan_objmgr_psoc *psoc;
303 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
304
305 if (!pdev) {
306 direct_buf_rx_err("pdev is null");
307 return;
308 }
309
310 psoc = wlan_pdev_get_psoc(pdev);
311 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
312 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
313
314 if (!dbr_pdev_obj) {
315 direct_buf_rx_err("dir buf rx object is null");
316 return;
317 }
318
319 qdf_snprintf(dir_name, sizeof(dir_name), "SOC%u_PDEV%u",
320 wlan_psoc_get_id(psoc),
321 wlan_objmgr_pdev_get_pdev_id(pdev));
322
323 /* Create debugfs entry for this radio */
324 dbr_pdev_obj->debugfs_entry = qdf_debugfs_create_dir(
325 dir_name, dbr_debugfs_entry);
326
327 if (!dbr_pdev_obj->debugfs_entry)
328 direct_buf_rx_err("error while creating direct_buf debugfs dir");
329 }
330
target_if_direct_buf_pdev_debugfs_deinit(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)331 static inline void target_if_direct_buf_pdev_debugfs_deinit(
332 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
333 {
334 if (!dbr_pdev_obj) {
335 direct_buf_rx_err("dir buf rx object is null");
336 return;
337 }
338 /* Remove the debugfs entry of the radio */
339 if (dbr_pdev_obj->debugfs_entry) {
340 qdf_debugfs_remove_dir_recursive(dbr_pdev_obj->debugfs_entry);
341 dbr_pdev_obj->debugfs_entry = NULL;
342 }
343 }
344 #else
target_if_direct_buf_pdev_debugfs_init(struct wlan_objmgr_pdev * pdev)345 static inline void target_if_direct_buf_pdev_debugfs_init(
346 struct wlan_objmgr_pdev *pdev)
347 {
348 }
349
target_if_direct_buf_pdev_debugfs_deinit(struct direct_buf_rx_pdev_obj * dbr_pdev_obj)350 static inline void target_if_direct_buf_pdev_debugfs_deinit(
351 struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
352 {
353 }
354 #endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
355
target_if_direct_buf_rx_pdev_create_handler(struct wlan_objmgr_pdev * pdev,void * data)356 QDF_STATUS target_if_direct_buf_rx_pdev_create_handler(
357 struct wlan_objmgr_pdev *pdev, void *data)
358 {
359 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
360 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
361 struct wlan_objmgr_psoc *psoc;
362 uint8_t num_modules;
363 QDF_STATUS status;
364
365 direct_buf_rx_enter();
366
367 if (!pdev) {
368 direct_buf_rx_err("pdev context passed is null");
369 return QDF_STATUS_E_INVAL;
370 }
371
372 psoc = wlan_pdev_get_psoc(pdev);
373
374 if (!psoc) {
375 direct_buf_rx_err("psoc is null");
376 return QDF_STATUS_E_INVAL;
377 }
378
379 dbr_psoc_obj =
380 wlan_objmgr_psoc_get_comp_private_obj(psoc,
381 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
382
383 if (!dbr_psoc_obj) {
384 direct_buf_rx_err("dir buf rx psoc object is null");
385 return QDF_STATUS_E_FAILURE;
386 }
387
388 dbr_pdev_obj = qdf_mem_malloc(sizeof(*dbr_pdev_obj));
389
390 if (!dbr_pdev_obj)
391 return QDF_STATUS_E_NOMEM;
392
393 status = wlan_objmgr_pdev_component_obj_attach(pdev,
394 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
395 dbr_pdev_obj, QDF_STATUS_SUCCESS);
396
397 if (status != QDF_STATUS_SUCCESS) {
398 direct_buf_rx_err("Failed to attach dir buf rx component %d",
399 status);
400 qdf_mem_free(dbr_pdev_obj);
401 return status;
402 }
403
404 dbr_psoc_obj->dbr_pdev_obj[wlan_objmgr_pdev_get_pdev_id(pdev)] =
405 dbr_pdev_obj;
406
407 num_modules = get_num_dbr_modules_per_pdev(pdev);
408 direct_buf_rx_debug("Number of modules = %d pdev %d DBR pdev obj %pK",
409 num_modules, wlan_objmgr_pdev_get_pdev_id(pdev),
410 dbr_pdev_obj);
411 dbr_pdev_obj->num_modules = num_modules;
412
413 if (!dbr_pdev_obj->num_modules) {
414 direct_buf_rx_info("Number of modules = %d", num_modules);
415 return QDF_STATUS_SUCCESS;
416 }
417
418 direct_buf_rx_debug("sring number = %d", DBR_SRNG_NUM);
419 dbr_pdev_obj->dbr_mod_param = qdf_mem_malloc(num_modules *
420 DBR_SRNG_NUM *
421 sizeof(struct direct_buf_rx_module_param));
422
423 if (!dbr_pdev_obj->dbr_mod_param) {
424 direct_buf_rx_err("alloc dbr mod param fail");
425 goto dbr_mod_param_fail;
426 }
427
428 if (target_if_direct_buf_rx_alloc_mod_debug(dbr_pdev_obj) !=
429 QDF_STATUS_SUCCESS)
430 goto dbr_mod_debug_fail;
431
432 target_if_direct_buf_pdev_debugfs_init(pdev);
433
434 return QDF_STATUS_SUCCESS;
435
436 dbr_mod_debug_fail:
437 qdf_mem_free(dbr_pdev_obj->dbr_mod_param);
438
439 dbr_mod_param_fail:
440 wlan_objmgr_pdev_component_obj_detach(
441 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
442 dbr_pdev_obj);
443 qdf_mem_free(dbr_pdev_obj);
444
445 return QDF_STATUS_E_NOMEM;
446 }
447
target_if_direct_buf_rx_pdev_destroy_handler(struct wlan_objmgr_pdev * pdev,void * data)448 QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler(
449 struct wlan_objmgr_pdev *pdev, void *data)
450 {
451 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
452 QDF_STATUS status;
453 uint8_t num_modules, mod_idx, srng_id;
454
455 if (!pdev) {
456 direct_buf_rx_err("pdev context passed is null");
457 return QDF_STATUS_E_INVAL;
458 }
459
460 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
461 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
462
463 if (!dbr_pdev_obj) {
464 direct_buf_rx_err("dir buf rx object is null");
465 return QDF_STATUS_E_FAILURE;
466 }
467
468 num_modules = dbr_pdev_obj->num_modules;
469 for (mod_idx = 0; mod_idx < num_modules; mod_idx++) {
470 /*
471 * If the module didn't stop the ring debug by this time,
472 * it will result in memory leak of its ring debug entries.
473 * So, stop the ring debug
474 */
475 target_if_dbr_stop_ring_debug(pdev, mod_idx);
476 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++)
477 target_if_deinit_dbr_ring(pdev, dbr_pdev_obj,
478 mod_idx, srng_id);
479 }
480
481 target_if_direct_buf_pdev_debugfs_deinit(dbr_pdev_obj);
482 target_if_direct_buf_rx_free_mod_debug(dbr_pdev_obj);
483 qdf_mem_free(dbr_pdev_obj->dbr_mod_param);
484 dbr_pdev_obj->dbr_mod_param = NULL;
485
486 status = wlan_objmgr_pdev_component_obj_detach(pdev,
487 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
488 dbr_pdev_obj);
489
490 if (status != QDF_STATUS_SUCCESS) {
491 direct_buf_rx_err("failed to detach dir buf rx component %d",
492 status);
493 }
494
495 qdf_mem_free(dbr_pdev_obj);
496
497 return status;
498 }
499
500 #if defined(DBR_HOLD_LARGE_MEM) && defined(CNSS_MEM_PRE_ALLOC)
501 /**
502 * struct direct_buf_rx_large_mem - large memory for DBR
503 * @node: large memory node
504 * @size: Size of the memory
505 * @vaddr_unaligned: unaligned base address of the memory
506 * @offset: offset between unaligned vaddr and aligned vaddr
507 * @align: Base address alignment
508 */
509 struct direct_buf_rx_large_mem {
510 qdf_list_node_t node;
511 uint32_t size;
512 void *vaddr_unaligned;
513 uint8_t offset;
514 uint32_t align;
515 };
516
517 /* check if the actual buffer_size/base_address_alignment match the request */
518 #define DBR_MEM_NODE_MATCH(_actual_align, _actual_size, _req_align, _req_size) \
519 ((_actual_align) == (_req_align) && \
520 ((_actual_size) == (_req_size) || \
521 (_actual_size) == ((_req_size) + (_req_align) - 1)))
522
523 /*
524 * Memory with a size(in bytes) equal or larger than this threshold will be
525 * hold during the entire PSOC lifetime.
526 * MUST equal or larger than the allocation threshold in cnss_prealloc module.
527 */
528 #define TARGET_IF_DBR_HOLD_MEM_THRESHOLD (8 * 1024)
529
530 /**
531 * target_if_dbr_init_mem_list() - init the large memory list for DBR
532 * @dbr_psoc_obj: pointer to direct buffer rx module psoc obj
533 *
534 * Return: None
535 */
536 static void
target_if_dbr_init_mem_list(struct direct_buf_rx_psoc_obj * dbr_psoc_obj)537 target_if_dbr_init_mem_list(struct direct_buf_rx_psoc_obj *dbr_psoc_obj)
538 {
539 int i;
540
541 qdf_spinlock_create(&dbr_psoc_obj->mem_list_lock);
542 qdf_spin_lock_bh(&dbr_psoc_obj->mem_list_lock);
543 for (i = 0; i < QDF_ARRAY_SIZE(dbr_psoc_obj->mem_list); i++)
544 qdf_list_create(&dbr_psoc_obj->mem_list[i], 0);
545
546 qdf_spin_unlock_bh(&dbr_psoc_obj->mem_list_lock);
547 }
548
549 /**
550 * target_if_dbr_deinit_mem_list() - deinit the large memory list for DBR
551 * @dbr_psoc_obj: pointer to direct buffer rx module psoc obj
552 *
553 * Return: None
554 */
555 static void
target_if_dbr_deinit_mem_list(struct direct_buf_rx_psoc_obj * dbr_psoc_obj)556 target_if_dbr_deinit_mem_list(struct direct_buf_rx_psoc_obj *dbr_psoc_obj)
557 {
558 struct direct_buf_rx_large_mem *cur, *next;
559 qdf_list_t *mem_list;
560 int i;
561
562 qdf_spin_lock_bh(&dbr_psoc_obj->mem_list_lock);
563 for (i = 0; i < QDF_ARRAY_SIZE(dbr_psoc_obj->mem_list); i++) {
564 mem_list = &dbr_psoc_obj->mem_list[i];
565 qdf_list_for_each_del(mem_list, cur, next, node) {
566 qdf_list_remove_node(mem_list, &cur->node);
567 qdf_mem_free(cur->vaddr_unaligned);
568 }
569
570 qdf_list_destroy(mem_list);
571 }
572
573 qdf_spin_unlock_bh(&dbr_psoc_obj->mem_list_lock);
574 qdf_spinlock_destroy(&dbr_psoc_obj->mem_list_lock);
575 }
576
577 /**
578 * target_if_dbr_mem_add() - allocate a new element for large memory list
579 * @dbr_psoc_obj: pointer to direct buffer rx module psoc obj
580 * @pdev_id: PDEV id
581 * @size: Size of the memory to be assigned to the new element
582 * @vaddr_unaligned: unaligned base address of the memory
583 * @offset: offset between unaligned vaddr and aligned vaddr
584 * @align: Base address alignment
585 *
586 * Return: None
587 */
588 static void
target_if_dbr_mem_add(struct direct_buf_rx_psoc_obj * dbr_psoc_obj,uint8_t pdev_id,uint32_t size,void * vaddr_unaligned,uint8_t offset,uint32_t align)589 target_if_dbr_mem_add(struct direct_buf_rx_psoc_obj *dbr_psoc_obj,
590 uint8_t pdev_id, uint32_t size, void *vaddr_unaligned,
591 uint8_t offset, uint32_t align)
592 {
593 struct direct_buf_rx_large_mem *new_node;
594 uint32_t list_size;
595
596 new_node = vaddr_unaligned;
597 qdf_mem_zero(new_node, sizeof(*new_node));
598 new_node->size = size;
599 new_node->vaddr_unaligned = vaddr_unaligned;
600 new_node->offset = offset;
601 new_node->align = align;
602
603 qdf_spin_lock_bh(&dbr_psoc_obj->mem_list_lock);
604 qdf_list_insert_back(&dbr_psoc_obj->mem_list[pdev_id],
605 &new_node->node);
606 list_size = qdf_list_size(&dbr_psoc_obj->mem_list[pdev_id]);
607 qdf_spin_unlock_bh(&dbr_psoc_obj->mem_list_lock);
608 }
609
610 /**
611 * target_if_dbr_mem_get() - get aligned memory
612 * @pdev: pointer to pdev object
613 * @size: Size to be allocated
614 * @offset: offset between unaligned vaddr and aligned vaddr
615 * @align: Base address alignment
616 * @mod_id: DBR module id (enum DBR_MODULE)
617 *
618 * If size to be allocated is equal or smaller than the threshold, this
619 * function will allocate the aligned memory dynamically;
620 * If NOT, it will search the saved memory list, return the one which meet the
621 * requirement, otherwise, allocate the aligned memory dynamically.
622 *
623 * Return:
624 * Unaligned base address of the memory on succeed, NULL otherwise.
625 */
626 static void *
target_if_dbr_mem_get(struct wlan_objmgr_pdev * pdev,uint32_t * size,uint8_t * offset,uint32_t align,uint32_t mod_id)627 target_if_dbr_mem_get(struct wlan_objmgr_pdev *pdev, uint32_t *size,
628 uint8_t *offset, uint32_t align, uint32_t mod_id)
629 {
630 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
631 struct wlan_objmgr_psoc *psoc;
632 struct direct_buf_rx_large_mem *cur, *next;
633 void *vaddr_unaligned = NULL, *vaddr_aligned;
634 dma_addr_t paddr_aligned, paddr_unaligned;
635 QDF_STATUS status;
636 qdf_list_t *mem_list;
637 uint8_t pdev_id;
638
639 if (*size < TARGET_IF_DBR_HOLD_MEM_THRESHOLD) {
640 vaddr_aligned = qdf_aligned_malloc(size, &vaddr_unaligned,
641 &paddr_unaligned,
642 &paddr_aligned, align);
643 if (!vaddr_aligned)
644 return NULL;
645
646 *offset = vaddr_aligned - vaddr_unaligned;
647
648 return vaddr_unaligned;
649 }
650
651 if (!pdev) {
652 direct_buf_rx_err("pdev context passed is null");
653 return vaddr_unaligned;
654 }
655
656 psoc = wlan_pdev_get_psoc(pdev);
657
658 if (!psoc) {
659 direct_buf_rx_err("psoc is null");
660 return vaddr_unaligned;
661 }
662
663 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
664 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
665
666 if (!dbr_psoc_obj) {
667 direct_buf_rx_err("dir buf rx psoc object is null");
668 return vaddr_unaligned;
669 }
670
671 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
672 qdf_spin_lock_bh(&dbr_psoc_obj->mem_list_lock);
673 mem_list = &dbr_psoc_obj->mem_list[pdev_id];
674 qdf_list_for_each_del(mem_list, cur, next, node) {
675 if (DBR_MEM_NODE_MATCH(cur->align, cur->size, align, *size)) {
676 status = qdf_list_remove_node(mem_list, &cur->node);
677 if (QDF_IS_STATUS_ERROR(status)) {
678 direct_buf_rx_err("failed to remove node: %d",
679 status);
680 break;
681 }
682
683 *offset = cur->offset;
684 *size = cur->size;
685 vaddr_unaligned = cur->vaddr_unaligned;
686 break;
687 }
688 }
689 qdf_spin_unlock_bh(&dbr_psoc_obj->mem_list_lock);
690
691 if (vaddr_unaligned) {
692 qdf_mem_zero(vaddr_unaligned, *size);
693 return vaddr_unaligned;
694 }
695
696 vaddr_aligned =
697 qdf_aligned_malloc(size, &vaddr_unaligned, &paddr_unaligned,
698 &paddr_aligned, align);
699 if (!vaddr_aligned)
700 return NULL;
701
702 *offset = vaddr_aligned - vaddr_unaligned;
703 return vaddr_unaligned;
704 }
705
706 /**
707 * target_if_dbr_mem_put() - put aligned memory
708 * @pdev: pointer to pdev object
709 * @size: size of the memory to be put
710 * @vaddr_unaligned: unaligned base address of the memory
711 * @offset: offset between unaligned vaddr and aligned vaddr
712 * @align: Base address alignment
713 * @mod_id: DBR module id (enum DBR_MODULE)
714 *
715 * If size to be allocated is equal or smaller than the threshold, this
716 * function will free the memory directly;
717 * If NOT, it will search the saved memory list, mark the one which meet the
718 * requirement as NOT in use; and if no element is found, free the memory.
719 *
720 * Return: None
721 */
722 static void
target_if_dbr_mem_put(struct wlan_objmgr_pdev * pdev,uint32_t size,void * vaddr_unaligned,uint8_t offset,uint32_t align,uint32_t mod_id)723 target_if_dbr_mem_put(struct wlan_objmgr_pdev *pdev, uint32_t size,
724 void *vaddr_unaligned, uint8_t offset,
725 uint32_t align, uint32_t mod_id)
726 {
727 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
728 struct wlan_objmgr_psoc *psoc;
729
730 if (!vaddr_unaligned)
731 return;
732
733 if (size < TARGET_IF_DBR_HOLD_MEM_THRESHOLD) {
734 qdf_mem_free(vaddr_unaligned);
735 return;
736 }
737
738 if (!pdev) {
739 direct_buf_rx_err("pdev context passed is null");
740 return;
741 }
742
743 psoc = wlan_pdev_get_psoc(pdev);
744 if (!psoc) {
745 direct_buf_rx_err("psoc is null");
746 return;
747 }
748
749 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
750 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
751 if (!dbr_psoc_obj) {
752 direct_buf_rx_err("dir buf rx psoc object is null");
753 return;
754 }
755
756 target_if_dbr_mem_add(dbr_psoc_obj, wlan_objmgr_pdev_get_pdev_id(pdev),
757 size, vaddr_unaligned, offset, align);
758 }
759 #else
760 static inline void
target_if_dbr_init_mem_list(struct direct_buf_rx_psoc_obj * dbr_psoc_obj)761 target_if_dbr_init_mem_list(struct direct_buf_rx_psoc_obj *dbr_psoc_obj)
762 {
763 }
764
765 static inline void
target_if_dbr_deinit_mem_list(struct direct_buf_rx_psoc_obj * dbr_psoc_obj)766 target_if_dbr_deinit_mem_list(struct direct_buf_rx_psoc_obj *dbr_psoc_obj)
767 {
768 }
769
770 static void *
target_if_dbr_mem_get(struct wlan_objmgr_pdev * pdev,uint32_t * size,uint8_t * offset,uint32_t align,uint32_t mod_id)771 target_if_dbr_mem_get(struct wlan_objmgr_pdev *pdev, uint32_t *size,
772 uint8_t *offset, uint32_t align, uint32_t mod_id)
773 {
774 void *vaddr_unaligned = NULL, *vaddr_aligned;
775 dma_addr_t paddr_aligned, paddr_unaligned;
776
777 vaddr_aligned = qdf_aligned_malloc(size, &vaddr_unaligned,
778 &paddr_unaligned, &paddr_aligned,
779 align);
780 if (!vaddr_aligned)
781 return NULL;
782
783 *offset = vaddr_aligned - vaddr_unaligned;
784 return vaddr_unaligned;
785 }
786
787 static inline void
target_if_dbr_mem_put(struct wlan_objmgr_pdev * pdev,uint32_t size,void * vaddr_unaligned,uint8_t offset,uint32_t align,uint32_t mod_id)788 target_if_dbr_mem_put(struct wlan_objmgr_pdev *pdev, uint32_t size,
789 void *vaddr_unaligned, uint8_t offset,
790 uint32_t align, uint32_t mod_id)
791 {
792 qdf_mem_free(vaddr_unaligned);
793 }
794 #endif /* DBR_HOLD_LARGE_MEM */
795
target_if_direct_buf_rx_psoc_create_handler(struct wlan_objmgr_psoc * psoc,void * data)796 QDF_STATUS target_if_direct_buf_rx_psoc_create_handler(
797 struct wlan_objmgr_psoc *psoc, void *data)
798 {
799 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
800 QDF_STATUS status;
801
802 direct_buf_rx_enter();
803
804 if (!psoc) {
805 direct_buf_rx_err("psoc context passed is null");
806 return QDF_STATUS_E_INVAL;
807 }
808
809 dbr_psoc_obj = qdf_mem_malloc(sizeof(*dbr_psoc_obj));
810
811 if (!dbr_psoc_obj)
812 return QDF_STATUS_E_NOMEM;
813
814 direct_buf_rx_debug("Dbr psoc obj %pK", dbr_psoc_obj);
815
816 target_if_dbr_init_mem_list(dbr_psoc_obj);
817
818 status = wlan_objmgr_psoc_component_obj_attach(psoc,
819 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, dbr_psoc_obj,
820 QDF_STATUS_SUCCESS);
821
822 if (status != QDF_STATUS_SUCCESS) {
823 direct_buf_rx_err("Failed to attach dir buf rx component %d",
824 status);
825 goto attach_error;
826 }
827
828 dbr_psoc_obj->handler_ctx = WMI_RX_UMAC_CTX;
829
830 return status;
831
832 attach_error:
833 qdf_mem_free(dbr_psoc_obj);
834
835 return status;
836 }
837
target_if_direct_buf_rx_psoc_destroy_handler(struct wlan_objmgr_psoc * psoc,void * data)838 QDF_STATUS target_if_direct_buf_rx_psoc_destroy_handler(
839 struct wlan_objmgr_psoc *psoc, void *data)
840 {
841 QDF_STATUS status;
842 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
843
844 direct_buf_rx_enter();
845
846 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
847 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
848
849 if (!dbr_psoc_obj) {
850 direct_buf_rx_err("dir buf rx psoc obj is null");
851 return QDF_STATUS_E_FAILURE;
852 }
853
854 target_if_dbr_deinit_mem_list(dbr_psoc_obj);
855 status = wlan_objmgr_psoc_component_obj_detach(psoc,
856 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
857 dbr_psoc_obj);
858
859 if (status != QDF_STATUS_SUCCESS) {
860 direct_buf_rx_err("failed to detach dir buf rx component %d",
861 status);
862 }
863
864 qdf_mem_free(dbr_psoc_obj);
865
866 return status;
867 }
868
869 #if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
870 /**
871 * target_if_dbr_debugfs_show_ring_debug() - Function to display ring debug
872 * entries in debugfs
873 * @file: qdf debugfs file handler
874 * @arg: pointer to DBR debugfs private object
875 *
876 * Return: QDF_STATUS of operation
877 */
target_if_dbr_debugfs_show_ring_debug(qdf_debugfs_file_t file,void * arg)878 static QDF_STATUS target_if_dbr_debugfs_show_ring_debug(
879 qdf_debugfs_file_t file, void *arg)
880 {
881 struct dbr_debugfs_priv *priv = arg;
882
883 return target_if_dbr_print_ring_debug_entries(qdf_debugfs_printer,
884 file, priv->dbr_pdev_obj,
885 priv->mod_id,
886 priv->srng_id);
887 }
888
889 /**
890 * target_if_dbr_mod_debugfs_init() - Init debugfs for a given module
891 * @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module
892 * @mod_id: Module ID corresponding to this ring
893 *
894 * Return: QDF_STATUS of operation
895 */
target_if_dbr_mod_debugfs_init(struct direct_buf_rx_pdev_obj * dbr_pdev_obj,enum DBR_MODULE mod_id)896 static QDF_STATUS target_if_dbr_mod_debugfs_init(
897 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
898 enum DBR_MODULE mod_id)
899 {
900 struct direct_buf_rx_module_debug *mod_debug;
901
902 mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
903 mod_id);
904
905 if (!mod_debug)
906 return QDF_STATUS_E_INVAL;
907
908 if (mod_debug->debugfs_entry) {
909 direct_buf_rx_err("debugfs mod entry was already created for %s module",
910 g_dbr_module_name[mod_id].module_name_str);
911 return QDF_STATUS_SUCCESS;
912 }
913
914 mod_debug->debugfs_entry =
915 qdf_debugfs_create_dir(g_dbr_module_name[mod_id].module_name_str,
916 dbr_pdev_obj->debugfs_entry);
917
918 if (!mod_debug->debugfs_entry) {
919 direct_buf_rx_err("error while creating direct_buf debugfs entry for %s module",
920 g_dbr_module_name[mod_id].module_name_str);
921 return QDF_STATUS_E_FAILURE;
922 }
923
924 return QDF_STATUS_SUCCESS;
925 }
926
927 /**
928 * target_if_dbr_ring_debugfs_init() - Init debugfs for a given ring
929 * @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module
930 * @mod_id: Module ID corresponding to this ring
931 * @srng_id: srng ID corresponding to this ring
932 *
933 * Return: QDF_STATUS of operation
934 */
target_if_dbr_ring_debugfs_init(struct direct_buf_rx_pdev_obj * dbr_pdev_obj,enum DBR_MODULE mod_id,uint8_t srng_id)935 static QDF_STATUS target_if_dbr_ring_debugfs_init(
936 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
937 enum DBR_MODULE mod_id, uint8_t srng_id)
938 {
939 struct direct_buf_rx_module_debug *mod_debug;
940 struct direct_buf_rx_ring_debug *ring_debug;
941 struct dbr_debugfs_priv *priv;
942 char debug_file_name[32];
943
944 mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
945 mod_id);
946
947 if (!mod_debug)
948 return QDF_STATUS_E_INVAL;
949
950 ring_debug = &mod_debug->dbr_ring_debug[srng_id];
951
952 if (!mod_debug->debugfs_entry) {
953 direct_buf_rx_err("error mod_debug->debugfs_entry not created");
954 return QDF_STATUS_E_FAILURE;
955 }
956
957 if (ring_debug->debugfs_entry) {
958 direct_buf_rx_err("debugfs file for %d ring under %s module already created",
959 srng_id,
960 g_dbr_module_name[mod_id].module_name_str);
961 return QDF_STATUS_SUCCESS;
962 }
963
964 qdf_snprintf(debug_file_name, sizeof(debug_file_name),
965 "ring_%d", srng_id);
966
967 // Allocate debugfs ops
968 ring_debug->debugfs_fops =
969 qdf_mem_malloc(sizeof(*ring_debug->debugfs_fops));
970 if (!ring_debug->debugfs_fops) {
971 direct_buf_rx_err("error in allocating debugfs ops");
972 return QDF_STATUS_E_NOMEM;
973 }
974
975 // Allocate private data
976 priv = qdf_mem_malloc(sizeof(*priv));
977 if (!priv) {
978 direct_buf_rx_err("error in creating debugfs private data");
979 goto priv_alloc_fail;
980 }
981 priv->dbr_pdev_obj = dbr_pdev_obj;
982 priv->mod_id = mod_id;
983 priv->srng_id = srng_id;
984
985 /* Fill in the debugfs ops for this ring.
986 * When the output time comes, the 'show' function will be
987 * called with 'priv' as an argument.
988 */
989 ring_debug->debugfs_fops->show = target_if_dbr_debugfs_show_ring_debug;
990 ring_debug->debugfs_fops->priv = priv;
991
992 ring_debug->debugfs_entry =
993 qdf_debugfs_create_file_simplified(
994 debug_file_name,
995 (QDF_FILE_USR_READ | QDF_FILE_GRP_READ |
996 QDF_FILE_OTH_READ),
997 mod_debug->debugfs_entry,
998 ring_debug->debugfs_fops);
999
1000 if (!ring_debug->debugfs_entry) {
1001 direct_buf_rx_err("error while creating direct_buf debugfs file for %d ring under %s module",
1002 srng_id,
1003 g_dbr_module_name[mod_id].module_name_str);
1004 goto file_creation_fail;
1005 }
1006
1007 return QDF_STATUS_SUCCESS;
1008
1009 file_creation_fail:
1010 qdf_mem_free(ring_debug->debugfs_fops->priv);
1011
1012 priv_alloc_fail:
1013 qdf_mem_free(ring_debug->debugfs_fops);
1014 ring_debug->debugfs_fops = NULL;
1015 return QDF_STATUS_E_NOMEM;
1016 }
1017
1018 /**
1019 * target_if_dbr_mod_debugfs_deinit() - De-init debugfs for a given module
1020 * @mod_debug: Pointer to direct_buf_rx_module_debug structure
1021 *
1022 * Return: void
1023 */
target_if_dbr_mod_debugfs_deinit(struct direct_buf_rx_module_debug * mod_debug)1024 static void target_if_dbr_mod_debugfs_deinit(
1025 struct direct_buf_rx_module_debug *mod_debug)
1026 {
1027 if (!mod_debug) {
1028 direct_buf_rx_err("mod_debug is null");
1029 return;
1030 }
1031
1032 if (mod_debug->debugfs_entry) {
1033 qdf_debugfs_remove_file(mod_debug->debugfs_entry);
1034 mod_debug->debugfs_entry = NULL;
1035 }
1036 }
1037
1038 /**
1039 * target_if_dbr_ring_debugfs_deinit() - De-init debugfs for a given ring
1040 * @ring_debug: Pointer to direct_buf_rx_ring_debug structure
1041 *
1042 * Return: void
1043 */
target_if_dbr_ring_debugfs_deinit(struct direct_buf_rx_ring_debug * ring_debug)1044 static void target_if_dbr_ring_debugfs_deinit(
1045 struct direct_buf_rx_ring_debug *ring_debug)
1046 {
1047 if (!ring_debug) {
1048 direct_buf_rx_err("ring_debug is null");
1049 return;
1050 }
1051
1052 if (ring_debug->debugfs_entry) {
1053 qdf_debugfs_remove_file(ring_debug->debugfs_entry);
1054 ring_debug->debugfs_entry = NULL;
1055 }
1056
1057 // Free the private data and debugfs ops of this ring
1058 if (ring_debug->debugfs_fops) {
1059 qdf_mem_free(ring_debug->debugfs_fops->priv);
1060 qdf_mem_free(ring_debug->debugfs_fops);
1061 ring_debug->debugfs_fops = NULL;
1062 }
1063 }
1064 #endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
1065
1066 #ifdef DIRECT_BUF_RX_DEBUG
target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)1067 QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
1068 uint8_t mod_id)
1069 {
1070 struct direct_buf_rx_module_debug *mod_debug;
1071 struct direct_buf_rx_ring_debug *ring_debug;
1072 uint8_t srng_id;
1073
1074 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
1075 if (!mod_debug)
1076 return QDF_STATUS_E_INVAL;
1077
1078 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
1079 ring_debug = &mod_debug->dbr_ring_debug[srng_id];
1080 if (!ring_debug->entries) {
1081 direct_buf_rx_debug("DBR ring debug for module %d srng %d was already disabled",
1082 mod_id, srng_id);
1083 continue;
1084 }
1085 /* De-init debugsfs for this ring */
1086 target_if_dbr_ring_debugfs_deinit(ring_debug);
1087 qdf_mem_free(ring_debug->entries);
1088 ring_debug->entries = NULL;
1089 ring_debug->ring_debug_idx = 0;
1090 ring_debug->num_ring_debug_entries = 0;
1091 direct_buf_rx_info("DBR ring debug for module %d srng %d is now stopped",
1092 mod_id, srng_id);
1093 }
1094 target_if_dbr_mod_debugfs_deinit(mod_debug);
1095
1096 return QDF_STATUS_SUCCESS;
1097 }
1098
target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint32_t num_ring_debug_entries)1099 QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev,
1100 uint8_t mod_id,
1101 uint32_t num_ring_debug_entries)
1102 {
1103 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
1104 struct direct_buf_rx_module_debug *mod_debug;
1105 struct direct_buf_rx_ring_debug *ring_debug;
1106 uint8_t srng_id;
1107
1108 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
1109
1110 if (!mod_debug)
1111 return QDF_STATUS_E_INVAL;
1112
1113 if (num_ring_debug_entries > DIRECT_BUF_RX_MAX_RING_DEBUG_ENTRIES) {
1114 direct_buf_rx_err("Requested number of ring debug entries(%d) exceed the maximum entries allowed(%d)",
1115 num_ring_debug_entries,
1116 DIRECT_BUF_RX_MAX_RING_DEBUG_ENTRIES);
1117
1118 return QDF_STATUS_E_FAILURE;
1119 }
1120
1121 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
1122 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1123
1124 target_if_dbr_mod_debugfs_init(dbr_pdev_obj, mod_id);
1125
1126 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
1127 ring_debug = &mod_debug->dbr_ring_debug[srng_id];
1128
1129 if (ring_debug->entries) {
1130 direct_buf_rx_err("DBR ring debug for module %d srng %d was already enabled",
1131 mod_id, srng_id);
1132 continue;
1133 }
1134
1135 ring_debug->entries = qdf_mem_malloc(
1136 num_ring_debug_entries *
1137 sizeof(*ring_debug->entries));
1138
1139 if (!ring_debug->entries)
1140 return QDF_STATUS_E_NOMEM;
1141
1142 ring_debug->ring_debug_idx = 0;
1143 ring_debug->num_ring_debug_entries = num_ring_debug_entries;
1144 /* Init debugsfs for this ring */
1145 target_if_dbr_ring_debugfs_init(
1146 dbr_pdev_obj,
1147 mod_id, srng_id);
1148 direct_buf_rx_info("DBR ring debug for module %d srng %d is now started",
1149 mod_id, srng_id);
1150 }
1151 return QDF_STATUS_SUCCESS;
1152 }
1153
target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint32_t value)1154 QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev,
1155 uint8_t mod_id, uint32_t value)
1156 {
1157 struct direct_buf_rx_module_debug *mod_debug;
1158
1159 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
1160
1161 if (!mod_debug)
1162 return QDF_STATUS_E_INVAL;
1163
1164 mod_debug->poisoning_enabled = true;
1165 mod_debug->poison_value = value; /* Save the poison value */
1166
1167 direct_buf_rx_debug("DBR buffer poisoning for module %d is now started",
1168 mod_id);
1169 return QDF_STATUS_SUCCESS;
1170 }
1171
target_if_dbr_stop_buffer_poisoning(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)1172 QDF_STATUS target_if_dbr_stop_buffer_poisoning(
1173 struct wlan_objmgr_pdev *pdev,
1174 uint8_t mod_id)
1175 {
1176 struct direct_buf_rx_module_debug *mod_debug;
1177
1178 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
1179
1180 if (!mod_debug)
1181 return QDF_STATUS_E_INVAL;
1182
1183 mod_debug->poisoning_enabled = false;
1184 mod_debug->poison_value = 0;
1185
1186 direct_buf_rx_debug("DBR buffer poisoning for module %d is now stopped",
1187 mod_id);
1188 return QDF_STATUS_SUCCESS;
1189 }
1190
1191 /**
1192 * target_if_dbr_fill_buffer_u32() - Fill buffer with an unsigned 32-bit value
1193 * @buffer: pointer to the buffer
1194 * @num_bytes: Size of the destination buffer in bytes
1195 * @value: Unsigned 32-bit value to be copied
1196 *
1197 * Return : void
1198 */
1199 static void
target_if_dbr_fill_buffer_u32(uint8_t * buffer,uint32_t num_bytes,uint32_t value)1200 target_if_dbr_fill_buffer_u32(uint8_t *buffer, uint32_t num_bytes,
1201 uint32_t value)
1202 {
1203 uint32_t *bufp;
1204 uint32_t idx;
1205 uint32_t size = (num_bytes >> 2);
1206
1207 if (!buffer) {
1208 direct_buf_rx_err("buffer empty");
1209 return;
1210 }
1211
1212 bufp = (uint32_t *)buffer;
1213
1214 for (idx = 0; idx < size; ++idx) {
1215 *bufp = value;
1216 ++bufp;
1217 }
1218 }
1219
1220 /**
1221 * target_if_dbr_debug_poison_buffer() - Poison a given DBR buffer
1222 * @pdev: pointer to pdev object
1223 * @mod_id: Module ID of the owner of the buffer
1224 * @aligned_vaddr: Virtual address(aligned) of the buffer
1225 * @size: Size of the buffer
1226 *
1227 * Value with which the buffers will be poisoned would have been saved
1228 * while starting the buffer poisoning for the module, use that value.
1229 *
1230 * Return : QDF status of operation
1231 */
target_if_dbr_debug_poison_buffer(struct wlan_objmgr_pdev * pdev,uint32_t mod_id,void * aligned_vaddr,uint32_t size)1232 static QDF_STATUS target_if_dbr_debug_poison_buffer(
1233 struct wlan_objmgr_pdev *pdev,
1234 uint32_t mod_id, void *aligned_vaddr, uint32_t size)
1235 {
1236 struct direct_buf_rx_module_debug *mod_debug;
1237
1238 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
1239
1240 if (!mod_debug)
1241 return QDF_STATUS_E_INVAL;
1242
1243 if (mod_debug->poisoning_enabled) {
1244 target_if_dbr_fill_buffer_u32(aligned_vaddr, size,
1245 mod_debug->poison_value);
1246 }
1247
1248 return QDF_STATUS_SUCCESS;
1249 }
1250
target_if_dbr_qdf_show_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint8_t srng_id)1251 static inline void target_if_dbr_qdf_show_ring_debug(
1252 struct wlan_objmgr_pdev *pdev,
1253 uint8_t mod_id, uint8_t srng_id)
1254 {
1255 struct direct_buf_rx_pdev_obj *dbr_pdev_obj =
1256 wlan_objmgr_pdev_get_comp_private_obj(
1257 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1258
1259 target_if_dbr_print_ring_debug_entries(
1260 target_if_dbr_qdf_err_printer,
1261 NULL, dbr_pdev_obj,
1262 mod_id, srng_id);
1263 }
1264 #else
target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)1265 QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
1266 uint8_t mod_id)
1267 {
1268 return QDF_STATUS_SUCCESS;
1269 }
1270
target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint32_t num_ring_debug_entries)1271 QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev,
1272 uint8_t mod_id,
1273 uint32_t num_ring_debug_entries)
1274 {
1275 return QDF_STATUS_SUCCESS;
1276 }
1277
target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint32_t value)1278 QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev,
1279 uint8_t mod_id, uint32_t value)
1280 {
1281 return QDF_STATUS_SUCCESS;
1282 }
1283
target_if_dbr_stop_buffer_poisoning(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)1284 QDF_STATUS target_if_dbr_stop_buffer_poisoning(
1285 struct wlan_objmgr_pdev *pdev,
1286 uint8_t mod_id)
1287 {
1288 return QDF_STATUS_SUCCESS;
1289 }
1290
target_if_dbr_debug_poison_buffer(struct wlan_objmgr_pdev * pdev,uint32_t mod_id,void * aligned_vaddr,uint32_t size)1291 static QDF_STATUS target_if_dbr_debug_poison_buffer(
1292 struct wlan_objmgr_pdev *pdev,
1293 uint32_t mod_id, void *aligned_vaddr, uint32_t size)
1294 {
1295 return QDF_STATUS_SUCCESS;
1296 }
1297
target_if_dbr_qdf_show_ring_debug(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,uint8_t srng_id)1298 static inline void target_if_dbr_qdf_show_ring_debug(
1299 struct wlan_objmgr_pdev *pdev,
1300 uint8_t mod_id, uint8_t srng_id)
1301 {
1302 }
1303 #endif /* DIRECT_BUF_RX_DEBUG */
1304
target_if_dbr_replenish_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param,void * aligned_vaddr,uint32_t cookie)1305 static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev,
1306 struct direct_buf_rx_module_param *mod_param,
1307 void *aligned_vaddr, uint32_t cookie)
1308 {
1309 uint32_t *ring_entry;
1310 uint32_t dw_lo, dw_hi = 0, map_status;
1311 void *hal_soc, *srng;
1312 qdf_dma_addr_t paddr;
1313 struct wlan_objmgr_psoc *psoc;
1314 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
1315 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
1316 struct direct_buf_rx_ring_cap *dbr_ring_cap;
1317 struct direct_buf_rx_buf_info *dbr_buf_pool;
1318
1319 dbr_ring_cfg = mod_param->dbr_ring_cfg;
1320 dbr_ring_cap = mod_param->dbr_ring_cap;
1321 dbr_buf_pool = mod_param->dbr_buf_pool;
1322
1323 psoc = wlan_pdev_get_psoc(pdev);
1324
1325 if (!psoc) {
1326 direct_buf_rx_err("psoc is null");
1327 return QDF_STATUS_E_FAILURE;
1328 }
1329
1330 if (cookie >= mod_param->dbr_ring_cfg->num_ptr) {
1331 direct_buf_rx_err("invalid cookie %d", cookie);
1332 return QDF_STATUS_E_INVAL;
1333 }
1334
1335 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
1336 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1337
1338 if (!dbr_psoc_obj) {
1339 direct_buf_rx_err("dir buf rx psoc object is null");
1340 return QDF_STATUS_E_FAILURE;
1341 }
1342
1343 hal_soc = dbr_psoc_obj->hal_soc;
1344 srng = dbr_ring_cfg->srng;
1345 if (!aligned_vaddr) {
1346 direct_buf_rx_err("aligned vaddr is null");
1347 return QDF_STATUS_SUCCESS;
1348 }
1349
1350 target_if_dbr_debug_poison_buffer(
1351 pdev, mod_param->mod_id, aligned_vaddr,
1352 dbr_ring_cap->min_buf_size);
1353
1354 map_status = qdf_mem_map_nbytes_single(dbr_psoc_obj->osdev,
1355 aligned_vaddr,
1356 QDF_DMA_FROM_DEVICE,
1357 dbr_ring_cap->min_buf_size,
1358 &paddr);
1359 if (map_status) {
1360 direct_buf_rx_err("mem map failed status = %d", map_status);
1361 return QDF_STATUS_E_FAILURE;
1362 }
1363
1364 QDF_ASSERT(!((uint64_t)paddr % dbr_ring_cap->min_buf_align));
1365 dbr_buf_pool[cookie].paddr = paddr;
1366
1367 hal_le_srng_access_start_in_cpu_order(hal_soc, srng);
1368 ring_entry = hal_srng_src_get_next(hal_soc, srng);
1369
1370 if (!ring_entry) {
1371 target_if_dbr_qdf_show_ring_debug(pdev, mod_param->mod_id,
1372 mod_param->srng_id);
1373 QDF_BUG(0);
1374 }
1375
1376 dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
1377 WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
1378 WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
1379 *ring_entry = qdf_cpu_to_le32(dw_lo);
1380 ring_entry++;
1381 *ring_entry = qdf_cpu_to_le32(dw_hi);
1382 hal_le_srng_access_end_in_cpu_order(hal_soc, srng);
1383
1384 return QDF_STATUS_SUCCESS;
1385 }
1386
target_if_dbr_fill_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)1387 static QDF_STATUS target_if_dbr_fill_ring(struct wlan_objmgr_pdev *pdev,
1388 struct direct_buf_rx_module_param *mod_param)
1389 {
1390 uint32_t idx;
1391 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
1392 struct direct_buf_rx_ring_cap *dbr_ring_cap;
1393 struct direct_buf_rx_buf_info *dbr_buf_pool;
1394 void *buf_vaddr_unaligned, *buf_vaddr_aligned;
1395 QDF_STATUS status;
1396 uint8_t offset = 0;
1397
1398 direct_buf_rx_enter();
1399
1400 dbr_ring_cfg = mod_param->dbr_ring_cfg;
1401 dbr_ring_cap = mod_param->dbr_ring_cap;
1402 dbr_buf_pool = mod_param->dbr_buf_pool;
1403
1404 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) {
1405 buf_vaddr_unaligned =
1406 target_if_dbr_mem_get(pdev, &dbr_ring_cap->min_buf_size,
1407 &offset,
1408 dbr_ring_cap->min_buf_align,
1409 mod_param->mod_id);
1410 if (!buf_vaddr_unaligned) {
1411 direct_buf_rx_err("dir buf rx ring alloc failed");
1412 return QDF_STATUS_E_NOMEM;
1413 }
1414
1415 dbr_buf_pool[idx].vaddr = buf_vaddr_unaligned;
1416 dbr_buf_pool[idx].offset = offset;
1417 dbr_buf_pool[idx].cookie = idx;
1418 buf_vaddr_aligned = buf_vaddr_unaligned + offset;
1419 status = target_if_dbr_replenish_ring(pdev, mod_param,
1420 buf_vaddr_aligned, idx);
1421 if (QDF_IS_STATUS_ERROR(status)) {
1422 direct_buf_rx_err("replenish failed with status : %d",
1423 status);
1424 target_if_dbr_mem_put(pdev, dbr_ring_cap->min_buf_size,
1425 buf_vaddr_unaligned, offset,
1426 dbr_ring_cap->min_buf_align,
1427 mod_param->mod_id);
1428 return QDF_STATUS_E_FAILURE;
1429 }
1430 }
1431
1432 direct_buf_rx_exit();
1433
1434 return QDF_STATUS_SUCCESS;
1435 }
1436
target_if_dbr_init_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)1437 static QDF_STATUS target_if_dbr_init_ring(struct wlan_objmgr_pdev *pdev,
1438 struct direct_buf_rx_module_param *mod_param)
1439 {
1440 void *srng;
1441 uint32_t num_entries, ring_alloc_size, max_entries, entry_size;
1442 qdf_dma_addr_t paddr;
1443 struct hal_srng_params ring_params = {0};
1444 struct wlan_objmgr_psoc *psoc;
1445 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
1446 struct direct_buf_rx_ring_cap *dbr_ring_cap;
1447 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
1448 QDF_STATUS status;
1449
1450 direct_buf_rx_enter();
1451
1452 psoc = wlan_pdev_get_psoc(pdev);
1453
1454 if (!psoc) {
1455 direct_buf_rx_err("psoc is null");
1456 return QDF_STATUS_E_FAILURE;
1457 }
1458
1459 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
1460 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1461
1462 if (!dbr_psoc_obj) {
1463 direct_buf_rx_err("dir buf rx psoc object is null");
1464 return QDF_STATUS_E_FAILURE;
1465 }
1466
1467 if (!dbr_psoc_obj->hal_soc ||
1468 !dbr_psoc_obj->osdev) {
1469 direct_buf_rx_err("dir buf rx target attach failed");
1470 return QDF_STATUS_E_FAILURE;
1471 }
1472
1473 max_entries = hal_srng_max_entries(dbr_psoc_obj->hal_soc,
1474 DIR_BUF_RX_DMA_SRC);
1475 entry_size = hal_srng_get_entrysize(dbr_psoc_obj->hal_soc,
1476 DIR_BUF_RX_DMA_SRC);
1477 direct_buf_rx_debug("Max Entries = %d", max_entries);
1478 direct_buf_rx_debug("Entry Size = %d", entry_size);
1479
1480 status = populate_dbr_cap_mod_param(pdev, mod_param);
1481 if (QDF_IS_STATUS_ERROR(status)) {
1482 direct_buf_rx_err("Module cap population failed");
1483 return QDF_STATUS_E_FAILURE;
1484 }
1485
1486 dbr_ring_cap = mod_param->dbr_ring_cap;
1487 dbr_ring_cfg = mod_param->dbr_ring_cfg;
1488 num_entries = dbr_ring_cap->ring_elems_min > max_entries ?
1489 max_entries : dbr_ring_cap->ring_elems_min;
1490 direct_buf_rx_debug("Num entries = %d", num_entries);
1491 dbr_ring_cfg->num_ptr = num_entries;
1492 mod_param->dbr_buf_pool = qdf_mem_malloc(num_entries * sizeof(
1493 struct direct_buf_rx_buf_info));
1494 if (!mod_param->dbr_buf_pool)
1495 return QDF_STATUS_E_NOMEM;
1496
1497 ring_alloc_size = (num_entries * entry_size) + DBR_RING_BASE_ALIGN - 1;
1498 dbr_ring_cfg->ring_alloc_size = ring_alloc_size;
1499 direct_buf_rx_debug("dbr_psoc_obj %pK", dbr_psoc_obj);
1500 dbr_ring_cfg->base_vaddr_unaligned = qdf_mem_alloc_consistent(
1501 dbr_psoc_obj->osdev, dbr_psoc_obj->osdev->dev, ring_alloc_size,
1502 &paddr);
1503 direct_buf_rx_debug("vaddr aligned allocated");
1504 dbr_ring_cfg->base_paddr_unaligned = paddr;
1505 if (!dbr_ring_cfg->base_vaddr_unaligned) {
1506 direct_buf_rx_err("dir buf rx vaddr alloc failed");
1507 qdf_mem_free(mod_param->dbr_buf_pool);
1508 return QDF_STATUS_E_NOMEM;
1509 }
1510
1511 /* Alignment is defined to 8 for now. Will be advertised by FW */
1512 dbr_ring_cfg->base_vaddr_aligned = (void *)(uintptr_t)qdf_roundup(
1513 (uint64_t)(uintptr_t)dbr_ring_cfg->base_vaddr_unaligned,
1514 DBR_RING_BASE_ALIGN);
1515 ring_params.ring_base_vaddr = dbr_ring_cfg->base_vaddr_aligned;
1516 dbr_ring_cfg->base_paddr_aligned = qdf_roundup(
1517 (uint64_t)dbr_ring_cfg->base_paddr_unaligned,
1518 DBR_RING_BASE_ALIGN);
1519 ring_params.ring_base_paddr =
1520 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_aligned;
1521 ring_params.num_entries = num_entries;
1522 srng = hal_srng_setup(dbr_psoc_obj->hal_soc, DIR_BUF_RX_DMA_SRC,
1523 mod_param->mod_id,
1524 mod_param->pdev_id, &ring_params, 0);
1525
1526 if (!srng) {
1527 direct_buf_rx_err("srng setup failed");
1528 qdf_mem_free(mod_param->dbr_buf_pool);
1529 qdf_mem_free_consistent(dbr_psoc_obj->osdev,
1530 dbr_psoc_obj->osdev->dev,
1531 ring_alloc_size,
1532 dbr_ring_cfg->base_vaddr_unaligned,
1533 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0);
1534 return QDF_STATUS_E_FAILURE;
1535 }
1536 dbr_ring_cfg->srng = srng;
1537 dbr_ring_cfg->tail_idx_addr =
1538 hal_srng_get_tp_addr(dbr_psoc_obj->hal_soc, srng);
1539 dbr_ring_cfg->head_idx_addr =
1540 hal_srng_get_hp_addr(dbr_psoc_obj->hal_soc, srng);
1541 dbr_ring_cfg->buf_size = dbr_ring_cap->min_buf_size;
1542
1543 return target_if_dbr_fill_ring(pdev, mod_param);
1544 }
1545
target_if_dbr_init_srng(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)1546 static QDF_STATUS target_if_dbr_init_srng(struct wlan_objmgr_pdev *pdev,
1547 struct direct_buf_rx_module_param *mod_param)
1548 {
1549 QDF_STATUS status;
1550
1551 direct_buf_rx_debug("Init DBR srng");
1552
1553 if (!mod_param) {
1554 direct_buf_rx_err("dir buf rx module param is null");
1555 return QDF_STATUS_E_INVAL;
1556 }
1557
1558 mod_param->dbr_ring_cap = qdf_mem_malloc(sizeof(
1559 struct direct_buf_rx_ring_cap));
1560
1561 if (!mod_param->dbr_ring_cap)
1562 return QDF_STATUS_E_NOMEM;
1563
1564 /* Allocate memory for DBR Ring Config */
1565 mod_param->dbr_ring_cfg = qdf_mem_malloc(sizeof(
1566 struct direct_buf_rx_ring_cfg));
1567
1568 if (!mod_param->dbr_ring_cfg) {
1569 qdf_mem_free(mod_param->dbr_ring_cap);
1570 return QDF_STATUS_E_NOMEM;
1571 }
1572
1573 status = target_if_dbr_init_ring(pdev, mod_param);
1574
1575 if (QDF_IS_STATUS_ERROR(status)) {
1576 direct_buf_rx_err("DBR ring init failed");
1577 qdf_mem_free(mod_param->dbr_ring_cfg);
1578 qdf_mem_free(mod_param->dbr_ring_cap);
1579 return QDF_STATUS_E_FAILURE;
1580 }
1581
1582 return QDF_STATUS_SUCCESS;
1583 }
1584
target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)1585 static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev,
1586 struct direct_buf_rx_module_param *mod_param)
1587 {
1588 QDF_STATUS status;
1589 struct wlan_objmgr_psoc *psoc;
1590 wmi_unified_t wmi_hdl;
1591 struct direct_buf_rx_cfg_req dbr_cfg_req = {0};
1592 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
1593 struct direct_buf_rx_ring_cap *dbr_ring_cap;
1594 struct dbr_module_config *dbr_config;
1595
1596 direct_buf_rx_enter();
1597
1598 psoc = wlan_pdev_get_psoc(pdev);
1599 if (!psoc) {
1600 direct_buf_rx_err("psoc is null");
1601 return QDF_STATUS_E_FAILURE;
1602 }
1603
1604 dbr_ring_cfg = mod_param->dbr_ring_cfg;
1605 dbr_ring_cap = mod_param->dbr_ring_cap;
1606 dbr_config = &mod_param->dbr_config;
1607 wmi_hdl = lmac_get_pdev_wmi_handle(pdev);
1608 if (!wmi_hdl) {
1609 direct_buf_rx_err("WMI handle null. Can't send WMI CMD");
1610 return QDF_STATUS_E_INVAL;
1611 }
1612
1613 direct_buf_rx_debug("Sending DBR Ring CFG to target");
1614 dbr_cfg_req.pdev_id = mod_param->pdev_id;
1615 /* Module ID numbering starts from 1 in FW. need to fix it */
1616 dbr_cfg_req.mod_id = mod_param->mod_id;
1617 dbr_cfg_req.base_paddr_lo =
1618 qdf_get_lower_32_bits(dbr_ring_cfg->base_paddr_aligned);
1619 dbr_cfg_req.base_paddr_hi =
1620 qdf_get_upper_32_bits(dbr_ring_cfg->base_paddr_aligned);
1621 dbr_cfg_req.head_idx_paddr_lo =
1622 qdf_get_lower_32_bits(dbr_ring_cfg->head_idx_addr);
1623 dbr_cfg_req.head_idx_paddr_hi =
1624 qdf_get_upper_32_bits(dbr_ring_cfg->head_idx_addr);
1625 dbr_cfg_req.tail_idx_paddr_lo =
1626 qdf_get_lower_32_bits(dbr_ring_cfg->tail_idx_addr);
1627 dbr_cfg_req.tail_idx_paddr_hi =
1628 qdf_get_upper_32_bits(dbr_ring_cfg->tail_idx_addr);
1629 dbr_cfg_req.num_elems = dbr_ring_cap->ring_elems_min;
1630 dbr_cfg_req.buf_size = dbr_ring_cap->min_buf_size;
1631 dbr_cfg_req.num_resp_per_event = dbr_config->num_resp_per_event;
1632 dbr_cfg_req.event_timeout_ms = dbr_config->event_timeout_in_ms;
1633 direct_buf_rx_debug("pdev id %d mod id %d base addr lo %x\n"
1634 "base addr hi %x head idx addr lo %x\n"
1635 "head idx addr hi %x tail idx addr lo %x\n"
1636 "tail idx addr hi %x num ptr %d\n"
1637 "num resp %d event timeout %d\n",
1638 dbr_cfg_req.pdev_id, dbr_cfg_req.mod_id,
1639 dbr_cfg_req.base_paddr_lo,
1640 dbr_cfg_req.base_paddr_hi,
1641 dbr_cfg_req.head_idx_paddr_lo,
1642 dbr_cfg_req.head_idx_paddr_hi,
1643 dbr_cfg_req.tail_idx_paddr_lo,
1644 dbr_cfg_req.tail_idx_paddr_hi,
1645 dbr_cfg_req.num_elems,
1646 dbr_cfg_req.num_resp_per_event,
1647 dbr_cfg_req.event_timeout_ms);
1648 status = wmi_unified_dbr_ring_cfg(wmi_hdl, &dbr_cfg_req);
1649
1650 return status;
1651 }
1652
target_if_init_dbr_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_pdev_obj * dbr_pdev_obj,enum DBR_MODULE mod_id,uint8_t srng_id)1653 static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev,
1654 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
1655 enum DBR_MODULE mod_id, uint8_t srng_id)
1656 {
1657 QDF_STATUS status = QDF_STATUS_SUCCESS;
1658 struct direct_buf_rx_module_param *mod_param;
1659
1660 direct_buf_rx_debug("Init DBR ring for module %d, srng %d",
1661 mod_id, srng_id);
1662
1663 if (!dbr_pdev_obj) {
1664 direct_buf_rx_err("dir buf rx object is null");
1665 return QDF_STATUS_E_INVAL;
1666 }
1667
1668 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id][srng_id]);
1669
1670 if (!mod_param) {
1671 direct_buf_rx_err("dir buf rx module param is null");
1672 return QDF_STATUS_E_FAILURE;
1673 }
1674
1675 direct_buf_rx_debug("mod_param %pK", mod_param);
1676
1677 mod_param->mod_id = mod_id;
1678 mod_param->pdev_id = dbr_get_pdev_id(
1679 srng_id, wlan_objmgr_pdev_get_pdev_id(pdev));
1680 mod_param->srng_id = srng_id;
1681
1682 /* Initialize DMA ring now */
1683 status = target_if_dbr_init_srng(pdev, mod_param);
1684 if (QDF_IS_STATUS_ERROR(status)) {
1685 direct_buf_rx_err("DBR ring init failed %d", status);
1686 return status;
1687 }
1688
1689 mod_param->srng_initialized = true;
1690
1691 /* Send CFG request command to firmware */
1692 status = target_if_dbr_cfg_tgt(pdev, mod_param);
1693 if (QDF_IS_STATUS_ERROR(status)) {
1694 direct_buf_rx_err("DBR config to target failed %d", status);
1695 goto dbr_srng_init_failed;
1696 }
1697
1698 return QDF_STATUS_SUCCESS;
1699
1700 dbr_srng_init_failed:
1701 target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_id, srng_id);
1702 return status;
1703 }
1704
target_if_direct_buf_rx_module_register(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,struct dbr_module_config * dbr_config,bool (* dbr_rsp_handler)(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_data * dbr_data))1705 QDF_STATUS target_if_direct_buf_rx_module_register(
1706 struct wlan_objmgr_pdev *pdev, uint8_t mod_id,
1707 struct dbr_module_config *dbr_config,
1708 bool (*dbr_rsp_handler)
1709 (struct wlan_objmgr_pdev *pdev,
1710 struct direct_buf_rx_data *dbr_data))
1711 {
1712 QDF_STATUS status;
1713 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
1714 struct dbr_module_config *config = NULL;
1715 struct direct_buf_rx_module_param *mod_param;
1716 uint8_t srng_id;
1717
1718 if (!pdev) {
1719 direct_buf_rx_err("pdev context passed is null");
1720 return QDF_STATUS_E_INVAL;
1721 }
1722
1723 if (!dbr_rsp_handler) {
1724 direct_buf_rx_err("Response handler is null");
1725 return QDF_STATUS_E_INVAL;
1726 }
1727
1728 if (mod_id >= DBR_MODULE_MAX) {
1729 direct_buf_rx_err("Invalid module id");
1730 return QDF_STATUS_E_INVAL;
1731 }
1732
1733 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1734 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1735
1736 if (!dbr_pdev_obj) {
1737 direct_buf_rx_err("dir buf rx object is null");
1738 return QDF_STATUS_E_FAILURE;
1739 }
1740
1741 direct_buf_rx_debug("Dbr pdev obj %pK", dbr_pdev_obj);
1742
1743 if (!dbr_pdev_obj->dbr_mod_param) {
1744 direct_buf_rx_err("dbr_pdev_obj->dbr_mod_param is NULL");
1745 return QDF_STATUS_E_FAILURE;
1746 }
1747
1748 if (mod_id >= dbr_pdev_obj->num_modules) {
1749 direct_buf_rx_err("Module %d not supported in target", mod_id);
1750 return QDF_STATUS_E_FAILURE;
1751 }
1752
1753 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
1754 mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id];
1755 config = &mod_param->dbr_config;
1756 mod_param->dbr_rsp_handler = dbr_rsp_handler;
1757 *config = *dbr_config;
1758
1759 status = target_if_init_dbr_ring(pdev, dbr_pdev_obj,
1760 (enum DBR_MODULE)mod_id,
1761 srng_id);
1762 if (QDF_IS_STATUS_ERROR(status))
1763 direct_buf_rx_err("init dbr ring fail, srng_id %d, status %d",
1764 srng_id, status);
1765 }
1766
1767 return status;
1768 }
1769
target_if_direct_buf_rx_module_unregister(struct wlan_objmgr_pdev * pdev,uint8_t mod_id)1770 QDF_STATUS target_if_direct_buf_rx_module_unregister(
1771 struct wlan_objmgr_pdev *pdev, uint8_t mod_id)
1772 {
1773 QDF_STATUS status;
1774 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
1775 uint8_t srng_id;
1776
1777 if (!pdev) {
1778 direct_buf_rx_err("pdev context passed is null");
1779 return QDF_STATUS_E_INVAL;
1780 }
1781
1782 if (mod_id >= DBR_MODULE_MAX) {
1783 direct_buf_rx_err("Invalid module id");
1784 return QDF_STATUS_E_INVAL;
1785 }
1786
1787 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj
1788 (pdev,
1789 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1790
1791 if (!dbr_pdev_obj) {
1792 direct_buf_rx_err("dir buf rx object is null");
1793 return QDF_STATUS_E_FAILURE;
1794 }
1795
1796 direct_buf_rx_debug("Dbr pdev obj %pK", dbr_pdev_obj);
1797
1798 if (!dbr_pdev_obj->dbr_mod_param) {
1799 direct_buf_rx_err("dbr_pdev_obj->dbr_mod_param is NULL");
1800 return QDF_STATUS_E_FAILURE;
1801 }
1802
1803 if (mod_id >= dbr_pdev_obj->num_modules) {
1804 direct_buf_rx_err("Module %d not supported in target", mod_id);
1805 return QDF_STATUS_E_FAILURE;
1806 }
1807
1808 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
1809 status = target_if_deinit_dbr_ring(pdev, dbr_pdev_obj,
1810 mod_id, srng_id);
1811 direct_buf_rx_info("status %d", status);
1812 }
1813
1814 return status;
1815 }
1816
target_if_dbr_vaddr_lookup(struct direct_buf_rx_module_param * mod_param,qdf_dma_addr_t paddr,uint32_t cookie)1817 static void *target_if_dbr_vaddr_lookup(
1818 struct direct_buf_rx_module_param *mod_param,
1819 qdf_dma_addr_t paddr, uint32_t cookie)
1820 {
1821 struct direct_buf_rx_buf_info *dbr_buf_pool;
1822
1823 dbr_buf_pool = mod_param->dbr_buf_pool;
1824
1825 if (cookie >= mod_param->dbr_ring_cfg->num_ptr) {
1826 direct_buf_rx_err("invalid cookie %d", cookie);
1827 return NULL;
1828 }
1829
1830 if (dbr_buf_pool[cookie].paddr == paddr) {
1831 return dbr_buf_pool[cookie].vaddr +
1832 dbr_buf_pool[cookie].offset;
1833 }
1834 direct_buf_rx_debug("Invalid paddr, cookie %d, pool paddr %pK, paddr %pK",
1835 cookie, (void *)dbr_buf_pool[cookie].paddr,
1836 (void *)paddr);
1837
1838 return NULL;
1839 }
1840
target_if_dbr_cookie_lookup(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,qdf_dma_addr_t paddr,uint32_t * cookie,uint8_t srng_id)1841 QDF_STATUS target_if_dbr_cookie_lookup(struct wlan_objmgr_pdev *pdev,
1842 uint8_t mod_id, qdf_dma_addr_t paddr,
1843 uint32_t *cookie, uint8_t srng_id)
1844 {
1845 struct direct_buf_rx_buf_info *dbr_buf_pool;
1846 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
1847 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
1848 struct direct_buf_rx_module_param *mod_param;
1849 enum wlan_umac_comp_id dbr_comp_id = WLAN_TARGET_IF_COMP_DIRECT_BUF_RX;
1850 uint32_t idx;
1851
1852 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, dbr_comp_id);
1853 if (!dbr_pdev_obj) {
1854 direct_buf_rx_err("dir buf rx object is null");
1855 return QDF_STATUS_E_FAILURE;
1856 }
1857
1858 mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id];
1859 if (!mod_param) {
1860 direct_buf_rx_err("dir buf rx module param is null");
1861 return QDF_STATUS_E_FAILURE;
1862 }
1863
1864 dbr_ring_cfg = mod_param->dbr_ring_cfg;
1865 dbr_buf_pool = mod_param->dbr_buf_pool;
1866
1867 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) {
1868 if (dbr_buf_pool[idx].paddr &&
1869 dbr_buf_pool[idx].paddr == paddr) {
1870 *cookie = idx;
1871 return QDF_STATUS_SUCCESS;
1872 }
1873 }
1874
1875 return QDF_STATUS_E_FAILURE;
1876 }
1877
target_if_dbr_buf_release(struct wlan_objmgr_pdev * pdev,uint8_t mod_id,qdf_dma_addr_t paddr,uint32_t cookie,uint8_t srng_id)1878 QDF_STATUS target_if_dbr_buf_release(struct wlan_objmgr_pdev *pdev,
1879 uint8_t mod_id, qdf_dma_addr_t paddr,
1880 uint32_t cookie, uint8_t srng_id)
1881 {
1882 struct direct_buf_rx_module_param *mod_param;
1883 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
1884 enum wlan_umac_comp_id dbr_comp_id = WLAN_TARGET_IF_COMP_DIRECT_BUF_RX;
1885 void *vaddr;
1886 QDF_STATUS status;
1887
1888 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, dbr_comp_id);
1889 if (!dbr_pdev_obj) {
1890 direct_buf_rx_err("dir buf rx object is null");
1891 return QDF_STATUS_E_FAILURE;
1892 }
1893
1894 mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id];
1895 if (!mod_param) {
1896 direct_buf_rx_err("dir buf rx module param is null");
1897 return QDF_STATUS_E_FAILURE;
1898 }
1899
1900 vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, cookie);
1901 if (!vaddr)
1902 return QDF_STATUS_E_FAILURE;
1903
1904 status = target_if_dbr_replenish_ring(pdev, mod_param,
1905 vaddr, cookie);
1906 if (QDF_IS_STATUS_ERROR(status)) {
1907 direct_buf_rx_err("Ring replenish failed");
1908 return QDF_STATUS_E_FAILURE;
1909 }
1910
1911 return QDF_STATUS_SUCCESS;
1912 }
1913
target_if_get_dbr_data(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param,struct direct_buf_rx_rsp * dbr_rsp,struct direct_buf_rx_data * dbr_data,uint8_t idx,uint32_t * cookie)1914 static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev,
1915 struct direct_buf_rx_module_param *mod_param,
1916 struct direct_buf_rx_rsp *dbr_rsp,
1917 struct direct_buf_rx_data *dbr_data,
1918 uint8_t idx, uint32_t *cookie)
1919 {
1920 qdf_dma_addr_t paddr = 0;
1921 uint32_t addr_hi;
1922 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
1923 struct direct_buf_rx_ring_cap *dbr_ring_cap;
1924 struct wlan_objmgr_psoc *psoc;
1925
1926 psoc = wlan_pdev_get_psoc(pdev);
1927 if (!psoc) {
1928 direct_buf_rx_err("psoc is null");
1929 return QDF_STATUS_E_FAILURE;
1930 }
1931
1932 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
1933 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
1934
1935 if (!dbr_psoc_obj) {
1936 direct_buf_rx_err("dir buf rx psoc object is null");
1937 return QDF_STATUS_E_FAILURE;
1938 }
1939
1940 dbr_ring_cap = mod_param->dbr_ring_cap;
1941 addr_hi = (uint64_t)WMI_HOST_DBR_DATA_ADDR_HI_GET(
1942 dbr_rsp->dbr_entries[idx].paddr_hi);
1943 paddr = (qdf_dma_addr_t)((uint64_t)addr_hi << 32 |
1944 dbr_rsp->dbr_entries[idx].paddr_lo);
1945 *cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET(
1946 dbr_rsp->dbr_entries[idx].paddr_hi);
1947 dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie);
1948
1949 if (!dbr_data->vaddr) {
1950 direct_buf_rx_debug("dbr vaddr lookup failed, cookie %d, hi %x, lo %x",
1951 *cookie, dbr_rsp->dbr_entries[idx].paddr_hi,
1952 dbr_rsp->dbr_entries[idx].paddr_lo);
1953 return QDF_STATUS_E_FAILURE;
1954 }
1955
1956 dbr_data->cookie = *cookie;
1957 dbr_data->paddr = paddr;
1958 direct_buf_rx_debug("Cookie = %d Vaddr look up = %pK",
1959 dbr_data->cookie, dbr_data->vaddr);
1960 dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len;
1961 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr,
1962 QDF_DMA_FROM_DEVICE,
1963 dbr_ring_cap->min_buf_size);
1964
1965 return QDF_STATUS_SUCCESS;
1966 }
1967
1968 #ifdef DBR_MULTI_SRNG_ENABLE
1969 /**
1970 * dbr_get_pdev_and_srng_id() - get pdev object and srng id
1971 *
1972 * @psoc: pointer to psoc object
1973 * @pdev_id: pdev id from wmi_pdev_dma_ring_buf_release eventid
1974 * @srng_id: pointer to return srng id
1975 *
1976 * Return : pointer to pdev
1977 */
1978 static struct wlan_objmgr_pdev *
dbr_get_pdev_and_srng_id(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id,uint8_t * srng_id)1979 dbr_get_pdev_and_srng_id(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
1980 uint8_t *srng_id)
1981 {
1982 struct wlan_objmgr_pdev *pdev;
1983 wlan_objmgr_ref_dbgid dbr_mod_id = WLAN_DIRECT_BUF_RX_ID;
1984
1985 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbr_mod_id);
1986 if (!pdev) {
1987 pdev = wlan_objmgr_get_pdev_by_id(psoc, TGT_WMI_PDEV_ID_SOC,
1988 dbr_mod_id);
1989 if (pdev) {
1990 direct_buf_rx_debug("update srng id from %d to %d",
1991 *srng_id, pdev_id);
1992 *srng_id = pdev_id;
1993 }
1994 }
1995
1996 return pdev;
1997 }
1998 #else
1999 static struct wlan_objmgr_pdev *
dbr_get_pdev_and_srng_id(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id,uint8_t * srng_id)2000 dbr_get_pdev_and_srng_id(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
2001 uint8_t *srng_id)
2002 {
2003 struct wlan_objmgr_pdev *pdev;
2004 wlan_objmgr_ref_dbgid dbr_mod_id = WLAN_DIRECT_BUF_RX_ID;
2005
2006 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbr_mod_id);
2007
2008 return pdev;
2009 }
2010 #endif
2011
2012 #ifdef DIRECT_BUF_RX_DEBUG
2013 /**
2014 * target_if_dbr_add_ring_debug_entry() - Add a DBR ring debug entry
2015 * @pdev: pointer to pdev object
2016 * @mod_id: Module ID
2017 * @event: ring debug event
2018 * @srng_id: ring id
2019 *
2020 * Log the given event, head and tail pointers of DBR ring of the given module
2021 * into its ring debug data structure.
2022 * Also, log the timestamp at the time of logging.
2023 */
target_if_dbr_add_ring_debug_entry(struct wlan_objmgr_pdev * pdev,uint32_t mod_id,enum DBR_RING_DEBUG_EVENT event,uint8_t srng_id)2024 static void target_if_dbr_add_ring_debug_entry(
2025 struct wlan_objmgr_pdev *pdev,
2026 uint32_t mod_id,
2027 enum DBR_RING_DEBUG_EVENT event,
2028 uint8_t srng_id)
2029 {
2030 struct wlan_objmgr_psoc *psoc;
2031 void *hal_soc, *srng;
2032 uint32_t hp = 0, tp = 0;
2033 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
2034 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
2035 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
2036 struct direct_buf_rx_module_debug *mod_debug;
2037 struct direct_buf_rx_module_param *mod_param;
2038 struct direct_buf_rx_ring_debug *ring_debug;
2039 struct direct_buf_rx_ring_debug_entry *entry;
2040
2041 mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
2042
2043 if (!mod_debug)
2044 return;
2045
2046 psoc = wlan_pdev_get_psoc(pdev);
2047
2048 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
2049 pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2050
2051 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
2052 psoc, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2053
2054 mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id];
2055 if (!mod_param) {
2056 direct_buf_rx_err("dir buf rx module param is null");
2057 return;
2058 }
2059
2060 hal_soc = dbr_psoc_obj->hal_soc;
2061 dbr_ring_cfg = mod_param->dbr_ring_cfg;
2062 srng = dbr_ring_cfg->srng;
2063 ring_debug = &mod_debug->dbr_ring_debug[srng_id];
2064
2065 if (ring_debug->entries) {
2066 if (hal_le_srng_access_start_in_cpu_order(hal_soc, srng)) {
2067 direct_buf_rx_err("module %d - HAL srng access failed",
2068 mod_id);
2069 return;
2070 }
2071 hal_get_sw_hptp(hal_soc, srng, &tp, &hp);
2072 hal_le_srng_access_end_in_cpu_order(hal_soc, srng);
2073 tp = qdf_le32_to_cpu(tp);
2074 entry = &ring_debug->entries[ring_debug->ring_debug_idx];
2075
2076 entry->head_idx = hp;
2077 entry->tail_idx = tp;
2078 entry->timestamp = qdf_get_log_timestamp();
2079 entry->event = event;
2080
2081 ring_debug->ring_debug_idx++;
2082 if (ring_debug->ring_debug_idx ==
2083 ring_debug->num_ring_debug_entries)
2084 ring_debug->ring_debug_idx = 0;
2085 }
2086 }
2087
2088 #else
target_if_dbr_add_ring_debug_entry(struct wlan_objmgr_pdev * pdev,uint32_t mod_id,enum DBR_RING_DEBUG_EVENT event,uint8_t srng_id)2089 static void target_if_dbr_add_ring_debug_entry(
2090 struct wlan_objmgr_pdev *pdev,
2091 uint32_t mod_id,
2092 enum DBR_RING_DEBUG_EVENT event,
2093 uint8_t srng_id)
2094 {
2095 }
2096 #endif /* DIRECT_BUF_RX_DEBUG */
2097
target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)2098 static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn,
2099 uint8_t *data_buf,
2100 uint32_t data_len)
2101 {
2102 int ret = 0;
2103 uint8_t i = 0;
2104 QDF_STATUS status;
2105 uint32_t cookie = 0;
2106 struct direct_buf_rx_rsp dbr_rsp = {0};
2107 struct direct_buf_rx_data dbr_data = {0};
2108 struct wlan_objmgr_psoc *psoc;
2109 struct wlan_objmgr_pdev *pdev;
2110 struct direct_buf_rx_buf_info *dbr_buf_pool;
2111 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
2112 struct direct_buf_rx_module_param *mod_param;
2113 struct wmi_unified *wmi_handle;
2114 wlan_objmgr_ref_dbgid dbr_mod_id = WLAN_DIRECT_BUF_RX_ID;
2115 uint8_t srng_id = 0;
2116
2117 direct_buf_rx_enter();
2118
2119 psoc = target_if_get_psoc_from_scn_hdl(scn);
2120 if (!psoc) {
2121 direct_buf_rx_err("psoc is null");
2122 return QDF_STATUS_E_FAILURE;
2123 }
2124
2125 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
2126 if (!wmi_handle) {
2127 direct_buf_rx_err("WMI handle is null");
2128 return QDF_STATUS_E_FAILURE;
2129 }
2130
2131 if (wmi_extract_dbr_buf_release_fixed(
2132 wmi_handle, data_buf, &dbr_rsp) != QDF_STATUS_SUCCESS) {
2133 direct_buf_rx_err("unable to extract DBR rsp fixed param");
2134 return QDF_STATUS_E_FAILURE;
2135 }
2136
2137 direct_buf_rx_debug("Num buf release entry = %d",
2138 dbr_rsp.num_buf_release_entry);
2139
2140 pdev = dbr_get_pdev_and_srng_id(psoc, (uint8_t)dbr_rsp.pdev_id,
2141 &srng_id);
2142 if (!pdev || (srng_id >= DBR_SRNG_NUM)) {
2143 direct_buf_rx_err("invalid pdev or srng, pdev %pK, srng %d",
2144 pdev, srng_id);
2145 return QDF_STATUS_E_INVAL;
2146 }
2147
2148 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
2149 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2150
2151 if (!dbr_pdev_obj) {
2152 direct_buf_rx_err("dir buf rx object is null");
2153 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2154 return QDF_STATUS_E_FAILURE;
2155 }
2156
2157 if (dbr_rsp.mod_id >= dbr_pdev_obj->num_modules) {
2158 direct_buf_rx_err("Invalid module id:%d", dbr_rsp.mod_id);
2159 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2160 return QDF_STATUS_E_FAILURE;
2161 }
2162 mod_param = &(dbr_pdev_obj->dbr_mod_param[dbr_rsp.mod_id][srng_id]);
2163
2164 if (!mod_param) {
2165 direct_buf_rx_err("dir buf rx module param is null");
2166 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2167 return QDF_STATUS_E_FAILURE;
2168 }
2169
2170 dbr_buf_pool = mod_param->dbr_buf_pool;
2171 dbr_rsp.dbr_entries = qdf_mem_malloc(dbr_rsp.num_buf_release_entry *
2172 sizeof(struct direct_buf_rx_entry));
2173 if (!dbr_rsp.dbr_entries) {
2174 direct_buf_rx_err("invalid dbr_entries");
2175 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2176 return QDF_STATUS_E_FAILURE;
2177 }
2178
2179 if (dbr_rsp.num_meta_data_entry > dbr_rsp.num_buf_release_entry) {
2180 direct_buf_rx_err("More than expected number of metadata");
2181 direct_buf_rx_err("meta_data_entry:%d cv_meta_data_entry:%d buf_release_entry:%d",
2182 dbr_rsp.num_meta_data_entry,
2183 dbr_rsp.num_cv_meta_data_entry,
2184 dbr_rsp.num_buf_release_entry);
2185 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2186 return QDF_STATUS_E_FAILURE;
2187 }
2188 if (dbr_rsp.num_cv_meta_data_entry > dbr_rsp.num_buf_release_entry) {
2189 direct_buf_rx_err("More than expected number of cv metadata");
2190 direct_buf_rx_err("meta_data_entry:%d cv_meta_data_entry:%d buf_release_entry:%d",
2191 dbr_rsp.num_meta_data_entry,
2192 dbr_rsp.num_cv_meta_data_entry,
2193 dbr_rsp.num_buf_release_entry);
2194 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2195 return QDF_STATUS_E_FAILURE;
2196 }
2197 if (dbr_rsp.num_cqi_meta_data_entry > dbr_rsp.num_buf_release_entry) {
2198 direct_buf_rx_err("More than expected number of cqi metadata");
2199 direct_buf_rx_err("meta_data_entry:%d cqi_meta_data_entry:%d buf_release_entry:%d",
2200 dbr_rsp.num_meta_data_entry,
2201 dbr_rsp.num_cqi_meta_data_entry,
2202 dbr_rsp.num_buf_release_entry);
2203 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2204 return QDF_STATUS_E_FAILURE;
2205 }
2206 QDF_ASSERT(!(dbr_rsp.num_cv_meta_data_entry &&
2207 dbr_rsp.num_meta_data_entry));
2208 for (i = 0; i < dbr_rsp.num_buf_release_entry; i++) {
2209 if (wmi_extract_dbr_buf_release_entry(
2210 wmi_handle, data_buf, i,
2211 &dbr_rsp.dbr_entries[i]) != QDF_STATUS_SUCCESS) {
2212 direct_buf_rx_err("Unable to extract DBR buf entry %d",
2213 i+1);
2214 qdf_mem_free(dbr_rsp.dbr_entries);
2215 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2216 return QDF_STATUS_E_FAILURE;
2217 }
2218 status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp,
2219 &dbr_data, i, &cookie);
2220
2221 if (QDF_IS_STATUS_ERROR(status)) {
2222 direct_buf_rx_err("DBR data get failed");
2223 qdf_mem_free(dbr_rsp.dbr_entries);
2224 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2225 return QDF_STATUS_E_FAILURE;
2226 }
2227
2228 dbr_data.meta_data_valid = false;
2229 if (i < dbr_rsp.num_meta_data_entry) {
2230 if (wmi_extract_dbr_buf_metadata(
2231 wmi_handle, data_buf, i,
2232 &dbr_data.meta_data) == QDF_STATUS_SUCCESS)
2233 dbr_data.meta_data_valid = true;
2234 }
2235
2236 dbr_data.cv_meta_data_valid = false;
2237 if (i < dbr_rsp.num_cv_meta_data_entry) {
2238 if (wmi_extract_dbr_buf_cv_metadata(
2239 wmi_handle, data_buf, i,
2240 &dbr_data.cv_meta_data) == QDF_STATUS_SUCCESS)
2241 dbr_data.cv_meta_data_valid = true;
2242 }
2243
2244 dbr_data.cqi_meta_data_valid = false;
2245 if (i < dbr_rsp.num_cqi_meta_data_entry) {
2246 if (wmi_extract_dbr_buf_cqi_metadata(
2247 wmi_handle, data_buf, i,
2248 &dbr_data.cqi_meta_data) == QDF_STATUS_SUCCESS)
2249 dbr_data.cqi_meta_data_valid = true;
2250 }
2251
2252 target_if_dbr_add_ring_debug_entry(pdev, dbr_rsp.mod_id,
2253 DBR_RING_DEBUG_EVENT_RX,
2254 srng_id);
2255 if (mod_param->dbr_rsp_handler(pdev, &dbr_data)) {
2256 status = target_if_dbr_replenish_ring(pdev, mod_param,
2257 dbr_data.vaddr,
2258 cookie);
2259
2260 target_if_dbr_add_ring_debug_entry(
2261 pdev, dbr_rsp.mod_id,
2262 DBR_RING_DEBUG_EVENT_REPLENISH_RING,
2263 srng_id);
2264
2265 if (QDF_IS_STATUS_ERROR(status)) {
2266 direct_buf_rx_err("Ring replenish failed");
2267 qdf_mem_free(dbr_rsp.dbr_entries);
2268 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2269 return QDF_STATUS_E_FAILURE;
2270 }
2271 }
2272 }
2273
2274 qdf_mem_free(dbr_rsp.dbr_entries);
2275 wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id);
2276
2277 return ret;
2278 }
2279
target_if_dbr_empty_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_psoc_obj * dbr_psoc_obj,struct direct_buf_rx_module_param * mod_param)2280 static QDF_STATUS target_if_dbr_empty_ring(struct wlan_objmgr_pdev *pdev,
2281 struct direct_buf_rx_psoc_obj *dbr_psoc_obj,
2282 struct direct_buf_rx_module_param *mod_param)
2283 {
2284 uint32_t idx;
2285 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
2286 struct direct_buf_rx_ring_cap *dbr_ring_cap;
2287 struct direct_buf_rx_buf_info *dbr_buf_pool;
2288
2289 direct_buf_rx_enter();
2290 dbr_ring_cfg = mod_param->dbr_ring_cfg;
2291 dbr_ring_cap = mod_param->dbr_ring_cap;
2292 dbr_buf_pool = mod_param->dbr_buf_pool;
2293
2294 direct_buf_rx_debug("dbr_ring_cfg %pK, ring_cap %pK buf_pool %pK",
2295 dbr_ring_cfg, dbr_ring_cap, dbr_buf_pool);
2296
2297 for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) {
2298 qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev,
2299 (qdf_dma_addr_t)dbr_buf_pool[idx].paddr,
2300 QDF_DMA_FROM_DEVICE,
2301 dbr_ring_cap->min_buf_size);
2302 target_if_dbr_mem_put(pdev, dbr_ring_cap->min_buf_size,
2303 dbr_buf_pool[idx].vaddr,
2304 dbr_buf_pool[idx].offset,
2305 dbr_ring_cap->min_buf_align,
2306 mod_param->mod_id);
2307 }
2308
2309 return QDF_STATUS_SUCCESS;
2310 }
2311
target_if_dbr_deinit_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)2312 static QDF_STATUS target_if_dbr_deinit_ring(struct wlan_objmgr_pdev *pdev,
2313 struct direct_buf_rx_module_param *mod_param)
2314 {
2315 struct wlan_objmgr_psoc *psoc;
2316 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
2317 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
2318
2319 direct_buf_rx_enter();
2320 psoc = wlan_pdev_get_psoc(pdev);
2321 if (!psoc) {
2322 direct_buf_rx_err("psoc is null");
2323 return QDF_STATUS_E_FAILURE;
2324 }
2325
2326 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
2327 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2328
2329 if (!dbr_psoc_obj) {
2330 direct_buf_rx_err("dir buf rx psoc object is null");
2331 return QDF_STATUS_E_FAILURE;
2332 }
2333 direct_buf_rx_debug("dbr_psoc_obj %pK", dbr_psoc_obj);
2334
2335 dbr_ring_cfg = mod_param->dbr_ring_cfg;
2336 if (dbr_ring_cfg) {
2337 target_if_dbr_empty_ring(pdev, dbr_psoc_obj, mod_param);
2338 hal_srng_cleanup(dbr_psoc_obj->hal_soc, dbr_ring_cfg->srng, 0);
2339 qdf_mem_free_consistent(dbr_psoc_obj->osdev,
2340 dbr_psoc_obj->osdev->dev,
2341 dbr_ring_cfg->ring_alloc_size,
2342 dbr_ring_cfg->base_vaddr_unaligned,
2343 (qdf_dma_addr_t)dbr_ring_cfg->base_paddr_unaligned, 0);
2344 }
2345
2346 return QDF_STATUS_SUCCESS;
2347 }
2348
target_if_dbr_deinit_srng(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_module_param * mod_param)2349 static QDF_STATUS target_if_dbr_deinit_srng(
2350 struct wlan_objmgr_pdev *pdev,
2351 struct direct_buf_rx_module_param *mod_param)
2352 {
2353 struct direct_buf_rx_buf_info *dbr_buf_pool;
2354
2355 direct_buf_rx_enter();
2356 dbr_buf_pool = mod_param->dbr_buf_pool;
2357 direct_buf_rx_debug("dbr buf pool %pK", dbr_buf_pool);
2358 target_if_dbr_deinit_ring(pdev, mod_param);
2359 if (mod_param->dbr_buf_pool)
2360 qdf_mem_free(dbr_buf_pool);
2361 mod_param->dbr_buf_pool = NULL;
2362
2363 return QDF_STATUS_SUCCESS;
2364 }
2365
target_if_deinit_dbr_ring(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_pdev_obj * dbr_pdev_obj,enum DBR_MODULE mod_id,uint8_t srng_id)2366 QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev,
2367 struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
2368 enum DBR_MODULE mod_id, uint8_t srng_id)
2369 {
2370 struct direct_buf_rx_module_param *mod_param;
2371
2372 direct_buf_rx_enter();
2373 mod_param = &(dbr_pdev_obj->dbr_mod_param[mod_id][srng_id]);
2374
2375 if (!mod_param) {
2376 direct_buf_rx_err("dir buf rx module param is null");
2377 return QDF_STATUS_E_FAILURE;
2378 }
2379 direct_buf_rx_debug("mod_param %pK, dbr_ring_cap %pK",
2380 mod_param, mod_param->dbr_ring_cap);
2381
2382 if (!mod_param->srng_initialized) {
2383 direct_buf_rx_err("module(%d) srng(%d) was not initialized",
2384 mod_id, srng_id);
2385 return QDF_STATUS_SUCCESS;
2386 }
2387
2388 target_if_dbr_deinit_srng(pdev, mod_param);
2389 if (mod_param->dbr_ring_cap)
2390 qdf_mem_free(mod_param->dbr_ring_cap);
2391 mod_param->dbr_ring_cap = NULL;
2392 if (mod_param->dbr_ring_cfg)
2393 qdf_mem_free(mod_param->dbr_ring_cfg);
2394 mod_param->dbr_ring_cfg = NULL;
2395
2396 mod_param->srng_initialized = false;
2397
2398 return QDF_STATUS_SUCCESS;
2399 }
2400
target_if_direct_buf_rx_register_events(struct wlan_objmgr_psoc * psoc)2401 QDF_STATUS target_if_direct_buf_rx_register_events(
2402 struct wlan_objmgr_psoc *psoc)
2403 {
2404 QDF_STATUS ret;
2405 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
2406
2407 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
2408 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null");
2409 return QDF_STATUS_E_INVAL;
2410 }
2411 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
2412 psoc,
2413 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2414
2415 if (!dbr_psoc_obj) {
2416 direct_buf_rx_err("dir buf rx psoc object is null");
2417 return QDF_STATUS_E_FAILURE;
2418 }
2419
2420 ret = wmi_unified_register_event_handler(
2421 get_wmi_unified_hdl_from_psoc(psoc),
2422 wmi_dma_buf_release_event_id,
2423 target_if_direct_buf_rx_rsp_event_handler,
2424 dbr_psoc_obj->handler_ctx);
2425
2426 direct_buf_rx_info("DBR Handler Context %d", dbr_psoc_obj->handler_ctx);
2427 if (QDF_IS_STATUS_ERROR(ret))
2428 direct_buf_rx_debug("event handler not supported, ret=%d", ret);
2429
2430 return QDF_STATUS_SUCCESS;
2431 }
2432
target_if_direct_buf_rx_unregister_events(struct wlan_objmgr_psoc * psoc)2433 QDF_STATUS target_if_direct_buf_rx_unregister_events(
2434 struct wlan_objmgr_psoc *psoc)
2435 {
2436 if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
2437 direct_buf_rx_err("psoc or psoc->tgt_if_handle is null");
2438 return QDF_STATUS_E_INVAL;
2439 }
2440
2441 wmi_unified_unregister_event_handler(
2442 get_wmi_unified_hdl_from_psoc(psoc),
2443 wmi_dma_buf_release_event_id);
2444
2445 return QDF_STATUS_SUCCESS;
2446 }
2447
target_if_direct_buf_rx_print_ring_stat(struct wlan_objmgr_pdev * pdev)2448 QDF_STATUS target_if_direct_buf_rx_print_ring_stat(
2449 struct wlan_objmgr_pdev *pdev)
2450 {
2451 struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
2452 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
2453 struct wlan_objmgr_psoc *psoc;
2454 void *srng, *hal_soc;
2455 uint32_t hp = 0, tp = 0;
2456 struct direct_buf_rx_module_param *mod_param;
2457 struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
2458 uint8_t num_modules, mod_idx;
2459 uint8_t srng_id;
2460
2461 if (!pdev) {
2462 direct_buf_rx_err("pdev is null");
2463 return QDF_STATUS_E_INVAL;
2464 }
2465
2466 psoc = wlan_pdev_get_psoc(pdev);
2467 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
2468 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2469 dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
2470 WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2471 hal_soc = dbr_psoc_obj->hal_soc;
2472 num_modules = dbr_pdev_obj->num_modules;
2473 direct_buf_rx_debug("--------------------------------------------------");
2474 direct_buf_rx_debug("| Module ID | Module | Head Idx | Tail Idx |");
2475 direct_buf_rx_debug("--------------------------------------------------");
2476 for (mod_idx = 0; mod_idx < num_modules; mod_idx++) {
2477 for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
2478 mod_param =
2479 &dbr_pdev_obj->dbr_mod_param[mod_idx][srng_id];
2480 dbr_ring_cfg = mod_param->dbr_ring_cfg;
2481 if (!dbr_ring_cfg) {
2482 direct_buf_rx_info("dbr_ring_cfg is NULL");
2483 direct_buf_rx_info("mod id %d mod %s", mod_idx,
2484 g_dbr_module_name[mod_idx].
2485 module_name_str);
2486 continue;
2487 }
2488 srng = dbr_ring_cfg->srng;
2489 hal_get_sw_hptp(hal_soc, srng, &tp, &hp);
2490 tp = qdf_le32_to_cpu(tp);
2491 direct_buf_rx_debug("|%11d|%14s|%10x|%10x|",
2492 mod_idx, g_dbr_module_name[mod_idx].
2493 module_name_str,
2494 hp, tp);
2495 }
2496 }
2497 direct_buf_rx_debug("--------------------------------------------------");
2498
2499 return QDF_STATUS_SUCCESS;
2500 }
2501
2502 QDF_STATUS
target_if_direct_buf_rx_get_ring_params(struct wlan_objmgr_pdev * pdev,struct module_ring_params * param,uint8_t mod_id,uint8_t srng_id)2503 target_if_direct_buf_rx_get_ring_params(struct wlan_objmgr_pdev *pdev,
2504 struct module_ring_params *param,
2505 uint8_t mod_id, uint8_t srng_id)
2506 {
2507 struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
2508 struct direct_buf_rx_module_param *dbr_mod_param;
2509
2510 if (!pdev) {
2511 direct_buf_rx_err("pdev context passed is null");
2512 return QDF_STATUS_E_INVAL;
2513 }
2514
2515 dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj
2516 (pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
2517
2518 if (!dbr_pdev_obj) {
2519 direct_buf_rx_err("dir buf rx object is null");
2520 return QDF_STATUS_E_FAILURE;
2521 }
2522
2523 if ((mod_id >= DBR_MODULE_MAX) || (srng_id >= DBR_SRNG_NUM)) {
2524 direct_buf_rx_err("invalid params, mod id %d, srng id %d",
2525 mod_id, srng_id);
2526 return QDF_STATUS_E_INVAL;
2527 }
2528
2529 dbr_mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id];
2530 param->num_bufs = dbr_mod_param->dbr_ring_cfg->num_ptr;
2531 param->buf_size = dbr_mod_param->dbr_ring_cfg->buf_size;
2532
2533 return QDF_STATUS_SUCCESS;
2534 }
2535