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