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